-
Notifications
You must be signed in to change notification settings - Fork 40
/
variables.py
192 lines (166 loc) · 6.84 KB
/
variables.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
"Implement Variable and ArrayVariable classes"
from collections.abc import Iterable
import numpy as np
from .data import NomialData
from .array import NomialArray
from .math import Monomial
from ..globals import NamedVariables, Vectorize
from ..varkey import VarKey
from ..small_classes import Strings, Numbers
from ..small_scripts import is_sweepvar
def addmodelstodescr(descr, addtonamedvars=None):
"Add models to descr, optionally adding the second argument to NAMEDVARS"
if NamedVariables.lineage:
descr["lineage"] = NamedVariables.lineage
if addtonamedvars:
NamedVariables.namedvars[descr["lineage"]].append(addtonamedvars)
class Variable(Monomial):
"""A described singlet Monomial.
Arguments
---------
*args : list
may contain "name" (Strings)
"value" (Numbers + Quantity) or (Iterable) for a sweep
"units" (Strings)
and/or "label" (Strings)
**descr : dict
VarKey description
Returns
-------
Monomials containing a VarKey with the name '$name',
where $name is the vector's name and i is the VarKey's index.
"""
def __init__(self, *args, **descr):
if len(args) == 1 and isinstance(args[0], VarKey):
self.key, = args
else:
for arg in args:
if isinstance(arg, Strings) and "name" not in descr:
descr["name"] = arg
elif (isinstance(arg, Numbers) or hasattr(arg, "__call__")
and "value" not in descr):
descr["value"] = arg
elif (isinstance(arg, Iterable)
and not isinstance(arg, Strings)):
if is_sweepvar(arg):
descr["value"] = arg
else:
descr["value"] = ("sweep", arg)
elif isinstance(arg, Strings) and "units" not in descr:
descr["units"] = arg
elif isinstance(arg, Strings) and "label" not in descr:
descr["label"] = arg
addmodelstodescr(descr, addtonamedvars=self)
self.key = VarKey(**descr)
Monomial.__init__(self, self.key.hmap)
# NOTE: needed because Signomial.__init__ will change the class
self.__class__ = Variable
__hash__ = NomialData.__hash__
def to(self, units):
"Create new Signomial converted to new units"
return Monomial(self).to(units) # pylint: disable=no-member
def sub(self, *args, **kwargs): # pylint: disable=arguments-differ
"""Same as nomial substitution, but also allows single-argument calls
Example
-------
x = Variable('x')
assert x.sub(3) == Variable('x', value=3)
"""
if len(args) == 1 and "val" not in kwargs:
arg, = args
if not isinstance(arg, dict):
args = [{self: arg}]
return Monomial.sub(self, *args, **kwargs)
class ArrayVariable(NomialArray): # pylint: disable=too-many-locals
"""A described vector of singlet Monomials.
Arguments
---------
shape : int or tuple
length or shape of resulting array
*args :
may contain "name" (Strings)
"value" (Iterable)
"units" (Strings)
and/or "label" (Strings)
**descr :
VarKey description
Returns
-------
NomialArray of Monomials, each containing a VarKey with name '$name_{i}',
where $name is the vector's name and i is the VarKey's index.
"""
def __new__(cls, shape, *args, **descr): # pylint: disable=too-many-branches, too-many-statements, arguments-differ
if "idx" in descr:
raise ValueError("the description field 'idx' is reserved")
shape = (shape,) if isinstance(shape, Numbers) else tuple(shape)
if Vectorize.vectorization:
shape += Vectorize.vectorization
descr["shape"] = shape
for arg in args:
if isinstance(arg, Strings) and "name" not in descr:
descr["name"] = arg
elif (isinstance(arg, (Numbers, Iterable))
and not isinstance(arg, Strings)
and "value" not in descr):
descr["value"] = arg
elif hasattr(arg, "__call__"):
descr["value"] = arg
elif isinstance(arg, Strings) and "units" not in descr:
descr["units"] = arg
elif isinstance(arg, Strings) and "label" not in descr:
descr["label"] = arg
if "name" not in descr:
descr["name"] = "\\fbox{%s}" % VarKey.unique_id()
value_option = None
if "value" in descr:
value_option = "value"
if value_option:
values = descr.pop(value_option)
if value_option and not hasattr(values, "__call__"):
if Vectorize.vectorization:
if not hasattr(values, "shape"):
values = np.full(shape, values, "f")
else:
values = np.broadcast_to(values, reversed(shape)).T
elif not hasattr(values, "shape"):
values = np.array(values)
if values.shape != shape:
raise ValueError("the value's shape %s is different than"
" the vector's %s." % (values.shape, shape))
veckeydescr = descr.copy()
addmodelstodescr(veckeydescr)
if value_option:
if hasattr(values, "__call__"):
veckeydescr["original_fn"] = values
veckeydescr[value_option] = values
veckey = VarKey(**veckeydescr)
descr["veckey"] = veckey
vl = np.empty(shape, dtype="object")
it = np.nditer(vl, flags=['multi_index', 'refs_ok'])
while not it.finished:
i = it.multi_index
it.iternext()
descr["idx"] = i
if value_option:
if hasattr(values, "__call__"):
descr[value_option] = veclinkedfn(values, i)
else:
descr[value_option] = values[i]
vl[i] = Variable(**descr)
obj = np.asarray(vl).view(NomialArray)
obj.key = veckey
obj.units = obj.key.units
return obj
def veclinkedfn(linkedfn, i):
"Generate an indexed linking function."
def newlinkedfn(c):
"Linked function that pulls out a particular index"
return np.array(linkedfn(c))[i]
return newlinkedfn
class VectorizableVariable(Variable, ArrayVariable): # pylint: disable=too-many-ancestors
"A Variable outside a vectorized environment, an ArrayVariable within."
def __new__(cls, *args, **descr):
if Vectorize.vectorization:
shape = descr.pop("shape", ())
return ArrayVariable.__new__(cls, shape, *args, **descr)
return Variable(*args, **descr)