pyiron_workflow.nodes.while_loop module

exception pyiron_workflow.nodes.while_loop.InvalidEdgeError[source]

Bases: ValueError

When a requested edge does not exist for the provided node types.

exception pyiron_workflow.nodes.while_loop.InvalidTestOutputError[source]

Bases: ValueError

When the test type doesn’t have the right output type.

exception pyiron_workflow.nodes.while_loop.NonTerminatingLoopError[source]

Bases: ValueError

When it is strictly impossible for the loop to terminate due to a lack of recursion

exception pyiron_workflow.nodes.while_loop.NotConnectionslikeError[source]

Bases: TypeError

A type checking problem.

class pyiron_workflow.nodes.while_loop.While(*args, label: str | None = None, parent: Composite | None = None, autoload: Literal['h5bag', 'pickle'] | StorageInterface | None = None, delete_existing_savefiles: bool = False, autorun: bool = False, checkpoint: Literal['h5bag', 'pickle'] | StorageInterface | None = None, strict_naming: bool = True, executor_for_test: Executor | tuple[Callable[[...], Executor], tuple, dict] | None = None, executor_for_body: Executor | tuple[Callable[[...], Executor], tuple, dict] | None = None, **kwargs)[source]

Bases: Composite, StaticNode, ABC

A second-order, stateful, dynamic node that resets its graph at each (non-cached) run to dynamically add copies of a body and test case node for as long as the test case node is outputting a true result.

Subclasses must define the types of nodes to use for the test and body, as well as at least one edge from the body to the test and from the body back to itself.

Instances can pass executor information to all child nodes of the same type using the executor_for_test and executor_for_body attributes.

pyiron_workflow.nodes.while_loop.while_node(test_node_class: type[StaticNode], body_node_class: type[StaticNode], body_to_test_connections: tuple[str, str] | list[tuple[str, str]] | tuple[tuple[str, str], ...], body_to_body_connections: tuple[str, str] | list[tuple[str, str]] | tuple[tuple[str, str], ...], *node_args, use_cache: bool = True, strict_condition_hint: bool = True, **node_kwargs)[source]

Make a new :param test_node_class: The class to use for the test condition.

Must have a single output channel, and this must be hinted as boolean when :arg:`strict_condition_hint = True`.

Parameters:
  • body_node_class (type[StaticNode]) – The class to use for the body of the loop.

  • body_to_test_connections (label_connections) – Stringy representations of edge(s) from the body to the test instances.

  • body_to_body_connections (label_connections) – Stringy representations of edge(s) from the last-body to the next-body instances.

  • *node_args – All the usual parent class args.

  • use_cache (bool) – Default class behavior for whether to skip running this node when its inputs match cached values. (Default is True, try to exploit caching.)

  • strict_condition_hint (bool) – Whether to demand that the :arg:`test_node_class` has its single output hinted as boolean. (Default is True.)

  • **node_kwargs – All the usual parent class kwargs, including :arg:`executor_for_test` and :arg:`executor_for_body` that are specific to While.

Returns:

An instance of the new While subclass.

Return type:

While

Examples

>>> from pyiron_workflow import Workflow
>>> wf = Workflow("my_while_loop")
>>> wf.x0 = Workflow.create.std.UserInput(0)
>>> wf.limit = Workflow.create.std.UserInput(5)
>>> wf.step = Workflow.create.std.UserInput(2)
>>> wf.add_while = Workflow.create.while_node(
...     Workflow.create.std.LessThan,  # Test
...     Workflow.create.std.Add,  # Body
...     (("add", "obj"),),  # body-to-test
...     (("add", "obj"),),  # body-to-body
...     strict_condition_hint=False,  # LessThan doesn't hint it's boolean return...
...     test_obj=wf.x0,
...     test_other=wf.limit,
...     body_obj=wf.x0,
...     body_other=wf.step
... )
>>> wf()
{'add_while__add': 6}

Note how the while-node input maps the test and body node inputs with a pre-pended identifier, while the output maps the body node outputs directly.