def countNMpmath (A, b, bstart, bend): N=mpm.matrix(len(b),len(b)) for j in range (len(b)): partone=mpm.mpf(2)*A[j,0]/(b[j]-bstart[j])**mpm.mpf(3) parttwo=mpm.mpf(2)*A[j,1]/(bend[j]-b[j])**mpm.mpf(3) N[j,j]+=parttwo+partone #так как матрица нулевая return N
def make_lgamma_vals(): from mpmath import loggamma x = [mpf('0.01')] + linspace(mpf('0.1'), 10, 100) + [mpf(20), mpf(30)] lga = [loggamma(val) for val in x] return make_special_vals('lgamma_vals', ('x', x), ('lga', lga))
def process(offer, xlimit0, ask): x = mpf(getAmount(offer['TakerGets'])) y = mpf(getAmount(offer['TakerPays'])) if ask: x, y = y, x xlimit = xlimit0 + x return (xlimit, { 'rate': rate(x,y), 'limit': x, 'xlimit': xlimit, 'account': offer['Account'], 'sequence': offer['Sequence'] })
def test(): # Basic test of the Weibull functions w = Weibull(shape=mpf(2.0), scale=mpf(12), location=6) print "Weibull(%s,%s,%s): " % (w.shape, w.scale, w.location) sum = 0 for i in range(10000): sum += w.draw_truncated(6) print "MEAN: ", mpf(sum) / 10000. print w.draw_inverse_transform(0) print w.draw_inverse_transform(0) print w.draw_inverse_transform(0) print w.draw_inverse_transform(0) print "Max hazard rate is %e\n" % w.get_max_hazard_rate(100) for i in range(0,200,5): print "CDF at time %d is %f\n" % (i, w.cdf_eval(i)) w = Weibull(shape=mpf(1.0), scale=mpf(120000)) print "Bunch of draws:" for i in range(10): print w.draw_inverse_transform(1000000) print "Weibull(%s,%s,%s): " % (w.shape, w.scale, w.location) print "Max hazard rate is %e\n" % w.get_max_hazard_rate(1000) for i in range(0,1000,100): print "Hazard rate at time %d is %e\n" % (i, w.hazard_rate(i))
def make_gamma_vals(): from mpmath import gamma x = [-mpf('0.5'), -mpf('0.01'), mpf('0.01')] + linspace(mpf('0.1'), 10, 100) + [mpf(20), mpf(30)] ga = [gamma(val) for val in x] return make_special_vals('gamma_vals', ('x', x), ('ga', ga))
def Pinv(self,P): from mpmath import ellipf, sqrt, asin, acos, mpc, mpf Delta = self.Delta e1, e2, e3 = self.__roots if self.__ng3: P = -P if Delta > 0: m = (e2 - e3) / (e1 - e3) retval = (1 / sqrt(e1 - e3)) * ellipf(asin(sqrt((e1 - e3)/(P - e3))),m=m) elif Delta < 0: H2 = (sqrt((e2 - e3) * (e2 - e1))).real assert(H2 > 0) m = mpf(1) / mpf(2) - 3 * e2 / (4 * H2) retval = 1 / (2 * sqrt(H2)) * ellipf(acos((e2-P+H2)/(e2-P-H2)),m=m) else: g2, g3 = self.__invariants if g2 == 0 and g3 == 0: retval = 1 / sqrt(P) else: c = e1 / 2 retval = (1 / sqrt(3 * c)) * asin(sqrt((3 * c)/(P + c))) if self.__ng3: retval /= mpc(0,1) alpha, beta, _, _ = self.reduce_to_fpp(retval) T1, T2 = self.periods return T1 * alpha + T2 * beta
def test_mpmath_lambda(): mpmath.mp.dps = 50 sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020") f = lambdify(x, sin(x), "mpmath") prec = 1e-49 # mpmath precision is around 50 decimal places assert -prec < f(mpmath.mpf("0.2")) - sin02 < prec raises(TypeError, lambda: f(x))
def __compute_periods(self): # A+S 18.9. from mpmath import sqrt, ellipk, mpc, pi, mpf Delta = self.Delta e1, e2, e3 = self.__roots if Delta > 0: m = (e2 - e3) / (e1 - e3) Km = ellipk(m) Kpm = ellipk(1 - m) om = Km / sqrt(e1 - e3) omp = mpc(0,1) * om * Kpm / Km elif Delta < 0: # NOTE: the expression in the sqrt has to be real and positive, as e1 and e3 are # complex conjugate and e2 is real. H2 = (sqrt((e2 - e3) * (e2 - e1))).real assert(H2 > 0) m = mpf(1) / mpf(2) - 3 * e2 / (4 * H2) Km = ellipk(m) Kpm = ellipk(1 - m) om2 = Km / sqrt(H2) om2p = mpc(0,1) * Kpm * om2 / Km om = (om2 - om2p) / 2 omp = (om2 + om2p) / 2 else: g2, g3 = self.__invariants if g2 == 0 and g3 == 0: om = mpf('+inf') omp = mpc(0,'+inf') else: # NOTE: here there is no need for the dichotomy on the sign of g3 because # we are already working in a regime in which g3 >= 0 by definition. c = e1 / 2 om = 1 / sqrt(12 * c) * pi() omp = mpc(0,'+inf') return 2 * om, 2 * omp
def findPoissonChangePoint( data, factorial ): # data is a list of counts in each time period, uniformly spaced # the denominator (including both P(D|H1) and constant parts of P(D|H2) ) C = data.sum() N = mpf(len(data)) denominator = factorial[C-1] * pi / ( 2 * N**C ) # the numerator (trickier) # this needs to be averaged over the possible change points weights = zeros(N,dtype=object) CA = 0 CB = C for i in range(1,N) : # points up through i are in data set A; the rest are in B datapoint = data[i-1] NA = mpf(i) ; CA += datapoint NB = mpf(N-i) ; CB -= datapoint fraction_num = factorial[CA] * factorial[CB] fraction_den = NA**(CA+1) * NB**(CB+1) * ( (CA/NA)**2 + (CB/NB)**2 ) #weights.append( fraction_num/fraction_den ) weights[i-1] = mpf(fraction_num)/fraction_den numerator = weights.mean() lognum= inv_log10 * log( numerator ) logden= inv_log10 * log( denominator ) logodds = lognum - logden print "num:",numerator, "log num:", lognum, "| denom:", denominator, "log denom:", logden, "|| log odds:", logodds # If there is a change point, then logodds will be greater than 0 if logodds < 0 : return None return ( weights.argmax(), logodds )
def P(self,z): # A+S 18.9. from mpmath import sqrt, mpc, sin, ellipfun, mpf Delta = self.Delta e1, e2, e3 = self.__roots if self.__ng3: z = mpc(0,1) * z if Delta > 0: zs = sqrt(e1 - e3) * z m = (e2 - e3) / (e1 - e3) retval = e3 + (e1 - e3) / ellipfun('sn',u=zs,m=m)**2 elif Delta < 0: H2 = (sqrt((e2 - e3) * (e2 - e1))).real assert(H2 > 0) m = mpf(1) / mpf(2) - 3 * e2 / (4 * H2) zp = 2 * z * sqrt(H2) retval = e2 + H2 * (1 + ellipfun('cn',u=zp,m=m)) / (1 - ellipfun('cn',u=zp,m=m)) else: g2, g3 = self.__invariants if g2 == 0 and g3 == 0: retval = 1 / (z**2) else: c = e1 / 2 retval = -c + 3 * c / (sin(sqrt(3 * c) * z))**2 if self.__ng3: return -retval else: return retval
def Pprime(self,z): # A+S 18.9. from mpmath import ellipfun, sqrt, cos, sin, mpc, mpf Delta = self.Delta e1, e2, e3 = self.__roots if self.__ng3: z = mpc(0,1) * z if Delta > 0: zs = sqrt(e1 - e3) * z m = (e2 - e3) / (e1 - e3) retval = -2 * sqrt((e1 - e3)**3) * ellipfun('cn',u=zs,m=m) * ellipfun('dn',u=zs,m=m) / (ellipfun('sn',u=zs,m=m)**3) elif Delta < 0: H2 = (sqrt((e2 - e3) * (e2 - e1))).real assert(H2 > 0) m = mpf(1) / mpf(2) - 3 * e2 / (4 * H2) zp = 2 * z * sqrt(H2) retval = -4 * sqrt(H2**3) * ellipfun('sn',u=zp,m=m) * ellipfun('dn',u=zp,m=m) / ((1 - ellipfun('cn',u=zp,m=m))**2) else: g2, g3 = self.__invariants if g2 == 0 and g3 == 0: retval = -2 / (z**3) else: c = e1 / 2 A = sqrt(3 * c) retval = -6 * c * A * cos(A * z) / (sin(A * z))**3 if self.__ng3: return mpc(0,-1) * retval else: return retval
def _noncentral_chi_cdf(x, df, nc, dps=None): if dps is None: dps = mpmath.mp.dps x, df, nc = mpmath.mpf(x), mpmath.mpf(df), mpmath.mpf(nc) with mpmath.workdps(dps): res = mpmath.quad(lambda t: _noncentral_chi_pdf(t, df, nc), [0, x]) return res
def lagrange_inversion(a): """Given a series f(x) = a[1]*x + a[2]*x**2 + ... + a[n-1]*x**(n - 1), use the Lagrange inversion formula to compute a series g(x) = b[1]*x + b[2]*x**2 + ... + b[n-1]*x**(n - 1) so that f(g(x)) = g(f(x)) = x mod x**n. We must have a[0] = 0, so necessarily b[0] = 0 too. The algorithm is naive and could be improved, but speed isn't an issue here and it's easy to read. """ n = len(a) f = sum(a[i]*x**i for i in range(len(a))) h = (x/f).series(x, 0, n).removeO() hpower = [h**0] for k in range(n): hpower.append((hpower[-1]*h).expand()) b = [mp.mpf(0)] for k in range(1, n): b.append(hpower[k].coeff(x, k - 1)/k) b = map(lambda x: mp.mpf(x), b) return b
def Test_sci(): f = mpFormat() mpFormat.show_zero_exponent = True x = mpf("1.2345678901234567890") f.digits( 0); assert(f.sci( x) == " 1.e+0") f.digits( 0); assert(f.sci(-x) == "-1.e+0") f.digits( 1); assert(f.sci(x) == " 1.e+0") f.digits( 1); assert(f.sci(-x) == "-1.e+0") f.digits( 2); assert(f.sci(x) == " 1.2e+0") f.digits( 3); assert(f.sci(x) == " 1.23e+0") f.digits( 3); assert(f.sci(-x) == "-1.23e+0") f.digits(20); assert(f.sci(x) == " 1.2345678901234567890e+0") mpFormat.show_zero_exponent = False f.digits( 0); assert(f.sci( x) == " 1.") f.digits( 0); assert(f.sci(-x) == "-1.") f.digits( 1); assert(f.sci(x) == " 1.") f.digits( 1); assert(f.sci(-x) == "-1.") f.digits( 2); assert(f.sci(x) == " 1.2") f.digits( 3); assert(f.sci(x) == " 1.23") f.digits( 3); assert(f.sci(-x) == "-1.23") f.digits(20); assert(f.sci(x) == " 1.2345678901234567890") x *= mpf("1e9") f.digits( 0); assert(f.sci(x) == " 1.e+9") f.digits( 0); assert(f.sci(-x) == "-1.e+9") f.digits( 1); assert(f.sci(x) == " 1.e+9") f.digits( 2); assert(f.sci(x) == " 1.2e+9") f.digits( 2); assert(f.sci(-x) == "-1.2e+9") x /= mpf("1e18") f.digits( 0); assert(f.sci(x) == " 1.e-9") f.digits( 1); assert(f.sci(x) == " 1.e-9") f.digits( 2); assert(f.sci(x) == " 1.2e-9") f.digits(20); assert(f.sci( x) == " 1.2345678901234567890e-9") f.digits(20); assert(f.sci(-x) == "-1.2345678901234567890e-9")
def _f_cdf(dfn, dfd, x): if x < 0: return mpmath.mpf(0) dfn, dfd, x = mpmath.mpf(dfn), mpmath.mpf(dfd), mpmath.mpf(x) ub = dfn*x/(dfn*x + dfd) res = mpmath.betainc(dfn/2, dfd/2, x2=ub, regularized=True) return res
def bissecao(func, a, b, erro, valor=mpf(0.0)): u''' Implementa o método da bisseção para encontrar o ponto onde a função encontra o valor desejado. Retorna (valor, numero_iter) ''' f = lambda x: func(x) - valor a, b = mpf(a), mpf(b) erro = fabs(erro) i = mpf(0) while True: i += 1 e = fabs(a-b) / 2 x = (a+b) / 2 if e <= erro: return (x, i) if f(a) * f(x) > 0: a, b = x, b elif f(x) * f(b) > 0: a, b = a, x else: raise ValueError('Nao ha variacao de sinal entre os dois.')
def Test_fix(): f = mpFormat() x = mpf("1.2345678901234567890") f.digits( 0); assert(f.fix(x) == " 1.") f.digits( 1); assert(f.fix(x) == " 1.2") f.digits( 2); assert(f.fix(x) == " 1.23") f.digits( 3); assert(f.fix(x) == " 1.235") f.digits(20); assert(f.fix(x) == " 1.23456789012345678900") f.digits(20); assert(f.fix(-x) == "-1.23456789012345678900") x *= mpf("1e9") f.digits( 0); assert(f.fix(x) == " 1234567890.") f.digits( 1); assert(f.fix(x) == " 1234567890.1") f.digits( 2); assert(f.fix(x) == " 1234567890.12") f.digits( 3); assert(f.fix(x) == " 1234567890.123") f.digits( 4); assert(f.fix(x) == " 1234567890.1235") f.digits(10); assert(f.fix(x) == " 1234567890.1234567890") x /= mpf("1e12") f.digits( 0); assert(f.fix(x) == " 0.") f.digits( 0); assert(f.fix(-x) == "-0.") f.digits( 1); assert(f.fix(x) == " 0.0") f.digits( 1); assert(f.fix(-x) == "-0.0") f.digits( 2); assert(f.fix(x) == " 0.00") f.digits( 2); assert(f.fix(-x) == "-0.00") f.digits( 3); assert(f.fix(x) == " 0.001") f.digits( 3); assert(f.fix(-x) == "-0.001") f.digits( 4); assert(f.fix(x) == " 0.0012") f.digits( 5); assert(f.fix(x) == " 0.00123") f.digits( 7); assert(f.fix(x) == " 0.0012346") f.digits(25); assert(f.fix(x) == " 0.0012345678901234567890000") f.digits(25); assert(f.fix(-x) == "-0.0012345678901234567890000")
def resolver_equacao(a, b, c): u''' Resolve uma equação do segundo grau. ''' a, b, c = mpf(a), mpf(b), mpf(c) d = b ** 2 - 4 * a * c return ( (-b+sqrt(d))/(2*a), (-b-sqrt(d))/(2*a) )
def newton(f, f_x, x0, erro, max_iter, valor=mpf(0.0)): u''' Implementa: Parâmetros: - f: function(x) => - f_x: function(x) => - x0: num => chute inicial - erro: num => valor de erro no qual o método vai parar - max_iter: num => máximo de iterações - valor: num => valor que o método espera a função alcançar Retorna (valor, numero_iter), onde: - valor: valor obtido pelo método - numero_iter: número de iterações necessárias ''' x0, erro, valor = mpf(x0), fabs(erro), mpf(valor) for i in range(max_iter): try: x1 = x0 - (f(x0)-valor) / f_x(x0) except TypeError: x1 = x0 + 300.0 #raise ValueError('O metodo teve uma aberracao') erro_iter = fabs(x1 - x0) x0 = x1 if erro_iter < erro: break else: raise ValueError('O metodo nao convergiu, o ultimo foi: %f' % x0) return (x0, i)
def multiprec_pdf(df, mu, x): df = mp.mpf(str(df)) mu = mp.mpf(str(mu)) x = mp.mpf(str(x)) pdf = (mp.exp(-mu**2 / 2) * 2**(-df) * df**(df/2) * mp.gamma(df+1) * \ ((mp.sqrt(2) * x * mu * (x**2+df)**(-df/2-1) * mp.hyp1f1(df/2+1,1.5,(mu**2 * x**2)/(2 * (x**2+df))))/(mp.gamma((df+1)/2))+((x**2+df)**(-df/2-0.5) * mp.hyp1f1((df+1)/2,0.5,(mu**2 * x**2)/(2 * (x**2+df))))/(mp.gamma(df/2+1))))/(mp.gamma(df/2)) return pdf
def takahata_concordance(r, s, q, T3, T2, F_dic, g_dic, W_dic): '''returns probability of takahata (???) concordance''' total = 0 for m in range(1, r + 1): m = mpmath.mpf(m) for n in range(1, s + 1): n = mpmath.mpf(n) for k in range(1, m + n + 1): k = mpmath.mpf(k) print m, n, k xsum = 0 for x in range(1, k): x = mpmath.mpf(x) lsum = 0 for l in range(1, q): # MISSING +1 l = mpmath.mpf(l) lsum += g(q, l, T3 + T2, g_dic) * F(1, x, k-x, l, F_dic) xsum += W(m, n, x, k, T2, W_dic, g_dic) * lsum total += g(r, m, T3, g_dic) * g(s, n, T3, g_dic) * g(m + n, k, T2, g_dic) * \ (F(k, m, n, 0, F_dic) + \ (1 - F(k, m, n, 0, F_dic)) * \ xsum) return total
def __call__(self, s): assert len(s) > 0 suffix = 1 if s != "now" and s != "today": if len(s) > 1 and s[:2] != "0x": if s[-1] in suffixes_ln: exponent = suffixes_ln[s[-1]] if exponent >= 0: suffix = Zn(10**exponent) else: suffix = mpf("1e" + str(exponent)) s = s[:-1] for func in (self.j, self.i, self.q, self.v, self.r, self.c): x = func(s) if x != None: if suffix == 1: return x if isint(x): if isint(suffix): return Zn(suffix*x) else: return suffix*mpf(int(x)) elif isinstance(x, Rational): if isint(suffix): return Rational(suffix*x.n, x.d) else: return suffix*x.mpf() elif isinstance(x, mpf) or \ isinstance(x, mpc) or \ isinstance(x, mpi): if isint(suffix): return mpf(int(suffix))*x else: return suffix*x else: return None return None
def testing_kbes(Rt,Xt): [R0,R1,NR]=Rt [X0,X1,NX]=Xt NRr=mpmath.mpf(NR) NXr=mpmath.mpf(NX) for j in range(1,NR): rj=mpmath.mpf(j) R=R0+R1*rj/NRr iR=mpmath.mpc(0,R) for k in range(1,NX): rk=mpmath.mpf(k) x=X0+X1*rk/NXr print "r,x=",R,x if(x>R): print "kbes_asymp=" timeit( "kbes_asymp(R,x)",repeat=1) else: print "kbes_rec=" timeit( "kbes_rec(R,x)",repeat=1) print "mpmath.besselk=" timeit("mpmath.besselk(iR,x)",repeat=1) #print "t1(",R,x,")=",t1 #print "t2(",R,x,")=",t2 if(R<15.0): if(x<0.3 *R): print "Case 1" elif(x<=max(10.0 +1.2*R,2 *R)): print "Case 2" elif(R>20 and x>4 *R): print "Case 3" else: print "Case 4"
def findGaussianChangePoint( data ): # the denominator. This is the easy part. N = len( data ) if N<6 : return None # can't find a cp in data this small # set up gamma function table #for i in range(N): s2 = mpf(data.var()) gpart = gamma( mpf(N)/2.0 - 1 ) denom = (pi**1.5) * mpf((N*s2))**( -N/2.0 + 0.5 ) * gpart # the numerator. A little trickier. # calc_twostate_weights() already deals with ts<3 and ts>N-2. weights=calc_twostate_weights( data ) if weights is None: return None num = 2.0**2.5 * abs(data.mean()) * weights.mean() logodds = log( num ) - log( denom ) print "num:", num, "log num:", log(num), "| denom:", denom, "log denom:", log(denom), "|| log odds:", logodds # If there is a change point, then logodds will be greater than 0 if logodds < 0 : return None return ( weights.argmax(), logodds )
def nodes(n): left = mp.mpf(0) right = mp.mpf(n+(n-1)*sqrt(n)*1.01) i = 2 factor = 2 while True: l = [ (x,mp.laguerre(n,0,x)) for x in mp.linspace(left,right,n*factor**i)] intervals = [] for j in range(len(l)-1): prod = l[j][1]*l[j+1][1] if prod < 0: intervals.append([l[j][0], l[j+1][0]]) if len(intervals) == n: break i += 1 roots = [] f = lambda x: mp.laguerre(n,0,x) for ab in intervals: a,b = ab try: z = mp.findroot(f, (a, b), tol=1e-50, solver='bisect') except: z = bisect(f, a, b, tol=1e-50) roots.append( z ) return roots
def hazard_rate(self, x): if x < self.location: return 0 elif self.shape == 1: return mpf(1) / self.scale else: return abs(self.pdf_eval(x) / (mpf(1) - self.cdf_eval(x)))
def locate(self,times,exclude): """locate(t,exclude) input: list-of-times in microseconds and what to exclude in calculations output (x, y) in meters """ sos = 340.2; times = times[:]; pts = self.sensors[:]; del pts[exclude]; del times[exclude]; x,y,t = sympy.symbols('x y t'); a,b = pts[0]; c,d = pts[1]; e,f = pts[2]; #print(a,b,c,d,e,f); t_1 = mpf(times[0])/1e6; t_2 = mpf(times[1])/1e6; t_3 = mpf(times[2])/1e6; #t_1,t_2,t_3 = 0,t_2-t_1,t_3-t_1; f_1 = (x-a)**2 + (y-b)**2 - ((t_1-t)*sos)**2; f_2 = (x-c)**2 + (y-d)**2 - ((t_2-t)*sos)**2; f_3 = (x-e)**2 + (y-f)**2 - ((t_3-t)*sos)**2; try: res = sympy.nsolve((f_1,f_2,f_3),(x,y,t),(0,0,min(t_1,t_2,t_3))); return ( float(res[0]), float(res[1]) ); except(ValueError,ZeroDivisionError): return ( float('NaN'), float('NaN') );
def dedekind(tau, floatpre): """ Algorithm 22 (Dedekind eta) Input : tau in the upper half-plane, k in N Output : eta(tau) """ a = 2 * mpmath.pi / mpmath.mpf(24) b = mpmath.exp(mpmath.mpc(0, a)) p = 1 m = 0 while m <= 0.999: n = nearest_integer(tau.real) if n != 0: tau -= n p *= b ** n m = tau.real * tau.real + tau.imag * tau.imag if m <= 0.999: ro = mpmath.sqrt(mpmath.power(tau, -1) * 1j) if ro.real < 0: ro = -ro p = p * ro tau = (-p.real + p.imag * 1j) / m q1 = mpmath.exp(a * tau * 1j) q = q1 ** 24 s = 1 qs = mpmath.mpc(1, 0) qn = 1 des = mpmath.mpf(10) ** (-floatpre) while abs(qs) > des: t = -q * qn * qn * qs qn = qn * q qs = qn * t s += t + qs return p * q1 * s
def cdf_eval(self, x): x = mpf(x) if x < self.location: return 0 return mpf(1) - mpmath.exp(-mpmath.power(((x-self.location)/self.scale), self.shape))
def solve(): # mpmath.mp = 100 fn1 = [0]*9 fn2 = [0]*9 fn1[8] = 1 fn2[8] = 1 k = 3 vn1 = mpmath.mpf(1.000000000e0) vn2 = mpmath.mpf(1.000000000e0) while True: # if k % 1000 == 0: # print k fn = add_last_digits(fn1,fn2) vn = vn1+vn2 if last_digits_are_pandigital(fn): if first_digits_are_pandigital(vn): mpmath.nprint(vn,n=10) return k vn2 = vn1 vn1 = vn fn2 = fn1 fn1 = fn k += 1
def test_number_precision(): mpmath.mp.dps = 50 sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020") f = lambdify(x, sin02, "mpmath") prec = 1e-49 # mpmath precision is around 50 decimal places assert -prec < f(0) - sin02 < prec
def list_zeros(filename, offset, block_number, number_of_zeros=2000, t_start=0, N_start=0): r""" Lower level function to list zeros starting at a specific place in a specific file. This function is meant to be called by a higher level function which does an initial query into the index in order to figure out what file and offset to start with. INPUT: - filename: the name of the file that we are going to grab the data from - offset: the position to seek to in the file to get the start of the block that we are going to grab initial data from - block_number: the index of this block in this file. (We need to know this because at least one of the files has some sort of garbage at the end, and so we might run out of blocks before we run out of file - number of zeros: the number of zeros to return - t_start/N_start: where to start the listing from. Either the height t_start or the N-th zero. If both are specified, then whichever comes last will be used. """ db = sqlite3.connect(db_location) c = db.cursor() eps = mpmath.mpf(2) ** (-101) # The (absolute!) precision to which # the zeros are stored. infile = open(os.path.join(data_location, filename), 'rb') # infile is the file that actually contains the data that we want. # It is in a compressed binary format that we aren't going to # describe completely here. See [TODO]. number_of_blocks = struct.unpack('Q', infile.read(8))[0] # The first 8 bytes of the # the file are a 64-bit # unsigned integer. # We move to the beginning of the block that we are interested in... infile.seek(offset, 0) t0, t1, Nt0, Nt1 = struct.unpack('ddQQ', infile.read(8 * 4)) # and then start reading. Each block has a 32 byte header with a pair of # doubles and a pair of integers. t0 is the offset for the imaginary parts # of the zeros in this block (and t1 the offset for the next block), # Nt0 = N(t0), the number of zeros with imaginary part < t0, and similarly # for t1. So the number of zeros in this block is Nt1 - Nt0. mpmath.mp.prec = log(t1, 2) + 10 + 101 # We make sure that the working precision # is large enough. Note that we are adding # a little too much here, so when these # numbers are printed, they will have too # many digits. t0 = mpmath.mpf(t0) Z = 0 # Z is going to be a python integer that holds the # difference gamma - t0, where gamma is a zero of # the zeta function. Z will be a 104+ bit positive integer, # and the difference is interpreted as Z * eps == Z * 2^(-101). count = 0 # the number of zeros we have found so far N = Nt0 # the index of the next zero # FIXME THIS VARIABLE IS NEVER USED #L = [] # the zeros we have found so far # now we start finding zeros while count < number_of_zeros: # # If the index of the next zero falls off the end of the # block we are going to need to go to the next block, and # possibly the next file. # if N == Nt1: block_number += 1 # # Check if we are at the end of the file... # if block_number == number_of_blocks: infile.close() # If we are at the end of the file, we have to make a new # query into the index to get the name of the next file. # # (Possible optimization: parse the file name properly, so # we can just look at a list to get the next one.) # c = db.cursor() query = 'select * from zero_index where N = %d limit 1' % N c.execute(query) result = c.fetchone() if result is None: return t0, N0, filename, offset, block_number = result infile = open(os.path.join(data_location, filename), 'rb') if not infile: return number_of_blocks = struct.unpack('Q', infile.read(8))[0] infile.seek(offset, 0) # # At this point we just repeat all of the above opening # code since we are starting a new block. # header = infile.read(8 * 4) t0, t1, Nt0, Nt1 = struct.unpack('ddQQ', header) mpmath.mp.prec = log(t1, 2) + 10 + 101 t0 = mpmath.mpf(t0) Z = 0 # Now we are actually reading data from the block. # # Each block entry is a 13 byte integer... z1, z2, z3 = struct.unpack('QIB', infile.read(13)) Z = Z + (z3 << 96) + (z2 << 64) + z1 # now we have the zero: zero = t0 + mpmath.mpf(Z) * eps N = N + 1 # But we only append it to the list if # it belongs there. (We may want to start # the listing in the middle of a block. if N >= N_start and zero >= t_start: count = count + 1 yield (N, zero) infile.close()
def test_d(): # Compare the d_{k, n} to the results in appendix F of [1]. # # Sources # ------- # [1] DiDonato and Morris, Computation of the Incomplete Gamma # Function Ratios and their Inverse, ACM Transactions on # Mathematical Software, 1986. with mp.workdps(50): dataset = [(0, 0, -mp.mpf('0.333333333333333333333333333333')), (0, 12, mp.mpf('0.102618097842403080425739573227e-7')), (1, 0, -mp.mpf('0.185185185185185185185185185185e-2')), (1, 12, mp.mpf('0.119516285997781473243076536700e-7')), (2, 0, mp.mpf('0.413359788359788359788359788360e-2')), (2, 12, -mp.mpf('0.140925299108675210532930244154e-7')), (3, 0, mp.mpf('0.649434156378600823045267489712e-3')), (3, 12, -mp.mpf('0.191111684859736540606728140873e-7')), (4, 0, -mp.mpf('0.861888290916711698604702719929e-3')), (4, 12, mp.mpf('0.288658297427087836297341274604e-7')), (5, 0, -mp.mpf('0.336798553366358150308767592718e-3')), (5, 12, mp.mpf('0.482409670378941807563762631739e-7')), (6, 0, mp.mpf('0.531307936463992223165748542978e-3')), (6, 12, -mp.mpf('0.882860074633048352505085243179e-7')), (7, 0, mp.mpf('0.344367606892377671254279625109e-3')), (7, 12, -mp.mpf('0.175629733590604619378669693914e-6')), (8, 0, -mp.mpf('0.652623918595309418922034919727e-3')), (8, 12, mp.mpf('0.377358774161109793380344937299e-6')), (9, 0, -mp.mpf('0.596761290192746250124390067179e-3')), (9, 12, mp.mpf('0.870823417786464116761231237189e-6'))] d = compute_d(10, 13) res = [d[k][n] for k, n, std in dataset] std = map(lambda x: x[2], dataset) mp_assert_allclose(res, std)
def _cart_to_RSH_coeffs_gen(l): """ Generates a coefficients [ coef, x power, y power, z power ] for each component of a regular solid harmonic (in terms of raw Cartesians) with angular momentum l. See eq. 23 of ACS, F. C. Pickard, H. F. Schaefer and B. R. Brooks, JCP, 140, 184101 (2014) Returns coeffs with order 0, +1, -1, +2, -2, ... """ # Arbitrary precision math with 100 decimal places try: import mpmath mpmath.mp.dps = 100 except ImportError: raise ImportError("RSH coefficients requires mpmath to extend") terms = [] for m in range(l + 1): thisterm = {} p1 = mpmath.mp.sqrt((mpmath.mp.fac(l - m)) / (mpmath.mp.fac(l + m))) * ((mpmath.mp.fac(m)) / (2**l)) if m: p1 *= mpmath.mp.sqrt(2.0) # Loop over cartesian components for lz in range(l + 1): for ly in range(l - lz + 1): lx = l - ly - lz xyz = lx, ly, lz j = int((lx + ly - m) / 2) if (lx + ly - m) % 2 == 1 or j < 0: continue # P2 p2 = mpmath.mpf(0) for i in range(int((l - m) / 2) + 1): if i >= j: p2 += (-1)**i * mpmath.mp.fac(2 * l - 2 * i) / ( mpmath.mp.fac(l - i) * mpmath.mp.fac(i - j) * mpmath.mp.fac(l - m - 2 * i)) # P3 p3 = mpmath.mpf(0) for k in range(j + 1): if (j >= k) and (lx >= 2 * k) and (m + 2 * k >= lx): p3 += (-1)**k / ( mpmath.mp.fac(j - k) * mpmath.mp.fac(k) * mpmath.mp.fac(lx - 2 * k) * mpmath.mp.fac(m - lx + 2 * k)) p = p1 * p2 * p3 # Add in part if not already present if xyz not in thisterm: thisterm[xyz] = [mpmath.mp.mpf(0.0), mpmath.mp.mpf(0.0)] # Add the two components if (m - lx) % 2: # imaginary sign = mpmath.mp.mpf(-1.0)**mpmath.mp.mpf((m - lx - 1) / 2.0) thisterm[xyz][1] += sign * p else: # real sign = mpmath.mp.mpf(-1.0)**mpmath.mp.mpf((m - lx) / 2.0) thisterm[xyz][0] += sign * p tmp_R = [] tmp_I = [] for k, v in thisterm.items(): if abs(v[0]) > 0: tmp_R.append((k, v[0])) if abs(v[1]) > 0: tmp_I.append((k, v[1])) if m == 0: # name_R = "R_%d%d" % (l, m) terms.append(tmp_R) else: # name_R = "R_%d%dc" % (l, m) # name_I = "R_%d%ds" % (l, m) terms.append(tmp_R) terms.append(tmp_I) # terms[name_R] = tmp_R # terms[name_I] = tmp_I # for k, v in terms.items(): # print(k, v) return terms
# *** epsilon = 1.0e-3, tstar = 94.2547000020054, f(tstar) = 0.00099906001272887 # *** epsilon = 1.0e-4, tstar = 351.857199983313, f(tstar) = 9.91072890377254e-5 # *** epsilon = 1.0e-5, tstar = 1313.184599742, f(tstar) = 9.74361845684779e-6 # *** epsilon = 1.0e-6, tstar = 4900.88400532812, f(tstar) = 9.51986134034577e-7 # *** epsilon = 1.0e-7, tstar = 18290.3522752436, f(tstar) = 7.18960744272579e-8 # *** epsilon = 1.0e-8, tstar = 49970.1726016378, f(tstar) = 8.77679739996751e-9 # *** epsilon = 1.0e-9, tstar = 186491.223053476, f(tstar) = 7.1541417234755e-10 # ****************************************************************************** if (__name__ == "__main__"): mp.dps = 10 mp.pretty = True # Eigenvalues EIGENVALUES = [-mp.sqrt(3), mp.mpf("-1"), mp.mpf("0"), mp.mpf("1"), mp.sqrt(3)] COEFFICIENTS = [mp.mpf("1/12"), mp.mpf("1/ 4"), mp.mpf("1/ 3"), mp.mpf("1/ 4"), mp.mpf("1/12")] fmt = "epsilon = {0:>10s}, tstar = {1:>20s} f(tstar) = {2:>20s}" func = lambda t: psi(t, EIGENVALUES, COEFFICIENTS) TSTAR = [] for exponent in sorted(range(-9,0), reverse=True):
def check(self): np.random.seed(1234) # Generate values for the arguments if isinstance(self.arg_spec, np.ndarray): argarr = self.arg_spec.copy() else: num_args = len(self.arg_spec) ms = np.asarray([ 1.5 if isinstance(arg, ComplexArg) else 1.0 for arg in self.arg_spec ]) ms = (self.n**(ms / sum(ms))).astype(int) + 1 argvals = [] for arg, m in zip(self.arg_spec, ms): argvals.append(arg.values(m)) argarr = np.array(np.broadcast_arrays(*np.ix_(*argvals))).reshape( num_args, -1).T # Check old_dps, old_prec = mpmath.mp.dps, mpmath.mp.prec try: if self.dps is not None: dps_list = [self.dps] else: dps_list = [20] if self.prec is not None: mpmath.mp.prec = self.prec # Proper casting of mpmath input and output types. Using # native mpmath types as inputs gives improved precision # in some cases. if np.issubdtype(argarr.dtype, np.complexfloating): pytype = complex mptype = lambda x: mpmath.mpc(complex(x)) else: mptype = lambda x: mpmath.mpf(float(x)) def pytype(x): if abs(x.imag) > 1e-16 * (1 + abs(x.real)): return np.nan else: return float(x.real) # Try out different dps until one (or none) works for j, dps in enumerate(dps_list): mpmath.mp.dps = dps try: assert_func_equal( self.scipy_func, lambda *a: pytype(self.mpmath_func(*map(mptype, a))), argarr, vectorized=False, rtol=self.rtol, atol=self.atol, ignore_inf_sign=self.ignore_inf_sign, nan_ok=True) break except AssertionError: if j >= len(dps_list) - 1: reraise(*sys.exc_info()) finally: mpmath.mp.dps, mpmath.mp.prec = old_dps, old_prec
def produce_geometric_brownian_motion_paths(dt, method=None, approx=None): """ Perform path simulations of a geometric Brownian motion. :param dt: Float. (Fraction of time). :param method: Str. :param approx: List. :return: List. [x_fine_exact, x_coarse_exact, x_fine_approx, x_coarse_approx] """ assert isinstance( dt, float) and np.isfinite(dt) and dt > 0 and (1.0 / dt).is_integer() assert isinstance(method, str) and method in ['euler_maruyama', 'milstein'] assert approx is not None # The parameters. x_0 = 1.0 mu = 0.05 sigma = 0.2 T = 1.0 dt = dt * T t_fine = dt t_coarse = 2 * dt sqrt_t_fine = t_fine**0.5 w_coarse_exact = 0.0 w_coarse_approx = 0.0 x_fine_exact = x_0 x_coarse_exact = x_0 x_fine_approx = x_0 x_coarse_approx = x_0 n_fine = int(1.0 / dt) update_coarse = False x_0, mu, sigma, T, dt, t_fine, t_coarse, sqrt_t_fine, w_coarse_exact, w_coarse_approx = [ mpf(i) for i in [ x_0, mu, sigma, T, dt, t_fine, t_coarse, sqrt_t_fine, w_coarse_exact, w_coarse_approx ] ] fabs = mp.fabs path_update = None if method == 'euler_maruyama': path_update = lambda x, w, t: x + mu * x * t + sigma * x * w elif method == 'milstein': path_update = lambda x, w, t: x + mu * x * t + sigma * x * w + 0.5 * sigma * sigma * ( w * w - t) assert path_update is not None for n in range(n_fine): u = np.random.uniform() z_exact = norm.ppf(u) z_approx = approx(u) z_approx = z_approx if isinstance(z_approx, float) else z_approx[0] w_fine_exact = sqrt_t_fine * z_exact w_fine_approx = sqrt_t_fine * z_approx w_coarse_exact += w_fine_exact w_coarse_approx += w_fine_approx x_fine_exact = path_update(x_fine_exact, w_fine_exact, t_fine) x_fine_approx = path_update(x_fine_approx, w_fine_approx, t_fine) if update_coarse: x_coarse_exact = path_update(x_coarse_exact, w_coarse_exact, t_coarse) x_coarse_approx = path_update(x_coarse_approx, w_coarse_approx, t_coarse) w_coarse_exact *= 0.0 w_coarse_approx *= 0.0 update_coarse = not update_coarse # We toggle to achieve pairwise summation. assert not update_coarse # This should have been the last thing we did. return [x_fine_exact, x_coarse_exact, x_fine_approx, x_coarse_approx]
def eval_approx(self, n): """Evaluate this complex root to the given precision. This uses secant method and root bounds are used to both generate an initial guess and to check that the root returned is valid. If ever the method converges outside the root bounds, the bounds will be made smaller and updated. """ prec = dps_to_prec(n) with workprec(prec): g = self.poly.gen if not g.is_Symbol: d = Dummy('x') if self.is_imaginary: d *= I func = lambdify(d, self.expr.subs(g, d)) else: expr = self.expr if self.is_imaginary: expr = self.expr.subs(g, I * g) func = lambdify(g, expr) interval = self._get_interval() while True: if self.is_real: a = mpf(str(interval.a)) b = mpf(str(interval.b)) if a == b: root = a break x0 = mpf(str(interval.center)) x1 = x0 + mpf(str(interval.dx)) / 4 elif self.is_imaginary: a = mpf(str(interval.ay)) b = mpf(str(interval.by)) if a == b: root = mpc(mpf('0'), a) break x0 = mpf(str(interval.center[1])) x1 = x0 + mpf(str(interval.dy)) / 4 else: ax = mpf(str(interval.ax)) bx = mpf(str(interval.bx)) ay = mpf(str(interval.ay)) by = mpf(str(interval.by)) if ax == bx and ay == by: root = mpc(ax, ay) break x0 = mpc(*map(str, interval.center)) x1 = x0 + mpc(*map(str, (interval.dx, interval.dy))) / 4 try: # without a tolerance, this will return when (to within # the given precision) x_i == x_{i-1} root = findroot(func, (x0, x1)) # If the (real or complex) root is not in the 'interval', # then keep refining the interval. This happens if findroot # accidentally finds a different root outside of this # interval because our initial estimate 'x0' was not close # enough. It is also possible that the secant method will # get trapped by a max/min in the interval; the root # verification by findroot will raise a ValueError in this # case and the interval will then be tightened -- and # eventually the root will be found. # # It is also possible that findroot will not have any # successful iterations to process (in which case it # will fail to initialize a variable that is tested # after the iterations and raise an UnboundLocalError). if self.is_real or self.is_imaginary: if not bool(root.imag) == self.is_real and (a <= root <= b): if self.is_imaginary: root = mpc(mpf('0'), root.real) break elif (ax <= root.real <= bx and ay <= root.imag <= by): break except (UnboundLocalError, ValueError): pass interval = interval.refine() # update the interval so we at least (for this precision or # less) don't have much work to do to recompute the root self._set_interval(interval) return (Float._new(root.real._mpf_, prec) + I * Float._new(root.imag._mpf_, prec))
def test_mpf_norm(): assert mpf_norm((1, 0, 1, 0), 10) == mpf('0')._mpf_ assert Float._new((1, 0, 1, 0), 10)._mpf_ == mpf('0')._mpf_
def _eval_evalf(self, prec): """Evaluate this complex root to the given precision. """ with workprec(prec): g = self.poly.gen if not g.is_Symbol: d = Dummy('x') func = lambdify(d, self.expr.subs(g, d)) else: func = lambdify(g, self.expr) interval = self._get_interval() if not self.is_extended_real: # For complex intervals, we need to keep refining until the # imaginary interval is disjunct with other roots, that is, # until both ends get refined. ay = interval.ay by = interval.by while interval.ay == ay or interval.by == by: interval = interval.refine() while True: if self.is_extended_real: a = mpf(str(interval.a)) b = mpf(str(interval.b)) if a == b: root = a break x0 = mpf(str(interval.center)) else: ax = mpf(str(interval.ax)) bx = mpf(str(interval.bx)) ay = mpf(str(interval.ay)) by = mpf(str(interval.by)) if ax == bx and ay == by: # the sign of the imaginary part will be assigned # according to the desired index using the fact that # roots are sorted with negative imag parts coming # before positive (and all imag roots coming after real # roots) deg = self.poly.degree() i = self.index # a positive attribute after creation if (deg - i) % 2: if ay < 0: ay = -ay else: if ay > 0: ay = -ay root = mpc(ax, ay) break x0 = mpc(*map(str, interval.center)) try: root = findroot(func, x0) # If the (real or complex) root is not in the 'interval', # then keep refining the interval. This happens if findroot # accidentally finds a different root outside of this # interval because our initial estimate 'x0' was not close # enough. It is also possible that the secant method will # get trapped by a max/min in the interval; the root # verification by findroot will raise a ValueError in this # case and the interval will then be tightened -- and # eventually the root will be found. if self.is_extended_real: if (a <= root <= b): break elif (ax <= root.real <= bx and ay <= root.imag <= by): break except ValueError: pass interval = interval.refine() return Float._new(root.real._mpf_, prec) + I * Float._new(root.imag._mpf_, prec)
def pdf(*args): args_forward = np.append(np.append(args[:var], [args[var] + mpmath.mpf(dx)]), args[var + 1:]) args_backward = np.append(np.append(args[:var], [args[var] - mpmath.mpf(dx)]), args[var + 1:]) return (func(*args_forward) - func(*args_backward)) / (2 * mpmath.mpf(dx))
def check_score_of_hash_list_func(input_hash_list, difficulty_level, list_of_2_digits_chunks, list_of_mpmath_functions, list_of_mpmath_function_names, previous_block_final_hash_as_string_reversed_leading_zeros_stripped, use_verbose): hash_is_valid = 0 list_of_hash_integers = list() for current_hash in input_hash_list: list_of_hash_integers.append(mpf(int(current_hash, 16))) list_of_hashes_in_size_order = sorted(list_of_hash_integers) input_hash_list_sorted = sort_list_based_on_another_list_func(input_hash_list, list_of_hash_integers) list_of_hash_types = ['SHA-256 + (Repeated again in reverse)', 'SHA3-256 + (Repeated again in reverse)', 'SHA3-512', 'BLAKE2S + (Repeated again in reverse)', 'BLAKE2B'] list_of_hash_types_sorted = sort_list_based_on_another_list_func(list_of_hash_types, list_of_hash_integers) smallest_hash = list_of_hashes_in_size_order[0] second_smallest_hash = list_of_hashes_in_size_order[1] middle_hash = list_of_hashes_in_size_order[2] second_largest_hash = list_of_hashes_in_size_order[-2] largest_hash = list_of_hashes_in_size_order[-1] list_of_hashes_by_name = [smallest_hash, largest_hash, middle_hash, second_smallest_hash, second_largest_hash] list_of_hash_name_strings = ['smallest_hash', 'largest_hash', 'middle_hash', 'second_smallest_hash', 'second_largest_hash'] last_k_digits_to_extract_from_each_intermediate_result = difficulty_level*5 list_of_intermediate_results_last_k_digits = list() if use_verbose: printc('Previous final hash: ' + str(previous_block_final_hash),'b') printc('After being reversed and removing leading zeros: '+ previous_block_final_hash_as_string_reversed_leading_zeros_stripped + '\n\n','b') for cnt, current_formula in enumerate(list_of_mpmath_functions): current_formula_name = list_of_mpmath_function_names[cnt] two_digit_hash_chunk = list_of_2_digits_chunks[cnt] hash_index = cnt%len(list_of_hashes_by_name) current_hash_value = list_of_hashes_by_name[hash_index] current_hash_value_rescaled = mp.frac(mp.log10(current_hash_value)) current_hash_name_string = list_of_hash_name_strings[hash_index] current_intermediate_result = current_formula(current_hash_value_rescaled) current_intermediate_result_as_string = str(current_intermediate_result) current_intermediate_result_as_string_decimal_point_and_leading_zeros_stripped = current_intermediate_result_as_string.replace('.','').lstrip('0') current_intermediate_result_as_string_decimal_point_and_leading_zeros_stripped_last_k_digits = current_intermediate_result_as_string_decimal_point_and_leading_zeros_stripped[-last_k_digits_to_extract_from_each_intermediate_result:] list_of_intermediate_results_last_k_digits.append(int(current_intermediate_result_as_string_decimal_point_and_leading_zeros_stripped_last_k_digits)) if use_verbose: printc('Current 2-digit chunk of reversed previous hash: '+str(two_digit_hash_chunk),'m') printc('Corresponding mathematical formula for index '+str(two_digit_hash_chunk)+' (out of 100 distinct formulas from mpmath): y =' + current_formula_name,'r') printc('Current hash value to use in the formula: ' + list_of_hash_types_sorted[cnt] + ': ' + input_hash_list_sorted[cnt] + ')','y') printc('Hash Value as an Integer (i.e., whole number): ' + current_hash_name_string + ' = ' + str(int(current_hash_value)),'y') printc('Rescaled hash value (i.e., x = fractional_part( log(hash_value) ) in the formula): ' + str(current_hash_value_rescaled),'g') printc('Output from formula: (i.e., y in the formula): ' + str(current_intermediate_result),'g') printc('Output as string with decimal point and leading zeros removed: ' + str(current_intermediate_result_as_string_decimal_point_and_leading_zeros_stripped),'g') printc('Last '+str(last_k_digits_to_extract_from_each_intermediate_result)+' digits of rescaled output (these are multiplied together to produce the final hash): ' + str(current_intermediate_result_as_string_decimal_point_and_leading_zeros_stripped_last_k_digits)+'\n\n','c') final_hash = 1 for current_k_digit_chunk in list_of_intermediate_results_last_k_digits: final_hash = final_hash*current_k_digit_chunk difficulty_string = construct_difficulty_string_func(difficulty_level) number_of_matching_leading_characters = get_number_of_matching_leading_characters_in_string_func(final_hash, difficulty_string) if number_of_matching_leading_characters >= difficulty_level: hash_is_valid = 1 if use_verbose: print('\n') printc(make_text_indented_func('Final Hash (product of all the k-digit chunks): '+str(final_hash),5),'c') printc('\nDifficulty Level: ' + str(difficulty_level),'r') printc('Difficulty String: ' + difficulty_string,'r') if hash_is_valid: if difficulty_level == 1: digit_text = 'digit' else: digit_text = str(difficulty_level)+' digits' print_mining_congratulations_message_func() printc('\nSince the first ' + digit_text + ' of the final hash match all of the digits in the difficulty string, the hash is valid!', 'b') else: printc('\nHash is invalid, sorry!\n', 'b') if SLOWDOWN: sleep(0.1) return number_of_matching_leading_characters, hash_is_valid, final_hash
def __getnewargs_ex__(self): return (), { 'prec': self.precision, 'tol': mpmath.mpf(self.tolerance._mpf_) }
def test_conversion_to_mpmath(): assert mpmath.mpmathify(Integer(1)) == mpmath.mpf(1) assert mpmath.mpmathify(Rational(1, 2)) == mpmath.mpf(0.5) assert mpmath.mpmathify(Float('1.23', 15)) == mpmath.mpf('1.23')
def interpretAsFloat(n): intValue = struct.pack('I', int(n)) return mpf(struct.unpack('f', intValue)[0])
def partial_derivative(func, var, order=1, coordinates=None, dx='1e-6', precision=100): """ Generates a function which returns estimates of partial derivatives of <func> by argument with index <var> using the central difference formula. If <coordinates> are passed, provides a numerical estimate of the partial derivative. This is equivalent to passing <coordinates> to a generated function with <coordinates=None> https://en.wikipedia.org/wiki/Partial_derivative Parameters ---------- func : function Function, partial derivative of which is estimated. Takes n positional arguments X1...Xn var : int Index of argument by which <func> is differentiated. Each value should be in the range [0, len(<coordinates>)-1] order : int, optional Order of derivative (default=1) coordinates : array_like or float, optional List of n coordinates X1...Xn at which the <func> derivative is estimated (default=None) dx : str, optional String representing a float representing spacing at which the partial derivative is estimated (default='1e-6') precision : int, optional Precision of floating point calculations (see mpmath library documentation) (default=100) Set to None to run with numpy without mpmath Some functions are incompatible with mpmath. Set <precision> to None to avoid errors or rewrite the function. Derivative estimated without high <precision> may have a significant error due to rounding and under-/overflow Returns ------- function or float/mpmath.mpf (mpmath.mpf if <precision> is not None) Function estimating or numerical estimate of partial derivative of the <func> evaluated at <coordinates> """ if not isinstance(order, int) or order < 1: raise RuntimeError(f'Bad value passed in order={order}') # Convert inputs to mpmath real float objects if precision is not None: with mpmath.workdps(precision): if coordinates is not None: if np.isscalar(coordinates): coordinates = [mpmath.mpf(str(coordinates))] else: coordinates = [mpmath.mpf(str(_c)) for _c in coordinates] # Define numerical partial derivative function using the central difference formula def pdf(*args): args_forward = np.append(np.append(args[:var], [args[var] + mpmath.mpf(dx)]), args[var + 1:]) args_backward = np.append(np.append(args[:var], [args[var] - mpmath.mpf(dx)]), args[var + 1:]) return (func(*args_forward) - func(*args_backward)) / (2 * mpmath.mpf(dx)) # Estimate partial derivative if coordinates were provided if order == 1: if coordinates is not None: return pdf(*coordinates) else: return pdf else: return partial_derivative( func=pdf, var=var, order=order-1, coordinates=coordinates, dx=dx, precision=precision ) else: # Define numerical partial derivative function using the central difference formula def pdf(*args): args_forward = np.append(np.append(args[:var], [args[var] + float(dx)]), args[var + 1:]) args_backward = np.append(np.append(args[:var], [args[var] - float(dx)]), args[var + 1:]) return (func(*args_forward) - func(*args_backward)) / (2 * float(dx)) # Estimate partial derivative if coordinates were provided if order == 1: if coordinates is not None: return pdf(*coordinates) else: return pdf else: return partial_derivative( func=pdf, var=var, order=order-1, coordinates=coordinates, dx=dx, precision=precision )
def __call__(self, x): with workdps(self.dps): bits = decompose(math.fabs(x), self.gamma_pow, self.max_precision) ps = self.representation(bits) gammas = [mpf(self.gamma)]*bits.size return math.copysign(np.sum([c * gamma **(-power) for (c, gamma, power) in zip(ps, gammas, self.betas[:bits.size])]), x)
def interpretAsDouble(n): setAccuracy(25) intValue = struct.pack('Q', int(n)) return mpf(struct.unpack('d', intValue)[0])
def _psi(chi): return mpmath.ncdf(chi) - chi * mpmath.npdf(chi) - mpmath.mpf('0.5')
# f = lambda z: mpmath.sin(mpmath.mpc('2.5','0') * mpmath.pi / z) # f = lambda z: mpmath.sin(mpmath.mpc('7.8','0') / z) # f = lambda z: mpmath.sin(mpmath.mpc('1','0') / z) # f = lambda z: mpmath.sin(mpmath.mpc('1','0') / (z + mpmath.mpc('0','1.5'))) # f = lambda z: mpmath.sin(mpmath.mpc('1','0') / (z + mpmath.mpc('0','2.6'))) # f = lambda z: mpmath.power(mpmath.mpc('0.5', '0'), z) # f = lambda z: z + mpmath.sin(z) # f = lambda z: z + mpmath.mpc('1.5', '0') * mpmath.sin(z) f = lambda z: mpmath.power(z, z) # stop_iteration_near = [mpmath.mpc('0','-1.5')] # stop_iteration_near = [0] stop_iteration_near = [] # [(comdition_func, converged_result), ...] predefined_zones_of_attraction = [(lambda p: mpmath.mpf('0.5') < mpmath.re(p) <= mpmath.mpf('1') and mpmath.mpf('-0.5') < mpmath.im(p) < mpmath.mpf('0.5'), mpmath.mpc('1', '0'))] if __name__ == '__main__': # set precision mpmath.mp.dps = 50 max_legend_printed_dps = min(mpmath.mp.dps, 30) compute_timeout = 0.001 # Total thread count = this thread + plotting thread + compute threads # num_compute_threads = 1 num_compute_threads = 25 # magic number, keep an aspect ratio that satisifies an equivilent dpi on each axis of final image # This doesn't need to be exact (hence why we allow small adjustments in point counts) since the plot function
def make_gummy(sign=None, exp=None, uexp=-6, sometimes_small=True, dof=None, unit=None, units=None, mpf=False, allowzero=True, allowlargeu=True): utypes = ['A', 'B', 'D', None] if units is None: units = ['m', 'lb', 'm**2 s**3/kg**4', 'm**3', 's**-2', '1'] if rand.randint(10) == 0: if exp is None: x = rand.randint(6000) else: x = rand.randint(int(10**exp)) else: x = rand.rand() * 0.9 + 0.1 if exp is None: exp = rand.randint(1, 6) if rand.randint(2): exp = -exp x = x * 10**exp if sign is None: if rand.randint(2): x = -x else: x *= sign if not allowzero and x == 0: x = x + 1 if allowlargeu and rand.randint(10) == 0: u = rand.randint(20) + 1 else: u = rand.rand() * 0.5 + 0.5 if sometimes_small and not rand.randint(10): uexp -= 4 u = abs(x) * u * 10**uexp if mpf and mp is not None and not rand.randint(4): x = mp.mpf(x) if rand.randint(2): u = mp.mpf(u) if dof is None: if not rand.randint(4): dof = float('inf') else: dof = rand.randint(5, 15) if unit is None: unit = units[rand.randint(len(units))] utype = utypes[rand.randint(len(utypes))] g = uc.gummy(x, u=u, dof=dof, unit=unit, utype=utype) return (g, x, u, dof, unit, utype)
def pdf_gauss_mp(x, sigma, mean): return mp.mpf(1.) / mp.sqrt(mp.mpf("2.") * sigma ** 2 * mp.pi) * mp.exp( - (x - mean) ** 2 / (mp.mpf("2.") * sigma ** 2))
def distributions_mp(sigma, q): mu0 = lambda y: pdf_gauss_mp(y, sigma=sigma, mean=mp.mpf(0)) mu1 = lambda y: pdf_gauss_mp(y, sigma=sigma, mean=mp.mpf(1)) mu = lambda y: (1 - q) * mu0(y) + q * mu1(y) return mu0, mu1, mu
def test_tklmbda_zero_shape(self): # When lmbda = 0 the CDF has a simple closed form one = mpmath.mpf(1) assert_mpmath_equal(lambda x: sp.tklmbda(x, 0), lambda x: one / (mpmath.exp(-x) + one), [Arg()], rtol=1e-7)
def get_radius_p_si(self, index): self.adjust_prec() a = self.convert_nbody.to_si(nbody_system.length).number b = mpmath.mpf(self.get_radius_string(index + 1)) * a return b #* self.convert_nbody.to_si(nbody_system.energy).unit
def test_rationalize(): from mpmath import cos, pi, mpf assert rationalize(cos(pi / 3)) == Rational(1, 2) assert rationalize(mpf("0.333333333333333")) == Rational(1, 3) assert rationalize(mpf("-0.333333333333333")) == Rational(-1, 3) assert rationalize(pi, maxcoeff=250) == Rational(355, 113)
def get_kinetic_energy_p_si(self): self.adjust_prec() a = self.convert_nbody.to_si(nbody_system.energy).number # print (a) b = mpmath.mpf(self.get_kinetic_energy_string()) * a return b #* self.convert_nbody.to_si(nbody_system.energy).unit
def volume_solutions_mpmath(T, P, b, delta, epsilon, a_alpha, dps=30): r'''Solution of this form of the cubic EOS in terms of volumes, using the `mpmath` arbitrary precision library. The number of decimal places returned is controlled by the `dps` parameter. This function is the reference implementation which provides exactly correct solutions; other algorithms are compared against this one. Parameters ---------- T : float Temperature, [K] P : float Pressure, [Pa] b : float Coefficient calculated by EOS-specific method, [m^3/mol] delta : float Coefficient calculated by EOS-specific method, [m^3/mol] epsilon : float Coefficient calculated by EOS-specific method, [m^6/mol^2] a_alpha : float Coefficient calculated by EOS-specific method, [J^2/mol^2/Pa] dps : int Number of decimal places in the result by `mpmath`, [-] Returns ------- Vs : tuple[complex] Three possible molar volumes, [m^3/mol] Notes ----- Although `mpmath` has a cubic solver, it has been found to fail to solve in some cases. Accordingly, the algorithm is as follows: Working precision is `dps` plus 40 digits; and if P < 1e-10 Pa, it is `dps` plus 400 digits. The input parameters are converted exactly to `mpf` objects on input. `polyroots` from mpmath is used with `maxsteps=2000`, and extra precision of 15 digits. If the solution does not converge, 20 extra digits are added up to 8 times. If no solution is found, mpmath's `findroot` is called on the pressure error function using three initial guesses from another solver. Needless to say, this function is quite slow. Examples -------- Test case which presented issues for PR EOS (three roots were not being returned): >>> volume_solutions_mpmath(0.01, 1e-05, 2.5405184201558786e-05, 5.081036840311757e-05, -6.454233843151321e-10, 0.3872747173781095) (mpf('0.0000254054613415548712260258773060137'), mpf('4.66038025602155259976574392093252'), mpf('8309.80218708657190094424659859346')) References ---------- .. [1] Johansson, Fredrik. Mpmath: A Python Library for Arbitrary-Precision Floating-Point Arithmetic, 2010. ''' # Tried to remove some green on physical TV with more than 30, could not # 30 is fine, but do not dercease further! # No matter the precision, still cannot get better # Need to switch from `rindroot` to an actual cubic solution in mpmath # Three roots not found in some cases # PRMIX(T=1e-2, P=1e-5, Tcs=[126.1, 190.6], Pcs=[33.94E5, 46.04E5], omegas=[0.04, 0.011], zs=[0.5, 0.5], kijs=[[0,0],[0,0]]).volume_error() # Once found it possible to compute VLE down to 0.03 Tc with ~400 steps and ~500 dps. # need to start with a really high dps to get convergence or it is discontinuous if P == 0.0 or T == 0.0: raise ValueError("Bad P or T; issue is not the algorithm") import mpmath as mp mp.mp.dps = dps + 40#400#400 if P < 1e-10: mp.mp.dps = dps + 400 b, T, P, epsilon, delta, a_alpha = [mp.mpf(i) for i in [b, T, P, epsilon, delta, a_alpha]] roots = None if 1: RT_inv = 1/(mp.mpf(R)*T) P_RT_inv = P*RT_inv B = etas = b*P_RT_inv deltas = delta*P_RT_inv thetas = a_alpha*P_RT_inv*RT_inv epsilons = epsilon*P_RT_inv*P_RT_inv b = (deltas - B - 1) c = (thetas + epsilons - deltas*(B + 1)) d = -(epsilons*(B + 1) + thetas*etas) extraprec = 15 # extraprec alone is not enough to converge everything try: # found case 20 extrapec not enough, increased to 30 # Found another case needing 40 for i in range(8): try: # Found 1 case 100 steps not enough needed 200; then found place 400 was not enough roots = mp.polyroots([mp.mpf(1.0), b, c, d], extraprec=extraprec, maxsteps=2000) break except Exception as e: extraprec += 20 # print(e, extraprec) if i == 7: # print(e, 'failed') raise e if all(i == 0 or i == 1 for i in roots): return volume_solutions_mpmath(T, P, b, delta, epsilon, a_alpha, dps=dps*2) except: try: guesses = volume_solutions_fast(T, P, b, delta, epsilon, a_alpha) roots = mp.polyroots([mp.mpf(1.0), b, c, d], extraprec=40, maxsteps=100, roots_init=guesses) except: pass # roots = np.roots([1.0, b, c, d]).tolist() if roots is not None: RT_P = mp.mpf(R)*T/P hits = [V*RT_P for V in roots] if roots is None: # print('trying numerical mpmath') guesses = volume_solutions_fast(T, P, b, delta, epsilon, a_alpha) RT = T*R def err(V): return(RT/(V-b) - a_alpha/(V*(V + delta) + epsilon)) - P hits = [] for Vi in guesses: try: V_calc = mp.findroot(err, Vi, solver='newton') hits.append(V_calc) except Exception as e: pass if not hits: raise ValueError("Could not converge any mpmath volumes") # Return in the specified precision mp.mp.dps = dps sort_fun = lambda x: (x.real, x.imag) return tuple(sorted(hits, key=sort_fun))
def Interpolate(n, order, bounds, npoints, func): # return value is a dictionary ret = {} # for shifting the bounds bshift = (bounds[0] + bounds[1]) / 2.0 # Generate the chebyschev functions for this interval (T, xi) = GenCheby(order, bounds) # Evaluate all polynomials at roots of highest polynomial rts = xi[order] #print("Coefs of highest polynomial") #print(T[order,:]) #print() #print("Roots of highest polynomial") #print(mp.nstr(rts, 8)) Txi = mp.matrix(order + 1, order) for k in range(0, order + 1): Tn = T[k, :] for i, x in enumerate(rts): for j, a in enumerate(Tn): Txi[k, i] += a * mp.power(x, j) #print() #print("Matrix of root evaluations") #print(mp.nstr(Txi, 8)) # evaluate the boys function at roots # keeping in mind the shift Fxi = [func(n, x + bshift)[n] for x in rts] #print() #print("Value of boys function at (shifted) roots") #print(mp.nstr(Fxi, 8)) # Generate coefficients coef = [None] * (order) for i in range( 0, order ): # note that we are cutting off the last row - it should be zero! coef[i] = mp.mpf(0.0) for j in range(0, order): coef[i] += Txi[i, j] * Fxi[j] coef[i] *= mp.mpf(2.0) / mp.mpf(order) #print() #print("Chebyschev Intermediate Coefficients") #print(mp.nstr(coef, 8)) # Apply coefficients to the proper orders and obtain the coefficients of the Chebyschev polynomial ChebyMat = mp.matrix(order, order) c = [mp.mpf(0)] * order for i in range(0, order): for j in range(0, order): c[j] += T[i, j] * coef[i] # subtract 1/2 coef[0] from the x^0 term c[0] -= mp.mpf(0.5) * coef[0] #print() #print("Final polynomial coefficents") #print(mp.nstr(c, 8)) # return the polynomial ret["polynomial"] = c # Generate test points for this interval xval = np.linspace(bounds[0], bounds[1], npoints) ret["test_x"] = xval ret["test_fx"] = [func(n, x)[n] for x in xval] ret["test_ix"] = [EvalPolynomial(c, x - bshift) for x in xval] ret["test_abserr"] = [ a - b for a, b in zip(ret["test_ix"], ret["test_fx"]) ] ret["test_relerr"] = [ a / b for a, b in zip(ret["test_abserr"], ret["test_fx"]) ] ret["max_abserr"] = max([mp.fabs(a) for a in ret["test_abserr"]]) ret["max_relerr"] = max([mp.fabs(a) for a in ret["test_relerr"]]) return ret
def get_total_mass_p_si(self): self.adjust_prec() a = self.convert_nbody.to_si(nbody_system.mass).number b = mpmath.mpf(self.get_total_mass_string()) * a return b #* self.convert_nbody.to_si(nbody_system.energy).unit