ngcsimlib 0.2b0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ngcsimlib-0.2b0/AUTHORS +10 -0
- ngcsimlib-0.2b0/LICENSE +29 -0
- ngcsimlib-0.2b0/PKG-INFO +69 -0
- ngcsimlib-0.2b0/README.md +55 -0
- ngcsimlib-0.2b0/ngcsimlib/__init__.py +50 -0
- ngcsimlib-0.2b0/ngcsimlib/bundle_rules.py +64 -0
- ngcsimlib-0.2b0/ngcsimlib/commands/__init__.py +11 -0
- ngcsimlib-0.2b0/ngcsimlib/commands/advanceState.py +25 -0
- ngcsimlib-0.2b0/ngcsimlib/commands/clamp.py +58 -0
- ngcsimlib-0.2b0/ngcsimlib/commands/command.py +34 -0
- ngcsimlib-0.2b0/ngcsimlib/commands/compound.py +39 -0
- ngcsimlib-0.2b0/ngcsimlib/commands/evolve.py +41 -0
- ngcsimlib-0.2b0/ngcsimlib/commands/multiclamp.py +42 -0
- ngcsimlib-0.2b0/ngcsimlib/commands/reset.py +40 -0
- ngcsimlib-0.2b0/ngcsimlib/commands/save.py +46 -0
- ngcsimlib-0.2b0/ngcsimlib/commands/snapshot.py +39 -0
- ngcsimlib-0.2b0/ngcsimlib/commands/track.py +50 -0
- ngcsimlib-0.2b0/ngcsimlib/component.py +359 -0
- ngcsimlib-0.2b0/ngcsimlib/controller.py +378 -0
- ngcsimlib-0.2b0/ngcsimlib/utils.py +237 -0
- ngcsimlib-0.2b0/ngcsimlib.egg-info/PKG-INFO +69 -0
- ngcsimlib-0.2b0/ngcsimlib.egg-info/SOURCES.txt +24 -0
- ngcsimlib-0.2b0/ngcsimlib.egg-info/dependency_links.txt +1 -0
- ngcsimlib-0.2b0/ngcsimlib.egg-info/top_level.txt +2 -0
- ngcsimlib-0.2b0/pyproject.toml +114 -0
- ngcsimlib-0.2b0/setup.cfg +4 -0
ngcsimlib-0.2b0/AUTHORS
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# This file contains an official list of authors of this framework.
|
|
2
|
+
|
|
3
|
+
# Names should be added to this file as:
|
|
4
|
+
# Name or Organization <email address>
|
|
5
|
+
# The email address is not required for organizations.
|
|
6
|
+
|
|
7
|
+
Core Team
|
|
8
|
+
William Gebhardt <wdg1351@rit.edu>
|
|
9
|
+
Alexander Ororbia <ago@cs.rit.edu>
|
|
10
|
+
|
ngcsimlib-0.2b0/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023, The Neural Adaptive Computing Laboratory
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
ngcsimlib-0.2b0/PKG-INFO
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ngcsimlib
|
|
3
|
+
Version: 0.2b0
|
|
4
|
+
Summary: Simulation software backend for ngc-learn.
|
|
5
|
+
Author-email: William Gebhardt <wdg1351@rit.edu>, Alexander Ororbia <ago@cs.rit.edu>
|
|
6
|
+
License: BSD-3-Clause License
|
|
7
|
+
Project-URL: Homepage, https://github.com/NACLab/ngc-sim-lib
|
|
8
|
+
Project-URL: Lab Page, https://www.cs.rit.edu/~ago/nac_lab.html
|
|
9
|
+
Keywords: python,complex-systems,simulation
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
License-File: AUTHORS
|
|
14
|
+
|
|
15
|
+
[](https://www.python.org/downloads)[](https://opensource.org/licenses/BSD-3-Clause)[](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity)
|
|
16
|
+
[](https://zenodo.org/doi/10.5281/zenodo.10888210)
|
|
17
|
+
|
|
18
|
+
# NGC-Sim-Lib: Support Library for NGC-Learn
|
|
19
|
+
|
|
20
|
+
<b>ngc-sim-lib</b> is the support library and central dependency for
|
|
21
|
+
<i><a href="https://github.com/NACLab/ngc-learn/">ngc-learn</a></i>, a library
|
|
22
|
+
designed for computational neuroscience and cognitive neuroscience research.
|
|
23
|
+
While ngc-learn contains the JAX-implemented routines and any supporting C
|
|
24
|
+
code, ngc-sim-lib is a pure Python package, primarily meant for providing the
|
|
25
|
+
machinery, routines, and utilities that facilitate the general (abstract)
|
|
26
|
+
simulation of complex adaptive systems made up of dynamical components. For
|
|
27
|
+
information, including anything related to usage instructions and details,
|
|
28
|
+
please refer to the ngc-learn README:
|
|
29
|
+
https://github.com/NACLab/ngc-learn/.
|
|
30
|
+
|
|
31
|
+
This package is distributed under the 3-Clause BSD license. It is currently
|
|
32
|
+
maintained by the
|
|
33
|
+
<a href="https://www.cs.rit.edu/~ago/nac_lab.html">Neural Adaptive Computing
|
|
34
|
+
(NAC) laboratory</a>.
|
|
35
|
+
|
|
36
|
+
## <b>Installation:</b>
|
|
37
|
+
|
|
38
|
+
<i>Setup:</i> Ensure that you have installed the following base dependencies in
|
|
39
|
+
your system. Note that this library was developed and tested on
|
|
40
|
+
Ubuntu 22.04.3 LTS. ngc-sim-lib requires: `Python (>=3.10)`.
|
|
41
|
+
|
|
42
|
+
Once you have ensured that the appropriate Python is installed, you can then
|
|
43
|
+
have the <code>ngclib</code> package installed on your system using the
|
|
44
|
+
following bash command:
|
|
45
|
+
<pre>
|
|
46
|
+
$ pip install .
|
|
47
|
+
</pre>
|
|
48
|
+
or, if you are doing development, then do an editable install via:
|
|
49
|
+
<pre>
|
|
50
|
+
$ pip install --editable . # OR pip install -e .
|
|
51
|
+
</pre>
|
|
52
|
+
|
|
53
|
+
**Version:**<br>
|
|
54
|
+
0.2.0 <!-- -Alpha -->
|
|
55
|
+
|
|
56
|
+
Authors:
|
|
57
|
+
William Gebhardt, Alexander G. Ororbia II<br>
|
|
58
|
+
Neural Adaptive Computing (NAC) Laboratory<br>
|
|
59
|
+
Rochester Institute of Technology, Department of Computer Science
|
|
60
|
+
|
|
61
|
+
## <b>Copyright:</b>
|
|
62
|
+
|
|
63
|
+
Copyright (C) 2023 The Neural Adaptive Computing Laboratory - All Rights Reserved<br>
|
|
64
|
+
You may use, distribute and modify this code under the
|
|
65
|
+
terms of the BSD 3-clause license.
|
|
66
|
+
|
|
67
|
+
You should have received a copy of the BSD 3-clause license with
|
|
68
|
+
this software.<br>
|
|
69
|
+
If not, please [email us](mailto:ago@cs.rit.edu)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
[](https://www.python.org/downloads)[](https://opensource.org/licenses/BSD-3-Clause)[](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity)
|
|
2
|
+
[](https://zenodo.org/doi/10.5281/zenodo.10888210)
|
|
3
|
+
|
|
4
|
+
# NGC-Sim-Lib: Support Library for NGC-Learn
|
|
5
|
+
|
|
6
|
+
<b>ngc-sim-lib</b> is the support library and central dependency for
|
|
7
|
+
<i><a href="https://github.com/NACLab/ngc-learn/">ngc-learn</a></i>, a library
|
|
8
|
+
designed for computational neuroscience and cognitive neuroscience research.
|
|
9
|
+
While ngc-learn contains the JAX-implemented routines and any supporting C
|
|
10
|
+
code, ngc-sim-lib is a pure Python package, primarily meant for providing the
|
|
11
|
+
machinery, routines, and utilities that facilitate the general (abstract)
|
|
12
|
+
simulation of complex adaptive systems made up of dynamical components. For
|
|
13
|
+
information, including anything related to usage instructions and details,
|
|
14
|
+
please refer to the ngc-learn README:
|
|
15
|
+
https://github.com/NACLab/ngc-learn/.
|
|
16
|
+
|
|
17
|
+
This package is distributed under the 3-Clause BSD license. It is currently
|
|
18
|
+
maintained by the
|
|
19
|
+
<a href="https://www.cs.rit.edu/~ago/nac_lab.html">Neural Adaptive Computing
|
|
20
|
+
(NAC) laboratory</a>.
|
|
21
|
+
|
|
22
|
+
## <b>Installation:</b>
|
|
23
|
+
|
|
24
|
+
<i>Setup:</i> Ensure that you have installed the following base dependencies in
|
|
25
|
+
your system. Note that this library was developed and tested on
|
|
26
|
+
Ubuntu 22.04.3 LTS. ngc-sim-lib requires: `Python (>=3.10)`.
|
|
27
|
+
|
|
28
|
+
Once you have ensured that the appropriate Python is installed, you can then
|
|
29
|
+
have the <code>ngclib</code> package installed on your system using the
|
|
30
|
+
following bash command:
|
|
31
|
+
<pre>
|
|
32
|
+
$ pip install .
|
|
33
|
+
</pre>
|
|
34
|
+
or, if you are doing development, then do an editable install via:
|
|
35
|
+
<pre>
|
|
36
|
+
$ pip install --editable . # OR pip install -e .
|
|
37
|
+
</pre>
|
|
38
|
+
|
|
39
|
+
**Version:**<br>
|
|
40
|
+
0.2.0 <!-- -Alpha -->
|
|
41
|
+
|
|
42
|
+
Authors:
|
|
43
|
+
William Gebhardt, Alexander G. Ororbia II<br>
|
|
44
|
+
Neural Adaptive Computing (NAC) Laboratory<br>
|
|
45
|
+
Rochester Institute of Technology, Department of Computer Science
|
|
46
|
+
|
|
47
|
+
## <b>Copyright:</b>
|
|
48
|
+
|
|
49
|
+
Copyright (C) 2023 The Neural Adaptive Computing Laboratory - All Rights Reserved<br>
|
|
50
|
+
You may use, distribute and modify this code under the
|
|
51
|
+
terms of the BSD 3-clause license.
|
|
52
|
+
|
|
53
|
+
You should have received a copy of the BSD 3-clause license with
|
|
54
|
+
this software.<br>
|
|
55
|
+
If not, please [email us](mailto:ago@cs.rit.edu)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from . import utils
|
|
2
|
+
from . import controller
|
|
3
|
+
from . import commands
|
|
4
|
+
|
|
5
|
+
import argparse, os, warnings, json
|
|
6
|
+
from types import SimpleNamespace
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from sys import argv
|
|
9
|
+
from importlib import import_module
|
|
10
|
+
|
|
11
|
+
from pkg_resources import get_distribution
|
|
12
|
+
|
|
13
|
+
__version__ = get_distribution('ngcsimlib').version ## set software version
|
|
14
|
+
|
|
15
|
+
###### Preload Modules
|
|
16
|
+
def preload():
|
|
17
|
+
parser = argparse.ArgumentParser(description='Build and run a model using ngclearn')
|
|
18
|
+
parser.add_argument("--modules", type=str, help='location of modules.json file')
|
|
19
|
+
|
|
20
|
+
args = parser.parse_args()
|
|
21
|
+
try:
|
|
22
|
+
module_path = args.modules
|
|
23
|
+
except:
|
|
24
|
+
module_path = None
|
|
25
|
+
|
|
26
|
+
if module_path is None:
|
|
27
|
+
module_path = "json_files/modules.json"
|
|
28
|
+
|
|
29
|
+
if not os.path.isfile(module_path):
|
|
30
|
+
warnings.warn("Missing file to preload modules from. Attempted to locate file at \"" + str(module_path) + "\"" )
|
|
31
|
+
return
|
|
32
|
+
|
|
33
|
+
with open(module_path, 'r') as file:
|
|
34
|
+
modules = json.load(file, object_hook=lambda d: SimpleNamespace(**d))
|
|
35
|
+
|
|
36
|
+
for module in modules:
|
|
37
|
+
mod = import_module(module.absolute_path)
|
|
38
|
+
utils._Loaded_Modules[module.absolute_path] = mod
|
|
39
|
+
|
|
40
|
+
for attribute in module.attributes:
|
|
41
|
+
atr = getattr(mod, attribute.name)
|
|
42
|
+
utils._Loaded_Attributes[attribute.name] = atr
|
|
43
|
+
|
|
44
|
+
utils._Loaded_Attributes[".".join([module.absolute_path, attribute.name])] = atr
|
|
45
|
+
if hasattr(attribute, "keywords"):
|
|
46
|
+
for keyword in attribute.keywords:
|
|
47
|
+
utils._Loaded_Attributes[keyword] = atr
|
|
48
|
+
|
|
49
|
+
if not Path(argv[0]).name == "sphinx-build" or Path(argv[0]).name == "build.py":
|
|
50
|
+
preload()
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Contains all the built-in bundle rules as well as the default one for an unbundled
|
|
3
|
+
cable. Bundle(s) usage is that it is to be added to a component's bundle rules
|
|
4
|
+
(Note: the overwrite rule is the default rule).
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Template for bundle rules. The name of the bundle rule should be meaningful to what it does. All bundle rules will
|
|
8
|
+
be called with the same three inputs: component, value, and destination_compartment. These are not passed by keyword but
|
|
9
|
+
they will always be in the same order. The component is the component that the bundle has as a destination (target).
|
|
10
|
+
The value is the signal that goes into (or comes along to) the connected bundle. The destination_compartment is
|
|
11
|
+
the compartment that the bundle is connected to. Overall, the general usage of bundle rules is to modify the
|
|
12
|
+
behavior of an input to a compartment; generally, they should NOT modify any other aspect of the target
|
|
13
|
+
component aside from the destination compartment and, as a warning, should not try to reference compartments by
|
|
14
|
+
name as this will possibly result in runtime errors given that the required compartments for the bundle rule(s)
|
|
15
|
+
might not exist.
|
|
16
|
+
|
|
17
|
+
General bundle rule specification:
|
|
18
|
+
|
|
19
|
+
def BUNDLE_RULE_NAME(component, value, destination_compartment):
|
|
20
|
+
## Logic for processing transmitted value
|
|
21
|
+
## Syntax for referencing destination compartment -> component.compartments[destination_compartment]
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
def overwrite(component, value, destination_compartment):
|
|
25
|
+
"""
|
|
26
|
+
The overwrite bundle rule routine.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
component: target component node that this bundle rule will operate on
|
|
30
|
+
|
|
31
|
+
value: the value to insert into a compartment within the target component
|
|
32
|
+
|
|
33
|
+
destination_compartment: compartment within component to place a value w/in
|
|
34
|
+
"""
|
|
35
|
+
component.compartments[destination_compartment] = value
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def additive(component, value, destination_compartment):
|
|
39
|
+
"""
|
|
40
|
+
The additive/addition bundle rule routine.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
component: target component node that this bundle rule will operate on
|
|
44
|
+
|
|
45
|
+
value: the value to add to current state of compartment w/in target component
|
|
46
|
+
|
|
47
|
+
destination_compartment: compartment within component to add a value to
|
|
48
|
+
"""
|
|
49
|
+
component.compartments[destination_compartment] += value
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def append(component, value, destination_compartment):
|
|
53
|
+
"""
|
|
54
|
+
The append/aggregation bundle rule routine. This is primarily useful if
|
|
55
|
+
the compartment is a list of a values/objects (an appendable list construct).
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
component: target component node that this bundle rule will operate on
|
|
59
|
+
|
|
60
|
+
value: the value to append to current state of compartment w/in target component
|
|
61
|
+
|
|
62
|
+
destination_compartment: compartment within component to append to
|
|
63
|
+
"""
|
|
64
|
+
component.compartments[destination_compartment].append(value)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from .command import Command
|
|
2
|
+
from .advanceState import AdvanceState
|
|
3
|
+
from .clamp import Clamp
|
|
4
|
+
from .evolve import Evolve
|
|
5
|
+
from .reset import Reset
|
|
6
|
+
from .track import Track
|
|
7
|
+
from .save import Save
|
|
8
|
+
from .compound import Compound
|
|
9
|
+
from .snapshot import Snapshot
|
|
10
|
+
from .multiclamp import Multiclamp
|
|
11
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from ngcsimlib.commands import Command
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class AdvanceState(Command):
|
|
5
|
+
"""
|
|
6
|
+
As the general form, all models built in ngclearn are state machines and this
|
|
7
|
+
command is designed to advance the state of all of the components passed into
|
|
8
|
+
the command. Prior to advancing the state of each component, this will call the
|
|
9
|
+
`gather` method of that component.
|
|
10
|
+
"""
|
|
11
|
+
def __init__(self, components=None, command_name=None, **kwargs):
|
|
12
|
+
"""
|
|
13
|
+
Required calls on Components: ['advance_state', 'gather', 'name']
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
components: the list of components to advance the state of
|
|
17
|
+
command_name: the name of the command on the controller
|
|
18
|
+
"""
|
|
19
|
+
super().__init__(components=components, command_name=command_name,
|
|
20
|
+
required_calls=['advance_state', 'gather'])
|
|
21
|
+
|
|
22
|
+
def __call__(self, **kwargs):
|
|
23
|
+
for component in self.components:
|
|
24
|
+
self.components[component].gather()
|
|
25
|
+
self.components[component].advance_state(**kwargs)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from ngcsimlib.commands.command import Command
|
|
2
|
+
from ngcsimlib.utils import extract_args
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Clamp(Command):
|
|
6
|
+
"""
|
|
7
|
+
All components in ngclearn have compartments where they store information
|
|
8
|
+
pertaining to their internal state that can be read into or out of by
|
|
9
|
+
commands. The Clamp command is the primary way to manually set the value of
|
|
10
|
+
a compartment on a set of components. The Clamp command requires a
|
|
11
|
+
compartment that a value can be passed into and be clamped to,
|
|
12
|
+
as well as a `clamp_name` used to locate the value when called.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, components=None, compartment=None, clamp_name=None,
|
|
16
|
+
command_name=None, **kwargs):
|
|
17
|
+
"""
|
|
18
|
+
Required calls on Components: ['clamp', 'name']
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
components: a list of components to call clamp on
|
|
22
|
+
|
|
23
|
+
compartment: the compartment being clamped to
|
|
24
|
+
|
|
25
|
+
clamp_name: a keyword to bind the input for this command do
|
|
26
|
+
|
|
27
|
+
command_name: the name of the command on the controller
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
super().__init__(components=components, command_name=command_name,
|
|
31
|
+
required_calls=['clamp'])
|
|
32
|
+
if compartment is None:
|
|
33
|
+
raise RuntimeError(
|
|
34
|
+
self.name + " requires a \'compartment\' to clamp to for construction")
|
|
35
|
+
if clamp_name is None:
|
|
36
|
+
raise RuntimeError(
|
|
37
|
+
self.name + " requires a \'clamp_name\' to bind to for construction")
|
|
38
|
+
|
|
39
|
+
self.clamp_name = clamp_name
|
|
40
|
+
self.compartment = compartment
|
|
41
|
+
|
|
42
|
+
for component in self.components:
|
|
43
|
+
if self.compartment not in self.components[component].compartments.keys():
|
|
44
|
+
raise RuntimeError(self.name + " is attempting to "
|
|
45
|
+
"initialize clamp to "
|
|
46
|
+
"non-existent compartment.")
|
|
47
|
+
|
|
48
|
+
def __call__(self, *args, **kwargs):
|
|
49
|
+
try:
|
|
50
|
+
vals = extract_args([self.clamp_name], *args, **kwargs)
|
|
51
|
+
except RuntimeError:
|
|
52
|
+
raise RuntimeError(self.name + ", " + str(
|
|
53
|
+
self.clamp_name) + " is missing from keyword arguments or a positional "
|
|
54
|
+
"arguments can be provided")
|
|
55
|
+
|
|
56
|
+
for component in self.components:
|
|
57
|
+
self.components[component].clamp(self.compartment, vals[self.clamp_name])
|
|
58
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from ngcsimlib.utils import check_attributes
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Command(ABC):
|
|
6
|
+
"""
|
|
7
|
+
The base class for all commands found in ngcsimlib. At its core, a command is
|
|
8
|
+
essentially a method to be called by the controller that affects the
|
|
9
|
+
components in a simulated complex system / model in some way. When a command
|
|
10
|
+
is made, a preprocessing step is run to verify that all of the needed
|
|
11
|
+
attributes are present on each component. Note that this step does not
|
|
12
|
+
ensure types or values, just that they do or do not exist.
|
|
13
|
+
"""
|
|
14
|
+
def __init__(self, components=None, command_name=None, required_calls=None):
|
|
15
|
+
"""
|
|
16
|
+
Required calls on Components: ['name']
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
components: a list of components to run the command on
|
|
20
|
+
|
|
21
|
+
required_calls: a list of required attributes for all components
|
|
22
|
+
|
|
23
|
+
command_name: the name of the command on the controller
|
|
24
|
+
"""
|
|
25
|
+
self.name = str(command_name)
|
|
26
|
+
self.components = {}
|
|
27
|
+
required_calls = ['name'] if required_calls is None else required_calls + ['name']
|
|
28
|
+
for comp in components:
|
|
29
|
+
if check_attributes(comp, required_calls, fatal=True):
|
|
30
|
+
self.components[comp.name] = comp
|
|
31
|
+
|
|
32
|
+
@abstractmethod
|
|
33
|
+
def __call__(self, *args, **kwargs):
|
|
34
|
+
pass
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from ngcsimlib.commands import Command
|
|
2
|
+
from ngcsimlib.utils import check_attributes
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
class Compound(Command):
|
|
6
|
+
"""
|
|
7
|
+
There is sometimes a need by controllers to be able to call a set of commands
|
|
8
|
+
in series without writing custom command(s) for each combination. The
|
|
9
|
+
compound node/command is used to fill this need. A compound command set is
|
|
10
|
+
very similar to the cycle found inside/within a controller / simulation object.
|
|
11
|
+
"""
|
|
12
|
+
def __init__(self, components=None, command_name=None, command_list=None,
|
|
13
|
+
controller=None, **kwargs):
|
|
14
|
+
"""
|
|
15
|
+
Constructs a compound command construct.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
components: a list of components, this will go unused by default
|
|
19
|
+
|
|
20
|
+
command_name: the name of the compound command
|
|
21
|
+
|
|
22
|
+
command_list: a list of all commands to be called
|
|
23
|
+
|
|
24
|
+
controller: the controller that will be calling these commands
|
|
25
|
+
"""
|
|
26
|
+
super().__init__(components=components, command_name=command_name)
|
|
27
|
+
if controller is None:
|
|
28
|
+
raise RuntimeError("The controller is needed to build a compound command (This should be passed in by default)")
|
|
29
|
+
if command_list is None or len(command_list) == 0:
|
|
30
|
+
warnings.warn("The command list for command " + self.name + " is None or empty")
|
|
31
|
+
|
|
32
|
+
self.command_list = command_list
|
|
33
|
+
self.controller = controller
|
|
34
|
+
|
|
35
|
+
check_attributes(self.controller, self.command_list, fatal=True)
|
|
36
|
+
|
|
37
|
+
def __call__(self, *args, **kwargs):
|
|
38
|
+
for command in self.command_list:
|
|
39
|
+
self.controller.runCommand(command, *args, **kwargs)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from ngcsimlib.commands import Command
|
|
2
|
+
from ngcsimlib.utils import extract_args
|
|
3
|
+
|
|
4
|
+
class Evolve(Command):
|
|
5
|
+
"""
|
|
6
|
+
In many models, there is a need to have either a backward pass or a separate
|
|
7
|
+
method to update some particular internal state (value), e.g., a "learning"
|
|
8
|
+
or evolutionary change that is not related to central compartment states.
|
|
9
|
+
In general, this can be mapped to a call of `evolve`. Like with
|
|
10
|
+
`advanceState`, this will call the gather method prior to calling the
|
|
11
|
+
`evolve` function of every component.
|
|
12
|
+
|
|
13
|
+
"""
|
|
14
|
+
def __init__(self, components=None, frozen_flag=None, command_name=None,
|
|
15
|
+
**kwargs):
|
|
16
|
+
"""
|
|
17
|
+
Required calls on Components: ['evolve', 'gather', 'name']
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
components: the list of components to evolve
|
|
21
|
+
|
|
22
|
+
frozen_flag: the keyword for the flag to freeze this evolve step
|
|
23
|
+
|
|
24
|
+
command_name: the name of the command on the controller
|
|
25
|
+
"""
|
|
26
|
+
super().__init__(components=components, command_name=command_name,
|
|
27
|
+
required_calls=['evolve'])
|
|
28
|
+
|
|
29
|
+
self.frozen_flag = frozen_flag
|
|
30
|
+
|
|
31
|
+
def __call__(self, *args, **kwargs):
|
|
32
|
+
vals = {}
|
|
33
|
+
try:
|
|
34
|
+
vals = extract_args([self.frozen_flag], *args, **kwargs)
|
|
35
|
+
except RuntimeError:
|
|
36
|
+
vals[self.frozen_flag] = False
|
|
37
|
+
|
|
38
|
+
if not vals[self.frozen_flag]:
|
|
39
|
+
for component in self.components:
|
|
40
|
+
self.components[component].gather()
|
|
41
|
+
self.components[component].evolve(**kwargs)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from ngcsimlib.commands.command import Command
|
|
2
|
+
from ngcsimlib.utils import extract_args, check_attributes
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Multiclamp(Command):
|
|
6
|
+
"""
|
|
7
|
+
There are times when a model will have many clamp calls as there might be a
|
|
8
|
+
need to clamp many different values to a model at the same time. As a
|
|
9
|
+
solution to this, ngcsimlib provides the `multiclamp` command. This command is
|
|
10
|
+
used to set a wide range of values to all compartments with the same name
|
|
11
|
+
across all provided compartments.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, components=None, clamp_name=None, command_name=None,
|
|
15
|
+
**kwargs):
|
|
16
|
+
"""
|
|
17
|
+
Required calls on Components: ['clamp', 'name']
|
|
18
|
+
Args:
|
|
19
|
+
components: a list of components to call clamp on
|
|
20
|
+
|
|
21
|
+
clamp_name: a keyword to bind the input for this command do
|
|
22
|
+
|
|
23
|
+
command_name: the name of the command on the controller
|
|
24
|
+
"""
|
|
25
|
+
super().__init__(components=components, command_name=command_name,
|
|
26
|
+
required_calls=['clamp'])
|
|
27
|
+
if clamp_name is None:
|
|
28
|
+
raise RuntimeError(self.name + " requires a \'clamp_name\' to bind to for construction")
|
|
29
|
+
|
|
30
|
+
self.clamp_name = clamp_name
|
|
31
|
+
|
|
32
|
+
def __call__(self, *args, **kwargs):
|
|
33
|
+
try:
|
|
34
|
+
vals = extract_args([self.clamp_name], *args, **kwargs)
|
|
35
|
+
except RuntimeError:
|
|
36
|
+
raise RuntimeError(self.name + ", " + str(self.clamp_name) + " is missing from keyword arguments or a "
|
|
37
|
+
"positional arguments can be provided")
|
|
38
|
+
|
|
39
|
+
for compartment, value in vals[self.clamp_name].items():
|
|
40
|
+
for component in self.components:
|
|
41
|
+
if check_attributes(component, compartment, fatal=False):
|
|
42
|
+
self.components[component].clamp(compartment, value)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from ngcsimlib.commands import Command
|
|
2
|
+
from ngcsimlib.utils import extract_args
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
class Reset(Command):
|
|
6
|
+
"""
|
|
7
|
+
In every model/system, there is a need to reset components back to some
|
|
8
|
+
intial state value(s). As such, many components that maintain a state have a
|
|
9
|
+
reset method implemented within them. The reset command will go through
|
|
10
|
+
the list of components and trigger the reset within each of them.
|
|
11
|
+
"""
|
|
12
|
+
def __init__(self, components=None, reset_name=None, command_name=None,
|
|
13
|
+
**kwargs):
|
|
14
|
+
"""
|
|
15
|
+
Required calls on Components: ['reset', 'name']
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
components: a list of components to reset
|
|
19
|
+
|
|
20
|
+
reset_name: the keyword for the flag on if the reset should happen
|
|
21
|
+
|
|
22
|
+
command_name: the name of the command on the controller
|
|
23
|
+
"""
|
|
24
|
+
super().__init__(components=components, command_name=command_name,
|
|
25
|
+
required_calls=['reset'])
|
|
26
|
+
if reset_name is None:
|
|
27
|
+
raise RuntimeError(self.name + " requires a \'reset_name\' to bind to for construction")
|
|
28
|
+
self.reset_name = reset_name
|
|
29
|
+
|
|
30
|
+
def __call__(self, *args, **kwargs):
|
|
31
|
+
try:
|
|
32
|
+
vals = extract_args([self.reset_name], *args, **kwargs)
|
|
33
|
+
except RuntimeError:
|
|
34
|
+
warnings.warn(self.name + ", " + str(self.reset_name) + " is missing from keyword arguments and no "
|
|
35
|
+
"positional arguments were provided", stacklevel=6)
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
if vals[self.reset_name]:
|
|
39
|
+
for component in self.components:
|
|
40
|
+
self.components[component].reset()
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from ngcsimlib.commands import Command
|
|
2
|
+
from ngcsimlib.utils import extract_args
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
class Save(Command):
|
|
6
|
+
"""
|
|
7
|
+
When training models, there is often a need to snapshot the model and save
|
|
8
|
+
it to disk. The base controller in ngcsimlib is able to save all of the
|
|
9
|
+
commands, components, connections, and steps to a file in order to rebuild
|
|
10
|
+
the model at a later time. However, there is a good chance that the model
|
|
11
|
+
will contain components that have parts that need saving beyond the parameters
|
|
12
|
+
passed in to initialize the component. ngcsimlib solves this by providing a
|
|
13
|
+
save command; this command will call a custom save method on all components
|
|
14
|
+
provided to the command. This custom save method will be responsible for all
|
|
15
|
+
custom values to be saved and determining where to save them inside of a
|
|
16
|
+
provided directory.
|
|
17
|
+
"""
|
|
18
|
+
def __init__(self, components=None, directory_flag=None, command_name=None,
|
|
19
|
+
**kwargs):
|
|
20
|
+
"""
|
|
21
|
+
Required calls on Components: ['save', 'name']
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
components: a list of components to call the save function on
|
|
25
|
+
|
|
26
|
+
directory_flag: keyword for flag for the directory to save to
|
|
27
|
+
|
|
28
|
+
command_name: the name of the command on the controller
|
|
29
|
+
"""
|
|
30
|
+
super().__init__(components=components, command_name=command_name,
|
|
31
|
+
required_calls=['save'])
|
|
32
|
+
if directory_flag is None:
|
|
33
|
+
raise RuntimeError(self.name + " requires a \'directory_flag\' to bind to for construction")
|
|
34
|
+
self.directory_flag = directory_flag
|
|
35
|
+
|
|
36
|
+
def __call__(self, *args, **kwargs):
|
|
37
|
+
try:
|
|
38
|
+
vals = extract_args([self.directory_flag], *args, **kwargs)
|
|
39
|
+
except RuntimeError:
|
|
40
|
+
warnings.warn(self.name + ", " + str(self.directory_flag) + " is missing from keyword arguments and no "
|
|
41
|
+
"positional arguments were provided", stacklevel=6)
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
if vals[self.directory_flag]:
|
|
45
|
+
for component in self.components:
|
|
46
|
+
self.components[component].save(vals[self.directory_flag])
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from ngcsimlib.commands import Command
|
|
2
|
+
|
|
3
|
+
class Snapshot(Command):
|
|
4
|
+
"""
|
|
5
|
+
Sometimes when running through a model, there is a need to extract a value
|
|
6
|
+
from a compartment to the run loop. As such, ngcsimlib provides the snapshot
|
|
7
|
+
command. This command will extract a given attribute from all components
|
|
8
|
+
provided to the command. This command returns a single value if only one
|
|
9
|
+
component is given, otherwise it will return a list where each value
|
|
10
|
+
corresponds to the position of the component in the components list.
|
|
11
|
+
|
|
12
|
+
This command is regularly used for debugging/graph production code that
|
|
13
|
+
exists outside of the model. It would be incorrect to clamp the output of
|
|
14
|
+
this command into another component, if that is the intended goal, please
|
|
15
|
+
see `connect` in the controller.
|
|
16
|
+
"""
|
|
17
|
+
def __init__(self, components=None, attribute=None, command_name=None,
|
|
18
|
+
**kwargs):
|
|
19
|
+
"""
|
|
20
|
+
Required calls on Components: ['name'], and the passed-in attribute
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
components: the component extract the values of
|
|
24
|
+
|
|
25
|
+
attribute: a single attribute to return
|
|
26
|
+
|
|
27
|
+
command_name: the name of the command on the controller
|
|
28
|
+
"""
|
|
29
|
+
super().__init__(components=components, command_name=command_name,
|
|
30
|
+
required_calls=[attribute])
|
|
31
|
+
self.attribute = attribute
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def __call__(self, *args, **kwargs):
|
|
35
|
+
vals = []
|
|
36
|
+
for component in self.components:
|
|
37
|
+
vals.append(getattr(self.components[component], self.attribute))
|
|
38
|
+
|
|
39
|
+
return vals if len(vals) > 1 else vals[0]
|