qlang 0.0.27180000 → 0.0.27182000
Sign up to get free protection for your applications and to get access to all the features.
- 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
|