Skip to content

Commit bba20ca

Browse files
willgebhardtago109
andauthored
Adds validation and guides (#26)
* Adds validation and guides * Update compartment.py --------- Co-authored-by: Alex Ororbia <agocse109@gmail.com>
1 parent a9c6eac commit bba20ca

6 files changed

Lines changed: 411 additions & 83 deletions

File tree

ngcsimlib/compartment.py

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,21 @@
66

77
class Compartment:
88
"""
9-
Compartments in ngcsimlib are container objects for storing the stateful values of components. Compartments are
10-
tracked globaly and are automatically linked to components and methods during compiling to allow for stateful
11-
mechanics to be run without the need for the class object. Compartments also provide an entry and exit point for
12-
values inside of components allowing for cables to be connected for sending and receiving values.
9+
Compartments in ngcsimlib are container objects for storing the stateful
10+
values of components. Compartments are
11+
tracked globaly and are automatically linked to components and methods
12+
during compiling to allow for stateful
13+
mechanics to be run without the need for the class object. Compartments
14+
also provide an entry and exit point for
15+
values inside of components allowing for cables to be connected for
16+
sending and receiving values.
1317
"""
1418

1519
@classmethod
1620
def is_compartment(cls, obj):
1721
"""
18-
A method for verifying if a provided object is a compartment. All compartments have `_is_compartment` set to
22+
A method for verifying if a provided object is a compartment. All
23+
compartments have `_is_compartment` set to
1924
true by default and this is
2025
2126
Args:
@@ -26,14 +31,18 @@ def is_compartment(cls, obj):
2631
"""
2732
return hasattr(obj, "_is_compartment")
2833

29-
def __init__(self, initial_value=None, static=False):
34+
def __init__(self, initial_value=None, static=False, is_input=False):
3035
"""
31-
Builds a compartment to be used inside a component. It is important to note that building compartments
32-
outside of components may cause unexpected behavior as components interact with their compartments during
36+
Builds a compartment to be used inside a component. It is important
37+
to note that building compartments
38+
outside of components may cause unexpected behavior as components
39+
interact with their compartments during
3340
construction to finish initializing them.
3441
Args:
35-
initial_value: The initial value of the compartment. As a general practice it is a good idea to
36-
provide a value that is similar to the values that will normally be stored here, such as an array of
42+
initial_value: The initial value of the compartment. As a general
43+
practice it is a good idea to
44+
provide a value that is similar to the values that will
45+
normally be stored here, such as an array of
3746
zeros of the correct length. (default: None)
3847
3948
static: a flag to lock a compartment to be static (default: False)
@@ -45,11 +54,14 @@ def __init__(self, initial_value=None, static=False):
4554
self._uid = uuid.uuid4()
4655
self.name = None
4756
self.path = None
57+
self.is_input = is_input
58+
self._is_destination = False
4859

4960
def _setup(self, current_component, key):
5061
"""
51-
Finishes initializing the compartment, called by the component that builds the compartment
52-
(Handel automatically)
62+
Finishes initializing the compartment, called by the component that
63+
builds the compartment
64+
(Handled automatically)
5365
"""
5466
self.__add_connection = current_component.add_connection
5567
self.name = current_component.name + "/" + key
@@ -58,7 +70,8 @@ def _setup(self, current_component, key):
5870

5971
def set(self, value):
6072
"""
61-
Sets the value of the compartment if it not static (Raises a runtime error)
73+
Sets the value of the compartment if it not static (Raises a runtime
74+
error)
6275
Args:
6376
value: the new value to be set
6477
"""
@@ -89,8 +102,10 @@ def __str__(self):
89102

90103
def __lshift__(self, other) -> None:
91104
"""
92-
Overrides the left shift operation to be used for wiring compartments into one another
93-
if other is not an Operation it will create an overwrite operation with other as the argument,
105+
Overrides the left shift operation to be used for wiring compartments
106+
into one another
107+
if other is not an Operation it will create an overwrite operation
108+
with other as the argument,
94109
otherwise it will use the provided operation
95110
96111
Args:
@@ -103,3 +118,16 @@ def __lshift__(self, other) -> None:
103118
op = overwrite(other)
104119
op.set_destination(self)
105120
self.__add_connection(op)
121+
122+
self._is_destination = True
123+
124+
def is_wired(self):
125+
"""
126+
Returns: if this compartment not marked as an input, or is marked and
127+
has an input
128+
129+
"""
130+
if not self.is_input:
131+
return True
132+
133+
return self._is_destination

ngcsimlib/component.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
from abc import abstractmethod
22
from ngcsimlib.metaComponent import MetaComponent
33
from ngcsimlib.compartment import Compartment
4-
4+
from ngcsimlib.logger import warn
55

66
class Component(metaclass=MetaComponent):
77
"""
88
Components are a foundational part of ngclearn and its component/command
99
structure. In ngclearn, all stateful parts of a model take the form of
1010
components. The internal storage of the state within a component takes one
1111
of two forms, either as a compartment or as a member variable. The member
12-
variables are values such as hyperparameters and weights/synaptic efficacies,
12+
variables are values such as hyperparameters and weights/synaptic
13+
efficacies,
1314
where the transfer of their individual state from component to component is
1415
not needed.
1516
Compartments, on the other hand, are where the state information, both from
1617
and for other components, are stored. As the components are the stateful
17-
pieces of the model, they also contain the methods and logic behind advancing
18+
pieces of the model, they also contain the methods and logic behind
19+
advancing
1820
their internal state (values) forward in time.
1921
"""
2022

@@ -28,13 +30,13 @@ def __init__(self, name, **kwargs):
2830
Args:
2931
name: the name of the component
3032
31-
kwargs: additional keyword arguments. These are not used in the base class,
33+
kwargs: additional keyword arguments. These are not used in the
34+
base class,
3235
but this is here for future use if needed.
3336
"""
3437
# Component Data
3538
self.name = name
3639

37-
3840
##Intialization Methods
3941

4042
## Runtime Methods
@@ -47,9 +49,36 @@ def clamp(self, compartment, value):
4749
4850
value: provided Value
4951
"""
50-
if hasattr(self, compartment) and Compartment.is_compartment(getattr(self, compartment)):
52+
if hasattr(self, compartment) and Compartment.is_compartment(
53+
getattr(self, compartment)):
5154
getattr(self, compartment).set(value)
5255

56+
def validate(self):
57+
"""
58+
Validates that each compartment of the component is wired correctly
59+
60+
Returns: if it is valid
61+
"""
62+
valid = True
63+
for key, item in self.__dict__.items():
64+
if Compartment.is_compartment(item):
65+
if not item.is_wired():
66+
_help = self.help()
67+
_path = ("compartments/inputs/" + item.path.split("/")[-1])
68+
for _p in _path.split("/"):
69+
_help = _help.get(_p, None)
70+
if _help is None:
71+
break
72+
73+
msg = (f"The compartment at the path \"{item.path}\" is "
74+
f"expected to have an incoming cable and it "
75+
f"currently does not.")
76+
if _help is not None:
77+
msg += f"\nCompartment Description:\t{_help}"
78+
warn(msg)
79+
valid = False
80+
return valid
81+
5382
##Abstract Methods
5483
@abstractmethod
5584
def advance_state(self, **kwargs):
@@ -78,3 +107,9 @@ def save(self, directory, **kwargs):
78107
directory: the directory to save the state to
79108
"""
80109
pass
110+
111+
@classmethod
112+
@abstractmethod
113+
def help(cls):
114+
pass
115+

0 commit comments

Comments
 (0)