Source code for cottax.consumers.architectures.interface

'''
Interface for the architectures.

1. How a problem is placed: `ModelReading`, three questions, registered per condition class
2. How a group of cuts is closed: `Closing`, chosen

```
ModelReading  not_implicit(graph, problem)      why it is not an implicit model: refusals, none if it is
              body(graph, problem)              the function nodes that are its own: boxed with it, never cut
              combines_as(condition)            the kind whose `+` folds it (`Combine`), or None
Closing       __call__(cycle, group)            the op closing a group of cuts on a cycle
              bound_at(cycle, group)            the node name of the problem that op binds
```

A problem is asked by its node name in the graph handed; the answer is found by its
condition's class, a driven node's through its condition (`condition_of`).
'''

from abc import abstractmethod
from collections.abc import Iterable
from typing import Any

from ...core import ConditionalNode, GraphOp, Label, NestingGraph, Place, ToCut, Violation
from ...core.frozen import Answer, Choice, Frozen

# ============================================================================ registered

[docs] class ModelReading(Answer): ''' How a problem reads as a model: 1. Whether it is an implicit model 2. Its body, the function nodes that are its own 3. How it combines with other problems ''' about = ConditionalNode
[docs] @abstractmethod def not_implicit[N: Label, V: Place](self, graph: NestingGraph[N, V], problem: N ) -> Iterable[Violation]: '''Why the problem bound at `problem` is no implicit model in its language; nothing if it is.'''
[docs] @abstractmethod def body[N: Label, V: Place](self, graph: NestingGraph[N, V], problem: N) -> tuple[N, ...]: '''The function nodes that are its own, in binding order: what an architecture boxes with it, and never cuts inside.'''
[docs] @abstractmethod def combines_as(self, condition: Any) -> type | None: '''The kind whose `+` folds it (`Combine`'s `kind`), or `None`: it is folded into nothing.'''
# ============================================================================ chosen
[docs] class Closing[N: Label, V: Place](Frozen, Choice): ''' How a group of cuts is closed: the op closing it, and the name of the problem that op binds. (i.e. conventionally a fixed point cut) Handed in as: MDF(GaussSeidel(), cx.closing, top), an architecture's second argument; or CloseFunctionalCycles(GaussSeidel(), cx.closing). ''' @abstractmethod def __call__(self, cycle: tuple[N, ...], group: ToCut[N, V]) -> GraphOp[N, V]: '''The op closing `group`, cut on `cycle` (its members in binding order).'''
[docs] @abstractmethod def bound_at(self, cycle: tuple[N, ...], group: ToCut[N, V]) -> N: '''Where that op binds the problem closing `group`.'''
__all__ = ['ModelReading', 'Closing']