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

Feat/comp/mult proj between nodes #2251

Merged
merged 287 commits into from
Dec 18, 2021
Merged

Conversation

jdcpni
Copy link
Collaborator

@jdcpni jdcpni commented Dec 18, 2021

• composition.py
_add_linear_processing_pathway, add_projection, _is_pathway_entry_spec:
- support lists or sets of Projections between Nodes of nested Compositions in a Pathway
- support automatic specification of many->one and one->many projections between mech and comps in pathway spec
- test_composition/test_add_multiple_projections_for_nested_compositions tests for these features

• show_graph.py
_assign_cim_components(): fix bug in which comp1_output_cim->comp2_input_cim was skipped and not shown

jdcpni and others added 30 commits November 10, 2021 20:06
…ut_ports

# Conflicts:
#	psyneulink/core/components/mechanisms/modulatory/control/optimizationcontrolmechanism.py
  - __init__: moved controller instantiation until after nodes, projections and pathways
  - __init__: restored add_controller position
…teger

Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu>
…ut_ports

# Conflicts:
#	psyneulink/core/llvm/builder_context.py
  - _update_controller: added
  - add_controller and _analyze_graph(): call _update_controller
  _update_controller:  fixed to loop through all input_ports of comp INPUT nodes
  - test_agent_rep_assignement_as_controller_and_replacement:
      updated to test that shadowing projections to state_input_ports
      are properly added and deleted
…Link into refactor/ocm/state_input_ports

� Conflicts:
�	tests/composition/test_control.py
  - _function: refactored to put use aggregation_function at end
  - _grid_evaluate:  still needs to return all_samples
…rincetonUniversity/PsyNeuLink into refactor/ocm/state_input_ports

� Conflicts:
�	psyneulink/core/components/mechanisms/modulatory/control/optimizationcontrolmechanism.py
  - added call to _update_controller to add_node
  - moved test for projections to controller.state_input_ports to run()
  moved calls to _update_controller to _complete_init_of_partially_initialized_nodes
  moved _update_controller to ocm._update_state_input_ports

• optimizationcontrolmechanism.py:
  added _update_state_input_ports [**still needed work**]
  moved calls to _update_controller to _complete_init_of_partially_initialized_nodes
  moved _update_controller to ocm._update_state_input_ports
  _instantiate_controller_shadow_projections [still needs to be implemented]

• optimizationcontrolmechanism.py:
  added _update_state_input_ports [**still needed work**]
  added needs_update_controller
  - implemented self.needs_update_controller
  - moved implementation of controlsignal projections
    from add_controller to _instantiate_control_projections
    that is called in _complete_init_of_partially_initialized_nodes

Note: still need to set  self.needs_update_controller to False
      after instantiating state_input_ports and projections to them
jdcpni and others added 22 commits December 17, 2021 08:25
  add_projection:  working on adding support for projection sets
  - add _get_nested_nodes_with_same_roles_at_all_levels
  - add_linear_processing_pathway:
    call _get_nested_nodes_with_same_roles_at_all_levels
  - add_linear_processing_pathway:  add support for inline specification of set of Projections
  add_linear_processing_pathway: refactored to support inline specification of sets of Projections
  add_linear_processing_pathway: docstring edits for Projection set specification
…m/PrincetonUniversity/PsyNeuLink into feat/comp/mult_proj_between_nodes

� Conflicts:
�	psyneulink/core/compositions/composition.py
  - add test_add_multiple_projections_for_nested_compositions - IN PROGRESS
  - add test_add_multiple_projections_for_nested_compositions - passes
@github-actions
Copy link

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

