cottax.core.maths.cut_rules module¶
Rules on how to cut a graph’s couplings.
- type ToCut[N: Label, V: Place] = Mapping[V, tuple[N, ...]]¶
One closure’s worth: which variables are cut, for which readers.
- class CutRule[N: Label, V: Place][source]¶
Bases:
Frozen,Generic[N,V]What to cut in the graph handed: the coupling of its function nodes, one group per closure.
- type Opened[N: Label, V: Place] = tuple[tuple[N, ...], tuple[ToCut, ...]]¶
One cycle opened: its members in binding order, and the groups the rule cut it into.
- cuts_per_cycle[N: Label, V: Place](graph: NestingGraph[N, V], rule: CutRule[N, V])[source]¶
The rule asked of each functional cycle: the condition nodes dropped, and each cyclic component of what is left handed to the rule, alone. Per cycle, its members and its groups.
- Return type:
tuple[Opened[N,V],...]
- per_functional_cycle[N: Label, V: Place](graph: NestingGraph[N, V], rule: CutRule[N, V])[source]¶
cuts_per_cycle’s groups, every cycle’s in a row.
- Return type:
tuple[ToCut[N,V],...]
- coupling_reads[N: Label, V: Place](graph: AbstractGraph[N, V])[source]¶
Every read of every variable owned in the graph handed, holding nothing back.
- Return type:
ToCut[N,V]
- gauss_seidel[N: Label, V: Place](graph: AbstractGraph[N, V], order: Sequence[N])[source]¶
coupling_reads with every reader that follows its owner in order dropped: only the back edges are opened.
- Return type:
ToCut[N,V]
- minimal_feedback_order[N: Label, V: Place](graph: AbstractGraph[N, V], limit: int)[source]¶
The order of graph’s nodes a Gauss-Seidel sweep opens the fewest variables in. Exact: a DP over subsets, a node’s cost after a set being how many of its couplings that set reads. Ties fall to binding order.
- Return type:
tuple[N,...]
- check_keys_distinct(rule: ByName)[source]¶
No node keys two rules: which one applies would be the order written.
- Return type:
Iterator[Violation]
- class ByName[N: Label, V: Place](rules: tuple[tuple[N, CutRule[N, V]], ...])[source]¶
Bases:
CutRule[N,V],Generic[N,V]A rule per cycle, keyed by a node on it. Cycles are disjoint, so exactly one key lies on the graph handed; none or several is refused, never the first taken.
- class NoCuts[N: Label, V: Place][source]¶
Bases:
CutRule[N,V],Generic[N,V]Nothing opened, said rather than fallen into.
- class Jacobi[N: Label, V: Place][source]¶
Bases:
CutRule[N,V],Generic[N,V]Every coupling, for every reader, in one closure: each node runs from the previous iterate alone.
- class Sweep[N: Label, V: Place][source]¶
Bases:
CutRule[N,V],Generic[N,V]A Gauss-Seidel sweep: the back edges of an order only, in one closure, since a forward edge keeps this sweep’s value.
- abstractmethod order_of(graph: AbstractGraph[N, V])[source]¶
The order this graph is swept in, naming its nodes exactly once each.
- Return type:
tuple[N,...]
- class GaussSeidel[N: Label, V: Place][source]¶
Bases:
Sweep[N,V],Generic[N,V]In binding order.
- order_of(graph: AbstractGraph[N, V])[source]¶
The order this graph is swept in, naming its nodes exactly once each.
- Return type:
tuple[N,...]
- class GaussSeidelMinimal[N: Label, V: Place](limit: int)[source]¶
Bases:
Sweep[N,V],Generic[N,V]In the order minimal_feedback_order finds: the fewest variables opened.
- limit: int¶
Above this many nodes on one cycle the exact search (2^n n) is refused.
- order_of(graph: AbstractGraph[N, V])[source]¶
The order this graph is swept in, naming its nodes exactly once each.
- Return type:
tuple[N,...]
- class GaussSeidelOrdered[N: Label, V: Place](order: tuple[N, ...])[source]¶
Bases:
Sweep[N,V],Generic[N,V]In the order written, which names the graph’s nodes exactly once each or is refused: an order meant for one cycle and got wrong is what leaves it unswept.
- order: tuple[N, ...]¶
- order_of(graph: AbstractGraph[N, V])[source]¶
The order this graph is swept in, naming its nodes exactly once each.
- Return type:
tuple[N,...]
- class OrderMismatch(order: tuple, nodes: tuple)[source]¶
Bases:
Violation- order: tuple¶
- nodes: tuple¶
- template: AbstractClassVar[str] = 'gauss_seidel: the order {order!r} does not name the nodes {nodes!r} exactly once each -- an order sweeps one cycle, and one per cycle is `ByName`'¶
e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’
- Type:
Wording
- class CycleTooLarge(size: int, limit: int)[source]¶
Bases:
Violation- size: int¶
- limit: int¶
- template: AbstractClassVar[str] = '{size} nodes on one cycle is beyond the exact order search (limit {limit}): raise `GaussSeidelMinimal(limit=)`, or hand `GaussSeidelOrdered` an order'¶
e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’
- Type:
Wording
- class KeyRepeats(keys: tuple)[source]¶
Bases:
Violation- keys: tuple¶
- template: AbstractClassVar[str] = 'by_name: {keys!r} each key more than one rule'¶
e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’
- Type:
Wording
- class NoRule(nodes: tuple)[source]¶
Bases:
Violation- nodes: tuple¶
- template: AbstractClassVar[str] = 'no rule keyed by a node of {nodes!r}: key one, `NoCuts()` to leave it alone, or use the one rule alone for every cycle'¶
e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’
- Type:
Wording