diff --git a/.github/workflows/ci_test_all.yml b/.github/workflows/ci_test_all.yml index 5132e129..0036b309 100644 --- a/.github/workflows/ci_test_all.yml +++ b/.github/workflows/ci_test_all.yml @@ -1,4 +1,4 @@ -name: CI Test script +name: CI test_all.sh script on: push: @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ "3.12"] + python-version: [ "3.13" ] runs-on: [ubuntu-latest] steps: diff --git a/.gitignore b/.gitignore index 418556e3..c9289c52 100644 --- a/.gitignore +++ b/.gitignore @@ -317,3 +317,4 @@ examples/TensorFlow/Keras/keras_to_MDF /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 +/examples/MDF/networks/Net_network2 diff --git a/examples/MDF/Simple.bson b/examples/MDF/Simple.bson index c8e35f41..d609556c 100644 Binary files a/examples/MDF/Simple.bson and b/examples/MDF/Simple.bson differ diff --git a/examples/MDF/networks/Net_network2.json b/examples/MDF/networks/Net_network2.json new file mode 100644 index 00000000..b39eb9f3 --- /dev/null +++ b/examples/MDF/networks/Net_network2.json @@ -0,0 +1,50 @@ +{ + "Net_network2": { + "format": "ModECI MDF v0.4", + "generating_application": "Python modeci-mdf v0.4.14", + "graphs": { + "Net_network2": { + "nodes": { + "A": { + "input_ports": { + "in_port_0": { + "default_value": 5 + } + }, + "parameters": { + "total_inputs": { + "value": "total_inputs + in_port_0" + }, + "execute_count": { + "value": "execute_count + 1" + } + }, + "output_ports": { + "out_port_0": { + "value": "total_inputs" + } + } + }, + "B": { + "input_ports": { + "in_port_0": {} + }, + "parameters": { + "total_inputs": { + "value": "total_inputs + in_port_0" + }, + "execute_count": { + "value": "execute_count + 1" + } + }, + "output_ports": { + "out_port_0": { + "value": "total_inputs" + } + } + } + } + } + } + } +} diff --git a/examples/MDF/networks/Net_network2.png b/examples/MDF/networks/Net_network2.png new file mode 100644 index 00000000..6d808c8f Binary files /dev/null and b/examples/MDF/networks/Net_network2.png differ diff --git a/examples/MDF/networks/Net_network2.yaml b/examples/MDF/networks/Net_network2.yaml new file mode 100644 index 00000000..13d18b51 --- /dev/null +++ b/examples/MDF/networks/Net_network2.yaml @@ -0,0 +1,29 @@ +Net_network2: + format: ModECI MDF v0.4 + generating_application: Python modeci-mdf v0.4.14 + graphs: + Net_network2: + nodes: + A: + input_ports: + in_port_0: + default_value: 5 + parameters: + total_inputs: + value: total_inputs + in_port_0 + execute_count: + value: execute_count + 1 + output_ports: + out_port_0: + value: total_inputs + B: + input_ports: + in_port_0: {} + parameters: + total_inputs: + value: total_inputs + in_port_0 + execute_count: + value: execute_count + 1 + output_ports: + out_port_0: + value: total_inputs diff --git a/examples/MDF/networks/network2.py b/examples/MDF/networks/network2.py new file mode 100644 index 00000000..786c3830 --- /dev/null +++ b/examples/MDF/networks/network2.py @@ -0,0 +1,123 @@ +""" + 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="network2"): + + 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="in_port_0", default_value=5) + node.input_ports.append(ip1) + + if id == "B": + ip1 = InputPort(id="in_port_0") + node.input_ports.append(ip1) + + p1 = Parameter(id="total_inputs", value="total_inputs + in_port_0") + node.parameters.append(p1) + + p2 = Parameter(id="execute_count", value="execute_count + 1") + node.parameters.append(p2) + + op1 = OutputPort(id="out_port_0", 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) + + eg = None + + 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 = [] + at = [] + bt = [] + 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["execute_count"].curr_value) + bi.append(eg.enodes["B"].evaluable_parameters["execute_count"].curr_value) + at.append(eg.enodes["A"].evaluable_parameters["total_inputs"].curr_value) + bt.append(eg.enodes["B"].evaluable_parameters["total_inputs"].curr_value) + ao.append(eg.enodes["A"].evaluable_outputs["out_port_0"].curr_value) + bo.append(eg.enodes["B"].evaluable_outputs["out_port_0"].curr_value) + t += dt + + if "-nogui" not in sys.argv: + import matplotlib.pyplot as plt + + plt.plot(times, ai, marker="x", label="A exe count") + plt.plot(times, bi, label="B exe count") + plt.plot(times, at, marker="D", label="A total_inputs") + plt.plot(times, bt, label="B total_inputs") + + 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, eg + + +if __name__ == "__main__": + g, eg = main() + + print("--------------------") + print(g.to_yaml()) + print("--------------------") + if eg is not None: + for n in eg.enodes: + enode = eg.enodes[n] + print(enode) + print([enode.evaluable_outputs for enode in eg.enodes.values()]) + else: + print("No execution engine created. Run with: -run") diff --git a/examples/PyTorch/PyTorch_MDF/benchmark_script/squeezenet1_1_benchmark.json b/examples/PyTorch/PyTorch_MDF/benchmark_script/squeezenet1_1_benchmark.json index 4558ea97..59bb4671 100644 --- a/examples/PyTorch/PyTorch_MDF/benchmark_script/squeezenet1_1_benchmark.json +++ b/examples/PyTorch/PyTorch_MDF/benchmark_script/squeezenet1_1_benchmark.json @@ -2,11 +2,11 @@ { "model_name": "squeezenet1_1", "model_type": "SqueezeNet", - "pytorch_time": 0.0839, + "pytorch_time": 0.07, "pytorch_predictions": 10, - "mdf_time": 4.4275, + "mdf_time": 5.949, "mdf_predictions": 10, "node density": 66, - "mdf : pytorch ratio": "52.79" + "mdf : pytorch ratio": "84.98" } ] diff --git a/pyproject.toml b/pyproject.toml index fe04d89d..a474f792 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ name = "modeci-mdf" dynamic = ["version"] description = "ModECI (Model Exchange and Convergence Initiative) Model Description Format" readme = "README.md" -requires-python = ">=3.9" +requires-python = ">=3.10" license = {text = "LGPLv3"} authors = [ {name = "ModECI contributors", email = "p.gleeson@gmail.com"}, @@ -25,9 +25,7 @@ classifiers = [ "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", "Natural Language :: English", "Operating System :: OS Independent", - "Programming Language :: Python :: 3.8", "Topic :: Scientific/Engineering", - "Intended Audience :: Science/Research", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", @@ -35,13 +33,13 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", - "Topic :: Scientific/Engineering", "Topic :: Software Development", "Typing :: Typed", ] dependencies = [ "graph_scheduler>=1.1.1", "numpy", + "scipy", "matplotlib", "graphviz", "h5py", @@ -92,7 +90,6 @@ optional = [ "netron", "torch>=1.11.0", "torchvision", - "h5py", ] all_except_psyneulink = [ @@ -144,9 +141,6 @@ exclude = ["tests", "examples"] [tool.setuptools.dynamic] version = {attr = "modeci_mdf.__version__"} -#[tool.setuptools_scm] -#write_to = "src/modeci_mdf/version.py" - [tool.pytest.ini_options] junit_family = "xunit2" addopts = "--benchmark-disable -Wd --strict-markers" @@ -156,7 +150,7 @@ required_plugins = ["pytest-benchmark"] markers = [ "coremdf: marks tests which are core to the MDF specification", "actr: marks tests which require ACT-R to be installed.", - "pytorch: marks test which require PyTorch to be installed.')", + "pytorch: marks tests which require PyTorch to be installed.", "psyneulink: marks tests which require PsyNueLink to be installed.", "neuroml: marks tests which require NeuroML to be installed.", "tensorflow: marks tests which require TensorFlow to be installed.", @@ -182,7 +176,7 @@ per-file-ignores = [ [tool.mypy] warn_unused_configs = true -python_version = "3.6" +python_version = "3.10" files = ["src"] disallow_any_generics = true disallow_subclassing_any = true diff --git a/src/modeci_mdf/execution_engine.py b/src/modeci_mdf/execution_engine.py index ff71dd86..4b1bf3f7 100644 --- a/src/modeci_mdf/execution_engine.py +++ b/src/modeci_mdf/execution_engine.py @@ -679,6 +679,9 @@ def evaluate( ) return self.curr_value + def __repr__(self): + return f"EvaluableOutput({self.output_port.id} = {_val_info(self.curr_value)} )" + class EvaluableInput: """Evaluates input value at the :class:`~modeci_mdf.mdf.InputPort` of the node during MDF graph execution. @@ -766,7 +769,7 @@ def evaluate( ) ) - self.curr_value = None + self.curr_value = None # to be tested for conditions... return final_val