def FreeFermions(eigvec, subsystem, FermiVector): r=range(FermiVector) Cij=mp.matrix([[mp.fsum([eigvec[i,k]*eigvec[j,k] for k in r]) for i in subsystem] for j in subsystem]) C_eigval=mp.eigsy(Cij, eigvals_only=True) EH_eigval=mp.matrix([mp.log(mp.fdiv(mp.fsub(mp.mpf(1.0),x),x)) for x in C_eigval]) S=mp.re(mp.fsum([mp.log(mp.mpf(1.0)+mp.exp(-x))+mp.fdiv(x,mp.exp(x)+mp.mpf(1.0)) for x in EH_eigval])) return(S)
def mp_Lsolve(L, b): n = L.rows x = b.copy() for i in range(n): x[i] -= mp.fsum(L[i, j] * x[j] for j in range(i)) x[i] /= L[i, i] return x
def _error_estimate1( h, sinh_t, cosh_t, cosh_sinh_t, y0, y1, fly, fry, f_left, f_right, alpha, last_estimate, ): """ A pretty accurate error estimation is E(h) = h * (h/2/pi)**2 * sum_{-N}^{+N} F''(h*j) with F(t) = f(g(t)) * g'(t), g(t) = tanh(pi/2 sinh(t)). """ alpha2 = alpha / mp.mpf(2) sinh_sinh_t = numpy.array(list(map(mp.sinh, sinh_t))) tanh_sinh_t = sinh_sinh_t / cosh_sinh_t # More derivatives of y = 1-g(t). y2 = -alpha2 * (sinh_t - 2 * cosh_t**2 * tanh_sinh_t) / cosh_sinh_t**2 y3 = (-alpha2 * cosh_t * (+cosh_sinh_t - 4 * cosh_t**2 / cosh_sinh_t + 2 * cosh_t**2 * cosh_sinh_t + 2 * cosh_t**2 * tanh_sinh_t * sinh_sinh_t - 6 * sinh_t * sinh_sinh_t) / cosh_sinh_t**3) fl1_y = numpy.array([f_left[1](yy) for yy in y0]) fl2_y = numpy.array([f_left[2](yy) for yy in y0]) fr1_y = numpy.array([f_right[1](yy) for yy in y0]) fr2_y = numpy.array([f_right[2](yy) for yy in y0]) # Second derivative of F(t) = f(g(t)) * g'(t). summands = numpy.concatenate([ y3 * fly + 3 * y1 * y2 * fl1_y + y1**3 * fl2_y, y3 * fry + 3 * y1 * y2 * fr1_y + y1**3 * fr2_y, ]) val = h * (h / 2 / mp.pi)**2 * mp.fsum(summands) if last_estimate is None: # Root level: The midpoint is counted twice in the above sum. out = val / 2 else: out = last_estimate / 8 + val return out
def FreeFermions(subsystem, C): C = mp.matrix([[C[x, y] for x in subsystem] for y in subsystem]) C_eigval = mp.eigh(C, eigvals_only=True) EH_eigval = mp.matrix( [mp.log(mp.fdiv(mp.fsub(mp.mpf(1.0), x), x)) for x in C_eigval]) S = mp.re( mp.fsum([ mp.log(mp.mpf(1.0) + mp.exp(-x)) + mp.fdiv(x, mp.exp(x) + mp.mpf(1.0)) for x in EH_eigval ])) return (S)
def FreeFermions(subsystem, C_t): #implements free fermion technique by peschel C = mp.matrix([[C_t[x, y] for x in subsystem] for y in subsystem]) C_eigval = mp.eigh(C, eigvals_only=True) EH_eigval = mp.matrix( [mp.log(mp.fdiv(mp.fsub(mp.mpf(1.0), x), x)) for x in C_eigval]) S = mp.re( mp.fsum([ mp.log(mp.mpf(1.0) + mp.exp(-x)) + mp.fdiv(x, mp.exp(x) + mp.mpf(1.0)) for x in EH_eigval ])) return (S)
def rate_process_RMSE(rate_log_dic, correct_rate, size): l = [] dic = {} correct_rate_mpf = mp.mpf(correct_rate) for i in rate_log_dic: if rate_log_dic[i] == None: continue else: element = mp.fsub(rate_log_dic[i], correct_rate_mpf) l.append(element) square = mp.fsum(l, squared=True) mean = mp.fdiv(square, size) root = mp.sqrt(mean) dic['rate_RMSE'] = root return dic
def SvN(Dm, Dp, Kpart): dim = 2 * len(Kpart) gamma = mp.matrix(dim, dim) KpartH = Kpart.H for m in list(range(0, dim, 2)): for n in list(range(0, dim, 2)): row = int((m + 1) / 2) col = int((n + 1) / 2) gamma[m, n] = mp.j * Dp[row, col] gamma[m, n + 1] = mp.j * Kpart[row, col] gamma[m + 1, n] = -mp.j * KpartH[row, col] gamma[m + 1, n + 1] = mp.j * Dm[row, col] eigvalgamma = mp.eigh(gamma, eigvals_only=True) Spart = mp.fsum([ -((mp.mpf(1.0) + x) / mp.mpf(2)) * mp.log( (mp.mpf(1.0) + x) / mp.mpf(2)) for x in eigvalgamma ]) return (Spart)
def tanh_sinh_lr(f_left, f_right, alpha, eps, max_steps=10): '''Integrate a function `f` between `a` and `b` with accuracy `eps`. The function `f` is given in terms of two functions * `f_left(s) = f(a + s)`, i.e., `f` linearly scaled such that `f_left(0) = a`, `f_left(b-a) = b`, * `f_right(s) = f(b - s)`, i.e., `f` linearly scaled such that `f_right(0) = b`, `f_left(b-a) = a`. Implemented are Bailey's enhancements plus a few more tricks. David H. Bailey, Karthik Jeyabalan, and Xiaoye S. Li, Error function quadrature, Experiment. Math., Volume 14, Issue 3 (2005), 317-329, <https://projecteuclid.org/euclid.em/1128371757>. David H. Bailey, Tanh-Sinh High-Precision Quadrature, 2006, <http://www.davidhbailey.com/dhbpapers/dhb-tanh-sinh.pdf>. ''' num_digits = int(-mp.log10(eps) + 1) mp.dps = num_digits alpha2 = alpha / mp.mpf(2) # What's a good initial step size `h`? # The larger `h` is chosen, the fewer points will be part of the # evaluation. However, we don't want to choose the step size too large # since that means less accuracy for the quadrature overall. The idea would # then be too choose `h` such that it is just large enough for the first # tanh-sinh-step to contain only one point, the midpoint. The expression # # j = mp.ln(-2/mp.pi * mp.lambertw(-tau/h/2, -1)) / h # # hence needs to just smaller than 1. (Ideally, one would actually like to # get `j` from the full tanh-sinh formula, but the above approximation is # good enough.) One gets # # 0 = pi/2 * exp(h) - h - ln(h) - ln(pi/tau) # # for which there is no analytic solution. One can, however, approximate # it. Since pi/2 * exp(h) >> h >> ln(h) (for `h` large enough), one can # either forget about both h and ln(h) to get # # h0 = ln(2/pi * ln(pi/tau)) # # or just scratch ln(h) to get # # h1 = ln(tau/pi) - W_{-1}(-tau/2). # # Both of these suggestions underestimate and `j` will be too large. An # approximation that overestimates is obtained by replacing `ln(h)` by `h`, # # h2 = 1/2 - log(sqrt(pi/tau)) - W_{-1}(-sqrt(exp(1)*pi*tau) / 4). # # Application of Newton's method will improve all of these approximations # and will also always overestimate such that `j` won't exceed 1 in the # first step. Nice! # TODO since we're doing Newton iterations anyways, use a more accurate # representation for j, and consequently for h h = _solve_expx_x_logx(eps**2, tol=1.0e-10) last_error_estimate = None success = False for level in range(max_steps + 1): # We would like to calculate the weights until they are smaller than # tau, i.e., # # h * pi/2 * cosh(h*j) / cosh(pi/2 * sinh(h*j))**2 < tau. # # (TODO Newton on this expression to find tau?) # # To streamline the computation, j is estimated in advance. The only # assumption we're making is that h*j>>1 such that exp(-h*j) can be # neglected. With this, the above becomes # # tau > h * pi/2 * exp(h*j)/2 / cosh(pi/2 * exp(h*j)/2)**2 # # and further # # tau > h * pi * exp(h*j) / exp(pi/2 * exp(h*j)). # # Calling z = - pi/2 * exp(h*j), one gets # # tau > -2*h*z * exp(z) # # This inequality is fulfilled exactly if z = W(-tau/h/2) with W being # the (-1)-branch of the Lambert-W function IF exp(1)*tau < 2*h (which # we can assume since `tau` will generally be small). We finally get # # j > ln(-2/pi * W(-tau/h/2)) / h. # # We do require j to be positive, so -2/pi * W(-tau/h/2) > 1. This # translates to the slightly stricter requirement # # tau * exp(pi/2) < pi * h, # # i.e., h needs to be about 1.531 times larger than tau (not only 1.359 # times as the previous bound suggested). # # Note further that h*j is ever decreasing as h decreases. assert eps**2 * mp.exp(mp.pi / 2) < mp.pi * h j = int(mp.ln(-2 / mp.pi * mp.lambertw(-eps**2 / h / 2, -1)) / h) # At level 0, one only takes the midpoint, for all greater levels every # other point. The value estimation is later completed with the # estimation from the previous level which. if level == 0: t = [0] else: t = h * numpy.arange(1, j + 1, 2) sinh_t = mp.pi / 2 * numpy.array(list(map(mp.sinh, t))) cosh_t = mp.pi / 2 * numpy.array(list(map(mp.cosh, t))) cosh_sinh_t = numpy.array(list(map(mp.cosh, sinh_t))) # y = alpha/2 * (1 - x) # x = [mp.tanh(v) for v in u2] exp_sinh_t = numpy.array(list(map(mp.exp, sinh_t))) y0 = alpha2 / exp_sinh_t / cosh_sinh_t y1 = -alpha2 * cosh_t / cosh_sinh_t**2 weights = -h * y1 fly = numpy.array([f_left[0](yy) for yy in y0]) fry = numpy.array([f_right[0](yy) for yy in y0]) lsummands = fly * weights rsummands = fry * weights # Perform the integration. if level == 0: # The root level only contains one node, the midpoint; function # values of f_left and f_right are equal here. Deliberately take # lsummands here. value_estimates = list(lsummands) else: value_estimates.append( # Take the estimation from the previous step and half the step # size. Fill the gaps with the sum of the values of the current # step. value_estimates[-1] / 2 + mp.fsum(lsummands) + mp.fsum(rsummands)) # error estimation if 1 in f_left and 2 in f_left: assert 1 in f_right and 2 in f_right error_estimate = _error_estimate1(h, sinh_t, cosh_t, cosh_sinh_t, y0, y1, fly, fry, f_left, f_right, alpha, last_error_estimate) last_error_estimate = error_estimate else: error_estimate = _error_estimate2(eps, value_estimates, lsummands, rsummands) if abs(error_estimate) < eps: success = True break h /= 2 assert success return value_estimates[-1], error_estimate
def Sum(A): assert (len(A) > 0) return mp.fsum(A)
def Sum(A): assert(len(A) > 0) return mp.fsum(A)
def sum_exact(p): mp.dps = dps return mp.fsum(p)
def Entropy(sample): return -math.fsum(map(math.fmul, np.asarray(sample), map(math.log, map(math.fmul, np.asarray(sample), [len(sample)]*len(sample)))))
def kullbackLeiblerDivergence(sample,reference_sample): return -math.fsum(np.asarray(sample)*map(math.log,np.asarray(sample)/np.asarray(reference_sample)))
def ZPS(sample, beta=0.01): Z = math.fsum(map(math.exp, map(math.fmul, [-beta]*len(sample), np.asarray(sample)))) P = map(math.fdiv, map(math.exp, map(math.fmul, [-beta]*len(sample), np.asarray(sample))), np.asarray([Z]*len(sample))) S = Entropy(P) return Z, P, S
def is_inverse_sum(numbers): """This function checks if the array of integers are an inverse sum of 0.5""" return mp.fsum([mp.fdiv(1, (n * n)) for n in numbers]) == 0.5