topology#
import qrules.topology
Functionality for Topology
and Transition
instances.
Main interfaces
Topology
and its builder functionscreate_isobar_topologies()
andcreate_n_body_topology()
.Transition
and its two implementationsMutableTransition
andFrozenTransition
.
- class FrozenDict(mapping: Mapping | None = None)[source]#
Bases:
Hashable
,Mapping
,Generic
[KT
,VT
]An immutable and hashable version of a
dict
.FrozenDict
makes it possible to make classes hashable if they are decorated withattr.frozen()
and containMapping
-like attributes. If these attributes were to be implemented with a normaldict
, the instance is strictly speaking still mutable (even if those attributes are aproperty
) and the class is therefore not safely hashable.Warning
The keys have to be comparable, that is, they need to have a
__lt__()
method.
- class Edge(originating_node_id: int | None = None, ending_node_id: int | None = None)[source]#
Bases:
object
Struct-like definition of an edge, used in
Topology.edges
.- originating_node_id: int | None[source]#
Node ID where the
Edge
starts.An
Edge
is incoming to aTopology
if itsoriginating_node_id
isNone
(seeincoming_edge_ids
).
- ending_node_id: int | None[source]#
Node ID where the
Edge
ends.An
Edge
is outgoing from aTopology
if itsending_node_id
isNone
(seeoutgoing_edge_ids
).
- class Topology(nodes: Iterable[int], edges: Mapping[int, Edge])[source]#
Bases:
object
Directed Feynman-like graph without edge or node properties.
A
Topology
is directed in the sense that its edges are ingoing and outgoing to specific nodes. This is to mimic Feynman graphs, which have a time axis. Note that aTopology
is not strictly speaking a graph from graph theory, because it allows open edges, like a Feynman-diagram.The edges and nodes can be provided with properties with a
Transition
, which contains atopology
.As opposed to a
MutableTopology
, aTopology
is frozen, hashable, and ordered, so that it can be used as a kind of fingerprint for aTransition
. In addition, the IDs ofedges
are guaranteed to be sequential integers and follow a specific pattern:incoming_edge_ids
(initial_states
) are always negative.outgoing_edge_ids
(final_states
) lie in the range0...n-1
withn
the number of final states.intermediate_edge_ids
continue counting fromn
.
See also
MutableTopology.organize_edge_ids()
.Example
Isobar decay topologies can best be created as follows:
>>> topologies = create_isobar_topologies(number_of_final_states=3) >>> len(topologies) 1 >>> topologies[0] Topology(nodes=..., edges=...)
- incoming_edge_ids: FrozenSet[int][source]#
Edge IDs of edges that have no
originating_node_id
.Transition.initial_states
provide properties for these edges.
- outgoing_edge_ids: FrozenSet[int][source]#
Edge IDs of edges that have no
ending_node_id
.Transition.final_states
provide properties for these edges.
- is_isomorphic(other: Topology) bool [source]#
Check if two graphs are isomorphic.
Returns
True
if the two graphs have a one-to-one mapping of the node IDs and edge IDs.Warning
Not yet implemented.
- relabel_edges(old_to_new: Mapping[int, int]) Topology [source]#
Create a new
Topology
with new edge IDs.This method is particularly useful when creating permutations of a
Topology
, e.g.:>>> topologies = create_isobar_topologies(3) >>> len(topologies) 1 >>> topology = topologies[0] >>> final_state_ids = topology.outgoing_edge_ids >>> permuted_topologies = { ... topology.relabel_edges(dict(zip(final_state_ids, permutation))) ... for permutation in itertools.permutations(final_state_ids) ... } >>> len(permuted_topologies) 3
- get_originating_node_list(topology: Topology, edge_ids: Iterable[int]) List[int] [source]#
Get list of node ids from which the supplied edges originate from.
- class MutableTopology(nodes: Iterable[int] = _Nothing.NOTHING, edges: Mapping[int, Edge] = _Nothing.NOTHING)[source]#
Bases:
object
Mutable version of a
Topology
.A
MutableTopology
can be used to conveniently build up aTopology
(see e.g.SimpleStateTransitionTopologyBuilder
). It does not have restrictions on the numbering of edge and node IDs.- nodes: Set[int][source]#
See
Topology.nodes
.
- add_node(node_id: int) None [source]#
Adds a node with number
node_id
.- Raises:
ValueError – if
node_id
already exists innodes
.
- add_edges(edge_ids: Iterable[int]) None [source]#
Add edges with the ids in the
edge_ids
list.- Raises:
ValueError – if
edge_ids
already exist inedges
.
- attach_edges_to_node_ingoing(ingoing_edge_ids: Iterable[int], node_id: int) None [source]#
Attach existing edges to nodes.
So that the are ingoing to these nodes.
- Parameters:
- Raises:
ValueError – if an edge not doesn’t exist.
ValueError – if an edge ID is already an ingoing node.
- organize_edge_ids() MutableTopology [source]#
Organize edge IDS so that they lie in range
[-m, n+i]
.Here,
m
is the number ofincoming_edge_ids
,n
is the number ofoutgoing_edge_ids
, andi
is the number ofintermediate_edge_ids
.In other words, relabel the edges so that:
incoming edge IDs lie in the range
[-1, -2, ...]
,outgoing edge IDs lie in the range
[0, 1, ..., n]
,intermediate edge IDs lie in the range
[n+1, n+2, ...]
.
- freeze() Topology [source]#
Create an immutable
Topology
from thisMutableTopology
.You may need to call
organize_edge_ids()
first.
- class InteractionNode(number_of_ingoing_edges: int, number_of_outgoing_edges: int)[source]#
Bases:
object
Helper class for the
SimpleStateTransitionTopologyBuilder
.
- class SimpleStateTransitionTopologyBuilder(interaction_node_set: Iterable[InteractionNode])[source]#
Bases:
object
Simple topology builder.
Recursively tries to add the interaction nodes to available open end edges/lines in all combinations until the number of open end lines matches the final state lines.
- create_isobar_topologies(number_of_final_states: int) Tuple[Topology, ...] [source]#
Builder function to create a set of unique isobar decay topologies.
- Parameters:
number_of_final_states – The number of
outgoing_edge_ids
(final_states
).- Returns:
A sorted
tuple
of non-isomorphicTopology
instances, all with the same number of final states.
Example
>>> topologies = create_isobar_topologies(number_of_final_states=4) >>> len(topologies) 2 >>> len(topologies[0].outgoing_edge_ids) 4 >>> len(set(topologies)) # hashable 2 >>> list(topologies) == sorted(topologies) # ordered True
- create_n_body_topology(number_of_initial_states: int, number_of_final_states: int) Topology [source]#
Create a
Topology
that connects all edges through a single node.These types of “\(n\)-body topologies” are particularly important for
check_reaction_violations()
andconservation_rules
.- Parameters:
number_of_initial_states – The number of
incoming_edge_ids
(initial_states
).number_of_final_states – The number of
outgoing_edge_ids
(final_states
).
Example
>>> topology = create_n_body_topology( ... number_of_initial_states=2, ... number_of_final_states=5, ... ) >>> topology Topology(nodes=..., edges...) >>> len(topology.nodes) 1 >>> len(topology.incoming_edge_ids) 2 >>> len(topology.outgoing_edge_ids) 5
- class Transition[source]#
Bases:
ABC
,Generic
[EdgeType
,NodeType
]Mapping of edge and node properties over a
Topology
.This interface class describes a transition from an initial state to a final state by providing a mapping of properties over the
edges
andnodes
of itstopology
. Since aTopology
behaves like a Feynman graph, edges are considered as “states
” and nodes are considered asinteractions
between those states.There are two implementation classes:
FrozenTransition
: a complete, hashable and ordered mapping of properties over theedges
andnodes
in itstopology
.MutableTransition
: comparable toMutableTopology
in that it is used internally when finding solutions through theStateTransitionManager
etc.
These classes are also provided with mixin attributes
initial_states
,final_states
,intermediate_states
, andfilter_states()
.- abstract property topology: Topology[source]#
Topology
over whichstates
andinteractions
are defined.
- class FrozenTransition(topology: Topology, states: Mapping | None, interactions: Mapping | None)[source]#
Bases:
Transition
,Generic
[EdgeType
,NodeType
]Defines a frozen mapping of edge and node properties on a
Topology
.- states: FrozenDict[int, EdgeType][source]#
- interactions: FrozenDict[int, NodeType][source]#
- unfreeze() MutableTransition[EdgeType, NodeType] [source]#
Convert into a
MutableTransition
.
- convert() FrozenTransition[EdgeType, NodeType] [source]#
- convert(state_converter: Callable[[EdgeType], NewEdgeType]) FrozenTransition[NewEdgeType, NodeType]
- convert(*, interaction_converter: Callable[[NodeType], NewNodeType]) FrozenTransition[EdgeType, NewNodeType]
- convert(state_converter: Callable[[EdgeType], NewEdgeType], interaction_converter: Callable[[NodeType], NewNodeType]) FrozenTransition[NewEdgeType, NewNodeType]
Cast the edge and/or node properties to another type.
- class MutableTransition(topology: Topology, states: Mapping[int, EdgeType] = _Nothing.NOTHING, interactions: Mapping[int, NodeType] = _Nothing.NOTHING)[source]#
Bases:
Transition
,Generic
[EdgeType
,NodeType
]Mutable implementation of a
Transition
.Mainly used internally by the
StateTransitionManager
to build solutions.- compare(other: MutableTransition, state_comparator: Callable[[EdgeType, EdgeType], bool] | None = None, interaction_comparator: Callable[[NodeType, NodeType], bool] | None = None) bool [source]#
- freeze() FrozenTransition[EdgeType, NodeType] [source]#
Convert into a
FrozenTransition
.