From f190b2f3472f5b73012edf3d9a10f5d6b0e53c07 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Fri, 19 Jul 2024 11:09:30 +0200 Subject: [PATCH 01/17] Added '*.swp' (temporary vim-files) to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f7b7246a..6d036da1 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ oryx-build-commands.txt prof/ tags TAGS +*.swp # Virtual environments *venv/ From 67b674790262f6e6b8b7799e09b10393559a901f Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Tue, 23 Jul 2024 16:11:09 +0200 Subject: [PATCH 02/17] Added test-skeleton for Issue#272 --- tests/unit/test_solving.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/unit/test_solving.py diff --git a/tests/unit/test_solving.py b/tests/unit/test_solving.py new file mode 100644 index 00000000..c458bf34 --- /dev/null +++ b/tests/unit/test_solving.py @@ -0,0 +1,26 @@ +import qrules.particle +import qrules.solving +import qrules.system_control +import qrules.transition + + +def test_find_solutions(): + stm = qrules.StateTransitionManager( + initial_state=["psi(2S)"], + final_state=["gamma", "eta", "eta"], + formalism="helicity", + ) + problem_sets = stm.create_problem_sets() + qn_problem_sets = [ + p.to_qn_problem_set() for pl in problem_sets.values() for p in pl + ] + + # in principle the allowed intermediate states are already in the + particles = qrules.load_pdg() + allowed_intermediate_states = [ + qrules.system_control.create_edge_properties(part) for part in particles + ] + solver = qrules.solving.CSPSolver(allowed_intermediate_states) + solutions = solver.find_solutions(qn_problem_sets[0]) + + assert isinstance(solutions, qrules.solving.QNResult) From 631f692b95cb6e19125110189863f294cec09543 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Tue, 6 Aug 2024 10:25:41 +0200 Subject: [PATCH 03/17] created QNP-setter and its test --- docs/usage/visualize.ipynb | 4 +- tests/unit/test_solving.py | 189 +++++++++++++++++++++++++++++++++++-- 2 files changed, 182 insertions(+), 11 deletions(-) diff --git a/docs/usage/visualize.ipynb b/docs/usage/visualize.ipynb index ad4456fe..ec9c7a23 100644 --- a/docs/usage/visualize.ipynb +++ b/docs/usage/visualize.ipynb @@ -569,8 +569,8 @@ " text += render_sign(particle.c_parity)\n", " if particle.isospin is not None and particle.g_parity is not None:\n", " text += \"(\"\n", - " text += f\"{render_fraction(particle.isospin.magnitude)}\" # with opening brace\n", - " text += f\"{render_sign(particle.g_parity)}\" # with closing brace\n", + " text += f\"{render_fraction(particle.isospin.magnitude)}\"\n", + " text += f\"{render_sign(particle.g_parity)}\"\n", " text += \")\"\n", " return text\n", "\n", diff --git a/tests/unit/test_solving.py b/tests/unit/test_solving.py index c458bf34..6d32c4de 100644 --- a/tests/unit/test_solving.py +++ b/tests/unit/test_solving.py @@ -1,10 +1,156 @@ +from __future__ import annotations + +import copy +from typing import Any + +import attrs +import pytest + import qrules.particle +import qrules.quantum_numbers import qrules.solving import qrules.system_control import qrules.transition +from qrules.argument_handling import GraphEdgePropertyMap, GraphNodePropertyMap, Rule +from qrules.conservation_rules import ( + GraphElementRule, + parity_conservation, + spin_magnitude_conservation, +) +from qrules.quantum_numbers import EdgeQuantumNumbers, NodeQuantumNumbers + + +def test_solve( + particle_database: qrules.particle.ParticleCollection, + qn_problem_set: qrules.solving.QNProblemSet, + graph_edge_property_map: GraphEdgePropertyMap, + graph_node_property_map: GraphEdgePropertyMap, + edge_rules: set[GraphElementRule], + node_rules: set[Rule], + edge_domains: dict[Any, list], + node_domains: dict[Any, list], +): + allowed_intermediate_states = [ + qrules.system_control.create_edge_properties(part) for part in particle_database + ] + solver = qrules.solving.CSPSolver(allowed_intermediate_states) + new_qn_problem_set = qnp_with_new_properties( + qn_problem_set, graph_edge_property_map, graph_node_property_map + ) + new_qn_problem_set = qnp_with_new_settings( + new_qn_problem_set, edge_rules, node_rules, edge_domains, node_domains + ) + solutions = solver.find_solutions(new_qn_problem_set) + + assert isinstance(solutions, qrules.solving.QNResult) + + +def test_inner_dicts_unchanged( + qn_problem_set: qrules.solving.QNProblemSet, + graph_edge_property_map: GraphEdgePropertyMap, + graph_node_property_map: GraphNodePropertyMap, +) -> None: + old_inner_graph_edge_property_map = copy.deepcopy( + qn_problem_set.initial_facts.states + ) + old_inner_graph_node_property_map = copy.deepcopy( + qn_problem_set.initial_facts.interactions + ) + qnp_with_new_properties( + qn_problem_set, graph_edge_property_map, graph_node_property_map + ) + assert old_inner_graph_edge_property_map == qn_problem_set.initial_facts.states + assert ( + old_inner_graph_node_property_map == qn_problem_set.initial_facts.interactions + ) + + +def qnp_with_new_settings( + qn_problem_set: qrules.solving.QNProblemSet, + edge_rules: set[GraphElementRule], + node_rules: set[Rule], + edge_domains: dict[Any, list], + node_domains: dict[Any, list], +) -> qrules.solving.QNProblemSet: + def qnp_with_new_rules( + qn_problem_set: qrules.solving.QNProblemSet, + edge_rules: set[GraphElementRule], + node_rules: set[Rule], + ) -> qrules.solving.QNProblemSet: + old_settings = qn_problem_set.solving_settings + new_settings = attrs.evolve( + qn_problem_set.solving_settings, + states={ + edge_id: attrs.evolve( + setting, conservation_rules=setting.conservation_rules & edge_rules + ) + for edge_id, setting in old_settings.states.items() + }, + interactions={ + node_id: attrs.evolve( + setting, conservation_rules=setting.conservation_rules & node_rules + ) + for node_id, setting in old_settings.interactions.items() + }, + ) + return attrs.evolve(qn_problem_set, solving_settings=new_settings) + def qnp_with_new_domains( + qn_problem_set: qrules.solving.QNProblemSet, + edge_domains: dict[Any, list], + node_domains: dict[Any, list], + ) -> qrules.solving.QNProblemSet: + old_settings = qn_problem_set.solving_settings + new_settings = attrs.evolve( + old_settings, + states={ + edge_id: attrs.evolve(setting, qn_domains=edge_domains) + for edge_id, setting in old_settings.states.items() + }, + interactions={ + node_id: attrs.evolve(setting, qn_domains=node_domains) + for node_id, setting in old_settings.interactions.items() + }, + ) + return attrs.evolve(qn_problem_set, solving_settings=new_settings) -def test_find_solutions(): + return qnp_with_new_rules( + qnp_with_new_domains(qn_problem_set, edge_domains, node_domains), + edge_rules, + node_rules, + ) + + +def qnp_with_new_properties( + qn_problem_set: qrules.solving.QNProblemSet, + graph_edge_property_map: GraphEdgePropertyMap, + graph_node_property_map: GraphNodePropertyMap, +) -> qrules.solving.QNProblemSet: + old_facts = qn_problem_set.initial_facts + new_facts = attrs.evolve( + old_facts, + states={ + node_id: { + key: val + for key, val in prop_map.items() + if key in graph_edge_property_map + } + for node_id, prop_map in old_facts.states.items() + }, + interactions={ + node_id: { + key: val + for key, val in prop_map.items() + if key in graph_node_property_map + } + for node_id, prop_map in old_facts.interactions.items() + }, + ) + return attrs.evolve(qn_problem_set, initial_facts=new_facts) + + +@pytest.fixture(scope="session") +def qn_problem_set() -> qrules.solving.QNProblemSet: stm = qrules.StateTransitionManager( initial_state=["psi(2S)"], final_state=["gamma", "eta", "eta"], @@ -14,13 +160,38 @@ def test_find_solutions(): qn_problem_sets = [ p.to_qn_problem_set() for pl in problem_sets.values() for p in pl ] + return qn_problem_sets[0] - # in principle the allowed intermediate states are already in the - particles = qrules.load_pdg() - allowed_intermediate_states = [ - qrules.system_control.create_edge_properties(part) for part in particles - ] - solver = qrules.solving.CSPSolver(allowed_intermediate_states) - solutions = solver.find_solutions(qn_problem_sets[0]) - assert isinstance(solutions, qrules.solving.QNResult) +@pytest.fixture(scope="session") +def graph_edge_property_map() -> GraphEdgePropertyMap: + return { + EdgeQuantumNumbers.spin_magnitude: 1, + EdgeQuantumNumbers.parity: -1, + EdgeQuantumNumbers.c_parity: 1, + } + + +@pytest.fixture(scope="session") +def graph_node_property_map() -> GraphNodePropertyMap: + return {NodeQuantumNumbers.s_magnitude: 1, NodeQuantumNumbers.l_magnitude: 0} + + +@pytest.fixture(scope="session") +def edge_rules() -> set[GraphElementRule]: + return {spin_magnitude_conservation, parity_conservation} + + +@pytest.fixture(scope="session") +def node_rules() -> set[Rule]: + return {spin_magnitude_conservation, parity_conservation} + + +@pytest.fixture(scope="session") +def edge_domains() -> dict[Any, list]: + return {"spin_magnitude": [1], "parity": [-1, 1], "c_parity": [-1, 1]} + + +@pytest.fixture(scope="session") +def node_domains() -> dict[Any, list]: + return {"l_projection": [0]} From c18d411902ebc343fd009da7922e7115c28cb35d Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Tue, 6 Aug 2024 11:32:39 +0200 Subject: [PATCH 04/17] inlined fixture-arguments, function-renaming --- tests/unit/test_solving.py | 92 +++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 51 deletions(-) diff --git a/tests/unit/test_solving.py b/tests/unit/test_solving.py index 6d32c4de..8028fffe 100644 --- a/tests/unit/test_solving.py +++ b/tests/unit/test_solving.py @@ -1,7 +1,7 @@ from __future__ import annotations import copy -from typing import Any +from typing import TYPE_CHECKING, Any import attrs import pytest @@ -11,34 +11,49 @@ import qrules.solving import qrules.system_control import qrules.transition -from qrules.argument_handling import GraphEdgePropertyMap, GraphNodePropertyMap, Rule from qrules.conservation_rules import ( GraphElementRule, + isospin_validity, parity_conservation, spin_magnitude_conservation, + spin_validity, ) from qrules.quantum_numbers import EdgeQuantumNumbers, NodeQuantumNumbers +if TYPE_CHECKING: + from qrules.argument_handling import ( + GraphEdgePropertyMap, + GraphNodePropertyMap, + Rule, + ) + -def test_solve( +def test_solve_with_new_quantum_number_problem_set( particle_database: qrules.particle.ParticleCollection, qn_problem_set: qrules.solving.QNProblemSet, - graph_edge_property_map: GraphEdgePropertyMap, - graph_node_property_map: GraphEdgePropertyMap, - edge_rules: set[GraphElementRule], - node_rules: set[Rule], - edge_domains: dict[Any, list], - node_domains: dict[Any, list], -): +) -> None: allowed_intermediate_states = [ qrules.system_control.create_edge_properties(part) for part in particle_database ] solver = qrules.solving.CSPSolver(allowed_intermediate_states) - new_qn_problem_set = qnp_with_new_properties( - qn_problem_set, graph_edge_property_map, graph_node_property_map + new_qn_problem_set = quantum_number_problem_set_with_new_properties( + qn_problem_set, + graph_edge_property_map={ + EdgeQuantumNumbers.spin_magnitude: 1, + EdgeQuantumNumbers.parity: -1, + EdgeQuantumNumbers.c_parity: 1, + }, + graph_node_property_map={ + NodeQuantumNumbers.s_magnitude: 1, + NodeQuantumNumbers.l_magnitude: 0, + }, ) - new_qn_problem_set = qnp_with_new_settings( - new_qn_problem_set, edge_rules, node_rules, edge_domains, node_domains + new_qn_problem_set = quantum_number_problem_set_with_new_settings( + new_qn_problem_set, + edge_rules={spin_validity, isospin_validity}, + node_rules={spin_magnitude_conservation, parity_conservation}, + edge_domains={"spin_magnitude": [1], "parity": [-1, 1], "c_parity": [-1, 1]}, + node_domains={"l_projection": [0]}, ) solutions = solver.find_solutions(new_qn_problem_set) @@ -56,7 +71,16 @@ def test_inner_dicts_unchanged( old_inner_graph_node_property_map = copy.deepcopy( qn_problem_set.initial_facts.interactions ) - qnp_with_new_properties( + graph_edge_property_map = { + EdgeQuantumNumbers.spin_magnitude: 1, + EdgeQuantumNumbers.parity: -1, + EdgeQuantumNumbers.c_parity: 1, + } + graph_node_property_map = { + NodeQuantumNumbers.s_magnitude: 1, + NodeQuantumNumbers.l_magnitude: 0, + } + quantum_number_problem_set_with_new_properties( qn_problem_set, graph_edge_property_map, graph_node_property_map ) assert old_inner_graph_edge_property_map == qn_problem_set.initial_facts.states @@ -65,7 +89,7 @@ def test_inner_dicts_unchanged( ) -def qnp_with_new_settings( +def quantum_number_problem_set_with_new_settings( qn_problem_set: qrules.solving.QNProblemSet, edge_rules: set[GraphElementRule], node_rules: set[Rule], @@ -121,7 +145,7 @@ def qnp_with_new_domains( ) -def qnp_with_new_properties( +def quantum_number_problem_set_with_new_properties( qn_problem_set: qrules.solving.QNProblemSet, graph_edge_property_map: GraphEdgePropertyMap, graph_node_property_map: GraphNodePropertyMap, @@ -161,37 +185,3 @@ def qn_problem_set() -> qrules.solving.QNProblemSet: p.to_qn_problem_set() for pl in problem_sets.values() for p in pl ] return qn_problem_sets[0] - - -@pytest.fixture(scope="session") -def graph_edge_property_map() -> GraphEdgePropertyMap: - return { - EdgeQuantumNumbers.spin_magnitude: 1, - EdgeQuantumNumbers.parity: -1, - EdgeQuantumNumbers.c_parity: 1, - } - - -@pytest.fixture(scope="session") -def graph_node_property_map() -> GraphNodePropertyMap: - return {NodeQuantumNumbers.s_magnitude: 1, NodeQuantumNumbers.l_magnitude: 0} - - -@pytest.fixture(scope="session") -def edge_rules() -> set[GraphElementRule]: - return {spin_magnitude_conservation, parity_conservation} - - -@pytest.fixture(scope="session") -def node_rules() -> set[Rule]: - return {spin_magnitude_conservation, parity_conservation} - - -@pytest.fixture(scope="session") -def edge_domains() -> dict[Any, list]: - return {"spin_magnitude": [1], "parity": [-1, 1], "c_parity": [-1, 1]} - - -@pytest.fixture(scope="session") -def node_domains() -> dict[Any, list]: - return {"l_projection": [0]} From 5a997d00eb1bc1e7ed96408b19f0fcf3304ed431 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Thu, 8 Aug 2024 16:43:16 +0200 Subject: [PATCH 05/17] iss272: faulty filters for QNProblemSet --- tests/unit/test_solving.py | 292 ++++++++++++++++++++++++++++++------- 1 file changed, 240 insertions(+), 52 deletions(-) diff --git a/tests/unit/test_solving.py b/tests/unit/test_solving.py index 8028fffe..31d0d097 100644 --- a/tests/unit/test_solving.py +++ b/tests/unit/test_solving.py @@ -8,17 +8,18 @@ import qrules.particle import qrules.quantum_numbers -import qrules.solving import qrules.system_control import qrules.transition from qrules.conservation_rules import ( GraphElementRule, - isospin_validity, + c_parity_conservation, parity_conservation, spin_magnitude_conservation, spin_validity, ) from qrules.quantum_numbers import EdgeQuantumNumbers, NodeQuantumNumbers +from qrules.solving import CSPSolver, EdgeSettings, NodeSettings, QNProblemSet +from qrules.topology import MutableTransition if TYPE_CHECKING: from qrules.argument_handling import ( @@ -28,48 +29,138 @@ ) -def test_solve_with_new_quantum_number_problem_set( - particle_database: qrules.particle.ParticleCollection, - qn_problem_set: qrules.solving.QNProblemSet, +def test_solve( + all_particles: qrules.particle.ParticleCollection, + quantum_number_problem_set: QNProblemSet, ) -> None: - allowed_intermediate_states = [ - qrules.system_control.create_edge_properties(part) for part in particle_database - ] - solver = qrules.solving.CSPSolver(allowed_intermediate_states) - new_qn_problem_set = quantum_number_problem_set_with_new_properties( - qn_problem_set, - graph_edge_property_map={ - EdgeQuantumNumbers.spin_magnitude: 1, - EdgeQuantumNumbers.parity: -1, - EdgeQuantumNumbers.c_parity: 1, - }, - graph_node_property_map={ - NodeQuantumNumbers.s_magnitude: 1, - NodeQuantumNumbers.l_magnitude: 0, + solver = CSPSolver(all_particles) + result = solver.find_solutions(quantum_number_problem_set) + assert len(result.solutions) != 0 + + +def test_solve_with_filtered_quantum_number_problem_set( + all_particles: qrules.particle.ParticleCollection, + quantum_number_problem_set: QNProblemSet, +) -> None: + solver = CSPSolver(all_particles) + new_quantum_number_problem_set = filter_quantum_number_problem_set_settings( + quantum_number_problem_set, + edge_rules={spin_validity}, + node_rules={ + spin_magnitude_conservation, + parity_conservation, + c_parity_conservation, }, + edge_domains=( + EdgeQuantumNumbers.spin_magnitude, + EdgeQuantumNumbers.parity, + EdgeQuantumNumbers.c_parity, + ), + node_domains=(NodeQuantumNumbers.l_magnitude, NodeQuantumNumbers.s_magnitude), + ) + new_quantum_number_problem_set = filter_quantum_number_problem_set_properties( + new_quantum_number_problem_set, + edge_properties=( + EdgeQuantumNumbers.spin_magnitude, + EdgeQuantumNumbers.parity, + EdgeQuantumNumbers.c_parity, + ), + node_properties=( + NodeQuantumNumbers.l_magnitude, + NodeQuantumNumbers.s_magnitude, + ), + ) + result = solver.find_solutions(new_quantum_number_problem_set) + + assert len(result.solutions) != 0 + + +def remove_quantum_number_problem_set_settings( + quantum_number_problem_set: QNProblemSet, + edge_rules_to_be_removed: set[GraphElementRule], + node_rules_to_be_removed: set[Rule], + edge_domains_to_be_removed: tuple[Any, ...], + node_domains_to_be_removed: tuple[Any, ...], +) -> QNProblemSet: + old_edge_settings = quantum_number_problem_set.solving_settings.states + old_node_settings = quantum_number_problem_set.solving_settings.interactions + new_edge_settings = { + edge_id: EdgeSettings( + conservation_rules=edge_setting.conservation_rules + - edge_rules_to_be_removed, + rule_priorities=edge_setting.rule_priorities, + qn_domains={ + key: val + for key, val in edge_setting.qn_domains.items() + if key not in edge_domains_to_be_removed + }, + ) + for edge_id, edge_setting in old_edge_settings.items() + } + new_node_settings = { + node_id: NodeSettings( + conservation_rules=node_setting.conservation_rules + - node_rules_to_be_removed, + rule_priorities=node_setting.rule_priorities, + qn_domains={ + key: val + for key, val in node_setting.qn_domains.items() + if key not in node_domains_to_be_removed + }, + ) + for node_id, node_setting in old_node_settings.items() + } + new_mutable_transition = MutableTransition( + topology=quantum_number_problem_set.solving_settings.topology, + states=new_edge_settings, + interactions=new_node_settings, ) - new_qn_problem_set = quantum_number_problem_set_with_new_settings( - new_qn_problem_set, - edge_rules={spin_validity, isospin_validity}, - node_rules={spin_magnitude_conservation, parity_conservation}, - edge_domains={"spin_magnitude": [1], "parity": [-1, 1], "c_parity": [-1, 1]}, - node_domains={"l_projection": [0]}, + return attrs.evolve( + quantum_number_problem_set, solving_settings=new_mutable_transition ) - solutions = solver.find_solutions(new_qn_problem_set) - assert isinstance(solutions, qrules.solving.QNResult) + +def remove_quantum_number_problem_set_properties( + quantum_number_problem_set: QNProblemSet, + edge_properties_to_be_removed: tuple[EdgeQuantumNumbers], + node_properties_to_be_removed: tuple[NodeQuantumNumbers], +) -> QNProblemSet: + old_edge_properties = quantum_number_problem_set.initial_facts.states + old_node_properties = quantum_number_problem_set.initial_facts.interactions + new_edge_properties = { + edge_id: { + edge_quantum_number: scalar + for edge_quantum_number, scalar in graph_edge_property_map.items() + if edge_quantum_number not in edge_properties_to_be_removed + } + for edge_id, graph_edge_property_map in old_edge_properties.items() + } + new_node_properties = { + node_id: { + node_quantum_number: scalar + for node_quantum_number, scalar in graph_node_property_map.items() + if node_quantum_number not in node_properties_to_be_removed + } + for node_id, graph_node_property_map in old_node_properties.items() + } + new_mutable_transition = MutableTransition( + topology=quantum_number_problem_set.initial_facts.topology, + states=new_edge_properties, + interactions=new_node_properties, + ) + return attrs.evolve( + quantum_number_problem_set, initial_facts=new_mutable_transition + ) def test_inner_dicts_unchanged( - qn_problem_set: qrules.solving.QNProblemSet, - graph_edge_property_map: GraphEdgePropertyMap, - graph_node_property_map: GraphNodePropertyMap, + quantum_number_problem_set: QNProblemSet, ) -> None: old_inner_graph_edge_property_map = copy.deepcopy( - qn_problem_set.initial_facts.states + quantum_number_problem_set.initial_facts.states ) old_inner_graph_node_property_map = copy.deepcopy( - qn_problem_set.initial_facts.interactions + quantum_number_problem_set.initial_facts.interactions ) graph_edge_property_map = { EdgeQuantumNumbers.spin_magnitude: 1, @@ -81,29 +172,118 @@ def test_inner_dicts_unchanged( NodeQuantumNumbers.l_magnitude: 0, } quantum_number_problem_set_with_new_properties( - qn_problem_set, graph_edge_property_map, graph_node_property_map + quantum_number_problem_set, graph_edge_property_map, graph_node_property_map + ) + assert ( + old_inner_graph_edge_property_map + == quantum_number_problem_set.initial_facts.states ) - assert old_inner_graph_edge_property_map == qn_problem_set.initial_facts.states assert ( - old_inner_graph_node_property_map == qn_problem_set.initial_facts.interactions + old_inner_graph_node_property_map + == quantum_number_problem_set.initial_facts.interactions + ) + + +def filter_quantum_number_problem_set_settings( + quantum_number_problem_set: QNProblemSet, + edge_rules: set[GraphElementRule], + node_rules: set[Rule], + edge_domains: tuple[Any, ...], + node_domains: tuple[Any, ...], + keep_domains: bool = True, +) -> QNProblemSet: + old_edge_settings = quantum_number_problem_set.solving_settings.states + old_node_settings = quantum_number_problem_set.solving_settings.interactions + new_edge_settings = { + edge_id: EdgeSettings( + conservation_rules=edge_rules, + rule_priorities=edge_setting.rule_priorities, + qn_domains=( + edge_setting.qn_domains + if keep_domains + else { + key: val + for key, val in edge_setting.qn_domains.items() + if key in edge_domains + } + ), + ) + for edge_id, edge_setting in old_edge_settings.items() + } + new_node_settings = { + node_id: NodeSettings( + conservation_rules=node_rules, + rule_priorities=node_setting.rule_priorities, + qn_domains=( + node_setting.qn_domains + if keep_domains + else { + key: val + for key, val in node_setting.qn_domains.items() + if key in node_domains + } + ), + ) + for node_id, node_setting in old_node_settings.items() + } + new_mutable_transition = MutableTransition( + topology=quantum_number_problem_set.solving_settings.topology, + states=new_edge_settings, + interactions=new_node_settings, + ) + return attrs.evolve( + quantum_number_problem_set, solving_settings=new_mutable_transition + ) + + +def filter_quantum_number_problem_set_properties( + quantum_number_problem_set: QNProblemSet, + edge_properties: tuple[EdgeQuantumNumbers], + node_properties: tuple[NodeQuantumNumbers], +) -> QNProblemSet: + old_edge_properties = quantum_number_problem_set.initial_facts.states + old_node_properties = quantum_number_problem_set.initial_facts.interactions + new_edge_properties = { + edge_id: { + edge_quantum_number: scalar + for edge_quantum_number, scalar in graph_edge_property_map.items() + if edge_quantum_number in edge_properties + } + for edge_id, graph_edge_property_map in old_edge_properties.items() + } + new_node_properties = { + node_id: { + node_quantum_number: scalar + for node_quantum_number, scalar in graph_node_property_map.items() + if node_quantum_number in node_properties + } + for node_id, graph_node_property_map in old_node_properties.items() + } + new_mutable_transition = MutableTransition( + topology=quantum_number_problem_set.initial_facts.topology, + states=new_edge_properties, + interactions=new_node_properties, + ) + return attrs.evolve( + quantum_number_problem_set, initial_facts=new_mutable_transition ) def quantum_number_problem_set_with_new_settings( - qn_problem_set: qrules.solving.QNProblemSet, + quantum_number_problem_set: QNProblemSet, edge_rules: set[GraphElementRule], node_rules: set[Rule], edge_domains: dict[Any, list], node_domains: dict[Any, list], -) -> qrules.solving.QNProblemSet: +) -> QNProblemSet: def qnp_with_new_rules( - qn_problem_set: qrules.solving.QNProblemSet, + quantum_number_problem_set: QNProblemSet, edge_rules: set[GraphElementRule], node_rules: set[Rule], - ) -> qrules.solving.QNProblemSet: - old_settings = qn_problem_set.solving_settings + ) -> QNProblemSet: + old_settings = quantum_number_problem_set.solving_settings new_settings = attrs.evolve( - qn_problem_set.solving_settings, + quantum_number_problem_set.solving_settings, states={ edge_id: attrs.evolve( setting, conservation_rules=setting.conservation_rules & edge_rules @@ -117,14 +297,14 @@ def qnp_with_new_rules( for node_id, setting in old_settings.interactions.items() }, ) - return attrs.evolve(qn_problem_set, solving_settings=new_settings) + return attrs.evolve(quantum_number_problem_set, solving_settings=new_settings) def qnp_with_new_domains( - qn_problem_set: qrules.solving.QNProblemSet, + quantum_number_problem_set: QNProblemSet, edge_domains: dict[Any, list], node_domains: dict[Any, list], - ) -> qrules.solving.QNProblemSet: - old_settings = qn_problem_set.solving_settings + ) -> QNProblemSet: + old_settings = quantum_number_problem_set.solving_settings new_settings = attrs.evolve( old_settings, states={ @@ -136,21 +316,21 @@ def qnp_with_new_domains( for node_id, setting in old_settings.interactions.items() }, ) - return attrs.evolve(qn_problem_set, solving_settings=new_settings) + return attrs.evolve(quantum_number_problem_set, solving_settings=new_settings) return qnp_with_new_rules( - qnp_with_new_domains(qn_problem_set, edge_domains, node_domains), + qnp_with_new_domains(quantum_number_problem_set, edge_domains, node_domains), edge_rules, node_rules, ) def quantum_number_problem_set_with_new_properties( - qn_problem_set: qrules.solving.QNProblemSet, + quantum_number_problem_set: QNProblemSet, graph_edge_property_map: GraphEdgePropertyMap, graph_node_property_map: GraphNodePropertyMap, -) -> qrules.solving.QNProblemSet: - old_facts = qn_problem_set.initial_facts +) -> QNProblemSet: + old_facts = quantum_number_problem_set.initial_facts new_facts = attrs.evolve( old_facts, states={ @@ -170,11 +350,19 @@ def quantum_number_problem_set_with_new_properties( for node_id, prop_map in old_facts.interactions.items() }, ) - return attrs.evolve(qn_problem_set, initial_facts=new_facts) + return attrs.evolve(quantum_number_problem_set, initial_facts=new_facts) + + +@pytest.fixture(scope="session") +def all_particles(): + return [ + qrules.system_control.create_edge_properties(part) + for part in qrules.particle.load_pdg() + ] @pytest.fixture(scope="session") -def qn_problem_set() -> qrules.solving.QNProblemSet: +def quantum_number_problem_set(request) -> QNProblemSet: stm = qrules.StateTransitionManager( initial_state=["psi(2S)"], final_state=["gamma", "eta", "eta"], From ad5ea05297a7a47f74c6eac52c87c7b312a3501d Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Thu, 8 Aug 2024 21:34:05 +0200 Subject: [PATCH 06/17] FIX: stabilize test fixture --- tests/unit/test_solving.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_solving.py b/tests/unit/test_solving.py index 31d0d097..f01458ba 100644 --- a/tests/unit/test_solving.py +++ b/tests/unit/test_solving.py @@ -35,7 +35,7 @@ def test_solve( ) -> None: solver = CSPSolver(all_particles) result = solver.find_solutions(quantum_number_problem_set) - assert len(result.solutions) != 0 + assert len(result.solutions) == 19 def test_solve_with_filtered_quantum_number_problem_set( @@ -370,6 +370,8 @@ def quantum_number_problem_set(request) -> QNProblemSet: ) problem_sets = stm.create_problem_sets() qn_problem_sets = [ - p.to_qn_problem_set() for pl in problem_sets.values() for p in pl + p.to_qn_problem_set() + for strength in sorted(problem_sets) + for p in problem_sets[strength] ] return qn_problem_sets[0] From 6fbf83b7af916129c41515790fcc7f2a18fec90a Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Wed, 21 Aug 2024 15:37:40 +0200 Subject: [PATCH 07/17] added pid&spin_projection -> non-zero results --- tests/unit/test_solving.py | 274 +++++++------------------------------ 1 file changed, 51 insertions(+), 223 deletions(-) diff --git a/tests/unit/test_solving.py b/tests/unit/test_solving.py index f01458ba..42f26df2 100644 --- a/tests/unit/test_solving.py +++ b/tests/unit/test_solving.py @@ -1,7 +1,6 @@ from __future__ import annotations -import copy -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Iterable, Union import attrs import pytest @@ -22,11 +21,38 @@ from qrules.topology import MutableTransition if TYPE_CHECKING: - from qrules.argument_handling import ( - GraphEdgePropertyMap, - GraphNodePropertyMap, - Rule, - ) + from qrules.argument_handling import Rule + + +EdgeQuantumNumberTypes = Union[ + type[EdgeQuantumNumbers.pid], + type[EdgeQuantumNumbers.mass], + type[EdgeQuantumNumbers.width], + type[EdgeQuantumNumbers.spin_magnitude], + type[EdgeQuantumNumbers.spin_projection], + type[EdgeQuantumNumbers.charge], + type[EdgeQuantumNumbers.isospin_magnitude], + type[EdgeQuantumNumbers.isospin_projection], + type[EdgeQuantumNumbers.strangeness], + type[EdgeQuantumNumbers.charmness], + type[EdgeQuantumNumbers.bottomness], + type[EdgeQuantumNumbers.topness], + type[EdgeQuantumNumbers.baryon_number], + type[EdgeQuantumNumbers.electron_lepton_number], + type[EdgeQuantumNumbers.muon_lepton_number], + type[EdgeQuantumNumbers.tau_lepton_number], + type[EdgeQuantumNumbers.parity], + type[EdgeQuantumNumbers.c_parity], + type[EdgeQuantumNumbers.g_parity], +] + +NodeQuantumNumberTypes = Union[ + type[NodeQuantumNumbers.l_magnitude], + type[NodeQuantumNumbers.l_projection], + type[NodeQuantumNumbers.s_magnitude], + type[NodeQuantumNumbers.s_projection], + type[NodeQuantumNumbers.parity_prefactor], +] def test_solve( @@ -52,7 +78,9 @@ def test_solve_with_filtered_quantum_number_problem_set( c_parity_conservation, }, edge_domains=( + EdgeQuantumNumbers.pid, # had to be added for c_parity_conservation to work EdgeQuantumNumbers.spin_magnitude, + EdgeQuantumNumbers.spin_projection, # had to be added for spin_magnitude_conservation to work EdgeQuantumNumbers.parity, EdgeQuantumNumbers.c_parity, ), @@ -61,7 +89,9 @@ def test_solve_with_filtered_quantum_number_problem_set( new_quantum_number_problem_set = filter_quantum_number_problem_set_properties( new_quantum_number_problem_set, edge_properties=( + EdgeQuantumNumbers.pid, # had to be added for c_parity_conservation to work EdgeQuantumNumbers.spin_magnitude, + EdgeQuantumNumbers.spin_projection, # had to be added for spin_magnitude_conservation to work EdgeQuantumNumbers.parity, EdgeQuantumNumbers.c_parity, ), @@ -75,122 +105,12 @@ def test_solve_with_filtered_quantum_number_problem_set( assert len(result.solutions) != 0 -def remove_quantum_number_problem_set_settings( - quantum_number_problem_set: QNProblemSet, - edge_rules_to_be_removed: set[GraphElementRule], - node_rules_to_be_removed: set[Rule], - edge_domains_to_be_removed: tuple[Any, ...], - node_domains_to_be_removed: tuple[Any, ...], -) -> QNProblemSet: - old_edge_settings = quantum_number_problem_set.solving_settings.states - old_node_settings = quantum_number_problem_set.solving_settings.interactions - new_edge_settings = { - edge_id: EdgeSettings( - conservation_rules=edge_setting.conservation_rules - - edge_rules_to_be_removed, - rule_priorities=edge_setting.rule_priorities, - qn_domains={ - key: val - for key, val in edge_setting.qn_domains.items() - if key not in edge_domains_to_be_removed - }, - ) - for edge_id, edge_setting in old_edge_settings.items() - } - new_node_settings = { - node_id: NodeSettings( - conservation_rules=node_setting.conservation_rules - - node_rules_to_be_removed, - rule_priorities=node_setting.rule_priorities, - qn_domains={ - key: val - for key, val in node_setting.qn_domains.items() - if key not in node_domains_to_be_removed - }, - ) - for node_id, node_setting in old_node_settings.items() - } - new_mutable_transition = MutableTransition( - topology=quantum_number_problem_set.solving_settings.topology, - states=new_edge_settings, - interactions=new_node_settings, - ) - return attrs.evolve( - quantum_number_problem_set, solving_settings=new_mutable_transition - ) - - -def remove_quantum_number_problem_set_properties( - quantum_number_problem_set: QNProblemSet, - edge_properties_to_be_removed: tuple[EdgeQuantumNumbers], - node_properties_to_be_removed: tuple[NodeQuantumNumbers], -) -> QNProblemSet: - old_edge_properties = quantum_number_problem_set.initial_facts.states - old_node_properties = quantum_number_problem_set.initial_facts.interactions - new_edge_properties = { - edge_id: { - edge_quantum_number: scalar - for edge_quantum_number, scalar in graph_edge_property_map.items() - if edge_quantum_number not in edge_properties_to_be_removed - } - for edge_id, graph_edge_property_map in old_edge_properties.items() - } - new_node_properties = { - node_id: { - node_quantum_number: scalar - for node_quantum_number, scalar in graph_node_property_map.items() - if node_quantum_number not in node_properties_to_be_removed - } - for node_id, graph_node_property_map in old_node_properties.items() - } - new_mutable_transition = MutableTransition( - topology=quantum_number_problem_set.initial_facts.topology, - states=new_edge_properties, - interactions=new_node_properties, - ) - return attrs.evolve( - quantum_number_problem_set, initial_facts=new_mutable_transition - ) - - -def test_inner_dicts_unchanged( - quantum_number_problem_set: QNProblemSet, -) -> None: - old_inner_graph_edge_property_map = copy.deepcopy( - quantum_number_problem_set.initial_facts.states - ) - old_inner_graph_node_property_map = copy.deepcopy( - quantum_number_problem_set.initial_facts.interactions - ) - graph_edge_property_map = { - EdgeQuantumNumbers.spin_magnitude: 1, - EdgeQuantumNumbers.parity: -1, - EdgeQuantumNumbers.c_parity: 1, - } - graph_node_property_map = { - NodeQuantumNumbers.s_magnitude: 1, - NodeQuantumNumbers.l_magnitude: 0, - } - quantum_number_problem_set_with_new_properties( - quantum_number_problem_set, graph_edge_property_map, graph_node_property_map - ) - assert ( - old_inner_graph_edge_property_map - == quantum_number_problem_set.initial_facts.states - ) - assert ( - old_inner_graph_node_property_map - == quantum_number_problem_set.initial_facts.interactions - ) - - def filter_quantum_number_problem_set_settings( quantum_number_problem_set: QNProblemSet, edge_rules: set[GraphElementRule], node_rules: set[Rule], - edge_domains: tuple[Any, ...], - node_domains: tuple[Any, ...], - keep_domains: bool = True, + edge_domains: Iterable[Any], + node_domains: Iterable[Any], ) -> QNProblemSet: old_edge_settings = quantum_number_problem_set.solving_settings.states old_node_settings = quantum_number_problem_set.solving_settings.interactions @@ -198,15 +118,11 @@ def filter_quantum_number_problem_set_settings( edge_id: EdgeSettings( conservation_rules=edge_rules, rule_priorities=edge_setting.rule_priorities, - qn_domains=( - edge_setting.qn_domains - if keep_domains - else { - key: val - for key, val in edge_setting.qn_domains.items() - if key in edge_domains - } - ), + qn_domains=({ + key: val + for key, val in edge_setting.qn_domains.items() + if key in set(edge_domains) + }), ) for edge_id, edge_setting in old_edge_settings.items() } @@ -214,15 +130,11 @@ def filter_quantum_number_problem_set_settings( node_id: NodeSettings( conservation_rules=node_rules, rule_priorities=node_setting.rule_priorities, - qn_domains=( - node_setting.qn_domains - if keep_domains - else { - key: val - for key, val in node_setting.qn_domains.items() - if key in node_domains - } - ), + qn_domains=({ + key: val + for key, val in node_setting.qn_domains.items() + if key in set(node_domains) + }), ) for node_id, node_setting in old_node_settings.items() } @@ -238,8 +150,8 @@ def filter_quantum_number_problem_set_settings( def filter_quantum_number_problem_set_properties( quantum_number_problem_set: QNProblemSet, - edge_properties: tuple[EdgeQuantumNumbers], - node_properties: tuple[NodeQuantumNumbers], + edge_properties: Iterable[EdgeQuantumNumberTypes], + node_properties: Iterable[NodeQuantumNumberTypes], ) -> QNProblemSet: old_edge_properties = quantum_number_problem_set.initial_facts.states old_node_properties = quantum_number_problem_set.initial_facts.interactions @@ -269,90 +181,6 @@ def filter_quantum_number_problem_set_properties( ) -def quantum_number_problem_set_with_new_settings( - quantum_number_problem_set: QNProblemSet, - edge_rules: set[GraphElementRule], - node_rules: set[Rule], - edge_domains: dict[Any, list], - node_domains: dict[Any, list], -) -> QNProblemSet: - def qnp_with_new_rules( - quantum_number_problem_set: QNProblemSet, - edge_rules: set[GraphElementRule], - node_rules: set[Rule], - ) -> QNProblemSet: - old_settings = quantum_number_problem_set.solving_settings - new_settings = attrs.evolve( - quantum_number_problem_set.solving_settings, - states={ - edge_id: attrs.evolve( - setting, conservation_rules=setting.conservation_rules & edge_rules - ) - for edge_id, setting in old_settings.states.items() - }, - interactions={ - node_id: attrs.evolve( - setting, conservation_rules=setting.conservation_rules & node_rules - ) - for node_id, setting in old_settings.interactions.items() - }, - ) - return attrs.evolve(quantum_number_problem_set, solving_settings=new_settings) - - def qnp_with_new_domains( - quantum_number_problem_set: QNProblemSet, - edge_domains: dict[Any, list], - node_domains: dict[Any, list], - ) -> QNProblemSet: - old_settings = quantum_number_problem_set.solving_settings - new_settings = attrs.evolve( - old_settings, - states={ - edge_id: attrs.evolve(setting, qn_domains=edge_domains) - for edge_id, setting in old_settings.states.items() - }, - interactions={ - node_id: attrs.evolve(setting, qn_domains=node_domains) - for node_id, setting in old_settings.interactions.items() - }, - ) - return attrs.evolve(quantum_number_problem_set, solving_settings=new_settings) - - return qnp_with_new_rules( - qnp_with_new_domains(quantum_number_problem_set, edge_domains, node_domains), - edge_rules, - node_rules, - ) - - -def quantum_number_problem_set_with_new_properties( - quantum_number_problem_set: QNProblemSet, - graph_edge_property_map: GraphEdgePropertyMap, - graph_node_property_map: GraphNodePropertyMap, -) -> QNProblemSet: - old_facts = quantum_number_problem_set.initial_facts - new_facts = attrs.evolve( - old_facts, - states={ - node_id: { - key: val - for key, val in prop_map.items() - if key in graph_edge_property_map - } - for node_id, prop_map in old_facts.states.items() - }, - interactions={ - node_id: { - key: val - for key, val in prop_map.items() - if key in graph_node_property_map - } - for node_id, prop_map in old_facts.interactions.items() - }, - ) - return attrs.evolve(quantum_number_problem_set, initial_facts=new_facts) - - @pytest.fixture(scope="session") def all_particles(): return [ From 557ec5723433255f6dc942d3813e9c2b66002804 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Wed, 21 Aug 2024 16:24:08 +0200 Subject: [PATCH 08/17] cleanup of test_solving.py --- tests/unit/test_solving.py | 55 +++++++++++++------------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/tests/unit/test_solving.py b/tests/unit/test_solving.py index 42f26df2..5fa47a82 100644 --- a/tests/unit/test_solving.py +++ b/tests/unit/test_solving.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Iterable, Union +from typing import TYPE_CHECKING, Iterable, Union import attrs import pytest @@ -69,7 +69,7 @@ def test_solve_with_filtered_quantum_number_problem_set( quantum_number_problem_set: QNProblemSet, ) -> None: solver = CSPSolver(all_particles) - new_quantum_number_problem_set = filter_quantum_number_problem_set_settings( + new_quantum_number_problem_set = filter_quantum_number_problem_set( quantum_number_problem_set, edge_rules={spin_validity}, node_rules={ @@ -77,25 +77,14 @@ def test_solve_with_filtered_quantum_number_problem_set( parity_conservation, c_parity_conservation, }, - edge_domains=( + edge_properties_and_domains=( EdgeQuantumNumbers.pid, # had to be added for c_parity_conservation to work EdgeQuantumNumbers.spin_magnitude, EdgeQuantumNumbers.spin_projection, # had to be added for spin_magnitude_conservation to work EdgeQuantumNumbers.parity, EdgeQuantumNumbers.c_parity, ), - node_domains=(NodeQuantumNumbers.l_magnitude, NodeQuantumNumbers.s_magnitude), - ) - new_quantum_number_problem_set = filter_quantum_number_problem_set_properties( - new_quantum_number_problem_set, - edge_properties=( - EdgeQuantumNumbers.pid, # had to be added for c_parity_conservation to work - EdgeQuantumNumbers.spin_magnitude, - EdgeQuantumNumbers.spin_projection, # had to be added for spin_magnitude_conservation to work - EdgeQuantumNumbers.parity, - EdgeQuantumNumbers.c_parity, - ), - node_properties=( + node_properties_and_domains=( NodeQuantumNumbers.l_magnitude, NodeQuantumNumbers.s_magnitude, ), @@ -105,15 +94,17 @@ def test_solve_with_filtered_quantum_number_problem_set( assert len(result.solutions) != 0 -def filter_quantum_number_problem_set_settings( +def filter_quantum_number_problem_set( quantum_number_problem_set: QNProblemSet, edge_rules: set[GraphElementRule], node_rules: set[Rule], - edge_domains: Iterable[Any], - node_domains: Iterable[Any], + edge_properties_and_domains: Iterable[EdgeQuantumNumberTypes], + node_properties_and_domains: Iterable[NodeQuantumNumberTypes], ) -> QNProblemSet: old_edge_settings = quantum_number_problem_set.solving_settings.states old_node_settings = quantum_number_problem_set.solving_settings.interactions + old_edge_properties = quantum_number_problem_set.initial_facts.states + old_node_properties = quantum_number_problem_set.initial_facts.interactions new_edge_settings = { edge_id: EdgeSettings( conservation_rules=edge_rules, @@ -121,7 +112,7 @@ def filter_quantum_number_problem_set_settings( qn_domains=({ key: val for key, val in edge_setting.qn_domains.items() - if key in set(edge_domains) + if key in set(edge_properties_and_domains) }), ) for edge_id, edge_setting in old_edge_settings.items() @@ -133,33 +124,21 @@ def filter_quantum_number_problem_set_settings( qn_domains=({ key: val for key, val in node_setting.qn_domains.items() - if key in set(node_domains) + if key in set(node_properties_and_domains) }), ) for node_id, node_setting in old_node_settings.items() } - new_mutable_transition = MutableTransition( + new_combined_settings = MutableTransition( topology=quantum_number_problem_set.solving_settings.topology, states=new_edge_settings, interactions=new_node_settings, ) - return attrs.evolve( - quantum_number_problem_set, solving_settings=new_mutable_transition - ) - - -def filter_quantum_number_problem_set_properties( - quantum_number_problem_set: QNProblemSet, - edge_properties: Iterable[EdgeQuantumNumberTypes], - node_properties: Iterable[NodeQuantumNumberTypes], -) -> QNProblemSet: - old_edge_properties = quantum_number_problem_set.initial_facts.states - old_node_properties = quantum_number_problem_set.initial_facts.interactions new_edge_properties = { edge_id: { edge_quantum_number: scalar for edge_quantum_number, scalar in graph_edge_property_map.items() - if edge_quantum_number in edge_properties + if edge_quantum_number in edge_properties_and_domains } for edge_id, graph_edge_property_map in old_edge_properties.items() } @@ -167,17 +146,19 @@ def filter_quantum_number_problem_set_properties( node_id: { node_quantum_number: scalar for node_quantum_number, scalar in graph_node_property_map.items() - if node_quantum_number in node_properties + if node_quantum_number in node_properties_and_domains } for node_id, graph_node_property_map in old_node_properties.items() } - new_mutable_transition = MutableTransition( + new_combined_properties = MutableTransition( topology=quantum_number_problem_set.initial_facts.topology, states=new_edge_properties, interactions=new_node_properties, ) return attrs.evolve( - quantum_number_problem_set, initial_facts=new_mutable_transition + quantum_number_problem_set, + solving_settings=new_combined_settings, + initial_facts=new_combined_properties, ) From e54289e0e17c088fe40e0b4ccff047dcfeedc302 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Thu, 22 Aug 2024 14:10:43 +0200 Subject: [PATCH 09/17] changed tuple to set in test-case --- tests/unit/test_solving.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_solving.py b/tests/unit/test_solving.py index 5fa47a82..64047010 100644 --- a/tests/unit/test_solving.py +++ b/tests/unit/test_solving.py @@ -77,13 +77,13 @@ def test_solve_with_filtered_quantum_number_problem_set( parity_conservation, c_parity_conservation, }, - edge_properties_and_domains=( + edge_properties_and_domains={ EdgeQuantumNumbers.pid, # had to be added for c_parity_conservation to work EdgeQuantumNumbers.spin_magnitude, EdgeQuantumNumbers.spin_projection, # had to be added for spin_magnitude_conservation to work EdgeQuantumNumbers.parity, EdgeQuantumNumbers.c_parity, - ), + }, node_properties_and_domains=( NodeQuantumNumbers.l_magnitude, NodeQuantumNumbers.s_magnitude, From a045be5fbe29454a92b24739b6bc41dfa42c1c13 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Thu, 22 Aug 2024 16:15:45 +0200 Subject: [PATCH 10/17] removed projections from spin-mag.-cons. --- src/qrules/conservation_rules.py | 16 ++++++++-------- tests/unit/conservation_rules/test_spin.py | 7 ++++++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/qrules/conservation_rules.py b/src/qrules/conservation_rules.py index bb1cc356..b264f265 100644 --- a/src/qrules/conservation_rules.py +++ b/src/qrules/conservation_rules.py @@ -691,8 +691,8 @@ def spin_conservation( def spin_magnitude_conservation( - ingoing_spins: List[SpinEdgeInput], - outgoing_spins: List[SpinEdgeInput], + ingoing_spin_magnitudes: List[EdgeQN.spin_magnitude], + outgoing_spin_magnitudes: List[EdgeQN.spin_magnitude], interaction_qns: SpinMagnitudeNodeInput, ) -> bool: r"""Check for spin conservation. @@ -710,20 +710,20 @@ def spin_magnitude_conservation( # L and S can only be used if one side is a single state # and the other side contains of two states (isobar) # So do a full check if this is the case - if (len(ingoing_spins) == 1 and len(outgoing_spins) == 2) or ( - len(ingoing_spins) == 2 and len(outgoing_spins) == 1 + if (len(ingoing_spin_magnitudes) == 1 and len(outgoing_spin_magnitudes) == 2) or ( + len(ingoing_spin_magnitudes) == 2 and len(outgoing_spin_magnitudes) == 1 ): return _check_magnitude( - [x.spin_magnitude for x in ingoing_spins], - [x.spin_magnitude for x in outgoing_spins], + [float(x) for x in ingoing_spin_magnitudes], + [float(x) for x in outgoing_spin_magnitudes], interaction_qns, ) # otherwise don't use S and L and just check magnitude # are integral or non integral on both sides return ( - sum(float(x.spin_magnitude) for x in ingoing_spins).is_integer() # type: ignore[union-attr] - == sum(float(x.spin_magnitude) for x in outgoing_spins).is_integer() # type: ignore[union-attr] + sum(float(x) for x in ingoing_spin_magnitudes).is_integer() # type: ignore[union-attr] + == sum(float(x) for x in outgoing_spin_magnitudes).is_integer() # type: ignore[union-attr] ) diff --git a/tests/unit/conservation_rules/test_spin.py b/tests/unit/conservation_rules/test_spin.py index 3f370d3d..358ac1ad 100644 --- a/tests/unit/conservation_rules/test_spin.py +++ b/tests/unit/conservation_rules/test_spin.py @@ -11,8 +11,13 @@ spin_magnitude_conservation, ) from qrules.particle import Spin +from qrules.quantum_numbers import EdgeQuantumNumbers -_SpinRuleInputType = Tuple[List[SpinEdgeInput], List[SpinEdgeInput], SpinNodeInput] +_SpinRuleInputType = Tuple[ + List[EdgeQuantumNumbers.spin_magnitude], + List[EdgeQuantumNumbers.spin_magnitude], + SpinNodeInput, +] def __create_two_body_decay_spin_data( From 5ea1aeacafcd1388c513d8a8e65937e8d18d0fe2 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Thu, 22 Aug 2024 17:37:00 +0200 Subject: [PATCH 11/17] removed spin-proj. from test_solving&test_spin --- tests/unit/conservation_rules/test_spin.py | 25 ++++++++-------------- tests/unit/test_solving.py | 2 +- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/tests/unit/conservation_rules/test_spin.py b/tests/unit/conservation_rules/test_spin.py index 358ac1ad..921f1a56 100644 --- a/tests/unit/conservation_rules/test_spin.py +++ b/tests/unit/conservation_rules/test_spin.py @@ -13,11 +13,16 @@ from qrules.particle import Spin from qrules.quantum_numbers import EdgeQuantumNumbers -_SpinRuleInputType = Tuple[ +_SpinMagnitudeRuleInputType = Tuple[ List[EdgeQuantumNumbers.spin_magnitude], List[EdgeQuantumNumbers.spin_magnitude], SpinNodeInput, ] +_SpinRuleInputType = Tuple[ + List[SpinEdgeInput], + List[SpinEdgeInput], + SpinNodeInput, +] def __create_two_body_decay_spin_data( @@ -124,13 +129,7 @@ def test_spin_all_defined(rule_input: _SpinRuleInputType, expected: bool) -> Non ("rule_input", "expected"), [ ( - __create_two_body_decay_spin_data( - in_spin=Spin(1, 1), - out_spin1=Spin(spin2_mag, 0), - out_spin2=Spin(1, -1), - angular_momentum=Spin(ang_mom_mag, 0), - coupled_spin=Spin(coupled_spin_mag, -1), - ), + ([1], [spin2_mag, 1], SpinNodeInput(ang_mom_mag, 0, coupled_spin_mag, -1)), True, ) for spin2_mag, ang_mom_mag, coupled_spin_mag in zip( @@ -139,13 +138,7 @@ def test_spin_all_defined(rule_input: _SpinRuleInputType, expected: bool) -> Non ] + [ ( - __create_two_body_decay_spin_data( - in_spin=Spin(1, 1), - out_spin1=Spin(spin2_mag, 0), - out_spin2=Spin(1, -1), - angular_momentum=Spin(ang_mom_mag, 0), - coupled_spin=Spin(coupled_spin_mag, 0), - ), + ([1], [spin2_mag, 1], SpinNodeInput(ang_mom_mag, 0, coupled_spin_mag, 0)), False, ) for spin2_mag, ang_mom_mag, coupled_spin_mag in zip( @@ -154,6 +147,6 @@ def test_spin_all_defined(rule_input: _SpinRuleInputType, expected: bool) -> Non ], ) def test_spin_ignore_z_component( - rule_input: _SpinRuleInputType, expected: bool + rule_input: _SpinMagnitudeRuleInputType, expected: bool ) -> None: assert spin_magnitude_conservation(*rule_input) is expected # type: ignore[arg-type] diff --git a/tests/unit/test_solving.py b/tests/unit/test_solving.py index 64047010..50d69dd2 100644 --- a/tests/unit/test_solving.py +++ b/tests/unit/test_solving.py @@ -80,7 +80,7 @@ def test_solve_with_filtered_quantum_number_problem_set( edge_properties_and_domains={ EdgeQuantumNumbers.pid, # had to be added for c_parity_conservation to work EdgeQuantumNumbers.spin_magnitude, - EdgeQuantumNumbers.spin_projection, # had to be added for spin_magnitude_conservation to work + # EdgeQuantumNumbers.spin_projection, # can be removed to cut down the number of solutions EdgeQuantumNumbers.parity, EdgeQuantumNumbers.c_parity, }, From 8d3b815133832b0bb40421489b06b3d354b8a339 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Mon, 26 Aug 2024 15:26:46 +0200 Subject: [PATCH 12/17] Revert "Added '*.swp' (temporary vim-files) to .gitignore" This reverts commit f190b2f3472f5b73012edf3d9a10f5d6b0e53c07. --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6d036da1..f7b7246a 100644 --- a/.gitignore +++ b/.gitignore @@ -37,7 +37,6 @@ oryx-build-commands.txt prof/ tags TAGS -*.swp # Virtual environments *venv/ From a4335a5f432e2ce0b39db99db3154df646507d17 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Mon, 26 Aug 2024 15:33:55 +0200 Subject: [PATCH 13/17] removed test_solving.py -> smaller diff --- tests/unit/test_solving.py | 186 ------------------------------------- 1 file changed, 186 deletions(-) delete mode 100644 tests/unit/test_solving.py diff --git a/tests/unit/test_solving.py b/tests/unit/test_solving.py deleted file mode 100644 index 50d69dd2..00000000 --- a/tests/unit/test_solving.py +++ /dev/null @@ -1,186 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING, Iterable, Union - -import attrs -import pytest - -import qrules.particle -import qrules.quantum_numbers -import qrules.system_control -import qrules.transition -from qrules.conservation_rules import ( - GraphElementRule, - c_parity_conservation, - parity_conservation, - spin_magnitude_conservation, - spin_validity, -) -from qrules.quantum_numbers import EdgeQuantumNumbers, NodeQuantumNumbers -from qrules.solving import CSPSolver, EdgeSettings, NodeSettings, QNProblemSet -from qrules.topology import MutableTransition - -if TYPE_CHECKING: - from qrules.argument_handling import Rule - - -EdgeQuantumNumberTypes = Union[ - type[EdgeQuantumNumbers.pid], - type[EdgeQuantumNumbers.mass], - type[EdgeQuantumNumbers.width], - type[EdgeQuantumNumbers.spin_magnitude], - type[EdgeQuantumNumbers.spin_projection], - type[EdgeQuantumNumbers.charge], - type[EdgeQuantumNumbers.isospin_magnitude], - type[EdgeQuantumNumbers.isospin_projection], - type[EdgeQuantumNumbers.strangeness], - type[EdgeQuantumNumbers.charmness], - type[EdgeQuantumNumbers.bottomness], - type[EdgeQuantumNumbers.topness], - type[EdgeQuantumNumbers.baryon_number], - type[EdgeQuantumNumbers.electron_lepton_number], - type[EdgeQuantumNumbers.muon_lepton_number], - type[EdgeQuantumNumbers.tau_lepton_number], - type[EdgeQuantumNumbers.parity], - type[EdgeQuantumNumbers.c_parity], - type[EdgeQuantumNumbers.g_parity], -] - -NodeQuantumNumberTypes = Union[ - type[NodeQuantumNumbers.l_magnitude], - type[NodeQuantumNumbers.l_projection], - type[NodeQuantumNumbers.s_magnitude], - type[NodeQuantumNumbers.s_projection], - type[NodeQuantumNumbers.parity_prefactor], -] - - -def test_solve( - all_particles: qrules.particle.ParticleCollection, - quantum_number_problem_set: QNProblemSet, -) -> None: - solver = CSPSolver(all_particles) - result = solver.find_solutions(quantum_number_problem_set) - assert len(result.solutions) == 19 - - -def test_solve_with_filtered_quantum_number_problem_set( - all_particles: qrules.particle.ParticleCollection, - quantum_number_problem_set: QNProblemSet, -) -> None: - solver = CSPSolver(all_particles) - new_quantum_number_problem_set = filter_quantum_number_problem_set( - quantum_number_problem_set, - edge_rules={spin_validity}, - node_rules={ - spin_magnitude_conservation, - parity_conservation, - c_parity_conservation, - }, - edge_properties_and_domains={ - EdgeQuantumNumbers.pid, # had to be added for c_parity_conservation to work - EdgeQuantumNumbers.spin_magnitude, - # EdgeQuantumNumbers.spin_projection, # can be removed to cut down the number of solutions - EdgeQuantumNumbers.parity, - EdgeQuantumNumbers.c_parity, - }, - node_properties_and_domains=( - NodeQuantumNumbers.l_magnitude, - NodeQuantumNumbers.s_magnitude, - ), - ) - result = solver.find_solutions(new_quantum_number_problem_set) - - assert len(result.solutions) != 0 - - -def filter_quantum_number_problem_set( - quantum_number_problem_set: QNProblemSet, - edge_rules: set[GraphElementRule], - node_rules: set[Rule], - edge_properties_and_domains: Iterable[EdgeQuantumNumberTypes], - node_properties_and_domains: Iterable[NodeQuantumNumberTypes], -) -> QNProblemSet: - old_edge_settings = quantum_number_problem_set.solving_settings.states - old_node_settings = quantum_number_problem_set.solving_settings.interactions - old_edge_properties = quantum_number_problem_set.initial_facts.states - old_node_properties = quantum_number_problem_set.initial_facts.interactions - new_edge_settings = { - edge_id: EdgeSettings( - conservation_rules=edge_rules, - rule_priorities=edge_setting.rule_priorities, - qn_domains=({ - key: val - for key, val in edge_setting.qn_domains.items() - if key in set(edge_properties_and_domains) - }), - ) - for edge_id, edge_setting in old_edge_settings.items() - } - new_node_settings = { - node_id: NodeSettings( - conservation_rules=node_rules, - rule_priorities=node_setting.rule_priorities, - qn_domains=({ - key: val - for key, val in node_setting.qn_domains.items() - if key in set(node_properties_and_domains) - }), - ) - for node_id, node_setting in old_node_settings.items() - } - new_combined_settings = MutableTransition( - topology=quantum_number_problem_set.solving_settings.topology, - states=new_edge_settings, - interactions=new_node_settings, - ) - new_edge_properties = { - edge_id: { - edge_quantum_number: scalar - for edge_quantum_number, scalar in graph_edge_property_map.items() - if edge_quantum_number in edge_properties_and_domains - } - for edge_id, graph_edge_property_map in old_edge_properties.items() - } - new_node_properties = { - node_id: { - node_quantum_number: scalar - for node_quantum_number, scalar in graph_node_property_map.items() - if node_quantum_number in node_properties_and_domains - } - for node_id, graph_node_property_map in old_node_properties.items() - } - new_combined_properties = MutableTransition( - topology=quantum_number_problem_set.initial_facts.topology, - states=new_edge_properties, - interactions=new_node_properties, - ) - return attrs.evolve( - quantum_number_problem_set, - solving_settings=new_combined_settings, - initial_facts=new_combined_properties, - ) - - -@pytest.fixture(scope="session") -def all_particles(): - return [ - qrules.system_control.create_edge_properties(part) - for part in qrules.particle.load_pdg() - ] - - -@pytest.fixture(scope="session") -def quantum_number_problem_set(request) -> QNProblemSet: - stm = qrules.StateTransitionManager( - initial_state=["psi(2S)"], - final_state=["gamma", "eta", "eta"], - formalism="helicity", - ) - problem_sets = stm.create_problem_sets() - qn_problem_sets = [ - p.to_qn_problem_set() - for strength in sorted(problem_sets) - for p in problem_sets[strength] - ] - return qn_problem_sets[0] From 23b4d36974aae769c025fea4ee644985056334af Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Mon, 26 Aug 2024 15:58:33 +0200 Subject: [PATCH 14/17] adapted conservation.ipynb to spin-proj.-removal --- docs/usage/conservation.ipynb | 30 ++++++++++++++---------------- docs/usage/reaction.ipynb | 2 +- docs/usage/visualize.ipynb | 2 +- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/docs/usage/conservation.ipynb b/docs/usage/conservation.ipynb index 291ff1ea..f4a29ba0 100644 --- a/docs/usage/conservation.ipynb +++ b/docs/usage/conservation.ipynb @@ -286,22 +286,8 @@ "interaction = transition.interactions[node_id]\n", "\n", "spin_magnitude_conservation(\n", - " ingoing_spins=[\n", - " SpinEdgeInput(\n", - " spin_magnitude=incoming_state.particle.spin,\n", - " spin_projection=incoming_state.spin_projection,\n", - " )\n", - " ],\n", - " outgoing_spins=[\n", - " SpinEdgeInput(\n", - " spin_magnitude=outgoing_state1.particle.spin,\n", - " spin_projection=outgoing_state1.spin_projection,\n", - " ),\n", - " SpinEdgeInput(\n", - " spin_magnitude=outgoing_state2.particle.spin,\n", - " spin_projection=outgoing_state2.spin_projection,\n", - " ),\n", - " ],\n", + " ingoing_spins=[incoming_state.particle.spin],\n", + " outgoing_spins=[outgoing_state1.particle.spin, outgoing_state2.particle.spin],\n", " interaction_qns=interaction,\n", ")" ] @@ -417,6 +403,18 @@ "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" } }, "nbformat": 4, diff --git a/docs/usage/reaction.ipynb b/docs/usage/reaction.ipynb index 35c53455..3ed417d4 100644 --- a/docs/usage/reaction.ipynb +++ b/docs/usage/reaction.ipynb @@ -604,7 +604,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.17" + "version": "3.11.7" } }, "nbformat": 4, diff --git a/docs/usage/visualize.ipynb b/docs/usage/visualize.ipynb index ec9c7a23..126b4645 100644 --- a/docs/usage/visualize.ipynb +++ b/docs/usage/visualize.ipynb @@ -672,7 +672,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.19" + "version": "3.11.7" } }, "nbformat": 4, From bb80469f4f8b59ef33a545c5b11af1d194f44f23 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Mon, 26 Aug 2024 16:03:17 +0200 Subject: [PATCH 15/17] corrected keyw.-args in conservation.ipynb --- docs/usage/conservation.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/usage/conservation.ipynb b/docs/usage/conservation.ipynb index f4a29ba0..cdca01e2 100644 --- a/docs/usage/conservation.ipynb +++ b/docs/usage/conservation.ipynb @@ -286,8 +286,8 @@ "interaction = transition.interactions[node_id]\n", "\n", "spin_magnitude_conservation(\n", - " ingoing_spins=[incoming_state.particle.spin],\n", - " outgoing_spins=[outgoing_state1.particle.spin, outgoing_state2.particle.spin],\n", + " ingoing_spin_magnitudes=[incoming_state.particle.spin],\n", + " outgoing_spin_magnitudes=[outgoing_state1.particle.spin, outgoing_state2.particle.spin],\n", " interaction_qns=interaction,\n", ")" ] From 5bcfb9ba7c0f89174be812de35b6463649a1f5ad Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 14:04:09 +0000 Subject: [PATCH 16/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/usage/conservation.ipynb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/usage/conservation.ipynb b/docs/usage/conservation.ipynb index cdca01e2..5c77e239 100644 --- a/docs/usage/conservation.ipynb +++ b/docs/usage/conservation.ipynb @@ -287,7 +287,10 @@ "\n", "spin_magnitude_conservation(\n", " ingoing_spin_magnitudes=[incoming_state.particle.spin],\n", - " outgoing_spin_magnitudes=[outgoing_state1.particle.spin, outgoing_state2.particle.spin],\n", + " outgoing_spin_magnitudes=[\n", + " outgoing_state1.particle.spin,\n", + " outgoing_state2.particle.spin,\n", + " ],\n", " interaction_qns=interaction,\n", ")" ] From 7ed76938cd814d227bc516d1961468438614f2a3 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:48:30 +0200 Subject: [PATCH 17/17] MAINT: reduce diff --- docs/usage/reaction.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/reaction.ipynb b/docs/usage/reaction.ipynb index 3ed417d4..35c53455 100644 --- a/docs/usage/reaction.ipynb +++ b/docs/usage/reaction.ipynb @@ -604,7 +604,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.7" + "version": "3.8.17" } }, "nbformat": 4,