cottax.core.maths.plan.ops module

Ops on Redefine: what a node reads and owns renamed (Rewire, Rename, Cut), a definition replaced (Replace), and what it determines (Determine, Undetermine).

type Relabel[N: Label, V: Place] = Mapping[N, Renaming]

Per node, old place -> new. Keyed by place, so fn(x, x) renames both.

check_renames_places_the_node_has(op: Rewire, graph: NestingGraph)[source]

Cannot rename a place the node does not read or own.

Return type:

Iterator[Violation]

class Rewire[N: Label, V: Place][source]

Bases: Redefine[N, V], Generic[N, V]

Rename the places a definition reads and owns only.

checks_graph: PerLevel[tuple[Callable, ...]] = (<function check_renames_places_the_node_has>,)

(op, graph) -> Iterator[Violation], collected by refusals and raised by apply.

Type:

What the op needs of the graph before it can compute anything

abstractmethod renaming(graph: NestingGraph[N, V])[source]

Per node, old place -> new. One map: a node reads a place or owns it, never both, so nothing has to say which field a renaming lands in.

Return type:

Relabel[N, V]

redefined(graph: NestingGraph[N, V])[source]

The new definition for each node this touches. Names not here are untouched.

Return type:

Mapping[N, NodeDefinition[V]]

class Replace[N: Label, V: Place](node: N, definition: NodeDefinition[V])[source]

Bases: Redefine[N, V], Generic[N, V]

One binding given a definition the caller already holds.

node: N
definition: NodeDefinition[V]
redefined(graph: NestingGraph[N, V])[source]

The new definition for each node this touches. Names not here are untouched.

Return type:

Mapping[N, NodeDefinition[V]]

class Rename[N: Label, V: Place](node: N, onto: tuple[tuple[V, V], ...])[source]

Bases: Rewire[N, V], Generic[N, V]

One node’s places renamed by a mapping the caller already holds.

node: N
onto: tuple[tuple[V, V], ...]

Old place -> the place to use instead. Pairs, since an op is a record and hashes.

renaming(graph: NestingGraph[N, V])[source]

Per node, old place -> new. One map: a node reads a place or owns it, never both, so nothing has to say which field a renaming lands in.

Return type:

Relabel[N, V]

check_readers(op: Cut)[source]

A cut has readers: with none, the copy is a name nothing reads.

Return type:

Iterator[Violation]

check_cuts_a_produced_place(op: Cut, graph: NestingGraph)[source]

A boundary input renamed leaves nothing to close the cut against, and a second cut of one variable would put more readers on the first copy.

Return type:

Iterator[Violation]

check_readers_read_var(op: Cut, graph: NestingGraph)[source]

Every reader reads var. The producer owns it, so renaming there would move the output and leave var a boundary input.

Return type:

Iterator[Violation]

class Cut[N: Label, V: Place](var: V, readers: tuple[N, ...], copy_of: PlaceToPlace[V])[source]

Bases: Rewire[N, V], Generic[N, V]

Rewire the reads of readers onto a copy of var. The producer and var are untouched, so a reader outside readers still gets the computed value.

var: V
readers: tuple[N, ...]
copy_of: PlaceToPlace[V]

Derives the copy’s place from var.

checks: PerLevel[tuple[Callable[[Any], object], ...]] = (<function check_readers>,)

Callable [self] -> iterable of violations, which are raised at construction unless skipped (see unchecked).

checks_graph: PerLevel[tuple[Callable, ...]] = (<function check_cuts_a_produced_place>, <function check_readers_read_var>)

(op, graph) -> Iterator[Violation], collected by refusals and raised by apply.

Type:

What the op needs of the graph before it can compute anything

property copy: V

The boundary variable readers end up reading.

renaming(graph: NestingGraph[N, V])[source]

Per node, old place -> new. One map: a node reads a place or owns it, never both, so nothing has to say which field a renaming lands in.

Return type:

Relabel[N, V]

check_unknowns(op: Determine)[source]

Something is determined, and nothing twice.

Return type:

Iterator[Violation]

