neml2.models.resolver

DependencyResolver — topological sort of Model nodes.

Python equivalent of the C++ DependencyResolver<Model*, VariableName> template in include/neml2/models/DependencyResolver.h. Variable matching is exact string equality, mirroring the C++ behaviour. Cycle detection and duplicate-provider validation are both enforced.

class neml2.models.resolver.DependencyResolver[source]

Bases: object

Resolve execution order for a collection of Model nodes.

A model A is a dependency of model B if A’s provided_items intersects B’s consumed_items. The resolver enforces that each variable is provided by at most one model and that the dependency graph is acyclic, then returns the models sorted in execution order (dependencies first) via Kahn’s BFS algorithm.

add_node(model)[source]

Register a model as a node in the dependency graph.

Parameters:

model (Model)

Return type:

None

inbound_items(order)[source]

Variables that need to flow in from outside the composed model.

A name X is inbound iff at least one consumer of X has no earlier-in-execution-order model that provides X. This is the priority-aware refinement of “consumed but not provided”:

  • Regular pipeline (producer before consumer) — X has an earlier provider, not inbound.

  • In-place transformer with no upstream sibling (input='X' / output='X' and no other producer of X) — X has no earlier provider for the only consumer, so X stays inbound. The wrapper can’t satisfy its own input from its own output.

  • Priority chain (low → default → high all on X) — the chain’s earlier producers satisfy the higher consumer’s read; X is not inbound from the chain’s perspective.

Parameters:

order (list[Model])

Return type:

dict[str, type[TensorWrapper]]

outbound_items(order, additional_outputs=None)[source]

Variables to expose as the composed model’s outputs.

Default: variables whose final producer in order (the priority winner when multiple models provide the same name) isn’t consumed by any later model. additional_outputs forces extra intermediate variables to also be included in the composed model’s output.

The priority-aware filter is what lets an in-place transformer like FixOrientation (input='orientation' / output='orientation') expose its rewritten orientation even though it also consumes orientation – that consumption is reading the lower-priority sibling’s value, satisfied internally by the priority chain, not an external consumption of the winner’s output.

Parameters:
Return type:

dict[str, type[TensorWrapper]]

resolve()[source]

Return models sorted so every dependency runs before its consumer.

Raises:

ValueError – If two models provide the same variable name without output() priority disambiguation, or if a cycle exists.

Return type:

list[Model]