qlang 0.0.27180000 → 0.0.27182000
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.
- checksums.yaml +4 -4
- data/README.md +45 -12
- data/bin/qlang +2 -0
- data/lib/qlang.rb +21 -24
- data/lib/qlang/api.rb +2 -37
- data/lib/qlang/api/func_api.rb +5 -3
- data/lib/qlang/api/integral_api.rb +4 -4
- data/lib/qlang/api/list_api.rb +4 -4
- data/lib/qlang/api/matrix_api.rb +5 -3
- data/lib/qlang/api/vector_api.rb +7 -3
- data/lib/qlang/exec.rb +3 -2
- data/lib/qlang/lexer/base.rb +30 -62
- data/lib/qlang/lexer/tokens.rb +67 -34
- data/lib/qlang/lexer/wrap_lexer.rb +6 -7
- data/lib/qlang/parser.rb +47 -30
- data/lib/qlang/parser/formula_parser.rb +1 -1
- data/lib/qlang/parser/func_parser.rb +1 -1
- data/lib/qlang/parser/list_parser.rb +1 -2
- data/lib/qlang/utils/langs.yml +7 -0
- data/lib/qlang/utils/ruby_ext.rb +46 -0
- data/lib/qlang/version.rb +1 -1
- data/spec/langs/Haskell/ex1_after.hs +74 -0
- data/spec/langs/Haskell/ex1_before.hs +74 -0
- data/spec/langs/Python/ex1_after.py +426 -0
- data/spec/langs/Python/ex1_before.py +426 -0
- data/spec/langs/R/ex1_after.R +1 -1
- data/spec/lexer/regular_expressions_spec.rb +27 -0
- data/spec/objects/vector_spec.rb +11 -0
- metadata +12 -2
@@ -0,0 +1,426 @@
|
|
1
|
+
from __future__ import division, print_function, absolute_import
|
2
|
+
|
3
|
+
__all__ = ['fixed_quad','quadrature','romberg','trapz','simps','romb',
|
4
|
+
'cumtrapz','newton_cotes']
|
5
|
+
|
6
|
+
from scipy.special.orthogonal import p_roots
|
7
|
+
from scipy.special import gammaln
|
8
|
+
from numpy import sum, ones, add, diff, isinf, isscalar, \
|
9
|
+
asarray, real, trapz, arange, empty
|
10
|
+
import numpy as np
|
11
|
+
import math
|
12
|
+
import warnings
|
13
|
+
|
14
|
+
from scipy.lib.six import xrange
|
15
|
+
|
16
|
+
|
17
|
+
class AccuracyWarning(Warning):
|
18
|
+
pass
|
19
|
+
|
20
|
+
|
21
|
+
def _cached_p_roots(n):
|
22
|
+
|
23
|
+
if n in _cached_p_roots.cache:
|
24
|
+
return _cached_p_roots.cache[n]
|
25
|
+
|
26
|
+
_cached_p_roots.cache[n] = p_roots(n)
|
27
|
+
return _cached_p_roots.cache[n]
|
28
|
+
_cached_p_roots.cache = dict()
|
29
|
+
|
30
|
+
|
31
|
+
def fixed_quad(func,a,b,args=(),n=5):
|
32
|
+
|
33
|
+
[x,w] = _cached_p_roots(n)
|
34
|
+
x = real(x)
|
35
|
+
ainf, binf = map(isinf,(a,b))
|
36
|
+
if ainf or binf:
|
37
|
+
raise ValueError("Gaussian quadrature is only available for "
|
38
|
+
"finite limits.")
|
39
|
+
y = (b-a)*(x+1)/2.0 + a
|
40
|
+
return (b-a)/2.0*sum(w*func(y,*args),0), None
|
41
|
+
|
42
|
+
|
43
|
+
def vectorize1(func, args=(), vec_func=False):
|
44
|
+
if vec_func:
|
45
|
+
def vfunc(x):
|
46
|
+
return func(x, *args)
|
47
|
+
else:
|
48
|
+
def vfunc(x):
|
49
|
+
if isscalar(x):
|
50
|
+
return func(x, *args)
|
51
|
+
x = asarray(x)
|
52
|
+
# call with first point to get output type
|
53
|
+
y0 = func(x[0], *args)
|
54
|
+
n = len(x)
|
55
|
+
if hasattr(y0, 'dtype'):
|
56
|
+
output = empty((n,), dtype=y0.dtype)
|
57
|
+
else:
|
58
|
+
output = empty((n,), dtype=type(y0))
|
59
|
+
output[0] = y0
|
60
|
+
for i in xrange(1, n):
|
61
|
+
output[i] = func(x[i], *args)
|
62
|
+
return output
|
63
|
+
return vfunc
|
64
|
+
|
65
|
+
|
66
|
+
def quadrature(func, a, b, args=(), tol=1.49e-8, rtol=1.49e-8, maxiter=50,
|
67
|
+
vec_func=True, miniter=1):
|
68
|
+
|
69
|
+
if not isinstance(args, tuple):
|
70
|
+
args = (args,)
|
71
|
+
vfunc = vectorize1(func, args, vec_func=vec_func)
|
72
|
+
val = np.inf
|
73
|
+
err = np.inf
|
74
|
+
maxiter = max(miniter+1, maxiter)
|
75
|
+
for n in xrange(miniter, maxiter+1):
|
76
|
+
newval = fixed_quad(vfunc, a, b, (), n)[0]
|
77
|
+
err = abs(newval-val)
|
78
|
+
val = newval
|
79
|
+
|
80
|
+
if err < tol or err < rtol*abs(val):
|
81
|
+
break
|
82
|
+
else:
|
83
|
+
warnings.warn(
|
84
|
+
"maxiter (%d) exceeded. Latest difference = %e" % (maxiter, err),
|
85
|
+
AccuracyWarning)
|
86
|
+
return val, err
|
87
|
+
|
88
|
+
|
89
|
+
def tupleset(t, i, value):
|
90
|
+
l = list(t)
|
91
|
+
l[i] = value
|
92
|
+
return tuple(l)
|
93
|
+
|
94
|
+
|
95
|
+
def cumtrapz(y, x=None, dx=1.0, axis=-1, initial=None):
|
96
|
+
y = asarray(y)
|
97
|
+
if x is None:
|
98
|
+
d = dx
|
99
|
+
else:
|
100
|
+
x = asarray(x)
|
101
|
+
if x.ndim == 1:
|
102
|
+
d = diff(x)
|
103
|
+
# reshape to correct shape
|
104
|
+
shape = [1] * y.ndim
|
105
|
+
shape[axis] = -1
|
106
|
+
d = d.reshape(shape)
|
107
|
+
elif len(x.shape) != len(y.shape):
|
108
|
+
raise ValueError("If given, shape of x must be 1-d or the "
|
109
|
+
"same as y.")
|
110
|
+
else:
|
111
|
+
d = diff(x, axis=axis)
|
112
|
+
|
113
|
+
if d.shape[axis] != y.shape[axis] - 1:
|
114
|
+
raise ValueError("If given, length of x along axis must be the "
|
115
|
+
"same as y.")
|
116
|
+
|
117
|
+
nd = len(y.shape)
|
118
|
+
slice1 = tupleset((slice(None),)*nd, axis, slice(1, None))
|
119
|
+
slice2 = tupleset((slice(None),)*nd, axis, slice(None, -1))
|
120
|
+
res = add.accumulate(d * (y[slice1] + y[slice2]) / 2.0, axis)
|
121
|
+
|
122
|
+
if initial is not None:
|
123
|
+
if not np.isscalar(initial):
|
124
|
+
raise ValueError("`initial` parameter should be a scalar.")
|
125
|
+
|
126
|
+
shape = list(res.shape)
|
127
|
+
shape[axis] = 1
|
128
|
+
res = np.concatenate([np.ones(shape, dtype=res.dtype) * initial, res],
|
129
|
+
axis=axis)
|
130
|
+
|
131
|
+
return res
|
132
|
+
|
133
|
+
|
134
|
+
def _basic_simps(y,start,stop,x,dx,axis):
|
135
|
+
nd = len(y.shape)
|
136
|
+
if start is None:
|
137
|
+
start = 0
|
138
|
+
step = 2
|
139
|
+
all = (slice(None),)*nd
|
140
|
+
slice0 = tupleset(all, axis, slice(start, stop, step))
|
141
|
+
slice1 = tupleset(all, axis, slice(start+1, stop+1, step))
|
142
|
+
slice2 = tupleset(all, axis, slice(start+2, stop+2, step))
|
143
|
+
|
144
|
+
if x is None: # Even spaced Simpson's rule.
|
145
|
+
result = add.reduce(dx/3.0 * (y[slice0]+4*y[slice1]+y[slice2]),
|
146
|
+
axis)
|
147
|
+
else:
|
148
|
+
# Account for possibly different spacings.
|
149
|
+
# Simpson's rule changes a bit.
|
150
|
+
h = diff(x,axis=axis)
|
151
|
+
sl0 = tupleset(all, axis, slice(start, stop, step))
|
152
|
+
sl1 = tupleset(all, axis, slice(start+1, stop+1, step))
|
153
|
+
h0 = h[sl0]
|
154
|
+
h1 = h[sl1]
|
155
|
+
hsum = h0 + h1
|
156
|
+
hprod = h0 * h1
|
157
|
+
h0divh1 = h0 / h1
|
158
|
+
result = add.reduce(hsum/6.0*(y[slice0]*(2-1.0/h0divh1) +
|
159
|
+
y[slice1]*hsum*hsum/hprod +
|
160
|
+
y[slice2]*(2-h0divh1)),axis)
|
161
|
+
return result
|
162
|
+
|
163
|
+
|
164
|
+
def simps(y, x=None, dx=1, axis=-1, even='avg'):
|
165
|
+
|
166
|
+
y = asarray(y)
|
167
|
+
nd = len(y.shape)
|
168
|
+
N = y.shape[axis]
|
169
|
+
last_dx = dx
|
170
|
+
first_dx = dx
|
171
|
+
returnshape = 0
|
172
|
+
if x is not None:
|
173
|
+
x = asarray(x)
|
174
|
+
if len(x.shape) == 1:
|
175
|
+
shapex = ones(nd)
|
176
|
+
shapex[axis] = x.shape[0]
|
177
|
+
saveshape = x.shape
|
178
|
+
returnshape = 1
|
179
|
+
x = x.reshape(tuple(shapex))
|
180
|
+
elif len(x.shape) != len(y.shape):
|
181
|
+
raise ValueError("If given, shape of x must be 1-d or the "
|
182
|
+
"same as y.")
|
183
|
+
if x.shape[axis] != N:
|
184
|
+
raise ValueError("If given, length of x along axis must be the "
|
185
|
+
"same as y.")
|
186
|
+
if N % 2 == 0:
|
187
|
+
val = 0.0
|
188
|
+
result = 0.0
|
189
|
+
slice1 = (slice(None),)*nd
|
190
|
+
slice2 = (slice(None),)*nd
|
191
|
+
if even not in ['avg', 'last', 'first']:
|
192
|
+
raise ValueError("Parameter 'even' must be 'avg', 'last', or 'first'.")
|
193
|
+
# Compute using Simpson's rule on first intervals
|
194
|
+
if even in ['avg', 'first']:
|
195
|
+
slice1 = tupleset(slice1, axis, -1)
|
196
|
+
slice2 = tupleset(slice2, axis, -2)
|
197
|
+
if x is not None:
|
198
|
+
last_dx = x[slice1] - x[slice2]
|
199
|
+
val += 0.5*last_dx*(y[slice1]+y[slice2])
|
200
|
+
result = _basic_simps(y,0,N-3,x,dx,axis)
|
201
|
+
# Compute using Simpson's rule on last set of intervals
|
202
|
+
if even in ['avg', 'last']:
|
203
|
+
slice1 = tupleset(slice1, axis, 0)
|
204
|
+
slice2 = tupleset(slice2, axis, 1)
|
205
|
+
if x is not None:
|
206
|
+
first_dx = x[tuple(slice2)] - x[tuple(slice1)]
|
207
|
+
val += 0.5*first_dx*(y[slice2]+y[slice1])
|
208
|
+
result += _basic_simps(y,1,N-2,x,dx,axis)
|
209
|
+
if even == 'avg':
|
210
|
+
val /= 2.0
|
211
|
+
result /= 2.0
|
212
|
+
result = result + val
|
213
|
+
else:
|
214
|
+
result = _basic_simps(y,0,N-2,x,dx,axis)
|
215
|
+
if returnshape:
|
216
|
+
x = x.reshape(saveshape)
|
217
|
+
return result
|
218
|
+
|
219
|
+
|
220
|
+
def romb(y, dx=1.0, axis=-1, show=False):
|
221
|
+
|
222
|
+
y = asarray(y)
|
223
|
+
nd = len(y.shape)
|
224
|
+
Nsamps = y.shape[axis]
|
225
|
+
Ninterv = Nsamps-1
|
226
|
+
n = 1
|
227
|
+
k = 0
|
228
|
+
while n < Ninterv:
|
229
|
+
n <<= 1
|
230
|
+
k += 1
|
231
|
+
if n != Ninterv:
|
232
|
+
raise ValueError("Number of samples must be one plus a "
|
233
|
+
"non-negative power of 2.")
|
234
|
+
|
235
|
+
R = {}
|
236
|
+
all = (slice(None),) * nd
|
237
|
+
slice0 = tupleset(all, axis, 0)
|
238
|
+
slicem1 = tupleset(all, axis, -1)
|
239
|
+
h = Ninterv*asarray(dx)*1.0
|
240
|
+
R[(0,0)] = (y[slice0] + y[slicem1])/2.0*h
|
241
|
+
slice_R = all
|
242
|
+
start = stop = step = Ninterv
|
243
|
+
for i in range(1,k+1):
|
244
|
+
start >>= 1
|
245
|
+
slice_R = tupleset(slice_R, axis, slice(start,stop,step))
|
246
|
+
step >>= 1
|
247
|
+
R[(i,0)] = 0.5*(R[(i-1,0)] + h*add.reduce(y[slice_R],axis))
|
248
|
+
for j in range(1,i+1):
|
249
|
+
R[(i,j)] = R[(i,j-1)] + \
|
250
|
+
(R[(i,j-1)]-R[(i-1,j-1)]) / ((1 << (2*j))-1)
|
251
|
+
h = h / 2.0
|
252
|
+
|
253
|
+
if show:
|
254
|
+
if not isscalar(R[(0,0)]):
|
255
|
+
print("*** Printing table only supported for integrals" +
|
256
|
+
" of a single data set.")
|
257
|
+
else:
|
258
|
+
try:
|
259
|
+
precis = show[0]
|
260
|
+
except (TypeError, IndexError):
|
261
|
+
precis = 5
|
262
|
+
try:
|
263
|
+
width = show[1]
|
264
|
+
except (TypeError, IndexError):
|
265
|
+
width = 8
|
266
|
+
formstr = "%" + str(width) + '.' + str(precis)+'f'
|
267
|
+
|
268
|
+
print("\n Richardson Extrapolation Table for Romberg Integration ")
|
269
|
+
print("====================================================================")
|
270
|
+
for i in range(0,k+1):
|
271
|
+
for j in range(0,i+1):
|
272
|
+
print(formstr % R[(i,j)], end=' ')
|
273
|
+
print()
|
274
|
+
print("====================================================================\n")
|
275
|
+
|
276
|
+
return R[(k,k)]
|
277
|
+
|
278
|
+
|
279
|
+
def _difftrap(function, interval, numtraps):
|
280
|
+
if numtraps <= 0:
|
281
|
+
raise ValueError("numtraps must be > 0 in difftrap().")
|
282
|
+
elif numtraps == 1:
|
283
|
+
return 0.5*(function(interval[0])+function(interval[1]))
|
284
|
+
else:
|
285
|
+
numtosum = numtraps/2
|
286
|
+
h = float(interval[1]-interval[0])/numtosum
|
287
|
+
lox = interval[0] + 0.5 * h
|
288
|
+
points = lox + h * arange(0, numtosum)
|
289
|
+
s = sum(function(points),0)
|
290
|
+
return s
|
291
|
+
|
292
|
+
|
293
|
+
def _romberg_diff(b, c, k):
|
294
|
+
|
295
|
+
tmp = 4.0**k
|
296
|
+
return (tmp * c - b)/(tmp - 1.0)
|
297
|
+
|
298
|
+
|
299
|
+
def _printresmat(function, interval, resmat):
|
300
|
+
# Print the Romberg result matrix.
|
301
|
+
i = j = 0
|
302
|
+
print('Romberg integration of', repr(function), end=' ')
|
303
|
+
print('from', interval)
|
304
|
+
print('')
|
305
|
+
print('%6s %9s %9s' % ('Steps', 'StepSize', 'Results'))
|
306
|
+
for i in range(len(resmat)):
|
307
|
+
print('%6d %9f' % (2**i, (interval[1]-interval[0])/(2.**i)), end=' ')
|
308
|
+
for j in range(i+1):
|
309
|
+
print('%9f' % (resmat[i][j]), end=' ')
|
310
|
+
print('')
|
311
|
+
print('')
|
312
|
+
print('The final result is', resmat[i][j], end=' ')
|
313
|
+
print('after', 2**(len(resmat)-1)+1, 'function evaluations.')
|
314
|
+
|
315
|
+
|
316
|
+
def romberg(function, a, b, args=(), tol=1.48e-8, rtol=1.48e-8, show=False,
|
317
|
+
divmax=10, vec_func=False):
|
318
|
+
if isinf(a) or isinf(b):
|
319
|
+
raise ValueError("Romberg integration only available for finite limits.")
|
320
|
+
vfunc = vectorize1(function, args, vec_func=vec_func)
|
321
|
+
n = 1
|
322
|
+
interval = [a,b]
|
323
|
+
intrange = b-a
|
324
|
+
ordsum = _difftrap(vfunc, interval, n)
|
325
|
+
result = intrange * ordsum
|
326
|
+
resmat = [[result]]
|
327
|
+
err = np.inf
|
328
|
+
for i in xrange(1, divmax+1):
|
329
|
+
n = n * 2
|
330
|
+
ordsum = ordsum + _difftrap(vfunc, interval, n)
|
331
|
+
resmat.append([])
|
332
|
+
resmat[i].append(intrange * ordsum / n)
|
333
|
+
for k in range(i):
|
334
|
+
resmat[i].append(_romberg_diff(resmat[i-1][k], resmat[i][k], k+1))
|
335
|
+
result = resmat[i][i]
|
336
|
+
lastresult = resmat[i-1][i-1]
|
337
|
+
|
338
|
+
err = abs(result - lastresult)
|
339
|
+
if err < tol or err < rtol*abs(result):
|
340
|
+
break
|
341
|
+
else:
|
342
|
+
warnings.warn(
|
343
|
+
"divmax (%d) exceeded. Latest difference = %e" % (divmax, err),
|
344
|
+
AccuracyWarning)
|
345
|
+
|
346
|
+
if show:
|
347
|
+
_printresmat(vfunc, interval, resmat)
|
348
|
+
return result
|
349
|
+
|
350
|
+
_builtincoeffs = {
|
351
|
+
1:(1,2,[1,1],-1,12),
|
352
|
+
2:(1,3,[1,4,1],-1,90),
|
353
|
+
3:(3,8,[1,3,3,1],-3,80),
|
354
|
+
4:(2,45,[7,32,12,32,7],-8,945),
|
355
|
+
5:(5,288,[19,75,50,50,75,19],-275,12096),
|
356
|
+
6:(1,140,[41,216,27,272,27,216,41],-9,1400),
|
357
|
+
7:(7,17280,[751,3577,1323,2989,2989,1323,3577,751],-8183,518400),
|
358
|
+
8:(4,14175,[989,5888,-928,10496,-4540,10496,-928,5888,989],
|
359
|
+
-2368,467775),
|
360
|
+
9:(9,89600,[2857,15741,1080,19344,5778,5778,19344,1080,
|
361
|
+
15741,2857], -4671, 394240),
|
362
|
+
10:(5,299376,[16067,106300,-48525,272400,-260550,427368,
|
363
|
+
-260550,272400,-48525,106300,16067],
|
364
|
+
-673175, 163459296),
|
365
|
+
11:(11,87091200,[2171465,13486539,-3237113, 25226685,-9595542,
|
366
|
+
15493566,15493566,-9595542,25226685,-3237113,
|
367
|
+
13486539,2171465], -2224234463, 237758976000),
|
368
|
+
12:(1, 5255250, [1364651,9903168,-7587864,35725120,-51491295,
|
369
|
+
87516288,-87797136,87516288,-51491295,35725120,
|
370
|
+
-7587864,9903168,1364651], -3012, 875875),
|
371
|
+
13:(13, 402361344000,[8181904909, 56280729661, -31268252574,
|
372
|
+
156074417954,-151659573325,206683437987,
|
373
|
+
-43111992612,-43111992612,206683437987,
|
374
|
+
-151659573325,156074417954,-31268252574,
|
375
|
+
56280729661,8181904909], -2639651053,
|
376
|
+
344881152000),
|
377
|
+
14:(7, 2501928000, [90241897,710986864,-770720657,3501442784,
|
378
|
+
-6625093363,12630121616,-16802270373,19534438464,
|
379
|
+
-16802270373,12630121616,-6625093363,3501442784,
|
380
|
+
-770720657,710986864,90241897], -3740727473,
|
381
|
+
1275983280000)
|
382
|
+
}
|
383
|
+
|
384
|
+
|
385
|
+
def newton_cotes(rn, equal=0):
|
386
|
+
try:
|
387
|
+
N = len(rn)-1
|
388
|
+
if equal:
|
389
|
+
rn = np.arange(N+1)
|
390
|
+
elif np.all(np.diff(rn) == 1):
|
391
|
+
equal = 1
|
392
|
+
except:
|
393
|
+
N = rn
|
394
|
+
rn = np.arange(N+1)
|
395
|
+
equal = 1
|
396
|
+
|
397
|
+
if equal and N in _builtincoeffs:
|
398
|
+
na, da, vi, nb, db = _builtincoeffs[N]
|
399
|
+
return na*np.array(vi,float)/da, float(nb)/db
|
400
|
+
|
401
|
+
if (rn[0] != 0) or (rn[-1] != N):
|
402
|
+
raise ValueError("The sample positions must start at 0"
|
403
|
+
" and end at N")
|
404
|
+
yi = rn / float(N)
|
405
|
+
ti = 2.0*yi - 1
|
406
|
+
nvec = np.arange(0,N+1)
|
407
|
+
C = ti**nvec[:,np.newaxis]
|
408
|
+
Cinv = np.linalg.inv(C)
|
409
|
+
# improve precision of result
|
410
|
+
for i in range(2):
|
411
|
+
Cinv = 2*Cinv - Cinv.dot(C).dot(Cinv)
|
412
|
+
vec = 2.0 / (nvec[::2]+1)
|
413
|
+
ai = np.dot(Cinv[:,::2],vec) * N/2
|
414
|
+
|
415
|
+
if (N % 2 == 0) and equal:
|
416
|
+
BN = N/(N+3.)
|
417
|
+
power = N+2
|
418
|
+
else:
|
419
|
+
BN = N/(N+2.)
|
420
|
+
power = N+1
|
421
|
+
|
422
|
+
BN = BN - np.dot(yi**power, ai)
|
423
|
+
p1 = power+1
|
424
|
+
fac = power*math.log(N) - gammaln(p1)
|
425
|
+
fac = math.exp(fac)
|
426
|
+
return ai, BN*fac
|
@@ -0,0 +1,426 @@
|
|
1
|
+
from __future__ import division, print_function, absolute_import
|
2
|
+
|
3
|
+
__all__ = ['fixed_quad','quadrature','romberg','trapz','simps','romb',
|
4
|
+
'cumtrapz','newton_cotes']
|
5
|
+
|
6
|
+
from scipy.special.orthogonal import p_roots
|
7
|
+
from scipy.special import gammaln
|
8
|
+
from numpy import sum, ones, add, diff, isinf, isscalar, \
|
9
|
+
asarray, real, trapz, arange, empty
|
10
|
+
import numpy as np
|
11
|
+
import math
|
12
|
+
import warnings
|
13
|
+
|
14
|
+
from scipy.lib.six import xrange
|
15
|
+
|
16
|
+
|
17
|
+
class AccuracyWarning(Warning):
|
18
|
+
pass
|
19
|
+
|
20
|
+
|
21
|
+
def _cached_p_roots(n):
|
22
|
+
|
23
|
+
if n in _cached_p_roots.cache:
|
24
|
+
return _cached_p_roots.cache[n]
|
25
|
+
|
26
|
+
_cached_p_roots.cache[n] = p_roots(n)
|
27
|
+
return _cached_p_roots.cache[n]
|
28
|
+
_cached_p_roots.cache = dict()
|
29
|
+
|
30
|
+
|
31
|
+
def fixed_quad(func,a,b,args=(),n=5):
|
32
|
+
|
33
|
+
[x,w] = _cached_p_roots(n)
|
34
|
+
x = real(x)
|
35
|
+
ainf, binf = map(isinf,(a,b))
|
36
|
+
if ainf or binf:
|
37
|
+
raise ValueError("Gaussian quadrature is only available for "
|
38
|
+
"finite limits.")
|
39
|
+
y = (b-a)*(x+1)/2.0 + a
|
40
|
+
return (b-a)/2.0*sum(w*func(y,*args),0), None
|
41
|
+
|
42
|
+
|
43
|
+
def vectorize1(func, args=(), vec_func=False):
|
44
|
+
if vec_func:
|
45
|
+
def vfunc(x):
|
46
|
+
return func(x, *args)
|
47
|
+
else:
|
48
|
+
def vfunc(x):
|
49
|
+
if isscalar(x):
|
50
|
+
return func(x, *args)
|
51
|
+
x = asarray(x)
|
52
|
+
# call with first point to get output type
|
53
|
+
y0 = func(x[0], *args)
|
54
|
+
n = len(x)
|
55
|
+
if hasattr(y0, 'dtype'):
|
56
|
+
output = empty((n,), dtype=y0.dtype)
|
57
|
+
else:
|
58
|
+
output = empty((n,), dtype=type(y0))
|
59
|
+
output[0] = y0
|
60
|
+
for i in xrange(1, n):
|
61
|
+
output[i] = func(x[i], *args)
|
62
|
+
return output
|
63
|
+
return vfunc
|
64
|
+
|
65
|
+
|
66
|
+
def quadrature(func, a, b, args=(), tol=1.49e-8, rtol=1.49e-8, maxiter=50,
|
67
|
+
vec_func=True, miniter=1):
|
68
|
+
|
69
|
+
if not isinstance(args, tuple):
|
70
|
+
args = (args,)
|
71
|
+
vfunc = vectorize1(func, args, vec_func=vec_func)
|
72
|
+
val = np.inf
|
73
|
+
err = np.inf
|
74
|
+
maxiter = max(miniter+1, maxiter)
|
75
|
+
for n in xrange(miniter, maxiter+1):
|
76
|
+
newval = fixed_quad(vfunc, a, b, (), n)[0]
|
77
|
+
err = abs(newval-val)
|
78
|
+
val = newval
|
79
|
+
|
80
|
+
if err < tol or err < rtol*abs(val):
|
81
|
+
break
|
82
|
+
else:
|
83
|
+
warnings.warn(
|
84
|
+
"maxiter (%d) exceeded. Latest difference = %e" % (maxiter, err),
|
85
|
+
AccuracyWarning)
|
86
|
+
return val, err
|
87
|
+
|
88
|
+
|
89
|
+
def tupleset(t, i, value):
|
90
|
+
l = list(t)
|
91
|
+
l[i] = value
|
92
|
+
return tuple(l)
|
93
|
+
|
94
|
+
|
95
|
+
def cumtrapz(y, x=None, dx=1.0, axis=-1, initial=None):
|
96
|
+
y = asarray(y)
|
97
|
+
if x is None:
|
98
|
+
d = dx
|
99
|
+
else:
|
100
|
+
x = asarray(x)
|
101
|
+
if x.ndim == 1:
|
102
|
+
d = diff(x)
|
103
|
+
# reshape to correct shape
|
104
|
+
shape = [1] * y.ndim
|
105
|
+
shape[axis] = -1
|
106
|
+
d = d.reshape(shape)
|
107
|
+
elif len(x.shape) != len(y.shape):
|
108
|
+
raise ValueError("If given, shape of x must be 1-d or the "
|
109
|
+
"same as y.")
|
110
|
+
else:
|
111
|
+
d = diff(x, axis=axis)
|
112
|
+
|
113
|
+
if d.shape[axis] != y.shape[axis] - 1:
|
114
|
+
raise ValueError("If given, length of x along axis must be the "
|
115
|
+
"same as y.")
|
116
|
+
|
117
|
+
nd = len(y.shape)
|
118
|
+
slice1 = tupleset((slice(None),)*nd, axis, slice(1, None))
|
119
|
+
slice2 = tupleset((slice(None),)*nd, axis, slice(None, -1))
|
120
|
+
res = add.accumulate(d * (y[slice1] + y[slice2]) / 2.0, axis)
|
121
|
+
|
122
|
+
if initial is not None:
|
123
|
+
if not np.isscalar(initial):
|
124
|
+
raise ValueError("`initial` parameter should be a scalar.")
|
125
|
+
|
126
|
+
shape = list(res.shape)
|
127
|
+
shape[axis] = 1
|
128
|
+
res = np.concatenate([np.ones(shape, dtype=res.dtype) * initial, res],
|
129
|
+
axis=axis)
|
130
|
+
|
131
|
+
return res
|
132
|
+
|
133
|
+
|
134
|
+
def _basic_simps(y,start,stop,x,dx,axis):
|
135
|
+
nd = len(y.shape)
|
136
|
+
if start is None:
|
137
|
+
start = 0
|
138
|
+
step = 2
|
139
|
+
all = (slice(None),)*nd
|
140
|
+
slice0 = tupleset(all, axis, slice(start, stop, step))
|
141
|
+
slice1 = tupleset(all, axis, slice(start+1, stop+1, step))
|
142
|
+
slice2 = tupleset(all, axis, slice(start+2, stop+2, step))
|
143
|
+
|
144
|
+
if x is None: # Even spaced Simpson's rule.
|
145
|
+
result = add.reduce(dx/3.0 * (y[slice0]+4*y[slice1]+y[slice2]),
|
146
|
+
axis)
|
147
|
+
else:
|
148
|
+
# Account for possibly different spacings.
|
149
|
+
# Simpson's rule changes a bit.
|
150
|
+
h = diff(x,axis=axis)
|
151
|
+
sl0 = tupleset(all, axis, slice(start, stop, step))
|
152
|
+
sl1 = tupleset(all, axis, slice(start+1, stop+1, step))
|
153
|
+
h0 = h[sl0]
|
154
|
+
h1 = h[sl1]
|
155
|
+
hsum = h0 + h1
|
156
|
+
hprod = h0 * h1
|
157
|
+
h0divh1 = h0 / h1
|
158
|
+
result = add.reduce(hsum/6.0*(y[slice0]*(2-1.0/h0divh1) +
|
159
|
+
y[slice1]*hsum*hsum/hprod +
|
160
|
+
y[slice2]*(2-h0divh1)),axis)
|
161
|
+
return result
|
162
|
+
|
163
|
+
|
164
|
+
def simps(y, x=None, dx=1, axis=-1, even='avg'):
|
165
|
+
|
166
|
+
y = asarray(y)
|
167
|
+
nd = len(y.shape)
|
168
|
+
N = y.shape[axis]
|
169
|
+
last_dx = dx
|
170
|
+
first_dx = dx
|
171
|
+
returnshape = 0
|
172
|
+
if x is not None:
|
173
|
+
x = asarray(x)
|
174
|
+
if len(x.shape) == 1:
|
175
|
+
shapex = ones(nd)
|
176
|
+
shapex[axis] = x.shape[0]
|
177
|
+
saveshape = x.shape
|
178
|
+
returnshape = 1
|
179
|
+
x = x.reshape(tuple(shapex))
|
180
|
+
elif len(x.shape) != len(y.shape):
|
181
|
+
raise ValueError("If given, shape of x must be 1-d or the "
|
182
|
+
"same as y.")
|
183
|
+
if x.shape[axis] != N:
|
184
|
+
raise ValueError("If given, length of x along axis must be the "
|
185
|
+
"same as y.")
|
186
|
+
if N % 2 == 0:
|
187
|
+
val = 0.0
|
188
|
+
result = 0.0
|
189
|
+
slice1 = (slice(None),)*nd
|
190
|
+
slice2 = (slice(None),)*nd
|
191
|
+
if even not in ['avg', 'last', 'first']:
|
192
|
+
raise ValueError("Parameter 'even' must be 'avg', 'last', or 'first'.")
|
193
|
+
# Compute using Simpson's rule on first intervals
|
194
|
+
if even in ['avg', 'first']:
|
195
|
+
slice1 = tupleset(slice1, axis, -1)
|
196
|
+
slice2 = tupleset(slice2, axis, -2)
|
197
|
+
if x is not None:
|
198
|
+
last_dx = x[slice1] - x[slice2]
|
199
|
+
val += 0.5*last_dx*(y[slice1]+y[slice2])
|
200
|
+
result = _basic_simps(y,0,N-3,x,dx,axis)
|
201
|
+
# Compute using Simpson's rule on last set of intervals
|
202
|
+
if even in ['avg', 'last']:
|
203
|
+
slice1 = tupleset(slice1, axis, 0)
|
204
|
+
slice2 = tupleset(slice2, axis, 1)
|
205
|
+
if x is not None:
|
206
|
+
first_dx = x[tuple(slice2)] - x[tuple(slice1)]
|
207
|
+
val += 0.5*first_dx*(y[slice2]+y[slice1])
|
208
|
+
result += _basic_simps(y,1,N-2,x,dx,axis)
|
209
|
+
if even == 'avg':
|
210
|
+
val /= 2.0
|
211
|
+
result /= 2.0
|
212
|
+
result = result + val
|
213
|
+
else:
|
214
|
+
result = _basic_simps(y,0,N-2,x,dx,axis)
|
215
|
+
if returnshape:
|
216
|
+
x = x.reshape(saveshape)
|
217
|
+
return result
|
218
|
+
|
219
|
+
|
220
|
+
def romb(y, dx=1.0, axis=-1, show=False):
|
221
|
+
|
222
|
+
y = asarray(y)
|
223
|
+
nd = len(y.shape)
|
224
|
+
Nsamps = y.shape[axis]
|
225
|
+
Ninterv = Nsamps-1
|
226
|
+
n = 1
|
227
|
+
k = 0
|
228
|
+
while n < Ninterv:
|
229
|
+
n <<= 1
|
230
|
+
k += 1
|
231
|
+
if n != Ninterv:
|
232
|
+
raise ValueError("Number of samples must be one plus a "
|
233
|
+
"non-negative power of 2.")
|
234
|
+
|
235
|
+
R = {}
|
236
|
+
all = (slice(None),) * nd
|
237
|
+
slice0 = tupleset(all, axis, 0)
|
238
|
+
slicem1 = tupleset(all, axis, -1)
|
239
|
+
h = Ninterv*asarray(dx)*1.0
|
240
|
+
R[(0,0)] = (y[slice0] + y[slicem1])/2.0*h
|
241
|
+
slice_R = all
|
242
|
+
start = stop = step = Ninterv
|
243
|
+
for i in range(1,k+1):
|
244
|
+
start >>= 1
|
245
|
+
slice_R = tupleset(slice_R, axis, slice(start,stop,step))
|
246
|
+
step >>= 1
|
247
|
+
R[(i,0)] = 0.5*(R[(i-1,0)] + h*add.reduce(y[slice_R],axis))
|
248
|
+
for j in range(1,i+1):
|
249
|
+
R[(i,j)] = R[(i,j-1)] + \
|
250
|
+
(R[(i,j-1)]-R[(i-1,j-1)]) / ((1 << (2*j))-1)
|
251
|
+
h = h / 2.0
|
252
|
+
|
253
|
+
if show:
|
254
|
+
if not isscalar(R[(0,0)]):
|
255
|
+
print("*** Printing table only supported for integrals" +
|
256
|
+
" of a single data set.")
|
257
|
+
else:
|
258
|
+
try:
|
259
|
+
precis = show[0]
|
260
|
+
except (TypeError, IndexError):
|
261
|
+
precis = 5
|
262
|
+
try:
|
263
|
+
width = show[1]
|
264
|
+
except (TypeError, IndexError):
|
265
|
+
width = 8
|
266
|
+
formstr = "%" + str(width) + '.' + str(precis)+'f'
|
267
|
+
|
268
|
+
print("\n Richardson Extrapolation Table for Romberg Integration ")
|
269
|
+
print("====================================================================")
|
270
|
+
for i in range(0,k+1):
|
271
|
+
for j in range(0,i+1):
|
272
|
+
print(formstr % R[(i,j)], end=' ')
|
273
|
+
print()
|
274
|
+
print("====================================================================\n")
|
275
|
+
|
276
|
+
return R[(k,k)]
|
277
|
+
|
278
|
+
|
279
|
+
def _difftrap(function, interval, numtraps):
|
280
|
+
if numtraps <= 0:
|
281
|
+
raise ValueError("numtraps must be > 0 in difftrap().")
|
282
|
+
elif numtraps == 1:
|
283
|
+
return 0.5*(function(interval[0])+function(interval[1]))
|
284
|
+
else:
|
285
|
+
numtosum = numtraps/2
|
286
|
+
h = float(interval[1]-interval[0])/numtosum
|
287
|
+
lox = interval[0] + 0.5 * h
|
288
|
+
points = lox + h * arange(0, numtosum)
|
289
|
+
s = sum(function(points),0)
|
290
|
+
return s
|
291
|
+
|
292
|
+
|
293
|
+
def _romberg_diff(b, c, k):
|
294
|
+
|
295
|
+
tmp = 4.0**k
|
296
|
+
return (tmp * c - b)/(tmp - 1.0)
|
297
|
+
|
298
|
+
|
299
|
+
def _printresmat(function, interval, resmat):
|
300
|
+
# Print the Romberg result matrix.
|
301
|
+
i = j = 0
|
302
|
+
print('Romberg integration of', repr(function), end=' ')
|
303
|
+
print('from', interval)
|
304
|
+
print('')
|
305
|
+
print('%6s %9s %9s' % ('Steps', 'StepSize', 'Results'))
|
306
|
+
for i in range(len(resmat)):
|
307
|
+
print('%6d %9f' % (2**i, (interval[1]-interval[0])/(2.**i)), end=' ')
|
308
|
+
for j in range(i+1):
|
309
|
+
print('%9f' % (resmat[i][j]), end=' ')
|
310
|
+
print('')
|
311
|
+
print('')
|
312
|
+
print('The final result is', resmat[i][j], end=' ')
|
313
|
+
print('after', 2**(len(resmat)-1)+1, 'function evaluations.')
|
314
|
+
|
315
|
+
|
316
|
+
def romberg(function, a, b, args=(), tol=1.48e-8, rtol=1.48e-8, show=False,
|
317
|
+
divmax=10, vec_func=False):
|
318
|
+
if isinf(a) or isinf(b):
|
319
|
+
raise ValueError("Romberg integration only available for finite limits.")
|
320
|
+
vfunc = vectorize1(function, args, vec_func=vec_func)
|
321
|
+
n = 1
|
322
|
+
interval = [a,b]
|
323
|
+
intrange = b-a
|
324
|
+
ordsum = _difftrap(vfunc, interval, n)
|
325
|
+
result = intrange * ordsum
|
326
|
+
resmat = [[result]]
|
327
|
+
err = np.inf
|
328
|
+
for i in xrange(1, divmax+1):
|
329
|
+
n = n * 2
|
330
|
+
ordsum = ordsum + _difftrap(vfunc, interval, n)
|
331
|
+
resmat.append([])
|
332
|
+
resmat[i].append(intrange * ordsum / n)
|
333
|
+
for k in range(i):
|
334
|
+
resmat[i].append(_romberg_diff(resmat[i-1][k], resmat[i][k], k+1))
|
335
|
+
result = resmat[i][i]
|
336
|
+
lastresult = resmat[i-1][i-1]
|
337
|
+
|
338
|
+
err = abs(result - lastresult)
|
339
|
+
if err < tol or err < rtol*abs(result):
|
340
|
+
break
|
341
|
+
else:
|
342
|
+
warnings.warn(
|
343
|
+
"divmax (%d) exceeded. Latest difference = %e" % (divmax, err),
|
344
|
+
AccuracyWarning)
|
345
|
+
|
346
|
+
if show:
|
347
|
+
_printresmat(vfunc, interval, resmat)
|
348
|
+
return result
|
349
|
+
|
350
|
+
_builtincoeffs = {
|
351
|
+
1:(1,2,[1,1],-1,12),
|
352
|
+
2:(1,3,[1,4,1],-1,90),
|
353
|
+
3:(3,8,[1,3,3,1],-3,80),
|
354
|
+
4:(2,45,[7,32,12,32,7],-8,945),
|
355
|
+
5:(5,288,[19,75,50,50,75,19],-275,12096),
|
356
|
+
6:(1,140,[41,216,27,272,27,216,41],-9,1400),
|
357
|
+
7:(7,17280,[751,3577,1323,2989,2989,1323,3577,751],-8183,518400),
|
358
|
+
8:(4,14175,[989,5888,-928,10496,-4540,10496,-928,5888,989],
|
359
|
+
-2368,467775),
|
360
|
+
9:(9,89600,[2857,15741,1080,19344,5778,5778,19344,1080,
|
361
|
+
15741,2857], -4671, 394240),
|
362
|
+
10:(5,299376,[16067,106300,-48525,272400,-260550,427368,
|
363
|
+
-260550,272400,-48525,106300,16067],
|
364
|
+
-673175, 163459296),
|
365
|
+
11:(11,87091200,[2171465,13486539,-3237113, 25226685,-9595542,
|
366
|
+
15493566,15493566,-9595542,25226685,-3237113,
|
367
|
+
13486539,2171465], -2224234463, 237758976000),
|
368
|
+
12:(1, 5255250, [1364651,9903168,-7587864,35725120,-51491295,
|
369
|
+
87516288,-87797136,87516288,-51491295,35725120,
|
370
|
+
-7587864,9903168,1364651], -3012, 875875),
|
371
|
+
13:(13, 402361344000,[8181904909, 56280729661, -31268252574,
|
372
|
+
156074417954,-151659573325,206683437987,
|
373
|
+
-43111992612,-43111992612,206683437987,
|
374
|
+
-151659573325,156074417954,-31268252574,
|
375
|
+
56280729661,8181904909], -2639651053,
|
376
|
+
344881152000),
|
377
|
+
14:(7, 2501928000, [90241897,710986864,-770720657,3501442784,
|
378
|
+
-6625093363,12630121616,-16802270373,19534438464,
|
379
|
+
-16802270373,12630121616,-6625093363,3501442784,
|
380
|
+
-770720657,710986864,90241897], -3740727473,
|
381
|
+
1275983280000)
|
382
|
+
}
|
383
|
+
|
384
|
+
|
385
|
+
def newton_cotes(rn, equal=0):
|
386
|
+
try:
|
387
|
+
N = len(rn)-1
|
388
|
+
if equal:
|
389
|
+
rn = np.arange(N+1)
|
390
|
+
elif np.all(np.diff(rn) == 1):
|
391
|
+
equal = 1
|
392
|
+
except:
|
393
|
+
N = rn
|
394
|
+
rn = np.arange(N+1)
|
395
|
+
equal = 1
|
396
|
+
|
397
|
+
if equal and N in _builtincoeffs:
|
398
|
+
na, da, vi, nb, db = _builtincoeffs[N]
|
399
|
+
return na*np.array(vi,float)/da, float(nb)/db
|
400
|
+
|
401
|
+
if (rn[0] != 0) or (rn[-1] != N):
|
402
|
+
raise ValueError("The sample positions must start at 0"
|
403
|
+
" and end at N")
|
404
|
+
yi = rn / float(N)
|
405
|
+
ti = 2.0*yi - 1
|
406
|
+
nvec = np.arange(0,N+1)
|
407
|
+
C = ti**nvec[:,np.newaxis]
|
408
|
+
Cinv = np.linalg.inv(C)
|
409
|
+
# improve precision of result
|
410
|
+
for i in range(2):
|
411
|
+
Cinv = 2*Cinv - Cinv.dot(C).dot(Cinv)
|
412
|
+
vec = 2.0 / (nvec[::2]+1)
|
413
|
+
ai = np.dot(Cinv[:,::2],vec) * N/2
|
414
|
+
|
415
|
+
if (N % 2 == 0) and equal:
|
416
|
+
BN = N/(N+3.)
|
417
|
+
power = N+2
|
418
|
+
else:
|
419
|
+
BN = N/(N+2.)
|
420
|
+
power = N+1
|
421
|
+
|
422
|
+
BN = BN - np.dot(yi**power, ai)
|
423
|
+
p1 = power+1
|
424
|
+
fac = power*math.log(N) - gammaln(p1)
|
425
|
+
fac = math.exp(fac)
|
426
|
+
return ai, BN*fac
|