check_determines_nothing_yet(op: Determine, graph: NestingGraph)[source]

What a condition node determines is replaced, never added to.

Return type:

Iterator[Violation]

check_determines_something(op: Undetermine, graph: NestingGraph)[source]

The inverse: there is something to drop.

Return type:

Iterator[Violation]

class Determine[N: Label, V: Place](requirement: N, unknowns: tuple[V, ...])[source]

Bases: Redefine[N, V], Generic[N, V]

A requirement, with the unknowns it determines named: determined, asked of the node, so what makes an answer right stays the condition node’s own business.

requirement: N
unknowns: tuple[V, ...]
checks: PerLevel[tuple[Callable[[Any], object], ...]] = (<function check_unknowns>,)

Callable [self] -> iterable of violations, which are raised at construction unless skipped (see unchecked).

checks_graph: PerLevel[tuple[Callable, ...]] = (<function check_determines_nothing_yet>,)

(op, graph) -> Iterator[Violation], collected by refusals and raised by apply.

Type:

What the op needs of the graph before it can compute anything

redefined(graph: NestingGraph[N, V])[source]

The new definition for each node this touches. Names not here are untouched.

Return type:

Mapping[N, NodeDefinition[V]]

class Undetermine[N: Label, V: Place](problem: N)[source]

Bases: Redefine[N, V], Generic[N, V]

The inverse of Determine: the unknowns dropped, the condition node kept.

problem: N
checks_graph: PerLevel[tuple[Callable, ...]] = (<function check_determines_something>,)

(op, graph) -> Iterator[Violation], collected by refusals and raised by apply.

Type:

What the op needs of the graph before it can compute anything

redefined(graph: NestingGraph[N, V])[source]

The new definition for each node this touches. Names not here are untouched.

Return type:

Mapping[N, NodeDefinition[V]]

class NoReaders(var: Place, copy: Place)[source]

Bases: Violation

var: Place
copy: Place
template: AbstractClassVar[str] = 'cut({var}): no readers, so {copy!r} would be a name nothing reads'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class NoUnknowns[source]

Bases: Violation

template: AbstractClassVar[str] = 'determine(): no unknowns -- a condition node that determines nothing is what it already is'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class UnknownTwice(unknowns: tuple[Place, ...])[source]

Bases: Violation

unknowns: tuple[Place, ...]
template: AbstractClassVar[str] = 'determine(): {unknowns!r} names an unknown twice'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class AlreadyDetermined(requirement: Label, unknowns: tuple[Place, ...])[source]

Bases: Violation

requirement: Label
unknowns: tuple[Place, ...]
template: AbstractClassVar[str] = '{requirement!r} already determines {unknowns!r} -- `Undetermine` it first, so the earlier choice is dropped deliberately rather than silently replaced'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class AlreadyUndetermined(problem: Label)[source]

Bases: Violation

problem: Label
template: AbstractClassVar[str] = '{problem!r} already determines nothing, so there is nothing to take off'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class NotRenamed(node: Label, places: tuple[Place, ...])[source]

Bases: Violation

node: Label
places: tuple[Place, ...]
template: AbstractClassVar[str] = '{node!r} neither reads nor owns {places!r}'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class NotProduced(var: Place)[source]

Bases: Violation

var: Place
template: AbstractClassVar[str] = '{var!r} is not computed here, so there is nothing to cut'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class DoesNotRead(var: Place, nodes: tuple[Label, ...])[source]

Bases: Violation

var: Place
nodes: tuple[Label, ...]
template: AbstractClassVar[str] = "cut({var}): {nodes} do not read {var!r}, so there is no read to move onto the copy -- a cut's readers read the variable, and its producer stays as it is"

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording

class AlreadyCut(var: Place, copy: Place)[source]

Bases: Violation

var: Place
copy: Place
template: AbstractClassVar[str] = '{var!r} is already cut: its copy {copy} exists. A variable is cut at most once -- two cuts would assume two values for one place. Cut with more readers at once to share a copy'

e.g. ‘output {place!r} is owned by both {other!r} and {node!r}’

Type:

Wording