From f190b2f3472f5b73012edf3d9a10f5d6b0e53c07 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Fri, 19 Jul 2024 11:09:30 +0200 Subject: [PATCH 01/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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/12] 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 99a594d5a95d9414a3e76dd9594174228fb8c1bd Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Tue, 27 Aug 2024 15:07:03 +0200 Subject: [PATCH 10/12] got the test_solving.py from old branch: remove_spin-proj[...] --- 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 64047010..0e882d18 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 left out to reduce the number of solutions EdgeQuantumNumbers.parity, EdgeQuantumNumbers.c_parity, }, @@ -171,7 +171,7 @@ def all_particles(): @pytest.fixture(scope="session") -def quantum_number_problem_set(request) -> QNProblemSet: +def quantum_number_problem_set() -> QNProblemSet: stm = qrules.StateTransitionManager( initial_state=["psi(2S)"], final_state=["gamma", "eta", "eta"], From 559b2f4a3e03ee495a63c8d130750a78e7017111 Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Tue, 27 Aug 2024 15:14:43 +0200 Subject: [PATCH 11/12] moved Edge/NodeQuantumNumberTypes to quantum_numbers.py --- src/qrules/quantum_numbers.py | 32 ++++++++++++++++++++++++++++ tests/unit/test_solving.py | 40 ++++++----------------------------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/src/qrules/quantum_numbers.py b/src/qrules/quantum_numbers.py index a1a4f63f..5820b982 100644 --- a/src/qrules/quantum_numbers.py +++ b/src/qrules/quantum_numbers.py @@ -130,6 +130,29 @@ class EdgeQuantumNumbers: EdgeQuantumNumbers.g_parity, ] +# for accessing the keys of the dicts in EdgeSettings +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], +] + @frozen(init=False) class NodeQuantumNumbers: @@ -158,6 +181,15 @@ class NodeQuantumNumbers: ] """Type hint for quantum numbers of interaction nodes.""" +# for accessing the keys of the dicts in NodeSettings +NodeQuantumNumberTypes = Union[ + type[NodeQuantumNumbers.l_magnitude], + type[NodeQuantumNumbers.l_projection], + type[NodeQuantumNumbers.s_magnitude], + type[NodeQuantumNumbers.s_projection], + type[NodeQuantumNumbers.parity_prefactor], +] + def _to_optional_float(optional_float: float | None) -> float | None: if optional_float is None: diff --git a/tests/unit/test_solving.py b/tests/unit/test_solving.py index 0e882d18..3134b78f 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, Iterable, Union +from typing import TYPE_CHECKING, Iterable import attrs import pytest @@ -16,7 +16,12 @@ spin_magnitude_conservation, spin_validity, ) -from qrules.quantum_numbers import EdgeQuantumNumbers, NodeQuantumNumbers +from qrules.quantum_numbers import ( + EdgeQuantumNumbers, + EdgeQuantumNumberTypes, + NodeQuantumNumbers, + NodeQuantumNumberTypes, +) from qrules.solving import CSPSolver, EdgeSettings, NodeSettings, QNProblemSet from qrules.topology import MutableTransition @@ -24,37 +29,6 @@ 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, From 2808ed74737e3d5d17535ed368e193b9848affaf Mon Sep 17 00:00:00 2001 From: grayson-helmholz Date: Tue, 27 Aug 2024 15:43:51 +0200 Subject: [PATCH 12/12] domain-keys now have specific type --- src/qrules/solving.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/qrules/solving.py b/src/qrules/solving.py index 73b22a50..9e664878 100644 --- a/src/qrules/solving.py +++ b/src/qrules/solving.py @@ -33,7 +33,9 @@ from qrules.quantum_numbers import ( EdgeQuantumNumber, EdgeQuantumNumbers, + EdgeQuantumNumberTypes, NodeQuantumNumber, + NodeQuantumNumberTypes, ) from qrules.topology import MutableTransition, Topology @@ -47,7 +49,7 @@ class EdgeSettings: conservation_rules: set[GraphElementRule] = field(factory=set) rule_priorities: dict[GraphElementRule, int] = field(factory=dict) - qn_domains: dict[Any, list] = field(factory=dict) + qn_domains: dict[EdgeQuantumNumberTypes, list] = field(factory=dict) @implement_pretty_repr @@ -67,7 +69,7 @@ class NodeSettings: conservation_rules: set[Rule] = field(factory=set) rule_priorities: dict[Rule, int] = field(factory=dict) - qn_domains: dict[Any, list] = field(factory=dict) + qn_domains: dict[NodeQuantumNumberTypes, list] = field(factory=dict) interaction_strength: float = 1.0