Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support graph-scheduler graph structure conditions #2864

Merged
merged 5 commits into from
Dec 15, 2023

Conversation

kmantel
Copy link
Collaborator

@kmantel kmantel commented Dec 14, 2023

  • correct bug in autogenerating pnl Conditions from graph-scheduler Conditions
  • modify Scheduler wrappers to support both basic and structural Conditions
  • add wrappers for new graph_scheduler.Scheduler methods:
    • remove_condition
    • add_graph_edge
    • remove_graph_edge
  • update requirements to graph-scheduler<1.3.0 to include graph structure conditions release

- dependency dict must store names, not classes
- must exclude own class name from dependencies (but not "alias" class
names like And->All or Or->Any
Copy link

This PR causes the following changes to the html docs (ubuntu-latest-3.11-x64):

No differences!

...

See CI logs for the full diff.


import graph_scheduler
import pint

import psyneulink as pnl

Check notice

Code scanning / CodeQL

Module is imported with 'import' and 'import from' Note

Module 'psyneulink' is imported with both 'import' and 'import from'.
tests/composition/test_composition.py Fixed Show fixed Hide fixed
@@ -23,12 +22,44 @@
from psyneulink.core.globals.mdf import MDFSerializable
from psyneulink.core.globals.keywords import MODEL_SPEC_ID_TYPE, comparison_operators
from psyneulink.core.globals.parameters import parse_context
from psyneulink.core.globals.utilities import parse_valid_identifier
from psyneulink.core.globals.utilities import parse_valid_identifier, toposort_key

Check notice

Code scanning / CodeQL

Cyclic import Note

Import of module
psyneulink.core.globals.utilities
begins an import cycle.
from psyneulink import _unit_registry
from psyneulink.core.globals.context import Context, handle_external_context
from psyneulink.core.globals.mdf import MDFSerializable
from psyneulink.core.globals.utilities import parse_valid_identifier
from psyneulink.core.scheduling.condition import _create_as_pnl_condition
from psyneulink.core.scheduling.condition import _create_as_pnl_condition, graph_structure_conditions_available, gsc_unavailable_message

Check notice

Code scanning / CodeQL

Cyclic import Note

Import of module
psyneulink.core.scheduling.condition
begins an import cycle.
@kmantel kmantel force-pushed the structural-conditions branch from fe3dbe8 to 91b9b98 Compare December 14, 2023 22:19
Copy link

This PR causes the following changes to the html docs (ubuntu-latest-3.11-x64):

No differences!

...

See CI logs for the full diff.

@kmantel kmantel force-pushed the structural-conditions branch from 91b9b98 to 7b1ad6d Compare December 15, 2023 02:31
Copy link

This PR causes the following changes to the html docs (ubuntu-latest-3.11-x64):

diff -r docs-base/Condition.html docs-head/Condition.html
219c219,223
< can reference any node or its attributes, thus providing considerable flexibility for scheduling.</p>
---
> can reference any node or its attributes, thus providing considerable flexibility for scheduling.
> These Conditions may also be referred to as “basic” Conditions.
> <a class="reference internal" href="#condition-graph-structure-intro"><span class="std std-ref">Graph structure Conditions</span></a> are distinct,
> and affect scheduling instead by modifying the base ordering in which
> nodes are considered for execution.</p>
228c232,233
< <a class="reference internal" href="#psyneulink.core.scheduling.condition.Condition.owner" title="psyneulink.core.scheduling.condition.Condition.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">owner</span></code></a> attribute (a node to which the Condition belongs). Schedulers maintain the data
---
> <a class="reference internal" href="#psyneulink.core.scheduling.condition.ConditionBase.owner" title="psyneulink.core.scheduling.condition.ConditionBase.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">owner</span></code></a> attribute (a node to which the Condition
> belongs). Schedulers maintain the data
232c237
< the Condition’s <a class="reference internal" href="#psyneulink.core.scheduling.condition.Condition.owner" title="psyneulink.core.scheduling.condition.Condition.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">owner</span></code></a> is determined through
---
> the Condition’s <a class="reference internal" href="#psyneulink.core.scheduling.condition.ConditionBase.owner" title="psyneulink.core.scheduling.condition.ConditionBase.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">owner</span></code></a> is determined through
266a272,331
> <section id="graph-structure-conditions">
> <span id="condition-graph-structure-intro"></span><h3><em>Graph Structure Conditions</em><a class="headerlink" href="#graph-structure-conditions" title="Permalink to this headline">¶</a></h3>
> <p>Graph structure Conditions share the same interface as basic Conditions,
> but operate differently. Like basic Conditions, they are assigned to an
> <code class="xref any docutils literal notranslate"><span class="pre">owner</span></code>, and like <a class="reference internal" href="#conditions-node-based"><span class="std std-ref">node-based Conditions</span></a>, they also track other nodes. Each graph
> structure Condition represents a transformation that can be applied to a
> graph, adding and removing edges, which will result in modifying a
> Scheduler’s <a class="reference internal" href="Scheduler.html#scheduler-algorithm"><span class="std std-ref">consideration queue</span></a>. Some execution
> patterns that are difficult to create using basic Conditions can be
> achieved much more easily by making a simple change to the graph.</p>
> <p id="condition-graph-structure-example">For example, consider a situation in which a node computes an initial
> value and provides feedback to one or more of its ancestors. A direct
> construction of the scheduling graph with <code class="xref any docutils literal notranslate"><span class="pre">D</span></code> providing feedback to <code class="xref any docutils literal notranslate"><span class="pre">A</span></code>
> and <a class="reference internal" href="RegressionCFA.html#psyneulink.library.compositions.regressioncfa.PV.C" title="psyneulink.library.compositions.regressioncfa.PV.C"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">C</span></code></a> may be represented by:</p>
> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>  D
>  ↗ ↖
> B   C
> ↑
> A
> 
> {A: set(), B: {A}, C: set(), D: {B, C}}
> </pre></div>
> </div>
> <p>Creating a scheduling pattern for <code class="xref any docutils literal notranslate"><span class="pre">D</span></code> to compute its initial
> value first, like <code class="xref any docutils literal notranslate"><span class="pre">[{D},</span> <span class="pre">{A,</span> <span class="pre">C},</span> <span class="pre">{B}]</span></code>, would require several basic Conditions:</p>
> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">scheduler</span><span class="o">.</span><span class="n">add_condition</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">EveryNCalls</span><span class="p">(</span><span class="n">D</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
> <span class="n">scheduler</span><span class="o">.</span><span class="n">add_condition</span><span class="p">(</span><span class="n">B</span><span class="p">,</span> <span class="n">EveryNCalls</span><span class="p">(</span><span class="n">D</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
> <span class="n">scheduler</span><span class="o">.</span><span class="n">add_condition</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">EveryNCalls</span><span class="p">(</span><span class="n">D</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
> <span class="n">scheduler</span><span class="o">.</span><span class="n">add_condition</span><span class="p">(</span><span class="n">D</span><span class="p">,</span> <span class="n">Always</span><span class="p">())</span>
> </pre></div>
> </div>
> <p>This can become especially burdensome or impossible in larger graphs
> containing nodes that also need other Conditions. The same pattern would
> only require a single graph structure Condition:</p>
> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">scheduler</span><span class="o">.</span><span class="n">add_condition</span><span class="p">(</span><span class="n">D</span><span class="p">,</span> <span class="n">BeforeNodes</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">C</span><span class="p">))</span>
> </pre></div>
> </div>
> <p>which modifies the scheduler’s graph to behave as if it were
> originally the following graph:</p>
> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>B
> ↑
> A   C
>  ↖ ↗
>   D
> 
> {A: {D}, B: {A}, C: {D}, D: set()}
> </pre></div>
> </div>
> <p>Not only is this easier, but it also allows the simultaneous use of the
> full range of basic Conditions.</p>
> <p>Of course, this is the same as if you created a scheduler using the
> second graph. What graph structure Conditions do is provide an interface
> that can be used to avoid manually producing and managing
> transformations of an existing, possibly complicated, graph.</p>
> <div class="admonition note">
> <p class="admonition-title">Note</p>
> <p>Default behavior of graph structure conditions should be considered
> in beta and subject to change.</p>
> </div>
> </section>
270c335,338
< <p>The <a class="reference internal" href="Scheduler.html#psyneulink.core.scheduling.scheduler.Scheduler" title="psyneulink.core.scheduling.scheduler.Scheduler"><code class="xref any py py-class docutils literal notranslate"><span class="pre">Scheduler</span></code></a> associates every node with a Condition.  If a node has not been explicitly assigned a
---
> <p>The <a class="reference internal" href="Scheduler.html#psyneulink.core.scheduling.scheduler.Scheduler" title="psyneulink.core.scheduling.scheduler.Scheduler"><code class="xref any py py-class docutils literal notranslate"><span class="pre">Scheduler</span></code></a> associates every
> node with a single basic Condition and zero or more <a class="reference internal" href="#condition-graph-structure-intro"><span class="std std-ref">graph structure
> Conditions</span></a>. If a node has not been
> explicitly assigned a
274,275c342,343
< provide a standard set of Conditions that can be implemented simply by specifying their parameter(s). There are
< six types:</p>
---
> provide a standard set of Conditions that can be implemented simply by specifying their parameter(s).
> Along with graph structure Conditions, there are six types of basic Conditions:</p>
413a482,537
> <p id="conditions-graph-structure"><strong>Graph Structure Conditions</strong> (used to make modifications to the
> Scheduler graph):</p>
> <blockquote>
> <div><ul class="simple">
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.BeforeNodes" title="psyneulink.core.scheduling.condition.BeforeNodes"><code class="xref any py py-class docutils literal notranslate"><span class="pre">BeforeNodes</span></code></a> (<a href="#id21"><span class="problematic" id="id22">*</span></a>nodes, <a href="#id23"><span class="problematic" id="id24">**</span></a>options)</dt><dd><p>adds a dependency from the owner to each of the specified nodes
> and optionally modifies the senders and receivers of all
> affected nodes</p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.BeforeNode" title="psyneulink.core.scheduling.condition.BeforeNode"><code class="xref any py py-class docutils literal notranslate"><span class="pre">BeforeNode</span></code></a> (node, <a href="#id25"><span class="problematic" id="id26">**</span></a>options)</dt><dd><p>adds a dependency from the owner to the specified node and
> optionally modifies the senders and receivers of both</p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.WithNode" title="psyneulink.core.scheduling.condition.WithNode"><code class="xref any py py-class docutils literal notranslate"><span class="pre">WithNode</span></code></a> (node, <a href="#id27"><span class="problematic" id="id28">**</span></a>options)</dt><dd><p>adds a dependency from each of the senders of both the owner and
> the specified node to both the owner and the specified node, and
> optionally modifies the receivers of both</p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.AfterNodes" title="psyneulink.core.scheduling.condition.AfterNodes"><code class="xref any py py-class docutils literal notranslate"><span class="pre">AfterNodes</span></code></a> (<a href="#id29"><span class="problematic" id="id30">*</span></a>nodes, <a href="#id31"><span class="problematic" id="id32">**</span></a>options)</dt><dd><p>adds a dependency from each of the specified nodes to the owner
> and optionally modifies the senders and receivers of all
> affected nodes</p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.AfterNode" title="psyneulink.core.scheduling.condition.AfterNode"><code class="xref any py py-class docutils literal notranslate"><span class="pre">AfterNode</span></code></a> (node, <a href="#id33"><span class="problematic" id="id34">**</span></a>options)</dt><dd><p>adds a dependency from the specified node to the owner and
> optionally modifies the senders and receivers of both</p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.AddEdgeTo" title="psyneulink.core.scheduling.condition.AddEdgeTo"><code class="xref any py py-class docutils literal notranslate"><span class="pre">AddEdgeTo</span></code></a> (node)</dt><dd><p>adds an edge from <a class="reference internal" href="#psyneulink.core.scheduling.condition.ConditionBase.owner" title="psyneulink.core.scheduling.condition.ConditionBase.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">AddEdgeTo.owner</span></code></a> to
> <a class="reference internal" href="#psyneulink.core.scheduling.condition.AddEdgeTo.node" title="psyneulink.core.scheduling.condition.AddEdgeTo.node"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">AddEdgeTo.node</span></code></a></p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.RemoveEdgeFrom" title="psyneulink.core.scheduling.condition.RemoveEdgeFrom"><code class="xref any py py-class docutils literal notranslate"><span class="pre">RemoveEdgeFrom</span></code></a> (node)</dt><dd><p>removes an edge from <a class="reference internal" href="#psyneulink.core.scheduling.condition.RemoveEdgeFrom.node" title="psyneulink.core.scheduling.condition.RemoveEdgeFrom.node"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">RemoveEdgeFrom.node</span></code></a> to
> <a class="reference internal" href="#psyneulink.core.scheduling.condition.ConditionBase.owner" title="psyneulink.core.scheduling.condition.ConditionBase.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">RemoveEdgeFrom.owner</span></code></a></p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.CustomGraphStructureCondition" title="psyneulink.core.scheduling.condition.CustomGraphStructureCondition"><code class="xref any py py-class docutils literal notranslate"><span class="pre">CustomGraphStructureCondition</span></code></a> (callable, <a href="#id35"><span class="problematic" id="id36">**</span></a>kwargs)</dt><dd><p>applies a user-defined function to a graph</p>
> </dd>
> </dl>
> </li>
> </ul>
> </div></blockquote>
420c544,545
< to execute. It evaluates the nodes in each set by calling the <a class="reference internal" href="#psyneulink.core.scheduling.condition.Condition.is_satisfied" title="psyneulink.core.scheduling.condition.Condition.is_satisfied"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">is_satisfied</span></code></a> method of the Condition associated
---
> to execute. It evaluates the nodes in each set by calling the
> <a class="reference internal" href="#psyneulink.core.scheduling.condition.Condition.is_satisfied" title="psyneulink.core.scheduling.condition.Condition.is_satisfied"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">is_satisfied</span></code></a> method of the basic Condition associated
427,429c552,629
< <dt class="sig sig-object py" id="psyneulink.core.scheduling.condition.AfterCall">
< <em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">psyneulink.core.scheduling.condition.</span></span><span class="sig-name descname"><span class="pre">AfterCall</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">dependency</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">n</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">time_scale</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">TimeScale.ENVIRONMENT_STATE_UPDATE</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#psyneulink.core.scheduling.condition.AfterCall" title="Permalink to this definition">¶</a></dt>
< <dd><dl class="field-list simple">
---
> <dt class="sig sig-object py" id="psyneulink.core.scheduling.condition.Operation">
> <em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">psyneulink.core.scheduling.condition.</span></span><span class="sig-name descname"><span class="pre">Operation</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">value</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">names</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="o"><span class="pre">*</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">module</span></span><span class="o"><span class="pre">=</span></span>
...

See CI logs for the full diff.

supports graph structure conditions automatically
function that produces a python sorting key given a dependency
dictionary
- modify Scheduler wrappers to support both basic and structural
Conditions
- add wrappers for new graph_scheduler.Scheduler methods:
	- remove_condition
	- add_graph_edge
	- remove_graph_edge
- update requirements to graph-scheduler<1.3.0 to include graph
structure conditions release
@kmantel kmantel force-pushed the structural-conditions branch from 7b1ad6d to 1869c2e Compare December 15, 2023 04:11
Copy link

This PR causes the following changes to the html docs (ubuntu-latest-3.11-x64):

diff -r docs-base/Condition.html docs-head/Condition.html
219c219,223
< can reference any node or its attributes, thus providing considerable flexibility for scheduling.</p>
---
> can reference any node or its attributes, thus providing considerable flexibility for scheduling.
> These Conditions may also be referred to as “basic” Conditions.
> <a class="reference internal" href="#condition-graph-structure-intro"><span class="std std-ref">Graph structure Conditions</span></a> are distinct,
> and affect scheduling instead by modifying the base ordering in which
> nodes are considered for execution.</p>
228c232,233
< <a class="reference internal" href="#psyneulink.core.scheduling.condition.Condition.owner" title="psyneulink.core.scheduling.condition.Condition.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">owner</span></code></a> attribute (a node to which the Condition belongs). Schedulers maintain the data
---
> <a class="reference internal" href="#psyneulink.core.scheduling.condition.ConditionBase.owner" title="psyneulink.core.scheduling.condition.ConditionBase.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">owner</span></code></a> attribute (a node to which the Condition
> belongs). Schedulers maintain the data
232c237
< the Condition’s <a class="reference internal" href="#psyneulink.core.scheduling.condition.Condition.owner" title="psyneulink.core.scheduling.condition.Condition.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">owner</span></code></a> is determined through
---
> the Condition’s <a class="reference internal" href="#psyneulink.core.scheduling.condition.ConditionBase.owner" title="psyneulink.core.scheduling.condition.ConditionBase.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">owner</span></code></a> is determined through
266a272,331
> <section id="graph-structure-conditions">
> <span id="condition-graph-structure-intro"></span><h3><em>Graph Structure Conditions</em><a class="headerlink" href="#graph-structure-conditions" title="Permalink to this headline">¶</a></h3>
> <p>Graph structure Conditions share the same interface as basic Conditions,
> but operate differently. Like basic Conditions, they are assigned to an
> <code class="xref any docutils literal notranslate"><span class="pre">owner</span></code>, and like <a class="reference internal" href="#conditions-node-based"><span class="std std-ref">node-based Conditions</span></a>, they also track other nodes. Each graph
> structure Condition represents a transformation that can be applied to a
> graph, adding and removing edges, which will result in modifying a
> Scheduler’s <a class="reference internal" href="Scheduler.html#scheduler-algorithm"><span class="std std-ref">consideration queue</span></a>. Some execution
> patterns that are difficult to create using basic Conditions can be
> achieved much more easily by making a simple change to the graph.</p>
> <p id="condition-graph-structure-example">For example, consider a situation in which a node computes an initial
> value and provides feedback to one or more of its ancestors. A direct
> construction of the scheduling graph with <code class="xref any docutils literal notranslate"><span class="pre">D</span></code> providing feedback to <code class="xref any docutils literal notranslate"><span class="pre">A</span></code>
> and <a class="reference internal" href="RegressionCFA.html#psyneulink.library.compositions.regressioncfa.PV.C" title="psyneulink.library.compositions.regressioncfa.PV.C"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">C</span></code></a> may be represented by:</p>
> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>  D
>  ↗ ↖
> B   C
> ↑
> A
> 
> {A: set(), B: {A}, C: set(), D: {B, C}}
> </pre></div>
> </div>
> <p>Creating a scheduling pattern for <code class="xref any docutils literal notranslate"><span class="pre">D</span></code> to compute its initial
> value first, like <code class="xref any docutils literal notranslate"><span class="pre">[{D},</span> <span class="pre">{A,</span> <span class="pre">C},</span> <span class="pre">{B}]</span></code>, would require several basic Conditions:</p>
> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">scheduler</span><span class="o">.</span><span class="n">add_condition</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">EveryNCalls</span><span class="p">(</span><span class="n">D</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
> <span class="n">scheduler</span><span class="o">.</span><span class="n">add_condition</span><span class="p">(</span><span class="n">B</span><span class="p">,</span> <span class="n">EveryNCalls</span><span class="p">(</span><span class="n">D</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
> <span class="n">scheduler</span><span class="o">.</span><span class="n">add_condition</span><span class="p">(</span><span class="n">C</span><span class="p">,</span> <span class="n">EveryNCalls</span><span class="p">(</span><span class="n">D</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
> <span class="n">scheduler</span><span class="o">.</span><span class="n">add_condition</span><span class="p">(</span><span class="n">D</span><span class="p">,</span> <span class="n">Always</span><span class="p">())</span>
> </pre></div>
> </div>
> <p>This can become especially burdensome or impossible in larger graphs
> containing nodes that also need other Conditions. The same pattern would
> only require a single graph structure Condition:</p>
> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">scheduler</span><span class="o">.</span><span class="n">add_condition</span><span class="p">(</span><span class="n">D</span><span class="p">,</span> <span class="n">BeforeNodes</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">C</span><span class="p">))</span>
> </pre></div>
> </div>
> <p>which modifies the scheduler’s graph to behave as if it were
> originally the following graph:</p>
> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span>B
> ↑
> A   C
>  ↖ ↗
>   D
> 
> {A: {D}, B: {A}, C: {D}, D: set()}
> </pre></div>
> </div>
> <p>Not only is this easier, but it also allows the simultaneous use of the
> full range of basic Conditions.</p>
> <p>Of course, this is the same as if you created a scheduler using the
> second graph. What graph structure Conditions do is provide an interface
> that can be used to avoid manually producing and managing
> transformations of an existing, possibly complicated, graph.</p>
> <div class="admonition note">
> <p class="admonition-title">Note</p>
> <p>Default behavior of graph structure conditions should be considered
> in beta and subject to change.</p>
> </div>
> </section>
270c335,338
< <p>The <a class="reference internal" href="Scheduler.html#psyneulink.core.scheduling.scheduler.Scheduler" title="psyneulink.core.scheduling.scheduler.Scheduler"><code class="xref any py py-class docutils literal notranslate"><span class="pre">Scheduler</span></code></a> associates every node with a Condition.  If a node has not been explicitly assigned a
---
> <p>The <a class="reference internal" href="Scheduler.html#psyneulink.core.scheduling.scheduler.Scheduler" title="psyneulink.core.scheduling.scheduler.Scheduler"><code class="xref any py py-class docutils literal notranslate"><span class="pre">Scheduler</span></code></a> associates every
> node with a single basic Condition and zero or more <a class="reference internal" href="#condition-graph-structure-intro"><span class="std std-ref">graph structure
> Conditions</span></a>. If a node has not been
> explicitly assigned a
274,275c342,343
< provide a standard set of Conditions that can be implemented simply by specifying their parameter(s). There are
< six types:</p>
---
> provide a standard set of Conditions that can be implemented simply by specifying their parameter(s).
> Along with graph structure Conditions, there are six types of basic Conditions:</p>
413a482,537
> <p id="conditions-graph-structure"><strong>Graph Structure Conditions</strong> (used to make modifications to the
> Scheduler graph):</p>
> <blockquote>
> <div><ul class="simple">
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.BeforeNodes" title="psyneulink.core.scheduling.condition.BeforeNodes"><code class="xref any py py-class docutils literal notranslate"><span class="pre">BeforeNodes</span></code></a> (<a href="#id21"><span class="problematic" id="id22">*</span></a>nodes, <a href="#id23"><span class="problematic" id="id24">**</span></a>options)</dt><dd><p>adds a dependency from the owner to each of the specified nodes
> and optionally modifies the senders and receivers of all
> affected nodes</p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.BeforeNode" title="psyneulink.core.scheduling.condition.BeforeNode"><code class="xref any py py-class docutils literal notranslate"><span class="pre">BeforeNode</span></code></a> (node, <a href="#id25"><span class="problematic" id="id26">**</span></a>options)</dt><dd><p>adds a dependency from the owner to the specified node and
> optionally modifies the senders and receivers of both</p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.WithNode" title="psyneulink.core.scheduling.condition.WithNode"><code class="xref any py py-class docutils literal notranslate"><span class="pre">WithNode</span></code></a> (node, <a href="#id27"><span class="problematic" id="id28">**</span></a>options)</dt><dd><p>adds a dependency from each of the senders of both the owner and
> the specified node to both the owner and the specified node, and
> optionally modifies the receivers of both</p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.AfterNodes" title="psyneulink.core.scheduling.condition.AfterNodes"><code class="xref any py py-class docutils literal notranslate"><span class="pre">AfterNodes</span></code></a> (<a href="#id29"><span class="problematic" id="id30">*</span></a>nodes, <a href="#id31"><span class="problematic" id="id32">**</span></a>options)</dt><dd><p>adds a dependency from each of the specified nodes to the owner
> and optionally modifies the senders and receivers of all
> affected nodes</p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.AfterNode" title="psyneulink.core.scheduling.condition.AfterNode"><code class="xref any py py-class docutils literal notranslate"><span class="pre">AfterNode</span></code></a> (node, <a href="#id33"><span class="problematic" id="id34">**</span></a>options)</dt><dd><p>adds a dependency from the specified node to the owner and
> optionally modifies the senders and receivers of both</p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.AddEdgeTo" title="psyneulink.core.scheduling.condition.AddEdgeTo"><code class="xref any py py-class docutils literal notranslate"><span class="pre">AddEdgeTo</span></code></a> (node)</dt><dd><p>adds an edge from <a class="reference internal" href="#psyneulink.core.scheduling.condition.ConditionBase.owner" title="psyneulink.core.scheduling.condition.ConditionBase.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">AddEdgeTo.owner</span></code></a> to
> <a class="reference internal" href="#psyneulink.core.scheduling.condition.AddEdgeTo.node" title="psyneulink.core.scheduling.condition.AddEdgeTo.node"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">AddEdgeTo.node</span></code></a></p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.RemoveEdgeFrom" title="psyneulink.core.scheduling.condition.RemoveEdgeFrom"><code class="xref any py py-class docutils literal notranslate"><span class="pre">RemoveEdgeFrom</span></code></a> (node)</dt><dd><p>removes an edge from <a class="reference internal" href="#psyneulink.core.scheduling.condition.RemoveEdgeFrom.node" title="psyneulink.core.scheduling.condition.RemoveEdgeFrom.node"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">RemoveEdgeFrom.node</span></code></a> to
> <a class="reference internal" href="#psyneulink.core.scheduling.condition.ConditionBase.owner" title="psyneulink.core.scheduling.condition.ConditionBase.owner"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">RemoveEdgeFrom.owner</span></code></a></p>
> </dd>
> </dl>
> </li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#psyneulink.core.scheduling.condition.CustomGraphStructureCondition" title="psyneulink.core.scheduling.condition.CustomGraphStructureCondition"><code class="xref any py py-class docutils literal notranslate"><span class="pre">CustomGraphStructureCondition</span></code></a> (callable, <a href="#id35"><span class="problematic" id="id36">**</span></a>kwargs)</dt><dd><p>applies a user-defined function to a graph</p>
> </dd>
> </dl>
> </li>
> </ul>
> </div></blockquote>
420c544,545
< to execute. It evaluates the nodes in each set by calling the <a class="reference internal" href="#psyneulink.core.scheduling.condition.Condition.is_satisfied" title="psyneulink.core.scheduling.condition.Condition.is_satisfied"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">is_satisfied</span></code></a> method of the Condition associated
---
> to execute. It evaluates the nodes in each set by calling the
> <a class="reference internal" href="#psyneulink.core.scheduling.condition.Condition.is_satisfied" title="psyneulink.core.scheduling.condition.Condition.is_satisfied"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">is_satisfied</span></code></a> method of the basic Condition associated
427,429c552,628
< <dt class="sig sig-object py" id="psyneulink.core.scheduling.condition.AfterCall">
< <em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">psyneulink.core.scheduling.condition.</span></span><span class="sig-name descname"><span class="pre">AfterCall</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">dependency</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">n</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">time_scale</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">TimeScale.ENVIRONMENT_STATE_UPDATE</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#psyneulink.core.scheduling.condition.AfterCall" title="Permalink to this definition">¶</a></dt>
< <dd><dl class="field-list simple">
---
> <dt class="sig sig-object py" id="psyneulink.core.scheduling.condition.Operation">
> <em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">psyneulink.core.scheduling.condition.</span></span><span class="sig-name descname"><span class="pre">Operation</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">value</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">names</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="o"><span class="pre">*</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">module</span></span><span class="o"><span class="pre">=</span></span>
...

See CI logs for the full diff.

@kmantel kmantel merged commit a38768d into PrincetonUniversity:devel Dec 15, 2023
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant