chumpy-fixed 0.71__py3-none-any.whl
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.
- chumpy/__init__.py +117 -0
- chumpy/api_compatibility.py +534 -0
- chumpy/ch.py +1367 -0
- chumpy/ch_ops.py +814 -0
- chumpy/ch_random.py +32 -0
- chumpy/extras.py +72 -0
- chumpy/linalg.py +306 -0
- chumpy/logic.py +39 -0
- chumpy/monitor.py +149 -0
- chumpy/np_tensordot.py +228 -0
- chumpy/optimization.py +161 -0
- chumpy/optimization_internal.py +455 -0
- chumpy/reordering.py +454 -0
- chumpy/test_ch.py +621 -0
- chumpy/test_inner_composition.py +80 -0
- chumpy/test_linalg.py +272 -0
- chumpy/test_optimization.py +204 -0
- chumpy/testing.py +21 -0
- chumpy/utils.py +93 -0
- chumpy/version.py +3 -0
- chumpy_fixed-0.71.dist-info/METADATA +31 -0
- chumpy_fixed-0.71.dist-info/RECORD +25 -0
- chumpy_fixed-0.71.dist-info/WHEEL +5 -0
- chumpy_fixed-0.71.dist-info/licenses/LICENSE.txt +22 -0
- chumpy_fixed-0.71.dist-info/top_level.txt +1 -0
chumpy/ch_random.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author(s): Matthew Loper
|
|
3
|
+
|
|
4
|
+
See LICENCE.txt for licensing and contact information.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import numpy.random
|
|
8
|
+
from .ch import Ch
|
|
9
|
+
|
|
10
|
+
api_not_implemented = ['choice','bytes','shuffle','permutation']
|
|
11
|
+
|
|
12
|
+
api_wrapped_simple = [
|
|
13
|
+
# simple random data
|
|
14
|
+
'rand','randn','randint','random_integers','random_sample','random','ranf','sample',
|
|
15
|
+
|
|
16
|
+
# distributions
|
|
17
|
+
'beta','binomial','chisquare','dirichlet','exponential','f','gamma','geometric','gumbel','hypergeometric',
|
|
18
|
+
'laplace','logistic','lognormal','logseries','multinomial','multivariate_normal','negative_binomial',
|
|
19
|
+
'noncentral_chisquare','noncentral_f','normal','pareto','poisson','power','rayleigh','standard_cauchy',
|
|
20
|
+
'standard_exponential','standard_gamma','standard_normal','standard_t','triangular','uniform','vonmises',
|
|
21
|
+
'wald','weibull','zipf']
|
|
22
|
+
|
|
23
|
+
api_wrapped_direct = ['seed', 'get_state', 'set_state']
|
|
24
|
+
|
|
25
|
+
for rtn in api_wrapped_simple:
|
|
26
|
+
exec('def %s(*args, **kwargs) : return Ch(numpy.random.%s(*args, **kwargs))' % (rtn, rtn))
|
|
27
|
+
|
|
28
|
+
for rtn in api_wrapped_direct:
|
|
29
|
+
exec('%s = numpy.random.%s' % (rtn, rtn))
|
|
30
|
+
|
|
31
|
+
__all__ = api_wrapped_simple + api_wrapped_direct
|
|
32
|
+
|
chumpy/extras.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
__author__ = 'matt'
|
|
2
|
+
|
|
3
|
+
from . import ch
|
|
4
|
+
import numpy as np
|
|
5
|
+
from .utils import row, col
|
|
6
|
+
import scipy.sparse as sp
|
|
7
|
+
import scipy.special
|
|
8
|
+
|
|
9
|
+
class Interp3D(ch.Ch):
|
|
10
|
+
dterms = 'locations'
|
|
11
|
+
terms = 'image'
|
|
12
|
+
|
|
13
|
+
def on_changed(self, which):
|
|
14
|
+
if 'image' in which:
|
|
15
|
+
self.gx, self.gy, self.gz = np.gradient(self.image)
|
|
16
|
+
|
|
17
|
+
def compute_r(self):
|
|
18
|
+
locations = self.locations.r.copy()
|
|
19
|
+
for i in range(3):
|
|
20
|
+
locations[:,i] = np.clip(locations[:,i], 0, self.image.shape[i]-1)
|
|
21
|
+
locs = np.floor(locations).astype(np.uint32)
|
|
22
|
+
result = self.image[locs[:,0], locs[:,1], locs[:,2]]
|
|
23
|
+
offset = (locations - locs)
|
|
24
|
+
dr = self.dr_wrt(self.locations).dot(offset.ravel())
|
|
25
|
+
return result + dr
|
|
26
|
+
|
|
27
|
+
def compute_dr_wrt(self, wrt):
|
|
28
|
+
if wrt is self.locations:
|
|
29
|
+
locations = self.locations.r.copy()
|
|
30
|
+
for i in range(3):
|
|
31
|
+
locations[:,i] = np.clip(locations[:,i], 0, self.image.shape[i]-1)
|
|
32
|
+
locations = locations.astype(np.uint32)
|
|
33
|
+
|
|
34
|
+
xc = col(self.gx[locations[:,0], locations[:,1], locations[:,2]])
|
|
35
|
+
yc = col(self.gy[locations[:,0], locations[:,1], locations[:,2]])
|
|
36
|
+
zc = col(self.gz[locations[:,0], locations[:,1], locations[:,2]])
|
|
37
|
+
|
|
38
|
+
data = np.vstack([xc.ravel(), yc.ravel(), zc.ravel()]).T.copy()
|
|
39
|
+
JS = np.arange(locations.size)
|
|
40
|
+
IS = JS // 3
|
|
41
|
+
|
|
42
|
+
return sp.csc_matrix((data.ravel(), (IS, JS)))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class gamma(ch.Ch):
|
|
46
|
+
dterms = 'x',
|
|
47
|
+
|
|
48
|
+
def compute_r(self):
|
|
49
|
+
return scipy.special.gamma(self.x.r)
|
|
50
|
+
|
|
51
|
+
def compute_dr_wrt(self, wrt):
|
|
52
|
+
if wrt is self.x:
|
|
53
|
+
d = scipy.special.polygamma(0, self.x.r)*self.r
|
|
54
|
+
return sp.diags([d.ravel()], [0])
|
|
55
|
+
|
|
56
|
+
# This function is based directly on the "moment" function
|
|
57
|
+
# in scipy, specifically in mstats_basic.py.
|
|
58
|
+
def moment(a, moment=1, axis=0):
|
|
59
|
+
if moment == 1:
|
|
60
|
+
# By definition the first moment about the mean is 0.
|
|
61
|
+
shape = list(a.shape)
|
|
62
|
+
del shape[axis]
|
|
63
|
+
if shape:
|
|
64
|
+
# return an actual array of the appropriate shape
|
|
65
|
+
return ch.zeros(shape, dtype=float)
|
|
66
|
+
else:
|
|
67
|
+
# the input was 1D, so return a scalar instead of a rank-0 array
|
|
68
|
+
return np.float64(0.0)
|
|
69
|
+
else:
|
|
70
|
+
mn = ch.expand_dims(a.mean(axis=axis), axis)
|
|
71
|
+
s = ch.power((a-mn), moment)
|
|
72
|
+
return s.mean(axis=axis)
|
chumpy/linalg.py
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
Author(s): Matthew Loper
|
|
6
|
+
|
|
7
|
+
See LICENCE.txt for licensing and contact information.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
__all__ = ['inv', 'svd', 'det', 'slogdet', 'pinv', 'lstsq', 'norm']
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
import scipy.sparse as sp
|
|
15
|
+
from .ch import Ch, depends_on
|
|
16
|
+
from .ch_ops import NanDivide
|
|
17
|
+
from .ch_ops import asarray as ch_asarray
|
|
18
|
+
from .ch_ops import sqrt as ch_sqrt
|
|
19
|
+
from .ch_ops import sum as ch_sum
|
|
20
|
+
from .reordering import concatenate as ch_concatenate
|
|
21
|
+
from .ch_random import randn as ch_random_randn
|
|
22
|
+
from .utils import row, col
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
asarray = ch_asarray
|
|
27
|
+
import inspect
|
|
28
|
+
exec(''.join(inspect.getsourcelines(np.linalg.tensorinv)[0]))
|
|
29
|
+
__all__.append('tensorinv')
|
|
30
|
+
except: pass
|
|
31
|
+
|
|
32
|
+
def norm(x, ord=None, axis=None):
|
|
33
|
+
if ord is not None or axis is not None:
|
|
34
|
+
raise NotImplementedError("'ord' and 'axis' should be None for now.")
|
|
35
|
+
|
|
36
|
+
return ch_sqrt(ch_sum(x**2))
|
|
37
|
+
|
|
38
|
+
# This version works but derivatives are too slow b/c of nested loop in Svd implementation.
|
|
39
|
+
# def lstsq(a, b):
|
|
40
|
+
# u, s, v = Svd(a)
|
|
41
|
+
# x = (v.T / s).dot(u.T.dot(b))
|
|
42
|
+
# residuals = NotImplementedError # ch_sum((a.dot(x) - b)**2, axis=0)
|
|
43
|
+
# rank = NotImplementedError
|
|
44
|
+
# s = NotImplementedError
|
|
45
|
+
# return x, residuals, rank, s
|
|
46
|
+
|
|
47
|
+
def lstsq(a, b, rcond=-1):
|
|
48
|
+
if rcond != -1:
|
|
49
|
+
raise Exception('non-default rcond not yet implemented')
|
|
50
|
+
|
|
51
|
+
x = Ch(lambda a, b : pinv(a).dot(b))
|
|
52
|
+
x.a = a
|
|
53
|
+
x.b = b
|
|
54
|
+
residuals = ch_sum( (x.a.dot(x) - x.b) **2 , axis=0)
|
|
55
|
+
rank = NotImplementedError
|
|
56
|
+
s = NotImplementedError
|
|
57
|
+
|
|
58
|
+
return x, residuals, rank, s
|
|
59
|
+
|
|
60
|
+
def Svd(x, full_matrices=0, compute_uv=1):
|
|
61
|
+
|
|
62
|
+
if full_matrices != 0:
|
|
63
|
+
raise Exception('full_matrices must be 0')
|
|
64
|
+
if compute_uv != 1:
|
|
65
|
+
raise Exception('compute_uv must be 1')
|
|
66
|
+
|
|
67
|
+
need_transpose = x.shape[0] < x.shape[1]
|
|
68
|
+
|
|
69
|
+
if need_transpose:
|
|
70
|
+
x = x.T
|
|
71
|
+
|
|
72
|
+
svd_d = SvdD(x=x)
|
|
73
|
+
svd_v = SvdV(x=x, svd_d=svd_d)
|
|
74
|
+
svd_u = SvdU(x=x, svd_d=svd_d, svd_v=svd_v)
|
|
75
|
+
|
|
76
|
+
if need_transpose:
|
|
77
|
+
return svd_v, svd_d, svd_u.T
|
|
78
|
+
else:
|
|
79
|
+
return svd_u, svd_d, svd_v.T
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Pinv(Ch):
|
|
83
|
+
dterms = 'mtx'
|
|
84
|
+
|
|
85
|
+
def on_changed(self, which):
|
|
86
|
+
mtx = self.mtx
|
|
87
|
+
if mtx.shape[1] > mtx.shape[0]:
|
|
88
|
+
result = mtx.T.dot(Inv(mtx.dot(mtx.T)))
|
|
89
|
+
else:
|
|
90
|
+
result = Inv(mtx.T.dot(mtx)).dot(mtx.T)
|
|
91
|
+
self._result = result
|
|
92
|
+
|
|
93
|
+
def compute_r(self):
|
|
94
|
+
return self._result.r
|
|
95
|
+
|
|
96
|
+
def compute_dr_wrt(self, wrt):
|
|
97
|
+
if wrt is self.mtx:
|
|
98
|
+
return self._result.dr_wrt(self.mtx)
|
|
99
|
+
|
|
100
|
+
# Couldn't make the SVD version of pinv work yet...
|
|
101
|
+
#
|
|
102
|
+
# class Pinv(Ch):
|
|
103
|
+
# dterms = 'mtx'
|
|
104
|
+
#
|
|
105
|
+
# def on_changed(self, which):
|
|
106
|
+
# u, s, v = Svd(self.mtx)
|
|
107
|
+
# result = (v.T * (NanDivide(1.,row(s)))).dot(u.T)
|
|
108
|
+
# self.add_dterm('_result', result)
|
|
109
|
+
#
|
|
110
|
+
# def compute_r(self):
|
|
111
|
+
# return self._result.r
|
|
112
|
+
#
|
|
113
|
+
# def compute_dr_wrt(self, wrt):
|
|
114
|
+
# if wrt is self._result:
|
|
115
|
+
# return 1
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class LogAbsDet(Ch):
|
|
120
|
+
dterms = 'x'
|
|
121
|
+
|
|
122
|
+
def on_changed(self, which):
|
|
123
|
+
self.sign, self.slogdet = np.linalg.slogdet(self.x.r)
|
|
124
|
+
|
|
125
|
+
def compute_r(self):
|
|
126
|
+
return self.slogdet
|
|
127
|
+
|
|
128
|
+
def compute_dr_wrt(self, wrt):
|
|
129
|
+
if wrt is self.x:
|
|
130
|
+
return row(np.linalg.inv(self.x.r).T)
|
|
131
|
+
|
|
132
|
+
class SignLogAbsDet(Ch):
|
|
133
|
+
dterms = 'logabsdet',
|
|
134
|
+
|
|
135
|
+
def compute_r(self):
|
|
136
|
+
_ = self.logabsdet.r
|
|
137
|
+
return self.logabsdet.sign
|
|
138
|
+
|
|
139
|
+
def compute_dr_wrt(self, wrt):
|
|
140
|
+
return None
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class Det(Ch):
|
|
144
|
+
dterms = 'x'
|
|
145
|
+
|
|
146
|
+
def compute_r(self):
|
|
147
|
+
return np.linalg.det(self.x.r)
|
|
148
|
+
|
|
149
|
+
def compute_dr_wrt(self, wrt):
|
|
150
|
+
if wrt is self.x:
|
|
151
|
+
return row(self.r * np.linalg.inv(self.x.r).T)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class Inv(Ch):
|
|
155
|
+
dterms = 'a'
|
|
156
|
+
|
|
157
|
+
def compute_r(self):
|
|
158
|
+
return np.linalg.inv(self.a.r)
|
|
159
|
+
|
|
160
|
+
def compute_dr_wrt(self, wrt):
|
|
161
|
+
if wrt is not self.a:
|
|
162
|
+
return None
|
|
163
|
+
|
|
164
|
+
Ainv = self.r
|
|
165
|
+
|
|
166
|
+
if Ainv.ndim <= 2:
|
|
167
|
+
return -np.kron(Ainv, Ainv.T)
|
|
168
|
+
else:
|
|
169
|
+
Ainv = np.reshape(Ainv, (-1, Ainv.shape[-2], Ainv.shape[-1]))
|
|
170
|
+
AinvT = np.rollaxis(Ainv, -1, -2)
|
|
171
|
+
AinvT = np.reshape(AinvT, (-1, AinvT.shape[-2], AinvT.shape[-1]))
|
|
172
|
+
result = np.dstack([-np.kron(Ainv[i], AinvT[i]).T for i in range(Ainv.shape[0])]).T
|
|
173
|
+
result = sp.block_diag(result)
|
|
174
|
+
|
|
175
|
+
return result
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
class SvdD(Ch):
|
|
179
|
+
dterms = 'x'
|
|
180
|
+
|
|
181
|
+
@depends_on('x')
|
|
182
|
+
def UDV(self):
|
|
183
|
+
result = np.linalg.svd(self.x.r, full_matrices=False)
|
|
184
|
+
result = [result[0], result[1], result[2].T]
|
|
185
|
+
result[1][np.abs(result[1]) < np.spacing(1)] = 0.
|
|
186
|
+
return result
|
|
187
|
+
|
|
188
|
+
def compute_r(self):
|
|
189
|
+
return self.UDV[1]
|
|
190
|
+
|
|
191
|
+
def compute_dr_wrt(self, wrt):
|
|
192
|
+
if wrt is not self.x:
|
|
193
|
+
return
|
|
194
|
+
|
|
195
|
+
u, d, v = self.UDV
|
|
196
|
+
shp = self.x.r.shape
|
|
197
|
+
u = u[:shp[0], :shp[1]]
|
|
198
|
+
v = v[:shp[1], :d.size]
|
|
199
|
+
|
|
200
|
+
result = np.einsum('ik,jk->kij', u, v)
|
|
201
|
+
result = result.reshape((result.shape[0], -1))
|
|
202
|
+
return result
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class SvdV(Ch):
|
|
206
|
+
terms = 'svd_d'
|
|
207
|
+
dterms = 'x'
|
|
208
|
+
|
|
209
|
+
def compute_r(self):
|
|
210
|
+
return self.svd_d.UDV[2]
|
|
211
|
+
|
|
212
|
+
def compute_dr_wrt(self, wrt):
|
|
213
|
+
if wrt is not self.x:
|
|
214
|
+
return
|
|
215
|
+
|
|
216
|
+
U,_D,V = self.svd_d.UDV
|
|
217
|
+
|
|
218
|
+
shp = self.svd_d.x.r.shape
|
|
219
|
+
mxsz = max(shp[0], shp[1])
|
|
220
|
+
#mnsz = min(shp[0], shp[1])
|
|
221
|
+
D = np.zeros(mxsz)
|
|
222
|
+
D[:_D.size] = _D
|
|
223
|
+
|
|
224
|
+
omega = np.zeros((shp[0], shp[1], shp[1], shp[1]))
|
|
225
|
+
|
|
226
|
+
M = shp[0]
|
|
227
|
+
N = shp[1]
|
|
228
|
+
|
|
229
|
+
assert(M >= N)
|
|
230
|
+
|
|
231
|
+
for i in range(shp[0]):
|
|
232
|
+
for j in range(shp[1]):
|
|
233
|
+
for k in range(N):
|
|
234
|
+
for l in range(k+1, N):
|
|
235
|
+
mtx = np.array([
|
|
236
|
+
[D[l],D[k]],
|
|
237
|
+
[D[k],D[l]]])
|
|
238
|
+
|
|
239
|
+
rhs = np.array([U[i,k]*V[j,l], -U[i,l]*V[j,k]])
|
|
240
|
+
result = np.linalg.solve(mtx, rhs)
|
|
241
|
+
|
|
242
|
+
omega[i,j,k,l] = result[1]
|
|
243
|
+
omega[i,j,l,k] = -result[1]
|
|
244
|
+
|
|
245
|
+
#print 'v size is %s' % (str(V.shape),)
|
|
246
|
+
#print 'v omega size is %s' % (str(omega.shape),)
|
|
247
|
+
assert(V.shape[1] == omega.shape[2])
|
|
248
|
+
return np.einsum('ak,ijkl->alij', -V, omega).reshape((self.r.size, wrt.r.size))
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class SvdU(Ch):
|
|
252
|
+
dterms = 'x'
|
|
253
|
+
terms = 'svd_d', 'svd_v'
|
|
254
|
+
|
|
255
|
+
def compute_r(self):
|
|
256
|
+
return self.svd_d.UDV[0]
|
|
257
|
+
|
|
258
|
+
def compute_dr_wrt(self, wrt):
|
|
259
|
+
if wrt is self.x:
|
|
260
|
+
# return (
|
|
261
|
+
# self.svd_d.x.dot(self.svd_v)
|
|
262
|
+
# /
|
|
263
|
+
# self.svd_d.reshape((1,-1))
|
|
264
|
+
# ).dr_wrt(self.svd_d.x)
|
|
265
|
+
return (
|
|
266
|
+
NanDivide(
|
|
267
|
+
self.svd_d.x.dot(self.svd_v),
|
|
268
|
+
self.svd_d.reshape((1,-1)))
|
|
269
|
+
).dr_wrt(self.svd_d.x)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
inv = Inv
|
|
273
|
+
svd = Svd
|
|
274
|
+
det = Det
|
|
275
|
+
pinv = Pinv
|
|
276
|
+
|
|
277
|
+
def slogdet(*args):
|
|
278
|
+
n = len(args)
|
|
279
|
+
if n == 1:
|
|
280
|
+
r2 = LogAbsDet(x=args[0])
|
|
281
|
+
r1 = SignLogAbsDet(r2)
|
|
282
|
+
return r1, r2
|
|
283
|
+
else:
|
|
284
|
+
r2 = [LogAbsDet(x=arg) for arg in args]
|
|
285
|
+
r1 = [SignLogAbsDet(r) for r in r2]
|
|
286
|
+
r2 = ch_concatenate(r2)
|
|
287
|
+
return r1, r2
|
|
288
|
+
|
|
289
|
+
def main():
|
|
290
|
+
|
|
291
|
+
tmp = ch_random_randn(100).reshape((10,10))
|
|
292
|
+
print('chumpy version: ' + str(slogdet(tmp)[1].r))
|
|
293
|
+
print('old version:' + str(np.linalg.slogdet(tmp.r)[1]))
|
|
294
|
+
|
|
295
|
+
eps = 1e-10
|
|
296
|
+
diff = np.random.rand(100) * eps
|
|
297
|
+
diff_reshaped = diff.reshape((10,10))
|
|
298
|
+
print(np.linalg.slogdet(tmp.r+diff_reshaped)[1] - np.linalg.slogdet(tmp.r)[1])
|
|
299
|
+
print(slogdet(tmp)[1].dr_wrt(tmp).dot(diff))
|
|
300
|
+
|
|
301
|
+
print(np.linalg.slogdet(tmp.r)[0])
|
|
302
|
+
print(slogdet(tmp)[0])
|
|
303
|
+
|
|
304
|
+
if __name__ == '__main__':
|
|
305
|
+
main()
|
|
306
|
+
|
chumpy/logic.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author(s): Matthew Loper
|
|
3
|
+
|
|
4
|
+
See LICENCE.txt for licensing and contact information.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__author__ = 'matt'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
__all__ = [] # added to incrementally below
|
|
11
|
+
|
|
12
|
+
from . import ch
|
|
13
|
+
from .ch import Ch
|
|
14
|
+
import numpy as np
|
|
15
|
+
|
|
16
|
+
class LogicFunc(Ch):
|
|
17
|
+
dterms = 'a' # we keep this here so that changes to children of "a" will trigger cache changes
|
|
18
|
+
terms = 'args', 'kwargs', 'funcname'
|
|
19
|
+
|
|
20
|
+
def compute_r(self):
|
|
21
|
+
arr = self.a
|
|
22
|
+
fn = getattr(np, self.funcname)
|
|
23
|
+
return fn(arr, *self.args, **self.kwargs)
|
|
24
|
+
|
|
25
|
+
def compute_dr_wrt(self, wrt):
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
unaries = 'all', 'any', 'isfinite', 'isinf', 'isnan', 'isneginf', 'isposinf', 'logical_not'
|
|
30
|
+
for unary in unaries:
|
|
31
|
+
exec("def %s(a, *args, **kwargs): return LogicFunc(a=a, args=args, kwargs=kwargs, funcname='%s')" % (unary, unary))
|
|
32
|
+
__all__ += unaries
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
if __name__ == '__main__':
|
|
37
|
+
from . import ch
|
|
38
|
+
print(all(np.array([1,2,3])))
|
|
39
|
+
print(isinf(np.array([0,2,3])))
|
chumpy/monitor.py
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Logging service for tracking dr tree changes from root objective
|
|
3
|
+
and record every step that incrementally changes the dr tree
|
|
4
|
+
|
|
5
|
+
'''
|
|
6
|
+
import os, sys, time
|
|
7
|
+
import json
|
|
8
|
+
import psutil
|
|
9
|
+
|
|
10
|
+
import scipy.sparse as sp
|
|
11
|
+
import numpy as np
|
|
12
|
+
from . import reordering
|
|
13
|
+
|
|
14
|
+
_TWO_20 = float(2 **20)
|
|
15
|
+
|
|
16
|
+
'''
|
|
17
|
+
memory utils
|
|
18
|
+
|
|
19
|
+
'''
|
|
20
|
+
def pdb_mem():
|
|
21
|
+
from .monitor import get_current_memory
|
|
22
|
+
mem = get_current_memory()
|
|
23
|
+
if mem > 7000:
|
|
24
|
+
import pdb;pdb.set_trace()
|
|
25
|
+
|
|
26
|
+
def get_peak_mem():
|
|
27
|
+
'''
|
|
28
|
+
this returns peak memory use since process starts till the moment its called
|
|
29
|
+
'''
|
|
30
|
+
import resource
|
|
31
|
+
rusage_denom = 1024.
|
|
32
|
+
if sys.platform == 'darwin':
|
|
33
|
+
# ... it seems that in OSX the output is different units ...
|
|
34
|
+
rusage_denom = rusage_denom * rusage_denom
|
|
35
|
+
mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / rusage_denom
|
|
36
|
+
return mem
|
|
37
|
+
|
|
38
|
+
def get_current_memory():
|
|
39
|
+
p = psutil.Process(os.getpid())
|
|
40
|
+
mem = p.memory_info()[0]/_TWO_20
|
|
41
|
+
|
|
42
|
+
return mem
|
|
43
|
+
|
|
44
|
+
'''
|
|
45
|
+
Helper for Profiler
|
|
46
|
+
'''
|
|
47
|
+
|
|
48
|
+
def build_cache_info(k, v, info_dict):
|
|
49
|
+
if v is not None:
|
|
50
|
+
issparse = sp.issparse(v)
|
|
51
|
+
size = v.size
|
|
52
|
+
if issparse:
|
|
53
|
+
nonzero = len(v.data)
|
|
54
|
+
else:
|
|
55
|
+
nonzero = np.count_nonzero(v)
|
|
56
|
+
info_dict[k.short_name] = {
|
|
57
|
+
'sparse': issparse,
|
|
58
|
+
'size' : str(size),
|
|
59
|
+
'nonzero' : nonzero,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def cache_info(ch_node):
|
|
64
|
+
result = {}
|
|
65
|
+
if isinstance(ch_node, reordering.Concatenate) and hasattr(ch_node, 'dr_cached') and len(ch_node.dr_cached) > 0:
|
|
66
|
+
for k, v in ch_node.dr_cached.items():
|
|
67
|
+
build_cache_info(k, v, result)
|
|
68
|
+
elif len(ch_node._cache['drs']) > 0:
|
|
69
|
+
for k, v in ch_node._cache['drs'].items():
|
|
70
|
+
build_cache_info(k, v, result)
|
|
71
|
+
|
|
72
|
+
return result
|
|
73
|
+
|
|
74
|
+
class DrWrtProfiler(object):
|
|
75
|
+
base_path = os.path.abspath('profiles')
|
|
76
|
+
|
|
77
|
+
def __init__(self, root, base_path=None):
|
|
78
|
+
self.root = root.obj
|
|
79
|
+
self.history = []
|
|
80
|
+
|
|
81
|
+
ts = time.time()
|
|
82
|
+
if base_path:
|
|
83
|
+
self.base_path = base_path
|
|
84
|
+
|
|
85
|
+
self.path = os.path.join(self.base_path, 'profile_%s.json' % str(ts))
|
|
86
|
+
self.root_path = os.path.join(self.base_path, 'root_%s.json' % str(ts))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
with open(self.root_path, 'w') as f:
|
|
90
|
+
json.dump(self.dump_tree(self.root), f, indent=4)
|
|
91
|
+
|
|
92
|
+
def dump_tree(self, node):
|
|
93
|
+
if not hasattr(node, 'dterms'):
|
|
94
|
+
return []
|
|
95
|
+
|
|
96
|
+
node_dict = self.serialize_node(node, verbose=False)
|
|
97
|
+
if hasattr(node, 'visited') and node.visited:
|
|
98
|
+
node_dict.update({'indirect':True})
|
|
99
|
+
return node_dict
|
|
100
|
+
|
|
101
|
+
node.visited = True
|
|
102
|
+
children_list = []
|
|
103
|
+
for dterm in node.dterms:
|
|
104
|
+
if hasattr(node, dterm):
|
|
105
|
+
child = getattr(node, dterm)
|
|
106
|
+
if hasattr(child, 'dterms') or hasattr(child, 'terms'):
|
|
107
|
+
children_list.append(self.dump_tree(child))
|
|
108
|
+
node_dict.update({'children':children_list})
|
|
109
|
+
return node_dict
|
|
110
|
+
|
|
111
|
+
def serialize_node(self, ch_node, verbose=True):
|
|
112
|
+
node_id = id(ch_node)
|
|
113
|
+
name = ch_node.short_name
|
|
114
|
+
ts = time.time()
|
|
115
|
+
status = ch_node._status
|
|
116
|
+
mem = get_current_memory()
|
|
117
|
+
node_cache_info = cache_info(ch_node)
|
|
118
|
+
|
|
119
|
+
rec = {
|
|
120
|
+
'id': str(node_id),
|
|
121
|
+
'indirect' : False,
|
|
122
|
+
}
|
|
123
|
+
if verbose:
|
|
124
|
+
rec.update({
|
|
125
|
+
'name':name,
|
|
126
|
+
'ts' : ts,
|
|
127
|
+
'status':status,
|
|
128
|
+
'mem': mem,
|
|
129
|
+
'cache': node_cache_info,
|
|
130
|
+
})
|
|
131
|
+
return rec
|
|
132
|
+
|
|
133
|
+
def show_tree(self, label):
|
|
134
|
+
'''
|
|
135
|
+
show tree from the root node
|
|
136
|
+
'''
|
|
137
|
+
self.root.show_tree_cache(label)
|
|
138
|
+
|
|
139
|
+
def record(self, ch_node):
|
|
140
|
+
'''
|
|
141
|
+
Incremental changes
|
|
142
|
+
'''
|
|
143
|
+
rec = self.serialize_node(ch_node)
|
|
144
|
+
self.history.append(rec)
|
|
145
|
+
|
|
146
|
+
def harvest(self):
|
|
147
|
+
print('collecting and dump to file %s' % self.path)
|
|
148
|
+
with open(self.path, 'w') as f:
|
|
149
|
+
json.dump(self.history, f, indent=4)
|