Skip to content

Promotion devel to master#3598

Merged
kmantel merged 289 commits into
masterfrom
devel
Jul 17, 2026
Merged

Promotion devel to master#3598
kmantel merged 289 commits into
masterfrom
devel

Conversation

@jvesely

@jvesely jvesely commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

kmantel and others added 30 commits February 20, 2026 04:48
…init status (#3456)

some methods like _update_default_variable are called elsewhere after
initialization of the actual object, and this can cause state side-effects.

avoids incrementing some integrators, as in the duration_cost_fct for
OptimizationControlMechanism in test_modulation_simple or
test_control.py::TestControlSpecification::test_deferred_init

test results are modified; adding extra executions in the None context
prior to running the compositions reproduces the previous results:

test_deferred_init:
`comp.controller.state_input_ports[0].function.execute([1.1]`
`comp.controller.state_input_ports[1].function.execute([2.2]`

test_modulation_simple:
`comp.controller.control_signals[0].function.duration_cost_fct.execute([3]`

see #2721
intended to allow non-Component objects also maintain Parameters objects
used to retrieve projection objects by name
intended to allow throwing a consistent error in multiple places other
than just Parameter._validate
When a Parameter is tracking compiled struct storage, its current value may be
an ndarray view into LLVM param memory. Setting that param from a Python scalar
can fail the intended in-place update path and leave compiled memory stale.

Coerce scalar sources to np.asarray(...) only when:
- _tracking_compiled_struct is True, and
- target_value is an ndarray.

This preserves in-place mutation via update_array_in_place without changing
Python-only scalar behavior.

Fixes compiled-mode control-param updates (notably execute_until_finished),
which affected LCA step/time reporting in
tests/mechanisms/test_lca.py::TestLCA::test_LCAMechanism_standard_output_ports.
…Link into feat/lca/standard_output_ports_DEVEL_pec_fix
- In RecurrentTransferMechanism LLVM reset, stop zeroing `old_val`.
- After integrator reset, run the primary transfer function and update output ports
  from that result, so recurrent feedback state is seeded from reset outputs.
- This removes the LLVM/Python step-count divergence in
  `test_LCAMechanism_standard_output_ports` (LLVM now matches 56/.056).

tests: simplify LCA standard_output_ports mode handling

- Replace `return True` with `pytest.skip(...)` for unsupported execution modes.
- Collapse redundant `comp_mode` conditionals and duplicate expected-value branches.
- Update LLVM expected tuple to `(1, 56, .056)` to match aligned behavior.

chore: clean comment wrapping/whitespace in Parameter in-place update block
- single location/standardization of parsing and validation that does
not modify existing parameter values
- partial integration with Parameter classes (TBI: refactoring as a
sublcass of Parameter)
- projections: implement ProxyProjection
	- formal class for the 'virtual' projections that span a
	Composition and a nested Composition that each represent two
	projections: one from a node in one Composition to a CIM and one
	from that CIM to another node in the other Composition.
	- Simplifies storage of learning_rate/optimization parameters using
	SharedParameter

functional WIP with remaining tasks:
- generalize optimization parameters as subclass of Parameter, handling
more than learning_rate
- generalize optimization parameter dict spec to accept
Mechanism/Composition, not just Projection
#3466)

- single location/standardization of parsing and validation that does
not modify existing parameter values
- partial integration with Parameter classes (TBI: refactoring as a
sublcass of Parameter)
- projections: implement ProxyProjection
        - formal class for the 'virtual' projections that span a
        Composition and a nested Composition that each represent two
        projections: one from a node in one Composition to a CIM and one
        from that CIM to another node in the other Composition.
- Simplifies storage of learning_rate/optimization parameters using
        SharedParameter

functional WIP with remaining tasks:
- generalize optimization parameters as subclass of Parameter, handling
more than learning_rate
- generalize optimization parameter dict spec to accept
Mechanism/Composition, not just Projection
Updates the requirements on [pandas](https://github.com/pandas-dev/pandas) to permit the latest version.
- [Release notes](https://github.com/pandas-dev/pandas/releases)
- [Commits](pandas-dev/pandas@v3.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: pandas
  dependency-version: 3.0.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7 to 8.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v7...v8)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Updates the requirements on [protobuf](https://github.com/protocolbuffers/protobuf) to permit the latest version.
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Commits](https://github.com/protocolbuffers/protobuf/commits)

---
updated-dependencies:
- dependency-name: protobuf
  dependency-version: 7.34.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
davidt0x and others added 24 commits June 26, 2026 19:07
…y in a Mechanism (#3560)

## Summary

Fixes two related bugs affecting `FitzHughNagumoIntegrator` (and
multi-stateful integrators generally) when used inside a `Mechanism`.
Both surfaced from the reproducer below.

### Reproducer

```python
import psyneulink as pnl

inp = pnl.ProcessingMechanism(input_shapes=1)
lc = pnl.TransferMechanism(
    input_shapes=1,
    integrator_mode=True,
    integrator_function=pnl.FitzHughNagumoIntegrator(),
    function=pnl.Linear(),
    output_ports=[{pnl.VARIABLE: (pnl.OWNER_VALUE, 1)}],
    reset_stateful_function_when=pnl.AtTrialStart(),
)
comp = pnl.Composition()
comp.add_nodes([inp, lc])
comp.add_projection(sender=inp, receiver=lc)
comp.run(inputs={inp: [[1.0]]})   # IndexError in Python mode; worked in LLVMRun
```

## Bug 1 — `IndexError` on reset (`mechanism.py`)

On reset, the Mechanism rebuilt its value from the integrator's reset
output but kept only element `[0]`:

```python
new_input = self.integrator_function.reset(...)[0]
```

`StatefulFunction.reset()` returns one entry per stateful attribute. For
single-attribute integrators (`AdaptiveIntegrator` → `[previous_value]`)
the `[0]` correctly unwraps. For `FitzHughNagumoIntegrator` → `[v, w,
time]` it discarded `w` and `time`, leaving the value with a single
element, so an `OutputPort` selecting `(OWNER_VALUE, 1)` indexed past
the end → `IndexError`. Compiled mode was unaffected (statically-typed
value buffer; reset only rewrites the integrator state).

**Fix:** keep all stateful terms when there is more than one.

## Bug 2 — value-shape inconsistency between Python and compiled
(`integratorfunctions.py`)

Even after Bug 1, the mechanism's value shape differed between modes:
Python produced `(3, 1, 1)`, compiled `(3, 1)` (and `defaults.value` was
`(3, 1)`). FHN stacks its three stateful terms; in a Mechanism,
`variable` is the Mechanism's 2d variable `(1, 1)` while the stateful
values are 1d, so broadcasting during execution inflated each term to 2d
→ `(3, 1, 1)`. During initialization (which sizes `value`) the
un-broadcast 1d state is returned → `(3, 1)`. Compiled unwraps the same
leading dimension (`helpers.unwrap_2d_array`), so it stays `(3, 1)`.

**Fix:** conform `variable` to the rank of the stateful values at the
start of `_function` (drop the leading singleton input-port dimension),
so Python matches both the advertised default and compiled execution at
`(3, 1)`. Standalone use with a genuinely 2d variable (and 2d stateful
values) is unaffected. This required no compiled-codegen changes.

## Testing

- `test_reset_multi_stateful_integrator_with_owner_value_output_port`
runs across Python and all compiled modes, asserts the value shape is
`(3, 1)`, and asserts a shared value reference (tolerance covers fp32
compiled CI).
- `test_FitzHughNagumo_simple_scalar` previously added a dimension to
the Python expected result to work around the shape mismatch; that
workaround is removed (Python now matches compiled).
- `test_FitzHughNagumo_valid` and the gilzenrat figure-2 test were
updated from the inflated `(3, 1, 1)` indexing to `(3, 1)` (values
unchanged).
- Full FHN / transfer / integrator / processing / LCA / mdf suites pass
in Python and compiled.

## Notes

- `OrnsteinUhlenbeckIntegrator` has a similar shape inconsistency (plus
extra quirks and no existing compiled coverage). It is intentionally
left out of this PR and tracked separately.
- The construction-dependent FHN shape (`(3,1,1)` when the class, rather
than an instance, is passed) is a separate pre-existing issue (the
existing `xfail`) and is untouched here.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Updates the requirements on [scipy](https://github.com/scipy/scipy) to permit the latest version.
- [Release notes](https://github.com/scipy/scipy/releases)
- [Commits](scipy/scipy@v1.17.0...v1.18.0)

---
updated-dependencies:
- dependency-name: scipy
  dependency-version: 1.18.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu>
Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu>
Ignore generated files.
Ignore rules that do not currently pass.

Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu>
Ignore line length check.

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

Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu>
Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu>
Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu>
Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu>
No longer supported (pytest-pydocstyle repository is archived).
Use Ruff D* checks instead.

Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu>
Runs monthly or on dispatch.

The dispatch ref will be used. If it is left on its default value
(master), it will be set to devel.
pytest-pydocstyle is archived and no longer maintained.
Fixes: 536883e ("Remove pydocstyle")

Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu>
Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](pytest-dev/pytest@9.0.0...9.1.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-version: 9.1.1
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Updates the requirements on [pillow](https://github.com/python-pillow/Pillow) to permit the latest version.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](python-pillow/Pillow@12.2.0...12.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-version: 12.3.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Updates the requirements on [llvmlite](https://github.com/numba/llvmlite) to permit the latest version.
- [Release notes](https://github.com/numba/llvmlite/releases)
- [Commits](numba/llvmlite@v0.47.0...v0.48.0)

---
updated-dependencies:
- dependency-name: llvmlite
  dependency-version: 0.48.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
UserDefinedFunction is allowed in the check following the crash
Updates the requirements on [grpcio](https://github.com/grpc/grpc) to permit the latest version.
- [Release notes](https://github.com/grpc/grpc/releases)
- [Commits](grpc/grpc@v1.81.0...v1.82.1)

---
updated-dependencies:
- dependency-name: grpcio
  dependency-version: 1.82.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…3.0,<2.14.0 (#3597)

Updates the requirements on [pytorch](https://github.com/pytorch/pytorch) to permit the latest version.
- [Release notes](https://github.com/pytorch/pytorch/releases/tag/v2.13.1)
- [Commits](pytorch/pytorch@v2.12.0...v2.13.1)

Signed-off-by: Jan Vesely <jan.vesely@rutgers.edu>
'concatenate_queries': False,
'enable_learning': True,
'softmax_temperature': 0.1,
'softmax_threshold': 1e-5,
IDENTITY_MATRIX, INPUT_PORT, MAPPING_PROJECTION, MATRIX, OUTPUT_PORT, VALUE)
from psyneulink.core.globals.log import ContextFlags
from psyneulink.core.globals.parameters import FunctionParameter, Parameter, check_user_specified, copy_parameter_value
from psyneulink.core.globals.parameters import FunctionParameter, Parameter, SharedParameter, check_user_specified, copy_parameter_value
# defer initialization until they are added
elif agent_rep.componentCategory=='Composition':
from psyneulink.core.compositions.composition import NodeRole
from psyneulink.core.compositions.noderoles import NodeRole
Comment on lines +1484 to +1496
# if isinstance(scale, numbers.Number):
# # scalar scale
# product = combination * scale
# else:
# # Hadamard scale
# product = np.prod([combination, scale], axis=0)
#
# if isinstance(offset, numbers.Number):
# # scalar offset
# result = product + offset
# else:
# # Hadamard offset
# result = np.sum([product, offset], axis=0)
Comment on lines +1377 to +1380
# elif loss == Loss.MSE:
# self.loss_function = Distance(metric=EUCLIDEAN, normalize=normalize)
# elif loss == Loss.CROSS_ENTROPY:
# self.loss_function = Distance(metric=CROSS_ENTROPY, normalize=normalize)
# to prevent immediate NaN propagation due to zero inputs.
GRU_INITIAL_STATE = np.random.uniform(low=-0.01, high=0.01, size=HIDDEN_DIMENSION)
try: gru_hidden_node.parameters.initial_value.set(GRU_INITIAL_STATE)
except Exception: pass
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import psyneulink as pnl
import numpy as np
import torch
import torch.nn as nn
@@ -0,0 +1,221 @@
import psyneulink as pnl
import numpy as np
import torch

assert 0 <= integration_rate <= 1, \
f"integrator_retrieval_weight must be a number from 0 to 1"
enable_learning = learning_rate > 0
@github-actions

Copy link
Copy Markdown

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

diff -r docs-base/AutoAssociativeLearningMechanism.html docs-head/AutoAssociativeLearningMechanism.html
368c368
< It’s <a class="reference internal" href="Functions.html#psyneulink.core.components.functions.function.Function_Base.variable" title="psyneulink.core.components.functions.function.Function_Base.variable"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">variable</span></code></a> must be a list or 1d np.array of numeric entries, corresponding in
---
> its <a class="reference internal" href="Functions.html#psyneulink.core.components.functions.function.Function_Base.variable" title="psyneulink.core.components.functions.function.Function_Base.variable"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">variable</span></code></a> must be a list or 1d np.array of numeric entries, corresponding in
diff -r docs-base/AutodiffComposition.html docs-head/AutodiffComposition.html
218c218
< <div><ul>
---
> <div><ul class="simple">
220,221d219
< <li><dl>
< <dt><a class="reference internal" href="#autodiffcomposition-creation"><span class="std std-ref">Creating an AutodiffComposition</span></a></dt><dd><ul class="simple">
223,226c221,232
< <dt><a class="reference internal" href="#"><span class="doc">AutodiffComposition</span></a></dt><dd><ul>
< <li><p><a class="reference internal" href="#autodiffcomposition-modulatory-mechanisms"><span class="std std-ref">No Modulatory Components</span></a></p></li>
< <li><p><a class="reference internal" href="#autodiffcomposition-bias-parameters"><span class="std std-ref">No Bias Parameters</span></a></p></li>
< <li><p><a class="reference internal" href="#autodiffcomposition-nesting"><span class="std std-ref">Nesting</span></a></p></li>
---
> <dt><a class="reference internal" href="#autodiffcomposition-creation"><span class="std std-ref">Creating an AutodiffComposition</span></a></dt><dd><ul>
> <li><p><a href="#id1"><span class="problematic" id="id2">`</span></a>AutodiffComposition_Configuring_Learning</p></li>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#autodiffcomposition-learning-pathways"><span class="std std-ref">Learning Pathways</span></a></dt><dd><ul>
> <li><p><a class="reference internal" href="#autodiffcomposition-sample"><span class="std std-ref">Sample</span></a></p></li>
> <li><p><a class="reference internal" href="#autodiffcomposition-target"><span class="std std-ref">Target</span></a></p></li>
> <li><p><a class="reference internal" href="#autodiffcomposition-lossmechanism"><span class="std std-ref">LossMechanism</span></a></p></li>
> <li><p><a class="reference internal" href="#autodiffcomposition-specifying-learning-pathways"><span class="std std-ref">Specifying sample-target pairs</span></a></p></li>
> </ul>
> </dd>
> </dl>
> </li>
229c235
< <li><p><a class="reference internal" href="#autodiffcomposition-post-construction-modification"><span class="std std-ref">No Post-construction Modification</span></a></p></li>
---
> <li><p><a class="reference internal" href="#autodiffcomposition-restrictions"><span class="std std-ref">AutodiffComposition Restrictions</span></a></p></li>
233a240,245
> <li><dl class="simple">
> <dt><a class="reference internal" href="#autodiffcomposition-structure"><span class="std std-ref">Structure</span></a></dt><dd><ul>
> <li><dl class="simple">
> <dt><a class="reference internal" href="#autodiffcomposition-learning-components"><span class="std std-ref">Learning Components</span></a></dt><dd><ul>
> <li><p><a class="reference internal" href="#autodiffcomposition-structure-lossmechanisms"><span class="std std-ref">Loss Mechanism</span></a></p></li>
> <li><p><a class="reference internal" href="#autodiffcomposition-structure-target-mechanism"><span class="std std-ref">TARGET_MECHANISM</span></a></p></li>
235c247,255
< <ul class="simple">
---
> </dd>
> </dl>
> </li>
> <li><p><a class="reference internal" href="#autodiffcomposition-pytorchrepresentation"><span class="std std-ref">Pytorch Representation</span></a></p></li>
> <li><p><a class="reference internal" href="#autodiffcomposition-nesting"><span class="std std-ref">Nesting</span></a></p></li>
> </ul>
> </dd>
> </dl>
> </li>
238,242c258,262
< <li><p><a class="reference internal" href="#autodiffcomposition-pytorch"><span class="std std-ref">PyTorch mode</span></a></p></li>
< <li><p><a class="reference internal" href="#autodiffcomposition-llvm"><span class="std std-ref">LLVM mode</span></a></p></li>
< <li><p><a class="reference internal" href="#autodiffcomposition-python"><span class="std std-ref">Python mode</span></a></p></li>
< <li><p><a class="reference internal" href="#autodiffcomposition-nested-modulation"><span class="std std-ref">Nested Execution and Modulation</span></a></p></li>
< <li><p><a class="reference internal" href="#autodiffcomposition-logging"><span class="std std-ref">Logging</span></a></p></li>
---
> <li><dl class="simple">
> <dt><a class="reference internal" href="#autodiffcomposition-pytorch"><span class="std std-ref">PyTorch mode</span></a></dt><dd><ul>
> <li><p><a class="reference internal" href="#autodiffcomposition-additional-optimization-steps"><span class="std std-ref">Additional Optimizations Steps</span></a></p></li>
> <li><p><a class="reference internal" href="#autodiffcomposition-synchronization-with-pytorch"><span class="std std-ref">Synchronization of PsyNeuLink Values with PyTorch</span></a></p></li>
> <li><p><a class="reference internal" href="#autodiffcomposition-save-pytorch-training-data"><span class="std std-ref">Saving Pytorch Training Data</span></a></p></li>
246a267,269
> <li><p><a class="reference internal" href="#autodiffcomposition-llvm"><span class="std std-ref">LLVM mode</span></a></p></li>
> <li><p><a class="reference internal" href="#autodiffcomposition-python"><span class="std std-ref">Python mode</span></a></p></li>
> <li><p><a class="reference internal" href="#autodiffcomposition-logging"><span class="std std-ref">Logging</span></a></p></li>
258,266c281,294
< <p>AutodiffComposition is a subclass of <a class="reference internal" href="Composition.html"><span class="doc">Composition</span></a> for constructing and training feedforward neural network
< either, using either direct compilation (to LLVM) or automatic conversion to <a class="reference external" href="https://pytorch.org/">PyTorch</a>,
< both of which considerably accelerate training (by as much as three orders of magnitude) compared to the
< <a class="reference internal" href="Composition.html#composition-learning-standard"><span class="std std-ref">standard implementation of learning</span></a> in a Composition.  Although an
< AutodiffComposition is constructed and executed in much the same way as a standard Composition, it largely restricted
< to feedforward neural networks using <a class="reference internal" href="Composition.html#composition-learning-supervised"><span class="std std-ref">supervised learning</span></a>, and in particular the
< the <a class="reference external" href="https://en.wikipedia.org/wiki/Backpropagation">backpropagation learning algorithm</a>. although it can be used for
< some forms of <a class="reference internal" href="Composition.html#composition-learning-unsupervised"><span class="std std-ref">unsupervised learning</span></a> that are supported in PyTorch (e.g.,
< <a class="reference external" href="https://github.com/giannisnik/som">self-organized maps</a>).</p>
---
> <p>AutodiffComposition is a subclass of <a class="reference internal" href="Composition.html"><span class="doc">Composition</span></a> for constructing and training neural networks using
> <a class="reference external" href="https://pytorch.org/">PyTorch</a> and, in some cases, direct compilation using <a class="reference internal" href="#autodiffcomposition-llvm"><span class="std std-ref">LLVM</span></a>.
> These can considerably accelerate training, by as much as three orders of magnitude compared to <a class="reference internal" href="Composition.html#composition-learning-standard"><span class="std std-ref">Python mode</span></a> used by a standard Composition. An AutodiffComposition is constructed and
> executed in the same way as a standard Composition, though it provides additional <a class="reference internal" href="Composition.html#composition-compilation-table"><span class="std std-ref">functionality</span></a>, including:</p>
> <blockquote id="autodiffcomposition-additional-functionality">
> <div><ul class="simple">
> <li><p>use of <a class="reference internal" href="#autodiffcomposition-target"><span class="std std-ref">internal target signals</span></a> for training;</p></li>
> <li><p>training of <a class="reference internal" href="#autodiffcomposition-nesting"><span class="std std-ref">nested Compositions</span></a>.</p></li>
> <li><p>training of recurrent neural networks (RNNs, e.g., <a class="reference internal" href="GRUComposition.html"><span class="doc">GRUComposition</span></a>);</p></li>
> <li><p>training of external (episodic) memory structures (e.g., <a class="reference internal" href="EMComposition.html"><span class="doc">EMComposition</span></a>);</p></li>
> </ul>
> </div></blockquote>
> <p>In addition to supporting <a class="reference internal" href="Composition.html#composition-learning-supervised"><span class="std std-ref">supervised learning</span></a> using the <a class="reference external" href="https://en.wikipedia.org/wiki/Backpropagation">backpropagation learning
> algorithm</a>, it also supports some forms of <a class="reference internal" href="Composition.html#composition-learning-unsupervised"><span class="std std-ref">unsupervised learning</span></a> that are possible in PyTorch (e.g., <a class="reference external" href="https://github.com/giannisnik/som">self-organized maps</a>).</p>
270,310c298,352
< <p>An AutodiffComposition can be created by calling its constructor, and then adding <a class="reference internal" href="Component.html"><span class="doc">Components</span></a> using
< the standard <a class="reference internal" href="Composition.html#composition-creation"><span class="std std-ref">Composition methods</span></a> for doing so (e.g., <a class="reference internal" href="Composition.html#psyneulink.core.compositions.composition.Composition.add_node" title="psyneulink.core.compositions.composition.Composition.add_node"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">add_node</span></code></a>,
< <a class="reference internal" href="Composition.html#psyneulink.core.compositions.composition.Composition.add_projections" title="psyneulink.core.compositions.composition.Composition.add_projections"><code class="xref any py py-meth docutils literal notranslate"><span class="pre">add_projection</span></code></a>,  <a class="reference internal" href="Composition.html#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>, etc.). The constructor also includes a number of parameters that are
< specific to the AutodiffComposition (see <a class="reference internal" href="#autodiffcomposition-class-reference"><span class="std std-ref">Class Reference</span></a> for a list of these parameters,
< and <a class="reference internal" href="#autodiffcomposition-examples"><span class="std std-ref">examples</span></a> below). While an AutodiffComposition can generally be created using the
< same methods as a standard Composition, there are a few restrictions that apply to its construction, summarized below.</p>
< <section id="only-one-outputport-per-node">
< <span id="autodiffcomposition-restrictions"></span><h3><em>Only one OutputPort per Node</em><a class="headerlink" href="#only-one-outputport-per-node" title="Link to this heading">¶</a></h3>
< <p>The <a class="reference internal" href="Composition.html#composition-nodes"><span class="std std-ref">Nodes</span></a> of an AutodiffComposition currently can have only <em>one</em> <a class="reference internal" href="OutputPort.html"><span class="doc">OutputPort</span></a>, though that
< can have more than one <a class="reference internal" href="Port.html#psyneulink.core.components.ports.port.Port_Base.efferents" title="psyneulink.core.components.ports.port.Port_Base.efferents"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">efferent</span></code></a> <a class="reference internal" href="MappingProjection.html"><span class="doc">MappingProjection</span></a>.  Nodes can also have more than one
< <a class="reference internal" href="InputPort.html"><span class="doc">InputPort</span></a>, that can receive more than one <a class="reference internal" href="Port.html#psyneulink.core.components.ports.port.Port_Base.path_afferents" title="psyneulink.core.components.ports.port.Port_Base.path_afferents"><code class="xref any py py-attr docutils literal notranslate"><span class="pre">afferent</span> <span class="pre">`path_afferent</span></code></a> Projections.</p>
< </section>
< <section id="no-modulatory-components">
< <span id="autodiffcomposition-modulatory-mechanisms"></span><h3><em>No Modulatory Components</em><a class="headerlink" href="#no-modulatory-components" title="Link to this heading">¶</a></h3>
< <p>All of the Components in an AutodiffComposition must be able to be subjected to <a class="reference internal" href="Composition.html#composition-learning"><span class="std std-ref">learning</span></a>,
< which means that no <a class="reference internal" href="ModulatoryMechanism.html"><span class="doc">ModulatoryMechanisms</span></a> can be included in an AutodiffComposition.
< Specifically, this precludes any <a class="reference internal" href="Composition.html#composition-learning-components"><span class="std std-ref">learning components</span></a>, <a class="reference internal" href="ControlMechanism.html"><span class="doc">ControlMechanisms</span></a>, or a <a class="reference internal" href="Composition.html#composition-controller"><span class="std std-ref">controller</span></a>.</p>
< <p id="autodiff-learning-components-warning"><em>Learning Components</em>.  An AutodiffComposition <strong>cannot include any</strong> <a class="reference internal" href="Composition.html#composition-learning-components"><span class="std std-ref">learning components</span></a> themselves (i.e., <a class="reference internal" href="LearningMechanism.html"><span class="doc">LearningMechanisms</span></a>, <a class="reference internal" href="LearningSignal.html"><span class="doc">LearningSignals</span></a>, or <a class="reference internal" href="LearningProjection.html"><span class="doc">LearningProjections</span></a>, nor the <a class="reference internal" href="ComparatorMechanism.html"><span class="doc">ComparatorMechanism</span></a>
< or <a class="reference internal" href="ObjectiveMechanism.html"><span class="doc">ObjectiveMechanism</span></a> used to compute the loss for learning). These are constructed
< automatically when learning is executed in <a class="reference internal" href="#autodiffcomposition-python"><span class="std std-ref">Python mode</span></a> or <a class="reference internal" href="#autodiffcomposition-llvm"><span class="std std-ref">LLVM mode</span></a>, and PyTorch-compatible Components are constructed when it is executed in
< <a class="reference internal" href="#autodiffcomposition-pytorch"><span class="std std-ref">PyTorch mode</span></a>.</p>
< <p><em>Control Components</em>. An AutodiffComposition also cannot include any <a class="reference internal" href="ControlMechanism.html"><span class="doc">ControlMechanisms</span></a> or a
< <a class="reference internal" href="Composition.html#composition-controller"><span class="std std-ref">controller</span></a>.  However, it <em>can</em> include Mechanisms that are subject to modulatory control
< (see <a class="reference internal" href="ModulatorySignal.html#modulatorysignal-anatomy-figure"><span class="std std-ref">Figure</span></a>, and <a class="reference internal" href="ModulatorySignal.html#modulatorysignal-modulation"><span class="std std-ref">modulation</span></a>) by ControlMechanisms
< <em>outside</em> the Composition,
...

See CI logs for the full diff.

@kmantel
kmantel self-requested a review July 17, 2026 07:02
@kmantel
kmantel merged commit 604a47e into master Jul 17, 2026
108 of 110 checks passed
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 83.925% (-0.7%) from 84.591% — devel into master

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.

8 participants