diff -r docs-base/Composition.html docs-head/Composition.html
465c465,466
< inserting a default Projection between any adjacent pair of Nodes for which one is not otherwise specified;
---
> inserting a default Projection between any adjacent pair of Nodes for which one is not otherwise specified
> (or possibly a set of Projections if either Node is a Composition – see method documentation for details);
556,557c557
< <li><p>the <strong>roles</strong> argument of the <a class="reference internal" href="#psyneulink.core.compositions.composition.Composition.require_node_roles" title="psyneulink.core.compositions.composition.Composition.require_node_roles"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">require_node_roles</span></code></a> called for an
< an existing <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Node</span></a>.</p></li>
---
> <li><p>the <strong>roles</strong> argument of the <a class="reference internal" href="#psyneulink.core.compositions.composition.Composition.require_node_roles" title="psyneulink.core.compositions.composition.Composition.require_node_roles"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">require_node_roles</span></code></a> called for an existing Node.</p></li>
2548,2549c2548,2552
< argument of the Composition’s constructor and/or one of its <a class="reference internal" href="#composition-pathway-addition-methods"><span class="std std-ref">Pathway addition methods</span></a>; each item is a list of nodes (<a class="reference internal" href="Mechanism.html"><span class="doc">Mechanisms</span></a> and/or
< Compositions) intercolated with the <a class="reference internal" href="Projection.html"><span class="doc">Projection</span></a> between each pair of nodes.</p>
---
> argument of the Composition’s constructor and/or one of its <a class="reference internal" href="#composition-pathway-addition-methods"><span class="std std-ref">Pathway addition methods</span></a>; each item is a list of <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a>
> (<a class="reference internal" href="Mechanism.html"><span class="doc">Mechanisms</span></a> and/or Compositions) intercolated with the <a class="reference internal" href="Projection.html"><span class="doc">Projection(s)</span></a> between each
> pair of Nodes;  both Nodes are Mechanism, then only a single Projection can be specified;  if either is a
> Composition then, under some circumstances, there can be a set of Projections, specifying how the <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node(s) of the sender project to the <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node(s) of the receiver
> (see <a class="reference internal" href="#psyneulink.core.compositions.composition.Composition.add_linear_processing_pathway" title="psyneulink.core.compositions.composition.Composition.add_linear_processing_pathway"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">add_linear_processing_pathway</span></code></a> for additional details).</p>
3149a3153,3164
> <dt class="sig sig-object py" id="psyneulink.core.compositions.composition.Composition._get_nested_nodes_with_same_roles_at_all_levels">
> <span class="sig-name descname"><span class="pre">_get_nested_nodes_with_same_roles_at_all_levels</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">comp</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">include_roles</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">exclude_roles</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#psyneulink.core.compositions.composition.Composition._get_nested_nodes_with_same_roles_at_all_levels" title="Permalink to this definition">¶</a></dt>
> <dd><p>Return all Nodes from nested Compositions that have <em>include_roles</em> but not <em>exclude_roles at all levels</em>.
> Note:  need to do this recursively, checking roles on the “way down,” since a Node may have a role in a</p>
> <blockquote>
> <div><p>deeply nested Composition, but that Composition itself may not have the same role in the Composition
> within which <em>it</em> is nested (e.g., a Node might be an INPUT Node of a nested Composition, but that
> nested Composition may not be an INPUT Node of the Composition in which it is nested).</p>
> </div></blockquote>
> </dd></dl>
> 
> <dl class="py method">
3465,3467c3480,3482
< <p>If <strong>projection</strong> is an instantiated Projection (i.e., not in <code class="xref any docutils literal notranslate"><span class="pre">deferred_init</span></code>) and one already exists between
< its <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.sender" title="psyneulink.core.components.projections.projection.Projection_Base.sender"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">sender</span></code></a> and <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.receiver" title="psyneulink.core.components.projections.projection.Projection_Base.receiver"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">receiver</span></code></a> a warning is generated and
< the request is ignored.</p>
---
> <p>If <strong>projection</strong> is an instantiated Projection (i.e., not in <code class="xref any docutils literal notranslate"><span class="pre">deferred_init</span></code>), and one already exists
> between its <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.sender" title="psyneulink.core.components.projections.projection.Projection_Base.sender"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">sender</span></code></a> and <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.receiver" title="psyneulink.core.components.projections.projection.Projection_Base.receiver"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">receiver</span></code></a>, a warning is
> generated and the request is ignored.</p>
3553,3560c3568,3596
< <dd><p>Add sequence of Mechanisms and/or Compositions with intercolated Projections.</p>
< <p>A <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> is created for each contiguous pair of <a class="reference internal" href="Mechanism.html"><span class="doc">Mechanisms</span></a> and/or Compositions
< in the <strong>pathway</strong> argument, from the <a class="reference internal" href="OutputPort.html#outputport-primary"><span class="std std-ref">primary OutputPort</span></a> of the first one to the
< <a class="reference internal" href="InputPort.html#inputport-primary"><span class="std std-ref">primary InputPort</span></a> of the second.</p>
< <p>Tuples (Mechanism, <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole" title="psyneulink.core.compositions.composition.NodeRole"><code class="xref any py py-class docutils literal notranslate"><span class="pre">NodeRoles</span></code></a>) can be used to assign <code class="xref any docutils literal notranslate"><span class="pre">required_roles</span></code> to Mechanisms.</p>
< <p>Note that any specifications of the <strong>monitor_for_control</strong> <a class="reference internal" href="ControlMechanism.html#controlmechanism-monitor-for-control-argument"><span class="std std-ref">argument</span></a> of a constructor for a <a class="reference internal" href="ControlMechanism.html"><span class="doc">ControlMechanism</span></a> or the <strong>monitor</strong>
< argument specified in the constructor for an ObjectiveMechanism in the <strong>objective_mechanism</strong> <a class="reference internal" href="ControlMechanism.html#controlmechanism-objectivemechanism"><span class="std std-ref">argument</span></a> of a ControlMechanism supercede any MappingProjections that would
< otherwise be created for them when specified in the <strong>pathway</strong> argument of add_linear_processing_pathway.</p>
---
> <dd><p>Add sequence of <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a> with intercolated Projections.</p>
> <p id="composition-add-linear-processing-pathway">Each <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Node</span></a> can be either a <a class="reference internal" href="Mechanism.html"><span class="doc">Mechanism</span></a>, a <a class="reference internal" href="#"><span class="doc">Composition</span></a>, or a tuple (Mechanism, <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole" title="psyneulink.core.compositions.composition.NodeRole"><code class="xref any py py-class docutils literal notranslate"><span class="pre">NodeRoles</span></code></a>) that can be used to assign <code class="xref any docutils literal notranslate"><span class="pre">required_roles</span></code> to Mechanisms (see <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a> for additional
> details).</p>
> <p><a class="reference internal" href="Projection.html"><span class="doc">Projections</span></a> can be intercolated between any pair of <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a>. If both Nodes
> of a pair are Mechanisms, a single <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> can be <a class="reference internal" href="MappingProjection.html#mappingprojection-creation"><span class="std std-ref">specified</span></a>.  The
> same applies if the first Node is a <a class="reference internal" href="#"><span class="doc">Composition</span></a> with a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node and/or the
> second is a <a class="reference internal" href="#"><span class="doc">Composition</span></a> with a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node.  If either has more than one <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> or <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node, respectively, then a list or set of Projections can be
> specified for each pair of nested Nodes. If no <a class="reference internal" href="Projection.html"><span class="doc">Projection</span></a> is specified between a pair of contiguous Nodes,
> then default Projection(s) are constructed between them, as follows:</p>
> <ul class="simple">
> <li><p><em>One to one</em> - if both Nodes are Mechanisms or, if either is a Composition, the first (sender) has
> only a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node and the second (receiver) has only a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node, then a default <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> is created from the <a class="reference internal" href="OutputPort.html#outputport-primary"><span class="std std-ref">primary OutputPort</span></a> of the sender (or of its sole <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node if the sener is a
> Composition) to the <a class="reference internal" href="InputPort.html#inputport-primary"><span class="std std-ref">primary InputPort</span></a> of the receiver (or of its sole of <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node if the receiver is a Composition).</p></li>
> <li><p><em>One to many</em> - if the first Node (sender) is either a Mechanism or a Composition with a single
> <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node, but the second (receiver) is a Composition with more than one
> <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node, then a <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> is created from the <a class="reference internal" href="OutputPort.html#outputport-primary"><span class="std std-ref">primary OutputPort</span></a> of the sender Mechanism (or of its sole <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node if the
> sender is a Compostion) to each <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node of the receiver, and a <em>set</em>
> containing the Projections is intercolated between the two Nodes in the <a class="reference internal" href="Pathway.html"><span class="doc">Pathway</span></a>.</p></li>
> <li><p><em>Many to one</em> - if the first Node (sender) is a Composition with more than one <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a>
> Node, and the second (receiver) is either a Mechanism or a Composition with a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" ti
...

See CI logs for the full diff.

1 similar comment
@github-actions
Copy link

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

diff -r docs-base/Composition.html docs-head/Composition.html
465c465,466
< inserting a default Projection between any adjacent pair of Nodes for which one is not otherwise specified;
---
> inserting a default Projection between any adjacent pair of Nodes for which one is not otherwise specified
> (or possibly a set of Projections if either Node is a Composition – see method documentation for details);
556,557c557
< <li><p>the <strong>roles</strong> argument of the <a class="reference internal" href="#psyneulink.core.compositions.composition.Composition.require_node_roles" title="psyneulink.core.compositions.composition.Composition.require_node_roles"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">require_node_roles</span></code></a> called for an
< an existing <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Node</span></a>.</p></li>
---
> <li><p>the <strong>roles</strong> argument of the <a class="reference internal" href="#psyneulink.core.compositions.composition.Composition.require_node_roles" title="psyneulink.core.compositions.composition.Composition.require_node_roles"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">require_node_roles</span></code></a> called for an existing Node.</p></li>
2548,2549c2548,2552
< argument of the Composition’s constructor and/or one of its <a class="reference internal" href="#composition-pathway-addition-methods"><span class="std std-ref">Pathway addition methods</span></a>; each item is a list of nodes (<a class="reference internal" href="Mechanism.html"><span class="doc">Mechanisms</span></a> and/or
< Compositions) intercolated with the <a class="reference internal" href="Projection.html"><span class="doc">Projection</span></a> between each pair of nodes.</p>
---
> argument of the Composition’s constructor and/or one of its <a class="reference internal" href="#composition-pathway-addition-methods"><span class="std std-ref">Pathway addition methods</span></a>; each item is a list of <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a>
> (<a class="reference internal" href="Mechanism.html"><span class="doc">Mechanisms</span></a> and/or Compositions) intercolated with the <a class="reference internal" href="Projection.html"><span class="doc">Projection(s)</span></a> between each
> pair of Nodes;  both Nodes are Mechanism, then only a single Projection can be specified;  if either is a
> Composition then, under some circumstances, there can be a set of Projections, specifying how the <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node(s) of the sender project to the <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node(s) of the receiver
> (see <a class="reference internal" href="#psyneulink.core.compositions.composition.Composition.add_linear_processing_pathway" title="psyneulink.core.compositions.composition.Composition.add_linear_processing_pathway"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">add_linear_processing_pathway</span></code></a> for additional details).</p>
3149a3153,3164
> <dt class="sig sig-object py" id="psyneulink.core.compositions.composition.Composition._get_nested_nodes_with_same_roles_at_all_levels">
> <span class="sig-name descname"><span class="pre">_get_nested_nodes_with_same_roles_at_all_levels</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">comp</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">include_roles</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">exclude_roles</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#psyneulink.core.compositions.composition.Composition._get_nested_nodes_with_same_roles_at_all_levels" title="Permalink to this definition">¶</a></dt>
> <dd><p>Return all Nodes from nested Compositions that have <em>include_roles</em> but not <em>exclude_roles at all levels</em>.
> Note:  need to do this recursively, checking roles on the “way down,” since a Node may have a role in a</p>
> <blockquote>
> <div><p>deeply nested Composition, but that Composition itself may not have the same role in the Composition
> within which <em>it</em> is nested (e.g., a Node might be an INPUT Node of a nested Composition, but that
> nested Composition may not be an INPUT Node of the Composition in which it is nested).</p>
> </div></blockquote>
> </dd></dl>
> 
> <dl class="py method">
3465,3467c3480,3482
< <p>If <strong>projection</strong> is an instantiated Projection (i.e., not in <code class="xref any docutils literal notranslate"><span class="pre">deferred_init</span></code>) and one already exists between
< its <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.sender" title="psyneulink.core.components.projections.projection.Projection_Base.sender"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">sender</span></code></a> and <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.receiver" title="psyneulink.core.components.projections.projection.Projection_Base.receiver"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">receiver</span></code></a> a warning is generated and
< the request is ignored.</p>
---
> <p>If <strong>projection</strong> is an instantiated Projection (i.e., not in <code class="xref any docutils literal notranslate"><span class="pre">deferred_init</span></code>), and one already exists
> between its <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.sender" title="psyneulink.core.components.projections.projection.Projection_Base.sender"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">sender</span></code></a> and <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.receiver" title="psyneulink.core.components.projections.projection.Projection_Base.receiver"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">receiver</span></code></a>, a warning is
> generated and the request is ignored.</p>
3553,3560c3568,3596
< <dd><p>Add sequence of Mechanisms and/or Compositions with intercolated Projections.</p>
< <p>A <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> is created for each contiguous pair of <a class="reference internal" href="Mechanism.html"><span class="doc">Mechanisms</span></a> and/or Compositions
< in the <strong>pathway</strong> argument, from the <a class="reference internal" href="OutputPort.html#outputport-primary"><span class="std std-ref">primary OutputPort</span></a> of the first one to the
< <a class="reference internal" href="InputPort.html#inputport-primary"><span class="std std-ref">primary InputPort</span></a> of the second.</p>
< <p>Tuples (Mechanism, <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole" title="psyneulink.core.compositions.composition.NodeRole"><code class="xref any py py-class docutils literal notranslate"><span class="pre">NodeRoles</span></code></a>) can be used to assign <code class="xref any docutils literal notranslate"><span class="pre">required_roles</span></code> to Mechanisms.</p>
< <p>Note that any specifications of the <strong>monitor_for_control</strong> <a class="reference internal" href="ControlMechanism.html#controlmechanism-monitor-for-control-argument"><span class="std std-ref">argument</span></a> of a constructor for a <a class="reference internal" href="ControlMechanism.html"><span class="doc">ControlMechanism</span></a> or the <strong>monitor</strong>
< argument specified in the constructor for an ObjectiveMechanism in the <strong>objective_mechanism</strong> <a class="reference internal" href="ControlMechanism.html#controlmechanism-objectivemechanism"><span class="std std-ref">argument</span></a> of a ControlMechanism supercede any MappingProjections that would
< otherwise be created for them when specified in the <strong>pathway</strong> argument of add_linear_processing_pathway.</p>
---
> <dd><p>Add sequence of <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a> with intercolated Projections.</p>
> <p id="composition-add-linear-processing-pathway">Each <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Node</span></a> can be either a <a class="reference internal" href="Mechanism.html"><span class="doc">Mechanism</span></a>, a <a class="reference internal" href="#"><span class="doc">Composition</span></a>, or a tuple (Mechanism, <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole" title="psyneulink.core.compositions.composition.NodeRole"><code class="xref any py py-class docutils literal notranslate"><span class="pre">NodeRoles</span></code></a>) that can be used to assign <code class="xref any docutils literal notranslate"><span class="pre">required_roles</span></code> to Mechanisms (see <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a> for additional
> details).</p>
> <p><a class="reference internal" href="Projection.html"><span class="doc">Projections</span></a> can be intercolated between any pair of <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a>. If both Nodes
> of a pair are Mechanisms, a single <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> can be <a class="reference internal" href="MappingProjection.html#mappingprojection-creation"><span class="std std-ref">specified</span></a>.  The
> same applies if the first Node is a <a class="reference internal" href="#"><span class="doc">Composition</span></a> with a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node and/or the
> second is a <a class="reference internal" href="#"><span class="doc">Composition</span></a> with a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node.  If either has more than one <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> or <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node, respectively, then a list or set of Projections can be
> specified for each pair of nested Nodes. If no <a class="reference internal" href="Projection.html"><span class="doc">Projection</span></a> is specified between a pair of contiguous Nodes,
> then default Projection(s) are constructed between them, as follows:</p>
> <ul class="simple">
> <li><p><em>One to one</em> - if both Nodes are Mechanisms or, if either is a Composition, the first (sender) has
> only a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node and the second (receiver) has only a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node, then a default <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> is created from the <a class="reference internal" href="OutputPort.html#outputport-primary"><span class="std std-ref">primary OutputPort</span></a> of the sender (or of its sole <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node if the sener is a
> Composition) to the <a class="reference internal" href="InputPort.html#inputport-primary"><span class="std std-ref">primary InputPort</span></a> of the receiver (or of its sole of <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node if the receiver is a Composition).</p></li>
> <li><p><em>One to many</em> - if the first Node (sender) is either a Mechanism or a Composition with a single
> <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node, but the second (receiver) is a Composition with more than one
> <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node, then a <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> is created from the <a class="reference internal" href="OutputPort.html#outputport-primary"><span class="std std-ref">primary OutputPort</span></a> of the sender Mechanism (or of its sole <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node if the
> sender is a Compostion) to each <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node of the receiver, and a <em>set</em>
> containing the Projections is intercolated between the two Nodes in the <a class="reference internal" href="Pathway.html"><span class="doc">Pathway</span></a>.</p></li>
> <li><p><em>Many to one</em> - if the first Node (sender) is a Composition with more than one <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a>
> Node, and the second (receiver) is either a Mechanism or a Composition with a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" ti
...

See CI logs for the full diff.

@github-actions
Copy link

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

diff -r docs-base/Composition.html docs-head/Composition.html
465c465,466
< inserting a default Projection between any adjacent pair of Nodes for which one is not otherwise specified;
---
> inserting a default Projection between any adjacent pair of Nodes for which one is not otherwise specified
> (or possibly a set of Projections if either Node is a Composition – see method documentation for details);
556,557c557
< <li><p>the <strong>roles</strong> argument of the <a class="reference internal" href="#psyneulink.core.compositions.composition.Composition.require_node_roles" title="psyneulink.core.compositions.composition.Composition.require_node_roles"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">require_node_roles</span></code></a> called for an
< an existing <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Node</span></a>.</p></li>
---
> <li><p>the <strong>roles</strong> argument of the <a class="reference internal" href="#psyneulink.core.compositions.composition.Composition.require_node_roles" title="psyneulink.core.compositions.composition.Composition.require_node_roles"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">require_node_roles</span></code></a> called for an existing Node.</p></li>
2548,2549c2548,2552
< argument of the Composition’s constructor and/or one of its <a class="reference internal" href="#composition-pathway-addition-methods"><span class="std std-ref">Pathway addition methods</span></a>; each item is a list of nodes (<a class="reference internal" href="Mechanism.html"><span class="doc">Mechanisms</span></a> and/or
< Compositions) intercolated with the <a class="reference internal" href="Projection.html"><span class="doc">Projection</span></a> between each pair of nodes.</p>
---
> argument of the Composition’s constructor and/or one of its <a class="reference internal" href="#composition-pathway-addition-methods"><span class="std std-ref">Pathway addition methods</span></a>; each item is a list of <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a>
> (<a class="reference internal" href="Mechanism.html"><span class="doc">Mechanisms</span></a> and/or Compositions) intercolated with the <a class="reference internal" href="Projection.html"><span class="doc">Projection(s)</span></a> between each
> pair of Nodes;  both Nodes are Mechanism, then only a single Projection can be specified;  if either is a
> Composition then, under some circumstances, there can be a set of Projections, specifying how the <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node(s) of the sender project to the <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node(s) of the receiver
> (see <a class="reference internal" href="#psyneulink.core.compositions.composition.Composition.add_linear_processing_pathway" title="psyneulink.core.compositions.composition.Composition.add_linear_processing_pathway"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">add_linear_processing_pathway</span></code></a> for additional details).</p>
3149a3153,3164
> <dt class="sig sig-object py" id="psyneulink.core.compositions.composition.Composition._get_nested_nodes_with_same_roles_at_all_levels">
> <span class="sig-name descname"><span class="pre">_get_nested_nodes_with_same_roles_at_all_levels</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">comp</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">include_roles</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">exclude_roles</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#psyneulink.core.compositions.composition.Composition._get_nested_nodes_with_same_roles_at_all_levels" title="Permalink to this definition">¶</a></dt>
> <dd><p>Return all Nodes from nested Compositions that have <em>include_roles</em> but not <em>exclude_roles at all levels</em>.
> Note:  need to do this recursively, checking roles on the “way down,” since a Node may have a role in a</p>
> <blockquote>
> <div><p>deeply nested Composition, but that Composition itself may not have the same role in the Composition
> within which <em>it</em> is nested (e.g., a Node might be an INPUT Node of a nested Composition, but that
> nested Composition may not be an INPUT Node of the Composition in which it is nested).</p>
> </div></blockquote>
> </dd></dl>
> 
> <dl class="py method">
3448c3463
< construct any “shadow” projections that may be specified, and assign feedback if specified,</p></li>
---
> construct any “shadow” projections that may be specified, and assign feedback if specified.</p></li>
3465,3467c3480,3482
< <p>If <strong>projection</strong> is an instantiated Projection (i.e., not in <code class="xref any docutils literal notranslate"><span class="pre">deferred_init</span></code>) and one already exists between
< its <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.sender" title="psyneulink.core.components.projections.projection.Projection_Base.sender"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">sender</span></code></a> and <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.receiver" title="psyneulink.core.components.projections.projection.Projection_Base.receiver"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">receiver</span></code></a> a warning is generated and
< the request is ignored.</p>
---
> <p>If <strong>projection</strong> is an instantiated Projection (i.e., not in <code class="xref any docutils literal notranslate"><span class="pre">deferred_init</span></code>), and one already exists
> between its <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.sender" title="psyneulink.core.components.projections.projection.Projection_Base.sender"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">sender</span></code></a> and <a class="reference internal" href="Projection.html#psyneulink.core.components.projections.projection.Projection_Base.receiver" title="psyneulink.core.components.projections.projection.Projection_Base.receiver"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">receiver</span></code></a>, a warning is
> generated and the request is ignored.</p>
3553,3560c3568,3596
< <dd><p>Add sequence of Mechanisms and/or Compositions with intercolated Projections.</p>
< <p>A <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> is created for each contiguous pair of <a class="reference internal" href="Mechanism.html"><span class="doc">Mechanisms</span></a> and/or Compositions
< in the <strong>pathway</strong> argument, from the <a class="reference internal" href="OutputPort.html#outputport-primary"><span class="std std-ref">primary OutputPort</span></a> of the first one to the
< <a class="reference internal" href="InputPort.html#inputport-primary"><span class="std std-ref">primary InputPort</span></a> of the second.</p>
< <p>Tuples (Mechanism, <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole" title="psyneulink.core.compositions.composition.NodeRole"><code class="xref any py py-class docutils literal notranslate"><span class="pre">NodeRoles</span></code></a>) can be used to assign <code class="xref any docutils literal notranslate"><span class="pre">required_roles</span></code> to Mechanisms.</p>
< <p>Note that any specifications of the <strong>monitor_for_control</strong> <a class="reference internal" href="ControlMechanism.html#controlmechanism-monitor-for-control-argument"><span class="std std-ref">argument</span></a> of a constructor for a <a class="reference internal" href="ControlMechanism.html"><span class="doc">ControlMechanism</span></a> or the <strong>monitor</strong>
< argument specified in the constructor for an ObjectiveMechanism in the <strong>objective_mechanism</strong> <a class="reference internal" href="ControlMechanism.html#controlmechanism-objectivemechanism"><span class="std std-ref">argument</span></a> of a ControlMechanism supercede any MappingProjections that would
< otherwise be created for them when specified in the <strong>pathway</strong> argument of add_linear_processing_pathway.</p>
---
> <dd><p>Add sequence of <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a> with intercolated Projections.</p>
> <p id="composition-add-linear-processing-pathway">Each <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Node</span></a> can be either a <a class="reference internal" href="Mechanism.html"><span class="doc">Mechanism</span></a>, a <a class="reference internal" href="#"><span class="doc">Composition</span></a>, or a tuple (Mechanism, <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole" title="psyneulink.core.compositions.composition.NodeRole"><code class="xref any py py-class docutils literal notranslate"><span class="pre">NodeRoles</span></code></a>) that can be used to assign <code class="xref any docutils literal notranslate"><span class="pre">required_roles</span></code> to Mechanisms (see <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a> for additional
> details).</p>
> <p><a class="reference internal" href="Projection.html"><span class="doc">Projections</span></a> can be intercolated between any pair of <a class="reference internal" href="#composition-nodes"><span class="std std-ref">Nodes</span></a>. If both Nodes
> of a pair are Mechanisms, a single <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> can be <a class="reference internal" href="MappingProjection.html#mappingprojection-creation"><span class="std std-ref">specified</span></a>.  The
> same applies if the first Node is a <a class="reference internal" href="#"><span class="doc">Composition</span></a> with a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node and/or the
> second is a <a class="reference internal" href="#"><span class="doc">Composition</span></a> with a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node.  If either has more than one <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> or <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node, respectively, then a list or set of Projections can be
> specified for each pair of nested Nodes. If no <a class="reference internal" href="Projection.html"><span class="doc">Projection</span></a> is specified between a pair of contiguous Nodes,
> then default Projection(s) are constructed between them, as follows:</p>
> <ul class="simple">
> <li><p><em>One to one</em> - if both Nodes are Mechanisms or, if either is a Composition, the first (sender) has
> only a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node and the second (receiver) has only a single <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node, then a default <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> is created from the <a class="reference internal" href="OutputPort.html#outputport-primary"><span class="std std-ref">primary OutputPort</span></a> of the sender (or of its sole <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node if the sener is a
> Composition) to the <a class="reference internal" href="InputPort.html#inputport-primary"><span class="std std-ref">primary InputPort</span></a> of the receiver (or of its sole of <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node if the receiver is a Composition).</p></li>
> <li><p><em>One to many</em> - if the first Node (sender) is either a Mechanism or a Composition with a single
> <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node, but the second (receiver) is a Composition with more than one
> <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.INPUT" title="psyneulink.core.compositions.composition.NodeRole.INPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node, then a <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a> is created from the <a class="reference internal" href="OutputPort.html#outputport-primary"><span class="std std-ref">primary OutputPort</span></a> of the sender Mechanism (or of its sole <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">OUTPUT</span></code></a> Node if the
> sender is a Compostion) to each <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">INPUT</span></code></a> Node of the receiver, and a <em>set</em>
> containing the Projections is intercolated between the two Nodes in the <a class="reference internal" href="Pathway.html"><span class="doc">Pathway</span></a>.</p></li>
> <li><p><em>Many to one</em> - if the first Node (sender) is a Composition with more than one <a class="reference internal" href="#psyneulink.core.compositions.composition.NodeRole.OUTPUT" title="psyneulink.core.compositions.composition.NodeRole.OUTPUT"><code class="xref any py py-attr docutils literal notranslate
...

See CI logs for the full diff.

@lgtm-com
Copy link
Contributor

lgtm-com bot commented Dec 18, 2021

This pull request introduces 1 alert when merging 7a0542e into 7c2d3cf - view on LGTM.com

new alerts:

  • 1 for Unused local variable

@coveralls
Copy link

Coverage Status

Coverage increased (+0.06%) to 83.994% when pulling 7a0542e on feat/comp/mult_proj_between_nodes into 7c2d3cf on devel.

@jdcpni jdcpni merged commit 57f9f28 into devel Dec 18, 2021
@jdcpni jdcpni deleted the feat/comp/mult_proj_between_nodes branch December 18, 2021 15:12
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.

None yet

4 participants