diff --git a/.github/workflows/ci_test_all.yml b/.github/workflows/ci_test_all.yml index 8fc523a3..42207142 100644 --- a/.github/workflows/ci_test_all.yml +++ b/.github/workflows/ci_test_all.yml @@ -37,6 +37,7 @@ jobs: - name: Run test script run: | + pip install torch==2.8.0 # pinned to avoid issues with latest version taking up too much space... export NEURON_HOME=$pythonLocation ./test_all.sh diff --git a/.gitignore b/.gitignore index d0a1ba4e..418556e3 100644 --- a/.gitignore +++ b/.gitignore @@ -274,6 +274,9 @@ Thumbs.db #thumbnail cache on Windows /examples/PyTorch/simple_pytorch_to_mdf.1 /examples/MDF/NLP/TestNLP_3 /examples/MDF/NLP/TestNLP +/examples/MDF/networks/Net_acyclical +/examples/MDF/net/Net_acyclical +/examples/MDF/net/weight.py /examples/MDF/conditions/composite_example /examples/NeuroML/arm64 /examples/MDF/RNN/iaf.net @@ -313,3 +316,4 @@ examples/TensorFlow/Keras/keras_to_MDF /checkoutpngs.sh /docs/sphinx/source/api/export_format/MDF/images/newton.png /docs/sphinx/source/api/export_format/MDF/images/newton_plot.png +/examples/MDF/networks/Net_acyclical diff --git a/.readthedocs.yml b/.readthedocs.yml index b925ccb1..c3c1c0d7 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,21 +1,24 @@ -# .readthedocs.yml -# Read the Docs configuration file -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - -# Required version: 2 -# Build documentation in the docs/ directory with Sphinx sphinx: - configuration: docs/sphinx/source/conf.py + configuration: docs/sphinx/source/conf.py + +build: + os: ubuntu-24.04 + tools: + python: "3.13" + jobs: + pre_create_environment: + - asdf plugin add uv + - asdf install uv latest + - asdf global uv latest + create_environment: + - uv venv "${READTHEDOCS_VIRTUALENV_PATH}" + install: + - UV_PROJECT_ENVIRONMENT="${READTHEDOCS_VIRTUALENV_PATH}" uv sync --group docs -# Just generate htmlzip version, as pdf failing due to inclusion of svg files (in badges) formats: - htmlzip -python: - install: - - requirements: docs/sphinx/requirements.txt - submodules: exclude: all diff --git a/docs/MDF_specification.json b/docs/MDF_specification.json index 4f43de9b..0d15fd8d 100644 --- a/docs/MDF_specification.json +++ b/docs/MDF_specification.json @@ -106,6 +106,10 @@ "type": "str", "description": "The unique (for this Node) id of the input port," }, + "default_value": { + "type": "Union", + "description": "Value to set at this input port if no edge connected to it." + }, "shape": { "type": "Optional", "description": "The shape of the input port. This uses the same syntax as numpy ndarray shapes\n(e.g., :code:`numpy.zeros(shape)` would produce an array with the correct shape" @@ -113,6 +117,10 @@ "type": { "type": "Optional", "description": "The data type of the input received at a port." + }, + "reduce": { + "type": "Optional", + "description": "Specifies how to deal with multiple inputs to one port during a single timestep: add: add up all the values; multiply: multiply the values, overwrite: just use the last value supplied (default)" } } }, diff --git a/docs/MDF_specification.yaml b/docs/MDF_specification.yaml index f6ff63ab..26c580f4 100644 --- a/docs/MDF_specification.yaml +++ b/docs/MDF_specification.yaml @@ -91,6 +91,10 @@ specification: id: type: str description: The unique (for this Node) id of the input port, + default_value: + type: Union + description: Value to set at this input port if no edge connected + to it. shape: type: Optional description: 'The shape of the input port. This uses the same syntax @@ -101,6 +105,12 @@ specification: type: type: Optional description: The data type of the input received at a port. + reduce: + type: Optional + description: 'Specifies how to deal with multiple inputs to one port + during a single timestep: add: add up all the values; multiply: + multiply the values, overwrite: just use the last value supplied + (default)' Function: definition: A single value which is evaluated as a function of values on :class:`InputPort`(s) and other Functions diff --git a/docs/README.md b/docs/README.md index e0e2b208..185942c9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -179,6 +179,13 @@ The InputPort is an attribute of a Node which allows ex + + default_value + Union + Value to set at this input port if no edge connected to it. + + + shape Optional @@ -194,6 +201,13 @@ The InputPort is an attribute of a Node which allows ex + + reduce + Optional + Specifies how to deal with multiple inputs to one port during a single timestep: add: add up all the values; multiply: multiply the values, overwrite: just use the last value supplied (default) + + + ## Function diff --git a/docs/sphinx/requirements.txt b/docs/sphinx/requirements.txt deleted file mode 100644 index 759ed661..00000000 --- a/docs/sphinx/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -# Install all the dependencies ---group=docs diff --git a/docs/sphinx/source/api/Specification.rst b/docs/sphinx/source/api/Specification.rst index 886b17b0..0b56de98 100644 --- a/docs/sphinx/source/api/Specification.rst +++ b/docs/sphinx/source/api/Specification.rst @@ -87,15 +87,17 @@ The `InputPort <#inputport>`__ is an attribute of a Node which allows external i **Allowed parameters** -=============== =========== ============================================================================================= -Allowed field Data Type Description -=============== =========== ============================================================================================= -**metadata** Optional Optional metadata field, an arbitrary dictionary of string keys and JSON serializable values. -**id** str The unique (for this Node) id of the input port, -**shape** Optional The shape of the input port. This uses the same syntax as numpy ndarray shapes - (e.g., **numpy.zeros(shape)** would produce an array with the correct shape -**type** Optional The data type of the input received at a port. -=============== =========== ============================================================================================= +================= =========== ================================================================================================================================================================================================= +Allowed field Data Type Description +================= =========== ================================================================================================================================================================================================= +**metadata** Optional Optional metadata field, an arbitrary dictionary of string keys and JSON serializable values. +**id** str The unique (for this Node) id of the input port, +**default_value** Union Value to set at this input port if no edge connected to it. +**shape** Optional The shape of the input port. This uses the same syntax as numpy ndarray shapes + (e.g., **numpy.zeros(shape)** would produce an array with the correct shape +**type** Optional The data type of the input received at a port. +**reduce** Optional Specifies how to deal with multiple inputs to one port during a single timestep: add: add up all the values; multiply: multiply the values, overwrite: just use the last value supplied (default) +================= =========== ================================================================================================================================================================================================= ======== Function diff --git a/docs/sphinx/source/api/export_format/MDF/images/switched_rlc_plot.png b/docs/sphinx/source/api/export_format/MDF/images/switched_rlc_plot.png index 6627147d..2ce125ab 100644 Binary files a/docs/sphinx/source/api/export_format/MDF/images/switched_rlc_plot.png and b/docs/sphinx/source/api/export_format/MDF/images/switched_rlc_plot.png differ diff --git a/docs/sphinx/source/api/export_format/NeuroML/Izh.png b/docs/sphinx/source/api/export_format/NeuroML/Izh.png index 0ee1a7b9..077a4381 100644 Binary files a/docs/sphinx/source/api/export_format/NeuroML/Izh.png and b/docs/sphinx/source/api/export_format/NeuroML/Izh.png differ diff --git a/docs/sphinx/source/api/export_format/NeuroML/Izh_run.png b/docs/sphinx/source/api/export_format/NeuroML/Izh_run.png index 51949a3e..c467f278 100644 Binary files a/docs/sphinx/source/api/export_format/NeuroML/Izh_run.png and b/docs/sphinx/source/api/export_format/NeuroML/Izh_run.png differ diff --git a/docs/sphinx/source/api/export_format/NeuroML/IzhikevichTest.gv.png b/docs/sphinx/source/api/export_format/NeuroML/IzhikevichTest.gv.png index 120eef86..9334cdb1 100644 Binary files a/docs/sphinx/source/api/export_format/NeuroML/IzhikevichTest.gv.png and b/docs/sphinx/source/api/export_format/NeuroML/IzhikevichTest.gv.png differ diff --git a/docs/sphinx/source/api/export_format/NeuroML/MDFFNrun.multi.png b/docs/sphinx/source/api/export_format/NeuroML/MDFFNrun.multi.png index 795174ec..11a29768 100644 Binary files a/docs/sphinx/source/api/export_format/NeuroML/MDFFNrun.multi.png and b/docs/sphinx/source/api/export_format/NeuroML/MDFFNrun.multi.png differ diff --git a/docs/sphinx/source/api/export_format/NeuroML/MDFFNrun.png b/docs/sphinx/source/api/export_format/NeuroML/MDFFNrun.png index faf75a54..e06598d3 100644 Binary files a/docs/sphinx/source/api/export_format/NeuroML/MDFFNrun.png and b/docs/sphinx/source/api/export_format/NeuroML/MDFFNrun.png differ diff --git a/docs/sphinx/source/api/export_format/ONNX/abc.png b/docs/sphinx/source/api/export_format/ONNX/abc.png index e6cdc653..22c62cf2 100644 Binary files a/docs/sphinx/source/api/export_format/ONNX/abc.png and b/docs/sphinx/source/api/export_format/ONNX/abc.png differ diff --git a/examples/ACT-R/addition.json b/examples/ACT-R/addition.json index 87b31836..a288ed43 100644 --- a/examples/ACT-R/addition.json +++ b/examples/ACT-R/addition.json @@ -1,7 +1,7 @@ { "addition": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "addition_graph": { "nodes": { diff --git a/examples/ACT-R/addition.yaml b/examples/ACT-R/addition.yaml index d3edb9ac..7e6df724 100644 --- a/examples/ACT-R/addition.yaml +++ b/examples/ACT-R/addition.yaml @@ -1,6 +1,6 @@ addition: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: addition_graph: nodes: diff --git a/examples/ACT-R/count.json b/examples/ACT-R/count.json index f344afdf..1f11da00 100644 --- a/examples/ACT-R/count.json +++ b/examples/ACT-R/count.json @@ -1,7 +1,7 @@ { "count": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "count_graph": { "nodes": { diff --git a/examples/ACT-R/count.yaml b/examples/ACT-R/count.yaml index 2dfc1c17..8123bf7f 100644 --- a/examples/ACT-R/count.yaml +++ b/examples/ACT-R/count.yaml @@ -1,6 +1,6 @@ count: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: count_graph: nodes: diff --git a/examples/MDF/ABCD.json b/examples/MDF/ABCD.json index 9088b9cd..0d24f9da 100644 --- a/examples/MDF/ABCD.json +++ b/examples/MDF/ABCD.json @@ -1,7 +1,7 @@ { "ABCD": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "abcd_example": { "nodes": { diff --git a/examples/MDF/ABCD.yaml b/examples/MDF/ABCD.yaml index 751db848..b6733a88 100644 --- a/examples/MDF/ABCD.yaml +++ b/examples/MDF/ABCD.yaml @@ -1,6 +1,6 @@ ABCD: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: abcd_example: nodes: diff --git a/examples/MDF/Arrays.json b/examples/MDF/Arrays.json index 59550427..03477a69 100644 --- a/examples/MDF/Arrays.json +++ b/examples/MDF/Arrays.json @@ -1,7 +1,7 @@ { "Arrays": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "array_example": { "nodes": { diff --git a/examples/MDF/Arrays.yaml b/examples/MDF/Arrays.yaml index 1baf853f..ea200728 100644 --- a/examples/MDF/Arrays.yaml +++ b/examples/MDF/Arrays.yaml @@ -1,6 +1,6 @@ Arrays: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: array_example: nodes: diff --git a/examples/MDF/NewtonCoolingModel.json b/examples/MDF/NewtonCoolingModel.json index f90876f0..97b0b2b3 100644 --- a/examples/MDF/NewtonCoolingModel.json +++ b/examples/MDF/NewtonCoolingModel.json @@ -1,7 +1,7 @@ { "NewtonCoolingModel": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "cooling_process": { "nodes": { diff --git a/examples/MDF/NewtonCoolingModel.yaml b/examples/MDF/NewtonCoolingModel.yaml index fac3caf1..d1a29edc 100644 --- a/examples/MDF/NewtonCoolingModel.yaml +++ b/examples/MDF/NewtonCoolingModel.yaml @@ -1,6 +1,6 @@ NewtonCoolingModel: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: cooling_process: nodes: diff --git a/examples/MDF/ParametersFunctions.json b/examples/MDF/ParametersFunctions.json index 95e010b4..286b883d 100644 --- a/examples/MDF/ParametersFunctions.json +++ b/examples/MDF/ParametersFunctions.json @@ -1,7 +1,7 @@ { "ParametersFunctions": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "params_funcs_example": { "nodes": { diff --git a/examples/MDF/ParametersFunctions.yaml b/examples/MDF/ParametersFunctions.yaml index 7460bb1f..215418d6 100644 --- a/examples/MDF/ParametersFunctions.yaml +++ b/examples/MDF/ParametersFunctions.yaml @@ -1,6 +1,6 @@ ParametersFunctions: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: params_funcs_example: nodes: diff --git a/examples/MDF/RNN/IAF_net.json b/examples/MDF/RNN/IAF_net.json index 5a93fedb..23a2f1b6 100644 --- a/examples/MDF/RNN/IAF_net.json +++ b/examples/MDF/RNN/IAF_net.json @@ -1,7 +1,7 @@ { "IAF_net": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "iaf_example": { "nodes": { @@ -56,7 +56,8 @@ "current_input": { "shape": [ 8 - ] + ], + "reduce": "add" } }, "parameters": { @@ -140,7 +141,8 @@ "current_input": { "shape": [ 8 - ] + ], + "reduce": "add" } }, "parameters": { @@ -224,7 +226,8 @@ "spike_input": { "shape": [ 8 - ] + ], + "reduce": "add" } }, "parameters": { diff --git a/examples/MDF/RNN/IAF_net.yaml b/examples/MDF/RNN/IAF_net.yaml index 4efe41fc..0185b8cc 100644 --- a/examples/MDF/RNN/IAF_net.yaml +++ b/examples/MDF/RNN/IAF_net.yaml @@ -1,6 +1,6 @@ IAF_net: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: iaf_example: nodes: @@ -40,6 +40,7 @@ IAF_net: current_input: shape: - 8 + reduce: add parameters: v0: value: @@ -99,6 +100,7 @@ IAF_net: current_input: shape: - 8 + reduce: add parameters: v0: value: @@ -158,6 +160,7 @@ IAF_net: spike_input: shape: - 8 + reduce: add parameters: syn_tau: value: 10 diff --git a/examples/MDF/RNN/IAF_net2.json b/examples/MDF/RNN/IAF_net2.json index f702d3d6..44e13307 100644 --- a/examples/MDF/RNN/IAF_net2.json +++ b/examples/MDF/RNN/IAF_net2.json @@ -1,7 +1,7 @@ { "IAF_net2": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "iaf_example": { "nodes": { @@ -65,7 +65,8 @@ "current_input": { "shape": [ 8 - ] + ], + "reduce": "add" } }, "parameters": { @@ -149,7 +150,8 @@ "current_input": { "shape": [ 8 - ] + ], + "reduce": "add" } }, "parameters": { @@ -233,7 +235,8 @@ "spike_input": { "shape": [ 8 - ] + ], + "reduce": "add" } }, "parameters": { diff --git a/examples/MDF/RNN/IAF_net2.yaml b/examples/MDF/RNN/IAF_net2.yaml index deca79c3..44351dbe 100644 --- a/examples/MDF/RNN/IAF_net2.yaml +++ b/examples/MDF/RNN/IAF_net2.yaml @@ -1,6 +1,6 @@ IAF_net2: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: iaf_example: nodes: @@ -48,6 +48,7 @@ IAF_net2: current_input: shape: - 8 + reduce: add parameters: v0: value: @@ -107,6 +108,7 @@ IAF_net2: current_input: shape: - 8 + reduce: add parameters: v0: value: @@ -166,6 +168,7 @@ IAF_net2: spike_input: shape: - 8 + reduce: add parameters: syn_tau: value: 10 diff --git a/examples/MDF/RNN/IAF_net3.json b/examples/MDF/RNN/IAF_net3.json new file mode 100644 index 00000000..092c9f99 --- /dev/null +++ b/examples/MDF/RNN/IAF_net3.json @@ -0,0 +1,283 @@ +{ + "IAF_net3": { + "format": "ModECI MDF v0.4", + "generating_application": "Python modeci-mdf v0.4.14", + "graphs": { + "iaf_example": { + "nodes": { + "current_input_node": { + "parameters": { + "time": { + "default_initial_value": 0, + "time_derivative": "1" + }, + "start": { + "value": 20 + }, + "duration": { + "value": 10 + }, + "amplitude": { + "value": 10 + }, + "level": { + "value": 0, + "conditions": [ + { + "id": "on", + "test": "time > start", + "value": "amplitude" + }, + { + "id": "off", + "test": "time > start + duration", + "value": "amplitude*0" + } + ] + } + }, + "output_ports": { + "current_output": { + "value": "level" + } + } + }, + "current_input_node2": { + "parameters": { + "time": { + "default_initial_value": 0, + "time_derivative": "1" + }, + "start": { + "value": 60 + }, + "duration": { + "value": 10 + }, + "amplitude": { + "value": 3 + }, + "level": { + "value": 0, + "conditions": [ + { + "id": "on", + "test": "time > start", + "value": "amplitude" + }, + { + "id": "off", + "test": "time > start + duration", + "value": "amplitude*0" + } + ] + } + }, + "output_ports": { + "current_output": { + "value": "level" + } + } + }, + "pre": { + "input_ports": { + "current_input": { + "shape": [ + 1 + ], + "reduce": "add" + } + }, + "parameters": { + "v0": { + "value": [ + -60 + ] + }, + "erev": { + "value": [ + -70 + ] + }, + "tau": { + "value": 10.0 + }, + "thresh": { + "value": [ + -20 + ] + }, + "spiking": { + "default_initial_value": "0", + "conditions": [ + { + "id": "is_spiking", + "test": "v >= thresh", + "value": "1" + }, + { + "id": "not_spiking", + "test": "v < thresh", + "value": "0" + } + ] + }, + "v": { + "default_initial_value": "v0", + "time_derivative": "-1 * (v-erev)/tau + current_input", + "conditions": [ + { + "id": "reset", + "test": "v > thresh", + "value": "erev" + } + ] + } + }, + "output_ports": { + "v_output": { + "value": "v" + }, + "spiking_output": { + "value": "spiking" + } + } + }, + "post": { + "input_ports": { + "current_input": { + "shape": [ + 1 + ], + "reduce": "add" + } + }, + "parameters": { + "v0": { + "value": [ + -60 + ] + }, + "erev": { + "value": [ + -70 + ] + }, + "tau": { + "value": 10.0 + }, + "thresh": { + "value": [ + -20 + ] + }, + "spiking": { + "default_initial_value": "0", + "conditions": [ + { + "id": "is_spiking", + "test": "v >= thresh", + "value": "1" + }, + { + "id": "not_spiking", + "test": "v < thresh", + "value": "0" + } + ] + }, + "v": { + "default_initial_value": "v0", + "time_derivative": "-1 * (v-erev)/tau + current_input", + "conditions": [ + { + "id": "reset", + "test": "v > thresh", + "value": "erev" + } + ] + } + }, + "output_ports": { + "v_output": { + "value": "v" + }, + "spiking_output": { + "value": "spiking" + } + } + }, + "syn_post": { + "input_ports": { + "spike_input": { + "shape": [ + 1 + ], + "reduce": "add" + } + }, + "parameters": { + "syn_tau": { + "value": 10 + }, + "spike_weights": { + "value": [ + 40 + ] + }, + "weighted_spike": { + "function": "MatMul", + "args": { + "A": "spike_weights", + "B": "spike_input" + } + }, + "syn_i": { + "default_initial_value": "0", + "time_derivative": "-1 * syn_i", + "conditions": [ + { + "id": "spike_detected", + "test": "spike_input > 0", + "value": "weighted_spike" + } + ] + } + }, + "output_ports": { + "current_output": { + "value": "syn_i" + } + } + } + }, + "edges": { + "input_edge": { + "sender": "current_input_node", + "receiver": "pre", + "sender_port": "current_output", + "receiver_port": "current_input" + }, + "input_edge2": { + "sender": "current_input_node2", + "receiver": "pre", + "sender_port": "current_output", + "receiver_port": "current_input" + }, + "post_internal_edge": { + "sender": "syn_post", + "receiver": "post", + "sender_port": "current_output", + "receiver_port": "current_input" + }, + "syn_edge": { + "sender": "pre", + "receiver": "syn_post", + "sender_port": "spiking_output", + "receiver_port": "spike_input" + } + } + } + } + } +} diff --git a/examples/MDF/RNN/IAF_net3.yaml b/examples/MDF/RNN/IAF_net3.yaml new file mode 100644 index 00000000..0d054295 --- /dev/null +++ b/examples/MDF/RNN/IAF_net3.yaml @@ -0,0 +1,178 @@ +IAF_net3: + format: ModECI MDF v0.4 + generating_application: Python modeci-mdf v0.4.14 + graphs: + iaf_example: + nodes: + current_input_node: + parameters: + time: + default_initial_value: 0 + time_derivative: '1' + start: + value: 20 + duration: + value: 10 + amplitude: + value: 10 + level: + value: 0 + conditions: + - id: 'on' + test: time > start + value: amplitude + - id: 'off' + test: time > start + duration + value: amplitude*0 + output_ports: + current_output: + value: level + current_input_node2: + parameters: + time: + default_initial_value: 0 + time_derivative: '1' + start: + value: 60 + duration: + value: 10 + amplitude: + value: 3 + level: + value: 0 + conditions: + - id: 'on' + test: time > start + value: amplitude + - id: 'off' + test: time > start + duration + value: amplitude*0 + output_ports: + current_output: + value: level + pre: + input_ports: + current_input: + shape: + - 1 + reduce: add + parameters: + v0: + value: + - -60 + erev: + value: + - -70 + tau: + value: 10.0 + thresh: + value: + - -20 + spiking: + default_initial_value: '0' + conditions: + - id: is_spiking + test: v >= thresh + value: '1' + - id: not_spiking + test: v < thresh + value: '0' + v: + default_initial_value: v0 + time_derivative: -1 * (v-erev)/tau + current_input + conditions: + - id: reset + test: v > thresh + value: erev + output_ports: + v_output: + value: v + spiking_output: + value: spiking + post: + input_ports: + current_input: + shape: + - 1 + reduce: add + parameters: + v0: + value: + - -60 + erev: + value: + - -70 + tau: + value: 10.0 + thresh: + value: + - -20 + spiking: + default_initial_value: '0' + conditions: + - id: is_spiking + test: v >= thresh + value: '1' + - id: not_spiking + test: v < thresh + value: '0' + v: + default_initial_value: v0 + time_derivative: -1 * (v-erev)/tau + current_input + conditions: + - id: reset + test: v > thresh + value: erev + output_ports: + v_output: + value: v + spiking_output: + value: spiking + syn_post: + input_ports: + spike_input: + shape: + - 1 + reduce: add + parameters: + syn_tau: + value: 10 + spike_weights: + value: + - 40 + weighted_spike: + function: MatMul + args: + A: spike_weights + B: spike_input + syn_i: + default_initial_value: '0' + time_derivative: -1 * syn_i + conditions: + - id: spike_detected + test: spike_input > 0 + value: weighted_spike + output_ports: + current_output: + value: syn_i + edges: + input_edge: + sender: current_input_node + receiver: pre + sender_port: current_output + receiver_port: current_input + input_edge2: + sender: current_input_node2 + receiver: pre + sender_port: current_output + receiver_port: current_input + post_internal_edge: + sender: syn_post + receiver: post + sender_port: current_output + receiver_port: current_input + syn_edge: + sender: pre + receiver: syn_post + sender_port: spiking_output + receiver_port: spike_input diff --git a/examples/MDF/RNN/IAFs.json b/examples/MDF/RNN/IAFs.json index 5b359bdb..4a02d147 100644 --- a/examples/MDF/RNN/IAFs.json +++ b/examples/MDF/RNN/IAFs.json @@ -1,7 +1,7 @@ { "IAFs": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "iaf_example": { "nodes": { @@ -47,7 +47,8 @@ "current_input": { "shape": [ 1 - ] + ], + "reduce": "add" } }, "parameters": { @@ -110,7 +111,8 @@ "current_input": { "shape": [ 1 - ] + ], + "reduce": "add" } }, "parameters": { @@ -173,7 +175,8 @@ "spike_input": { "shape": [ 1 - ] + ], + "reduce": "add" } }, "parameters": { diff --git a/examples/MDF/RNN/IAFs.yaml b/examples/MDF/RNN/IAFs.yaml index 0e5492da..b114a055 100644 --- a/examples/MDF/RNN/IAFs.yaml +++ b/examples/MDF/RNN/IAFs.yaml @@ -1,6 +1,6 @@ IAFs: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: iaf_example: nodes: @@ -32,6 +32,7 @@ IAFs: current_input: shape: - 1 + reduce: add parameters: v0: value: @@ -70,6 +71,7 @@ IAFs: current_input: shape: - 1 + reduce: add parameters: v0: value: @@ -108,6 +110,7 @@ IAFs: spike_input: shape: - 1 + reduce: add parameters: syn_tau: value: 10 diff --git a/examples/MDF/RNN/IaF.net.run.png b/examples/MDF/RNN/IaF.net.run.png index 83f01547..d72ab2fb 100644 Binary files a/examples/MDF/RNN/IaF.net.run.png and b/examples/MDF/RNN/IaF.net.run.png differ diff --git a/examples/MDF/RNN/IaF.net2.run.png b/examples/MDF/RNN/IaF.net2.run.png index 9f805f66..e9c76d49 100644 Binary files a/examples/MDF/RNN/IaF.net2.run.png and b/examples/MDF/RNN/IaF.net2.run.png differ diff --git a/examples/MDF/RNN/IaF.net3.run.png b/examples/MDF/RNN/IaF.net3.run.png new file mode 100644 index 00000000..ef8c5b78 Binary files /dev/null and b/examples/MDF/RNN/IaF.net3.run.png differ diff --git a/examples/MDF/RNN/IaF.run.png b/examples/MDF/RNN/IaF.run.png index 2fa20289..5a197a6f 100644 Binary files a/examples/MDF/RNN/IaF.run.png and b/examples/MDF/RNN/IaF.run.png differ diff --git a/examples/MDF/RNN/RNN.run.png b/examples/MDF/RNN/RNN.run.png index 038d00fa..63393c32 100644 Binary files a/examples/MDF/RNN/RNN.run.png and b/examples/MDF/RNN/RNN.run.png differ diff --git a/examples/MDF/RNN/RNNs.json b/examples/MDF/RNN/RNNs.json index f68d5b30..608f55b1 100644 --- a/examples/MDF/RNN/RNNs.json +++ b/examples/MDF/RNN/RNNs.json @@ -1,7 +1,7 @@ { "RNNs": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "rnn_example": { "nodes": { @@ -46,6 +46,7 @@ ] }, "fb_input": { + "default_value": 0, "shape": [ 5 ] @@ -102,7 +103,7 @@ 0.10262953816578246, 0.43893793957112615 ], - "time_derivative": "-x + g*int_fb + ext_input" + "time_derivative": "-x + g*int_fb + ext_input + fb_input" }, "r": { "function": "tanh", @@ -185,6 +186,15 @@ "parameters": { "weight": 1 } + }, + "feedback_edge": { + "sender": "readout_node", + "receiver": "rnn_node", + "sender_port": "z", + "receiver_port": "fb_input", + "parameters": { + "weight": 0.3 + } } } } diff --git a/examples/MDF/RNN/RNNs.yaml b/examples/MDF/RNN/RNNs.yaml index e1a0bfbe..04076c79 100644 --- a/examples/MDF/RNN/RNNs.yaml +++ b/examples/MDF/RNN/RNNs.yaml @@ -1,6 +1,6 @@ RNNs: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: rnn_example: nodes: @@ -31,6 +31,7 @@ RNNs: shape: - 5 fb_input: + default_value: 0 shape: - 5 parameters: @@ -70,7 +71,7 @@ RNNs: - -0.5462970928715938 - 0.10262953816578246 - 0.43893793957112615 - time_derivative: -x + g*int_fb + ext_input + time_derivative: -x + g*int_fb + ext_input + fb_input r: function: tanh args: @@ -127,3 +128,10 @@ RNNs: receiver_port: input parameters: weight: 1 + feedback_edge: + sender: readout_node + receiver: rnn_node + sender_port: z + receiver_port: fb_input + parameters: + weight: 0.3 diff --git a/examples/MDF/RNN/generate_iaf.py b/examples/MDF/RNN/generate_iaf.py index a333dffa..1eed843c 100644 --- a/examples/MDF/RNN/generate_iaf.py +++ b/examples/MDF/RNN/generate_iaf.py @@ -58,7 +58,7 @@ def create_iaf_syn_node( syn_tau = Parameter(id="syn_tau", value=syn_tau) syn_node.parameters.append(syn_tau) - ip_spike = InputPort(id="spike_input", shape="(%i,)" % num_cells) + ip_spike = InputPort(id="spike_input", shape="(%i,)" % num_cells, reduce="add") syn_node.input_ports.append(ip_spike) spike_weights = Parameter(id="spike_weights", value=numpy.identity(num_cells)) @@ -91,7 +91,7 @@ def create_iaf_syn_node( ## IAF node... iaf_node = Node(id) - ip_current = InputPort(id="current_input", shape="(%i,)" % num_cells) + ip_current = InputPort(id="current_input", shape="(%i,)" % num_cells, reduce="add") iaf_node.input_ports.append(ip_current) v0 = Parameter( @@ -293,7 +293,8 @@ def main(): recorded = {} times = [] t = [] - i = [] + input1 = [] + input2 = [] s1 = [] sp1 = [] s2 = [] @@ -313,9 +314,15 @@ def main(): % eg.enodes["post"].evaluable_outputs["v_output"].curr_value ) - i.append( + input1.append( eg.enodes[input_node.id].evaluable_outputs["current_output"].curr_value ) + if net3: + input2.append( + eg.enodes[input_node2.id] + .evaluable_outputs["current_output"] + .curr_value + ) t.append(eg.enodes[input_node.id].evaluable_parameters["time"].curr_value) s1.append(eg.enodes["pre"].evaluable_outputs["v_output"].curr_value) sp1.append(eg.enodes["pre"].evaluable_parameters["spiking"].curr_value) @@ -331,16 +338,18 @@ def main(): markersize = 2 if num_cells < 20 else 0.5 - if type(i[0]) == numpy.ndarray and i[0].size > 1: - for ii in range(len(i[0])): + if type(input1[0]) == numpy.ndarray and input1[0].size > 1: + for ii in range(len(input1[0])): iii = [] for ti in range(len(t)): - iii.append(i[ti][ii]) + iii.append(input1[ti][ii]) axis[0].plot( times, iii, label="Input node %s current" % ii, linewidth="0.5" ) else: - axis[0].plot(times, i, label="Input node current", color="k") + axis[0].plot(times, input1, label="Input node current", color="k") + if net3: + axis[0].plot(times, input2, label="Input node current 2", color="g") if not some_net: axis[0].legend() @@ -443,7 +452,7 @@ def main(): engine="dot", output_format="png", view_on_render=False, - level=2, + level=1 if net3 else 2, filename_root="iaf%s" % ( ".net" diff --git a/examples/MDF/RNN/generate_rnn.py b/examples/MDF/RNN/generate_rnn.py index 05b92cb3..79a14886 100644 --- a/examples/MDF/RNN/generate_rnn.py +++ b/examples/MDF/RNN/generate_rnn.py @@ -87,16 +87,15 @@ def main(): ) mod_graph.edges.append(e2) - """ e3 = Edge( id="feedback_edge", - parameters={"weight": 0.1}, + parameters={"weight": 0.3}, sender=readout_node.id, sender_port=readout_node.get_output_port("z").id, receiver=rnn_node.id, receiver_port=rnn_node.get_input_port("fb_input").id, ) - mod_graph.edges.append(e3)""" + mod_graph.edges.append(e3) if N < 100: new_file = mod.to_json_file("%s.json" % mod.id) diff --git a/examples/MDF/RNN/iaf.net.png b/examples/MDF/RNN/iaf.net.png index 30db8f94..1a8a3bd1 100644 Binary files a/examples/MDF/RNN/iaf.net.png and b/examples/MDF/RNN/iaf.net.png differ diff --git a/examples/MDF/RNN/iaf.net2.png b/examples/MDF/RNN/iaf.net2.png index 22784bc0..ceec52d2 100644 Binary files a/examples/MDF/RNN/iaf.net2.png and b/examples/MDF/RNN/iaf.net2.png differ diff --git a/examples/MDF/RNN/iaf.png b/examples/MDF/RNN/iaf.png index acd54abb..e2785d20 100644 Binary files a/examples/MDF/RNN/iaf.png and b/examples/MDF/RNN/iaf.png differ diff --git a/examples/MDF/RNN/regenerate.sh b/examples/MDF/RNN/regenerate.sh index 6a6b140e..9911be35 100755 --- a/examples/MDF/RNN/regenerate.sh +++ b/examples/MDF/RNN/regenerate.sh @@ -10,6 +10,7 @@ python generate_iaf.py -net2 -graph python generate_iaf.py -run -nogui python generate_iaf.py -run -net -nogui python generate_iaf.py -run -net2 -nogui +python generate_iaf.py -run -net3 -nogui #Fix dimensions! #python generate_iaf.py -neuroml #pynml LEMS_Simiaf_example.xml -lems-graph diff --git a/examples/MDF/RNN/rnn.png b/examples/MDF/RNN/rnn.png index ea726f10..963bdbc8 100644 Binary files a/examples/MDF/RNN/rnn.png and b/examples/MDF/RNN/rnn.png differ diff --git a/examples/MDF/RNN/utils.py b/examples/MDF/RNN/utils.py index 6688add9..1899769f 100644 --- a/examples/MDF/RNN/utils.py +++ b/examples/MDF/RNN/utils.py @@ -8,11 +8,11 @@ def create_rnn_node(id, N, g, seed=1234): ## RNN node... rnn_node = Node(id=id) - ipr1 = InputPort(id="ext_input", shape="(%i,)" % N) - rnn_node.input_ports.append(ipr1) + ext_ip = InputPort(id="ext_input", shape="(%i,)" % N) + rnn_node.input_ports.append(ext_ip) - ipr2 = InputPort(id="fb_input", shape="(%i,)" % N) - rnn_node.input_ports.append(ipr2) + fb_ip = InputPort(id="fb_input", default_value=0, shape="(%i,)" % N) + rnn_node.input_ports.append(fb_ip) default_initial_value = np.zeros(N) default_initial_value = 2 * np.random.random(N) - 1 @@ -26,7 +26,7 @@ def create_rnn_node(id, N, g, seed=1234): x = Parameter( id="x", default_initial_value=default_initial_value, - time_derivative="-x + g*int_fb + %s" % ipr1.id, + time_derivative=f"-x + g*int_fb + {ext_ip.id} + {fb_ip.id}", ) rnn_node.parameters.append(x) diff --git a/examples/MDF/Simple.bson b/examples/MDF/Simple.bson index 1af6cdd2..48433c8c 100644 Binary files a/examples/MDF/Simple.bson and b/examples/MDF/Simple.bson differ diff --git a/examples/MDF/Simple.json b/examples/MDF/Simple.json index a94c7355..6f5bfb70 100644 --- a/examples/MDF/Simple.json +++ b/examples/MDF/Simple.json @@ -1,7 +1,7 @@ { "Simple": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "simple_example": { "nodes": { diff --git a/examples/MDF/Simple.yaml b/examples/MDF/Simple.yaml index 8c43c59e..4e73e3d4 100644 --- a/examples/MDF/Simple.yaml +++ b/examples/MDF/Simple.yaml @@ -1,6 +1,6 @@ Simple: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: simple_example: nodes: diff --git a/examples/MDF/States.json b/examples/MDF/States.json index cf22cb88..1be78346 100644 --- a/examples/MDF/States.json +++ b/examples/MDF/States.json @@ -1,7 +1,7 @@ { "States": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "state_example": { "nodes": { diff --git a/examples/MDF/States.yaml b/examples/MDF/States.yaml index 45addf23..327792fb 100644 --- a/examples/MDF/States.yaml +++ b/examples/MDF/States.yaml @@ -1,6 +1,6 @@ States: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: state_example: nodes: diff --git a/examples/MDF/SwitchedRLC_Circuit.json b/examples/MDF/SwitchedRLC_Circuit.json index bc14167e..3b18562d 100644 --- a/examples/MDF/SwitchedRLC_Circuit.json +++ b/examples/MDF/SwitchedRLC_Circuit.json @@ -1,7 +1,7 @@ { "SwitchedRLC_Circuit": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "metadata": { "preferred_duration": 2, "preferred_dt": 0.001 diff --git a/examples/MDF/SwitchedRLC_Circuit.yaml b/examples/MDF/SwitchedRLC_Circuit.yaml index d049071e..fc1f8a80 100644 --- a/examples/MDF/SwitchedRLC_Circuit.yaml +++ b/examples/MDF/SwitchedRLC_Circuit.yaml @@ -1,6 +1,6 @@ SwitchedRLC_Circuit: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 metadata: preferred_duration: 2 preferred_dt: 0.001 diff --git a/examples/MDF/abc_conditions.json b/examples/MDF/abc_conditions.json index a4abbce2..6b42fecd 100644 --- a/examples/MDF/abc_conditions.json +++ b/examples/MDF/abc_conditions.json @@ -1,7 +1,7 @@ { "abc_conditions": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "abc_conditions_example": { "nodes": { diff --git a/examples/MDF/abc_conditions.yaml b/examples/MDF/abc_conditions.yaml index 4be8f7e1..e391b0e2 100644 --- a/examples/MDF/abc_conditions.yaml +++ b/examples/MDF/abc_conditions.yaml @@ -1,6 +1,6 @@ abc_conditions: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: abc_conditions_example: nodes: diff --git a/examples/MDF/conditions/Composite_mdf_condition.json b/examples/MDF/conditions/Composite_mdf_condition.json index ecea0f52..878aaec7 100644 --- a/examples/MDF/conditions/Composite_mdf_condition.json +++ b/examples/MDF/conditions/Composite_mdf_condition.json @@ -1,7 +1,7 @@ { "Composite_mdf_condition": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "Composite_mdf_condition_example": { "nodes": { diff --git a/examples/MDF/conditions/Composite_mdf_condition.yaml b/examples/MDF/conditions/Composite_mdf_condition.yaml index 7fb26f97..6140e478 100644 --- a/examples/MDF/conditions/Composite_mdf_condition.yaml +++ b/examples/MDF/conditions/Composite_mdf_condition.yaml @@ -1,6 +1,6 @@ Composite_mdf_condition: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: Composite_mdf_condition_example: nodes: diff --git a/examples/MDF/conditions/everyncalls_condition.json b/examples/MDF/conditions/everyncalls_condition.json index b06ab4b5..197e2977 100644 --- a/examples/MDF/conditions/everyncalls_condition.json +++ b/examples/MDF/conditions/everyncalls_condition.json @@ -1,7 +1,7 @@ { "everyncalls_condition": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "everyncalls_example": { "nodes": { diff --git a/examples/MDF/conditions/everyncalls_condition.yaml b/examples/MDF/conditions/everyncalls_condition.yaml index 066532fd..c43d81a0 100644 --- a/examples/MDF/conditions/everyncalls_condition.yaml +++ b/examples/MDF/conditions/everyncalls_condition.yaml @@ -1,6 +1,6 @@ everyncalls_condition: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: everyncalls_example: nodes: diff --git a/examples/MDF/conditions/threshold_condition.json b/examples/MDF/conditions/threshold_condition.json index 08dad14b..27ac7fbc 100644 --- a/examples/MDF/conditions/threshold_condition.json +++ b/examples/MDF/conditions/threshold_condition.json @@ -1,7 +1,7 @@ { "threshold_condition": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "threshold_example": { "nodes": { diff --git a/examples/MDF/conditions/threshold_condition.yaml b/examples/MDF/conditions/threshold_condition.yaml index fd5cf809..10a50e70 100644 --- a/examples/MDF/conditions/threshold_condition.yaml +++ b/examples/MDF/conditions/threshold_condition.yaml @@ -1,6 +1,6 @@ threshold_condition: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: threshold_example: nodes: diff --git a/examples/MDF/conditions/timeinterval_condition.json b/examples/MDF/conditions/timeinterval_condition.json index 95974e72..e22f7932 100644 --- a/examples/MDF/conditions/timeinterval_condition.json +++ b/examples/MDF/conditions/timeinterval_condition.json @@ -1,7 +1,7 @@ { "timeinterval_condition": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "timeinterval_example": { "nodes": { diff --git a/examples/MDF/conditions/timeinterval_condition.yaml b/examples/MDF/conditions/timeinterval_condition.yaml index 5d5caf30..2f539385 100644 --- a/examples/MDF/conditions/timeinterval_condition.yaml +++ b/examples/MDF/conditions/timeinterval_condition.yaml @@ -1,6 +1,6 @@ timeinterval_condition: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: timeinterval_example: nodes: diff --git a/examples/MDF/images/newton_plot.png b/examples/MDF/images/newton_plot.png index cdb4c6cc..735c8ddb 100644 Binary files a/examples/MDF/images/newton_plot.png and b/examples/MDF/images/newton_plot.png differ diff --git a/examples/MDF/images/switched_rlc_plot.png b/examples/MDF/images/switched_rlc_plot.png index 6627147d..2ce125ab 100644 Binary files a/examples/MDF/images/switched_rlc_plot.png and b/examples/MDF/images/switched_rlc_plot.png differ diff --git a/examples/MDF/networks/Net_acyclical.json b/examples/MDF/networks/Net_acyclical.json new file mode 100644 index 00000000..c1be5e99 --- /dev/null +++ b/examples/MDF/networks/Net_acyclical.json @@ -0,0 +1,64 @@ +{ + "Net_acyclical": { + "format": "ModECI MDF v0.4", + "generating_application": "Python modeci-mdf v0.4.14", + "graphs": { + "Net_acyclical": { + "nodes": { + "A": { + "input_ports": { + "input_port": { + "default_value": 0 + } + }, + "parameters": { + "passed_token": { + "value": "input_port + 1" + }, + "internal_count": { + "value": "internal_count + 1" + } + }, + "output_ports": { + "out_port": { + "value": "passed_token" + } + } + }, + "B": { + "input_ports": { + "input_port": {} + }, + "parameters": { + "passed_token": { + "value": "input_port + 1" + }, + "internal_count": { + "value": "internal_count + 1" + } + }, + "output_ports": { + "out_port": { + "value": "passed_token" + } + } + } + }, + "edges": { + "edge_A_B": { + "sender": "A", + "receiver": "B", + "sender_port": "out_port", + "receiver_port": "input_port" + }, + "edge_B_A": { + "sender": "B", + "receiver": "A", + "sender_port": "out_port", + "receiver_port": "input_port" + } + } + } + } + } +} diff --git a/examples/MDF/networks/Net_acyclical.png b/examples/MDF/networks/Net_acyclical.png new file mode 100644 index 00000000..22386968 Binary files /dev/null and b/examples/MDF/networks/Net_acyclical.png differ diff --git a/examples/MDF/networks/Net_acyclical.yaml b/examples/MDF/networks/Net_acyclical.yaml new file mode 100644 index 00000000..0be7ffc0 --- /dev/null +++ b/examples/MDF/networks/Net_acyclical.yaml @@ -0,0 +1,40 @@ +Net_acyclical: + format: ModECI MDF v0.4 + generating_application: Python modeci-mdf v0.4.14 + graphs: + Net_acyclical: + nodes: + A: + input_ports: + input_port: + default_value: 0 + parameters: + passed_token: + value: input_port + 1 + internal_count: + value: internal_count + 1 + output_ports: + out_port: + value: passed_token + B: + input_ports: + input_port: {} + parameters: + passed_token: + value: input_port + 1 + internal_count: + value: internal_count + 1 + output_ports: + out_port: + value: passed_token + edges: + edge_A_B: + sender: A + receiver: B + sender_port: out_port + receiver_port: input_port + edge_B_A: + sender: B + receiver: A + sender_port: out_port + receiver_port: input_port diff --git a/examples/MDF/networks/network.py b/examples/MDF/networks/network.py new file mode 100644 index 00000000..4f72f718 --- /dev/null +++ b/examples/MDF/networks/network.py @@ -0,0 +1,105 @@ +""" + Example of ModECI MDF - Testing networks +""" + +from modeci_mdf.mdf import * +import sys +import os +from modeci_mdf.utils import simple_connect + + +def main(ref="acyclical"): + + mod = Model(id="Net_%s" % ref) + + mod_graph = Graph(id="Net_%s" % ref) + mod.graphs.append(mod_graph) + + for id in ["A", "B"]: + + node = Node(id=id) + + if id == "A": + ip1 = InputPort(id="input_port", default_value=0) + node.input_ports.append(ip1) + + if id == "B": + ip1 = InputPort(id="input_port") + node.input_ports.append(ip1) + + p1 = Parameter(id="passed_token", value="input_port + 1") + node.parameters.append(p1) + + p2 = Parameter(id="internal_count", value="internal_count + 1") + node.parameters.append(p2) + + op1 = OutputPort(id="out_port", value=p1.id) + node.output_ports.append(op1) + + mod_graph.nodes.append(node) + + simple_connect(mod_graph.get_node("A"), mod_graph.get_node("B"), mod_graph) + simple_connect(mod_graph.get_node("B"), mod_graph.get_node("A"), mod_graph) + + new_file = mod.to_json_file("%s.json" % mod.id) + new_file = mod.to_yaml_file("%s.yaml" % mod.id) + + if "-run" in sys.argv: + verbose = True + # verbose = False + from modeci_mdf.utils import load_mdf, print_summary + + from modeci_mdf.execution_engine import EvaluableGraph + + eg = EvaluableGraph(mod_graph, verbose) + dt = 1 + + duration = 2 + t = 0 + recorded = {} + times = [] + ai = [] + bi = [] + ao = [] + bo = [] + while t <= duration: + times.append(t) + print("====== Evaluating at t = %s ======" % (t)) + if t == 0: + eg.evaluate() # replace with initialize? + else: + eg.evaluate(time_increment=dt) + + ai.append(eg.enodes["A"].evaluable_parameters["internal_count"].curr_value) + bi.append(eg.enodes["B"].evaluable_parameters["internal_count"].curr_value) + ao.append(eg.enodes["A"].evaluable_outputs["out_port"].curr_value) + bo.append(eg.enodes["B"].evaluable_outputs["out_port"].curr_value) + t += dt + + if "-nogui" not in sys.argv: + import matplotlib.pyplot as plt + + plt.plot(times, ai, marker="x", label="A count") + plt.plot(times, bi, label="B count") + plt.plot(times, ao, marker="o", label="A token") + plt.plot(times, bo, label="B token") + plt.legend() + plt.show() + + if "-graph" in sys.argv: + mod.to_graph_image( + engine="dot", + output_format="png", + view_on_render=False, + level=3, + filename_root=mod_graph.id, + only_warn_on_fail=( + os.name == "nt" + ), # Makes sure test of this doesn't fail on Windows on GitHub Actions + ) + + return mod_graph + + +if __name__ == "__main__": + main() diff --git a/examples/MDF/networks/regenerate.sh b/examples/MDF/networks/regenerate.sh new file mode 100755 index 00000000..acb22dd6 --- /dev/null +++ b/examples/MDF/networks/regenerate.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -ex + +python network.py -run -graph -nogui diff --git a/examples/NeuroML/Izh.png b/examples/NeuroML/Izh.png index 0ee1a7b9..077a4381 100644 Binary files a/examples/NeuroML/Izh.png and b/examples/NeuroML/Izh.png differ diff --git a/examples/NeuroML/Izh_run.png b/examples/NeuroML/Izh_run.png index 51949a3e..c467f278 100644 Binary files a/examples/NeuroML/Izh_run.png and b/examples/NeuroML/Izh_run.png differ diff --git a/examples/NeuroML/IzhikevichTest.gv.png b/examples/NeuroML/IzhikevichTest.gv.png index 120eef86..9334cdb1 100644 Binary files a/examples/NeuroML/IzhikevichTest.gv.png and b/examples/NeuroML/IzhikevichTest.gv.png differ diff --git a/examples/NeuroML/MDFFNrun.multi.png b/examples/NeuroML/MDFFNrun.multi.png index 795174ec..11a29768 100644 Binary files a/examples/NeuroML/MDFFNrun.multi.png and b/examples/NeuroML/MDFFNrun.multi.png differ diff --git a/examples/NeuroML/MDFFNrun.png b/examples/NeuroML/MDFFNrun.png index faf75a54..e06598d3 100644 Binary files a/examples/NeuroML/MDFFNrun.png and b/examples/NeuroML/MDFFNrun.png differ diff --git a/examples/NeuroML/PyNN/HH.mdf.png b/examples/NeuroML/PyNN/HH.mdf.png index 7cb45a8b..42975df9 100644 Binary files a/examples/NeuroML/PyNN/HH.mdf.png and b/examples/NeuroML/PyNN/HH.mdf.png differ diff --git a/examples/NeuroML/PyNN/InputWeights.mdf.png b/examples/NeuroML/PyNN/InputWeights.mdf.png index a34f50a1..f91fa93c 100644 Binary files a/examples/NeuroML/PyNN/InputWeights.mdf.png and b/examples/NeuroML/PyNN/InputWeights.mdf.png differ diff --git a/examples/NeuroML/PyNN/Net1.mdf.png b/examples/NeuroML/PyNN/Net1.mdf.png index 8d21027b..3cbf34f6 100644 Binary files a/examples/NeuroML/PyNN/Net1.mdf.png and b/examples/NeuroML/PyNN/Net1.mdf.png differ diff --git a/examples/NeuroML/PyNN/OneCell.mdf.png b/examples/NeuroML/PyNN/OneCell.mdf.png index d67c5aff..74fb0b69 100644 Binary files a/examples/NeuroML/PyNN/OneCell.mdf.png and b/examples/NeuroML/PyNN/OneCell.mdf.png differ diff --git a/examples/NeuroML/PyNN/SimpleNet.mdf.png b/examples/NeuroML/PyNN/SimpleNet.mdf.png index 52d272aa..f94a631f 100644 Binary files a/examples/NeuroML/PyNN/SimpleNet.mdf.png and b/examples/NeuroML/PyNN/SimpleNet.mdf.png differ diff --git a/examples/ONNX/ab.json b/examples/ONNX/ab.json index d7d8097c..71dad49f 100644 --- a/examples/ONNX/ab.json +++ b/examples/ONNX/ab.json @@ -1,7 +1,7 @@ { "ONNX Model": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "main_graph": { "nodes": { diff --git a/examples/ONNX/ab.yaml b/examples/ONNX/ab.yaml index 96efadbd..8039d6f2 100644 --- a/examples/ONNX/ab.yaml +++ b/examples/ONNX/ab.yaml @@ -1,6 +1,6 @@ ONNX Model: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: main_graph: nodes: diff --git a/examples/ONNX/abc.json b/examples/ONNX/abc.json index 9213fb9f..97515fee 100644 --- a/examples/ONNX/abc.json +++ b/examples/ONNX/abc.json @@ -1,7 +1,7 @@ { "ONNX Model": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "main_graph": { "nodes": { diff --git a/examples/ONNX/abc.png b/examples/ONNX/abc.png index e6cdc653..22c62cf2 100644 Binary files a/examples/ONNX/abc.png and b/examples/ONNX/abc.png differ diff --git a/examples/ONNX/abc.yaml b/examples/ONNX/abc.yaml index 52481493..39f52693 100644 --- a/examples/ONNX/abc.yaml +++ b/examples/ONNX/abc.yaml @@ -1,6 +1,6 @@ ONNX Model: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: main_graph: nodes: diff --git a/examples/ONNX/abc_basic-mdf.json b/examples/ONNX/abc_basic-mdf.json index 03225073..793027f5 100644 --- a/examples/ONNX/abc_basic-mdf.json +++ b/examples/ONNX/abc_basic-mdf.json @@ -1,7 +1,7 @@ { "ONNX Model": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "main_graph": { "nodes": { diff --git a/examples/ONNX/abc_basic-mdf.yaml b/examples/ONNX/abc_basic-mdf.yaml index f997af0c..ddabc3bc 100644 --- a/examples/ONNX/abc_basic-mdf.yaml +++ b/examples/ONNX/abc_basic-mdf.yaml @@ -1,6 +1,6 @@ ONNX Model: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: main_graph: nodes: diff --git a/examples/ONNX/abcd.json b/examples/ONNX/abcd.json index 2ded22d9..c84579a5 100644 --- a/examples/ONNX/abcd.json +++ b/examples/ONNX/abcd.json @@ -1,7 +1,7 @@ { "ONNX Model": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "main_graph": { "nodes": { diff --git a/examples/ONNX/abcd.yaml b/examples/ONNX/abcd.yaml index bfa60c3c..beab1f98 100644 --- a/examples/ONNX/abcd.yaml +++ b/examples/ONNX/abcd.yaml @@ -1,6 +1,6 @@ ONNX Model: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: main_graph: nodes: diff --git a/examples/PyTorch/MDF_PyTorch/ABCD_pytorch.py b/examples/PyTorch/MDF_PyTorch/ABCD_pytorch.py index 56095be2..cbb01e53 100644 --- a/examples/PyTorch/MDF_PyTorch/ABCD_pytorch.py +++ b/examples/PyTorch/MDF_PyTorch/ABCD_pytorch.py @@ -1,5 +1,5 @@ """ -This script has been generated by modeci_mdf v0.4.13. +This script has been generated by modeci_mdf v0.4.14. It is an export of a MDF model (mdf.s - MDF stateful, i.e. full MDF allowing stateful parameters) to PyTorch """ diff --git a/examples/PyTorch/MDF_PyTorch/Arrays_pytorch.py b/examples/PyTorch/MDF_PyTorch/Arrays_pytorch.py index 362f7f68..8a2d0069 100644 --- a/examples/PyTorch/MDF_PyTorch/Arrays_pytorch.py +++ b/examples/PyTorch/MDF_PyTorch/Arrays_pytorch.py @@ -1,5 +1,5 @@ """ -This script has been generated by modeci_mdf v0.4.13. +This script has been generated by modeci_mdf v0.4.14. It is an export of a MDF model (mdf.s - MDF stateful, i.e. full MDF allowing stateful parameters) to PyTorch """ diff --git a/examples/PyTorch/MDF_PyTorch/Simple_pytorch.py b/examples/PyTorch/MDF_PyTorch/Simple_pytorch.py index d98b074e..e3875863 100644 --- a/examples/PyTorch/MDF_PyTorch/Simple_pytorch.py +++ b/examples/PyTorch/MDF_PyTorch/Simple_pytorch.py @@ -1,5 +1,5 @@ """ -This script has been generated by modeci_mdf v0.4.13. +This script has been generated by modeci_mdf v0.4.14. It is an export of a MDF model (mdf.s - MDF stateful, i.e. full MDF allowing stateful parameters) to PyTorch """ diff --git a/examples/PyTorch/inception.json b/examples/PyTorch/inception.json index 6eef335f..fc232e28 100644 --- a/examples/PyTorch/inception.json +++ b/examples/PyTorch/inception.json @@ -1,7 +1,7 @@ { "InceptionBlocks": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "InceptionBlocksGraph": { "nodes": { diff --git a/examples/PyTorch/mlp_pure_mdf.json b/examples/PyTorch/mlp_pure_mdf.json index 179bfbb3..22160972 100644 --- a/examples/PyTorch/mlp_pure_mdf.json +++ b/examples/PyTorch/mlp_pure_mdf.json @@ -1,7 +1,7 @@ { "mlp_pure_mdf": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "mlp_pure_mdf": { "nodes": { diff --git a/examples/PyTorch/mlp_pure_mdf.yaml b/examples/PyTorch/mlp_pure_mdf.yaml index b4fce58c..c8a37d9c 100644 --- a/examples/PyTorch/mlp_pure_mdf.yaml +++ b/examples/PyTorch/mlp_pure_mdf.yaml @@ -1,6 +1,6 @@ mlp_pure_mdf: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: mlp_pure_mdf: nodes: diff --git a/examples/PyTorch/simple_pytorch_to_mdf.json b/examples/PyTorch/simple_pytorch_to_mdf.json index 4c54f15b..e6f03bf2 100644 --- a/examples/PyTorch/simple_pytorch_to_mdf.json +++ b/examples/PyTorch/simple_pytorch_to_mdf.json @@ -1,7 +1,7 @@ { "SimpleNet": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "SimpleNetGraph": { "nodes": { diff --git a/examples/TensorFlow/Keras/IRIS/keras_to_MDF.json b/examples/TensorFlow/Keras/IRIS/keras_to_MDF.json index c20f3d8e..83bef853 100644 --- a/examples/TensorFlow/Keras/IRIS/keras_to_MDF.json +++ b/examples/TensorFlow/Keras/IRIS/keras_to_MDF.json @@ -1,7 +1,7 @@ { "Sequential": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "Sequential_graph": { "nodes": { diff --git a/examples/TensorFlow/Keras/IRIS/keras_to_MDF.yaml b/examples/TensorFlow/Keras/IRIS/keras_to_MDF.yaml index 401b1e64..bd24e6b8 100644 --- a/examples/TensorFlow/Keras/IRIS/keras_to_MDF.yaml +++ b/examples/TensorFlow/Keras/IRIS/keras_to_MDF.yaml @@ -1,6 +1,6 @@ Sequential: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: Sequential_graph: nodes: diff --git a/examples/TensorFlow/Keras/MNIST/keras_to_MDF.json b/examples/TensorFlow/Keras/MNIST/keras_to_MDF.json index f236a0d3..b5ae341d 100644 --- a/examples/TensorFlow/Keras/MNIST/keras_to_MDF.json +++ b/examples/TensorFlow/Keras/MNIST/keras_to_MDF.json @@ -1,7 +1,7 @@ { "Sequential": { "format": "ModECI MDF v0.4", - "generating_application": "Python modeci-mdf v0.4.13", + "generating_application": "Python modeci-mdf v0.4.14", "graphs": { "Sequential_graph": { "nodes": { diff --git a/examples/TensorFlow/Keras/MNIST/keras_to_MDF.yaml b/examples/TensorFlow/Keras/MNIST/keras_to_MDF.yaml index ae8af52c..152ca23e 100644 --- a/examples/TensorFlow/Keras/MNIST/keras_to_MDF.yaml +++ b/examples/TensorFlow/Keras/MNIST/keras_to_MDF.yaml @@ -1,6 +1,6 @@ Sequential: format: ModECI MDF v0.4 - generating_application: Python modeci-mdf v0.4.13 + generating_application: Python modeci-mdf v0.4.14 graphs: Sequential_graph: nodes: diff --git a/pyproject.toml b/pyproject.toml index 25402296..fe68909f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,6 +105,7 @@ all = [ "modeci-mdf[all_except_psyneulink]", "modeci-mdf[psyneulink]", "modeci-mdf[neuroml_simulators]", + "modeci-mdf[test]", ] # Development dependency groups (PEP 735) diff --git a/src/modeci_mdf/__init__.py b/src/modeci_mdf/__init__.py index 45510701..79ee1392 100644 --- a/src/modeci_mdf/__init__.py +++ b/src/modeci_mdf/__init__.py @@ -13,4 +13,4 @@ MODECI_MDF_VERSION = "0.4" # Version of the Python module. -__version__ = "0.4.13" +__version__ = "0.4.14" diff --git a/src/modeci_mdf/execution_engine.py b/src/modeci_mdf/execution_engine.py index 2922a23b..ff71dd86 100644 --- a/src/modeci_mdf/execution_engine.py +++ b/src/modeci_mdf/execution_engine.py @@ -692,10 +692,17 @@ class EvaluableInput: def __init__(self, input_port: InputPort, verbose: Optional[bool] = False): self.verbose = verbose self.input_port = input_port - default = 0 - if input_port.type and "float" in input_port.type: - default = 0.0 - self.curr_value = np.full(input_port.shape, default) + + if self.input_port.reduce == "overwrite": + if self.input_port.default_value is not None: + self.curr_value = self.input_port.default_value + else: + default = 0 + if input_port.type and "float" in input_port.type: + default = 0.0 + self.curr_value = np.full(input_port.shape, default) + else: + self.curr_value = None def set_input_value(self, value: Union[str, int, np.ndarray]): """Set a new value at input port @@ -703,9 +710,30 @@ def set_input_value(self, value: Union[str, int, np.ndarray]): Args: value: Value to be set at Input Port """ - if self.verbose: - print(f" Input value in {self.input_port.id} set to {_val_info(value)}") - self.curr_value = value + + if self.curr_value is None: + ## No value set yet, so just set to value being input now + print( + f" Input value in {self.input_port.id} being set to {_val_info(value)}" + ) + self.curr_value = value + else: + ## A previous value has been set during this time step. So reduce it... + if self.input_port.reduce == "overwrite": + print( + f" Input value in {self.input_port.id} being set to {_val_info(value)}" + ) + self.curr_value = value + elif self.input_port.reduce == "add": + print( + f" Input value in {self.input_port.id} was {self.curr_value}, increasing by {_val_info(value)}" + ) + self.curr_value += value + elif self.input_port.reduce == "multiply": + print( + f" Input value in {self.input_port.id} was {self.curr_value}, increasing by {_val_info(value)}" + ) + self.curr_value *= value def evaluate( self, parameters: Dict[str, Any] = None, array_format: str = FORMAT_DEFAULT @@ -719,16 +747,27 @@ def evaluate( Returns: value at Input port """ + + if self.curr_value is None: + if self.input_port.default_value is not None: + self.curr_value = self.input_port.default_value + else: + self.curr_value = np.full(self.input_port.shape, 0.0) + + final_val = self.curr_value + if self.verbose: print( - " Evaluated %s with params %s =\t%s" + " Evaluated the %s with params %s \n =\t%s" % ( self.input_port, _params_info(parameters), - _val_info(self.curr_value), + _val_info(final_val), ) ) - return self.curr_value + + self.curr_value = None + return final_val class EvaluableNode: @@ -1034,6 +1073,14 @@ def __init__(self, graph: Graph, verbose: Optional[bool] = False): ): # It could have been already removed... self.root_nodes.remove(edge.receiver) + if len(self.root_nodes) == 0: + for node in graph.nodes: + for ip in node.input_ports: + if ip.default_value is not None: + self.root_nodes.append(node.id) + + print("Root nodes evaluated as: %s" % (self.root_nodes)) + self.ordered_edges = [] evaluated_nodes = [] for rn in self.root_nodes: @@ -1049,6 +1096,8 @@ def __init__(self, graph: Graph, verbose: Optional[bool] = False): self.ordered_edges.append(edge) evaluated_nodes.append(edge.receiver) + print("Ordered_edges as: %s" % (self.ordered_edges)) + if self.graph.conditions is not None: if self.graph.conditions.node_specific is None: conditions = {} @@ -1076,6 +1125,7 @@ def __init__(self, graph: Graph, verbose: Optional[bool] = False): else: conditions = {} termination_conds = {} + self.scheduler = graph_scheduler.Scheduler( graph=self.graph.dependency_dict, conditions=conditions, @@ -1147,9 +1197,16 @@ def evaluate( for node in ts: self.order_of_execution.append(node.id) for edge in incoming_edges[node]: - self.evaluate_edge( - edge, time_increment=time_increment, array_format=array_format - ) + if edge.sender in self.order_of_execution: + self.evaluate_edge( + edge, + time_increment=time_increment, + array_format=array_format, + ) + else: + print( + "> Not evaluating edge: %s, as sender not run yet..." % edge + ) self.enodes[node.id].evaluate( time_increment=time_increment, array_format=array_format ) diff --git a/src/modeci_mdf/interfaces/graphviz/exporter.py b/src/modeci_mdf/interfaces/graphviz/exporter.py index e34c32ac..833a9786 100644 --- a/src/modeci_mdf/interfaces/graphviz/exporter.py +++ b/src/modeci_mdf/interfaces/graphviz/exporter.py @@ -285,9 +285,9 @@ def mdf_to_graphviz( additional = "" if ip.shape is not None and ip.shape != (): additional += "shape: %s, " % str(ip.shape) - """if ip.reduce is not None: + if ip.reduce is not None: if ip.reduce != "overwrite": # since this is the default... - additional += "reduce: %s, " % str(ip.reduce)""" + additional += "reduce: %s, " % str(ip.reduce) if ip.type is not None: additional += "type: %s, " % str(ip.type) diff --git a/src/modeci_mdf/mdf.py b/src/modeci_mdf/mdf.py index 327240be..d6f908e6 100644 --- a/src/modeci_mdf/mdf.py +++ b/src/modeci_mdf/mdf.py @@ -99,19 +99,25 @@ class InputPort(MdfBase): Attributes: id: The unique (for this Node) id of the input port, + default_value: Value to set at this input port if no edge connected to it. shape: The shape of the input port. This uses the same syntax as numpy ndarray shapes (e.g., :code:`numpy.zeros(shape)` would produce an array with the correct shape type: The data type of the input received at a port. + reduce: Specifies how to deal with multiple inputs to one port during a single timestep: add: add up all the values; multiply: multiply the values, overwrite: just use the last value supplied (default) """ id: str = field(validator=instance_of(str)) + default_value: Optional[ValueExprType] = field(default=None) shape: Optional[Tuple[int, ...]] = field( validator=optional(instance_of(tuple)), default=(), converter=lambda x: make_tuple(x) if type(x) is str else x, ) type: Optional[str] = field(validator=optional(instance_of(str)), default=None) + reduce: Optional[str] = field( + validator=optional(instance_of(str)), default="overwrite" + ) @modelspec.define(eq=False) @@ -488,7 +494,10 @@ def dependency_dict(self) -> Dict[Node, Set[Node]]: sender = self.get_node(edge.sender) receiver = self.get_node(edge.receiver) - dependencies[receiver].add(sender) + if receiver.get_input_port(edge.receiver_port).default_value is not None: + pass + else: + dependencies[receiver].add(sender) return dependencies diff --git a/test_all.sh b/test_all.sh index 41816de5..506459d6 100755 --- a/test_all.sh +++ b/test_all.sh @@ -1,7 +1,24 @@ #!/bin/bash set -ex -pip install .[all] --group "dev" +## This is overkill, but it seems to lead to less space being used on install, which was +## causing issues on GHA CI. +df -h + +pip install . --cache-dir=/home/runner/tmp --prefer-binary +df -h +pip cache info +pip cache purge +df -h + +pip install .[optional] --cache-dir=/home/runner/tmp --prefer-binary +df -h +pip cache purge +df -h + +pip install .[all] --cache-dir=/home/runner/tmp --prefer-binary +df -h + # Note this: # 1) runs examples to regenerate yaml/json... @@ -72,6 +89,11 @@ cd .. cd RNN ./regenerate.sh +## Test regenerating network example + +cd ../networks +./regenerate.sh + ## Test regenerating NeuroML diff --git a/tests/test_mdf_functions.py b/tests/test_mdf_functions.py index e8b3e48a..d19d728e 100644 --- a/tests/test_mdf_functions.py +++ b/tests/test_mdf_functions.py @@ -40,7 +40,10 @@ def test_std_functions(name, expected_result, parameters): try: assert stdf.mdf_functions[name]["function"](**parameters) == expected_result - except ValueError: - assert numpy.array_equal( - stdf.mdf_functions[name]["function"](**parameters), expected_result + except: + assert numpy.allclose( + stdf.mdf_functions[name]["function"](**parameters), + expected_result, + atol=0, + rtol=1e-8, ) diff --git a/tests/test_scheduler.py b/tests/test_scheduler.py index 45b5356a..f8f9984c 100644 --- a/tests/test_scheduler.py +++ b/tests/test_scheduler.py @@ -15,7 +15,7 @@ def test_execution_engine_main(tmpdir): mdf_formats = ["json", "yaml"] array_formats = [FORMAT_NUMPY, FORMAT_TENSORFLOW] - # For now, don't make tensorflow a requiremnt... + # For now, don't make tensorflow a requirement... try: import tensorflow except: @@ -221,7 +221,7 @@ def test_threshold(create_model): [ ("A", "A_output"), ("A", "A_param_2"), - ("B", "B_input"), + ("B", "B_output"), ], ) @pytest.mark.parametrize(