def process(seed, K): """ K is model order / number of zeros """ # create the dirac locations with many, many points rng = np.random.RandomState(seed) tk = np.sort(rng.rand(K)*period) # true zeros uk = np.exp(-1j*2*np.pi*tk/period) coef_poly = poly.polyfromroots(uk) # more accurate than np.poly # estimate zeros uk_hat = np.roots(np.flipud(coef_poly)) uk_hat_poly = poly.polyroots(coef_poly) uk_hat_mpmath = mpmath.polyroots(np.flipud(coef_poly), maxsteps=100, cleanup=True, error=False, extraprec=50) # compute error min_dev_norm = distance(uk, uk_hat)[0] _err_roots = 20*np.log10(np.linalg.norm(uk)/min_dev_norm) min_dev_norm = distance(uk, uk_hat_poly)[0] _err_poly = 20*np.log10(np.linalg.norm(uk)/min_dev_norm) # for mpmath, need to compute error with its precision uk = np.sort(uk) uk_mpmath = [mpmath.mpc(z) for z in uk] uk_hat_mpmath = sorted(uk_hat_mpmath, key=cmp_to_key(compare_mpc)) dev = [uk_mpmath[k] - uk_hat_mpmath[k] for k in range(len(uk_mpmath))] _err_mpmath = 20*mpmath.log(mpmath.norm(uk_mpmath) / mpmath.norm(dev), b=10) return _err_roots, _err_poly, _err_mpmath
def visibility_first_derivative(self, posix_time): """Calculate the derivative of the visibility function of the satellite and the site at a given time. Args: posix_time (float): The UNIX time to evaluate the derivative visibility function at. Returns: The value of the visibility function evaluated at the provided time. """ # Since most helper functions don't play well with mpmath floats we have to perform a lossy # conversion. posix_time = float(posix_time) sat_pos_vel = np.array( self.sat_irp.interpolate(posix_time)) * mp.mpf(1.0) site_pos = np.array(self.site_ecef) * mp.mpf(1.0) pos_diff = np.subtract(sat_pos_vel[0], site_pos) vel_diff = sat_pos_vel[1] site_normal_pos = site_pos / mp.norm(site_pos) site_normal_vel = [0, 0, 0] first_term = mp.mpf( ((1.0 / mp.norm(pos_diff)) * (mp.fdot(vel_diff, site_normal_pos) + mp.fdot(pos_diff, site_normal_vel)))) second_term = mp.mpf(((1.0 / mp.power( (mp.norm(pos_diff)), 3)) * mp.fdot(pos_diff, vel_diff) * mp.fdot(pos_diff, site_normal_pos))) return first_term - second_term
def run_stoch_eig(P, verbose=0): """ stoch_eig returns a stochastic vector x such that x P = x for an irreducible stochstic matrix P. """ if verbose > 1: print("original matrix (stoch_eig):\n", P) x = mp.stoch_eig(P) if verbose > 1: print("x\n", x) eps = mp.exp(0.8 * mp.log(mp.eps)) # From test_eigen.py # x is a left eigenvector of P with eigenvalue unity err0 = mp.norm(x*P-x, p=1) if verbose > 0: print("|xP - x| (stoch_eig):", err0) assert err0 < eps # x is a nonnegative vector if verbose > 0: print("min(x) (stoch_eig):", min(x)) assert min(x) >= 0 - eps # 1-norm of x is one err1 = mp.fabs(mp.norm(x, p=1) - 1) if verbose > 0: print("||x| - 1| (stoch_eig):", err1) assert err1 < eps
def _view_cone_calc(lat_geoc, lon_geoc, sat_pos, sat_vel, q_max, m): """Semi-private: Performs the viewing cone visibility calculation for the day defined by m. Note: This function is based on a paper titled "rapid satellite-to-site visibility determination based on self-adaptive interpolation technique" with some variation to account for interaction of viewing cone with the satellite orbit. Args: lat_geoc (float): site location in degrees at the start of POI lon_geoc (float): site location in degrees at the start of POI sat_pos (Vector3D): position of satellite (at the same time as sat_vel) sat_vel (Vector3D): velocity of satellite (at the same time as sat_pos) q_max (float): maximum orbital radius m (int): interval offsets (number of days after initial condition) Returns: Returns 4 numbers representing times at which the orbit is tangent to the viewing cone, Raises: ValueError: if any of the 4 formulas has a complex answer. This happens when the orbit and viewing cone do not intersect or only intersect twice. Note: With more analysis it should be possible to find a correct interval even in the case where there are only two intersections but this is beyond the current scope of the project. """ lat_geoc = (lat_geoc * mp.pi) / 180 lon_geoc = (lon_geoc * mp.pi) / 180 # P vector (also referred to as orbital angular momentum in the paper) calculations p_unit_x, p_unit_y, p_unit_z = cross(sat_pos, sat_vel) / (mp.norm(sat_pos) * mp.norm(sat_vel)) # Following are equations from Viewing cone section of referenced paper r_site_magnitude = earth_radius_at_geocetric_lat(lat_geoc) gamma1 = THETA_NAUGHT + mp.asin((r_site_magnitude * mp.sin((mp.pi / 2) + THETA_NAUGHT)) / q_max) gamma2 = mp.pi - gamma1 # Note: atan2 instead of atan to get the correct quadrant. arctan_term = mp.atan2(p_unit_x, p_unit_y) arcsin_term_gamma, arcsin_term_gamma2 = [(mp.asin((mp.cos(gamma) - p_unit_z * mp.sin(lat_geoc)) / (mp.sqrt((p_unit_x ** 2) + (p_unit_y ** 2)) * mp.cos(lat_geoc)))) for gamma in [gamma1, gamma2]] angle_1 = (arcsin_term_gamma - lon_geoc - arctan_term + 2 * mp.pi * m) angle_2 = (mp.pi - arcsin_term_gamma - lon_geoc - arctan_term + 2 * mp.pi * m) angle_3 = (arcsin_term_gamma2 - lon_geoc - arctan_term + 2 * mp.pi * m) angle_4 = (mp.pi - arcsin_term_gamma2 - lon_geoc - arctan_term + 2 * mp.pi * m) angles = [angle_1, angle_2, angle_3, angle_4] # Check for complex answers if any([not isinstance(angle, mp.mpf) for angle in angles]): raise ValueError() # Map all angles to 0 to 2*pi for idx in range(len(angles)): while angles[idx] < 0: angles[idx] += 2 * mp.pi while angles[idx] > 2 * mp.pi: angles[idx] -= 2 * mp.pi # Calculate the corresponding time for each angle and return return [mp.nint((1 / ANGULAR_VELOCITY_EARTH) * angle) for angle in angles]
def rotate_3D_mp(x, y): xnorm = mpm.norm(x) ynorm = mpm.norm(y) cos = mpm.fdot(x,y)/(xnorm*ynorm) sin = mpm.sqrt(1.-cos**2) K = (y.T*x-x.T*y)/(xnorm*ynorm*sin) return mpm.eye(3) + sin*K + (1.-cos)*(K*K)
def run_gth_solve(A, verbose=0): """ gth_solve returns a stochastic vector x such that x A = 0 for an irreducible transition rate matrix A. """ if verbose > 1: print("original matrix (gth_solve):\n", A) x = mp.gth_solve(A) if verbose > 1: print("x\n", x) eps = mp.exp(0.8 * mp.log(mp.eps)) # test_eigen.py # x is a solution to x A = 0 err0 = mp.norm(x*A, p=1) if verbose > 0: print("|xA| (gth_solve):", err0) assert err0 < eps # x is a nonnegative vector if verbose > 0: print("min(x) (gth_solve):", min(x)) assert min(x) >= 0 - eps # 1-norm of x is one err1 = mp.fabs(mp.norm(x, p=1) - 1) if verbose > 0: print("||x| - 1| (gth_solve):", err1) assert err1 < eps
def test_poincare_reflect0(): z = mpm.matrix([[0., 0., 0.5]]) x = mpm.matrix([[0.1, -0.2, 0.1]]) assert mpm.norm(poincare_reflect0(z, z)) < TOL y = poincare_reflect0(z, x) assert mpm.norm(poincare_reflect0(z, y) - x) < TOL
def test_poincare_reflect(): x = mpm.matrix([[0.3, -0.3, 0.0]]) a = mpm.matrix([[0.5, 0., 0.0]]) y = poincare_reflect(a, x) R = mpm.norm(a) r1 = mpm.norm(x - a) r2 = mpm.norm(y - a) assert R**2 - r1 * r2 < TOL
def rotate_mp(pts, x, y): out = mpm.zeros(pts.rows, pts.cols) v = x/mpm.norm(x) cos = mpm.fdot(x,y) / (mpm.norm(x), mpm.norm(y)) sin = mpm.sqrt(1.-cos**2) u = y - mpm.fdot(v, y) * v mat = mpm.eye(x.cols) - u.T * u - v.T * v \ + cos * u.T * u - sin * v.T * u + sin * u.T * v + cos * v.T * v return mat
def sphericalknn(data, no_clusters): H = len(data) W = len(data[0]) #calculating the mean to remove the dc component sum_sample = sum(data) norm_sample = np.linalg.norm(sum_sample) mean_sample = (sum_sample) / (norm_sample) #calculating global mean to get centroids of the clusters deviation = 0.01 mean_global = np.zeros([no_clusters, W]) for i in range(0, no_clusters): random_sample = np.random.rand(1, W) - 0.5 random_norm = deviation * (np.random.rand()) random_sample2 = (random_norm * random_sample) / np.linalg.norm(random_sample) temp = mean_sample + random_sample2 mean_global[i, :] = temp / np.linalg.norm(temp) #calculating mean from spherical kmeans sum_sample3 = np.zeros([1, W]) difference = 1 epsilon = 0.01 number = 100 iteration = 0 while (difference > epsilon): iteration = iteration + 1 number2 = number #computing the nearest neighbour and assigning the points #E Step in EM algorithm mean_global2 = np.transpose(mean_global) value = np.dot(data, mean_global2) value_max = value.max(1) clusters = np.argmax(value, axis=1) #computing value of the function number = sum(value_max) #print(number) #computing centroids for the clusters #M step in EM algorithm for i in range(0, no_clusters): sum_sample3 = sum(data[np.where(clusters == i)]) if (mpmath.norm(sum_sample3) != 0): temp2 = sum_sample3 / mpmath.norm( sum_sample3) #np.linalg.norm(sum_sample3) #Check this mean_global[i, :] = temp2 difference = abs(number - number2) return clusters
def refine_model_mdnewton_mpmath(low_dimensional_model, newton_steps=5, expected_quality=(0.1, 0.01, 1e-3, 1e-5, 1e-8, 1e-12, 1e-18, 1e-24), log10_stop_quality=-130, still_good=lambda v70: True, norm=1): """Refines a model using mpmath's MDNewton() solver. For some solutions, this fails due to the critical point being not a 'generic' one. Args: low_dimensional_model: A LowDimensionalModel. still_good: f(v70) -> bool, determines if the solution is still good. newton_steps: The number of multidimensional Newton steps to take. expected_quality: List of expected quality thresholds for each step. (Last entry implicitly repeats.) log10_stop_quality: Stop early if this quality-threshold is reached. norm: The `norm` parameter for mpmath.calculus.optimization.MDNewton(). Returns: A refined LowDimensionalModel. Raises: ValueError, if the solution is no longer good. """ if len(low_dimensional_model.params) == 0: return low_dimensional_model def f_off(*model_vec): v70 = numpy.dot(low_dimensional_model.v70_from_params, numpy.array(model_vec, dtype=mpmath.mpf)) sinfo = scalar_sector_mpmath.mpmath_scalar_manifold_evaluator(v70) return tuple(sinfo.grad_potential) newton = mpmath.calculus.optimization.MDNewton( mpmath.mp, f_off, tuple(low_dimensional_model.params), verbose=1, norm=lambda x: mpmath.norm(x, norm)) newton_iter = iter(newton) for num_step in range(1, newton_steps + 1): opt, stationarity = next(newton_iter) opt_v70 = numpy.dot(low_dimensional_model.v70_from_params, opt) if mpmath.log(stationarity, 10) <= log10_stop_quality: break expected_stationarity = expected_quality[min( len(expected_quality) - 1, num_step)] if stationarity > expected_stationarity: raise ValueError('Stationarity does not improve as expected: ' 'seen=%.6g, wanted=%.6g, step=%d' % (stationarity, expected_stationarity, num_step)) if not still_good(opt_v70): raise ValueError('Solution is no longer good.') print('[MDNewton] Step %d: stat=%s' % (num_step, mpfmt(stationarity))) return LowDimensionalModel( v70_from_params=low_dimensional_model.v70_from_params, params=numpy.array(opt, dtype=mpmath.mpf))
def poincare_dist0(x, c=1.0, precision=None): ''' Distance from 0 to x in the Poincare model with curvature -1/c''' if precision is not None: mpm.mp.dps = precision x_norm = mpm.norm(x) sqrt_c = mpm.sqrt(c) return 2 / sqrt_c * mpm.atanh(x_norm / sqrt_c)
def are_nested(self, v1: NormalVector, r1: float, v2: NormalVector, r2: float): from numpy.linalg import norm distance = norm(v1.get_coordinate() - v2.get_coordinate()) return max(r1, r2) >= distance + min(r1, r2)
def __init__(self, theta, phi, r=None, is_polar=True): from mpmath import mpf, mp, norm, fabs, chop if not r: r = Point._scale else: r *= Point._scale Point._can_change_the_scale = False mp.dps = Point._precision if not is_polar: self.x = mpf(theta) self.y = mpf(phi) self.z = mpf(r) self.norm = norm(self.get_coordinate(), 2) self.set_polar_coordinate() else: self.norm = fabs(r) self.theta = theta self.phi = phi self.set_coordinate() # Setting float parameters self.floatx = float(self.x) self.floaty = float(self.y) self.floatz = float(self.z)
def test_gth_solve_fp(): P = mp.fp.matrix([[-0.1, 0.075, 0.025], [0.15, -0.2 , 0.05 ], [0.25, 0.25 , -0.5 ]]) x_expected = mp.fp.matrix([[0.625, 0.3125, 0.0625]]) x = mp.fp.gth_solve(P) eps = mp.exp(0.8 * mp.log(mp.eps)) # test_eigen.py err0 = mp.norm(x-x_expected, p=1) assert err0 < eps
def test_stoch_eig_fp(): P = mp.fp.matrix([[0.9 , 0.075, 0.025], [0.15, 0.8 , 0.05 ], [0.25, 0.25 , 0.5 ]]) x_expected = mp.fp.matrix([[0.625, 0.3125, 0.0625]]) x = mp.fp.stoch_eig(P) eps = mp.exp(0.8 * mp.log(mp.eps)) # test_eigen.py err0 = mp.norm(x-x_expected, p=1) assert err0 < eps
def newtonMethod(VF, X_start): X = X_start Y = getYacobyMatrix(VF, X) Y_1 = Y**-1 while mp.norm(Y_1 * VF(X), 2) > eps: Y = getYacobyMatrix(VF, X) Y_1 = Y**-1 X = X - (Y_1 * VF(X)) return X
def has_intersection(self, v1: NormalVector, r1: float, v2: NormalVector, r2: float): # v1 and v2 are two distinict points on unit upper semisphere.It returns true if two balls B[v1, r1] and # B[v2, r2] has intersection on unit sphere and in this case answers will be returned as # up_intersect and down_intersect relative to Z - axis. It is O(1) from numpy import cross, dot from numpy.linalg import norm from math import sqrt t1 = r_to_dot(r1) t2 = r_to_dot(r2) u1 = v1.get_coordinate() u2 = v2.get_coordinate() t = dot(u1, u2) dot_equation_solution_on_u1u2 = ((t1 - t * t2) / (1 - t**2)) * u1 + ((t2 - t * t1) / (1 - t**2)) * u2 norm_on_u1u2 = norm(dot_equation_solution_on_u1u2) if norm_on_u1u2 > 1: return False, None, None perp = cross(u1, u2) perp /= norm(perp) if perp[2] < 0: perp *= -1 perp_projection = sqrt(1 - norm_on_u1u2**2) * perp up = dot_equation_solution_on_u1u2 + perp_projection down = dot_equation_solution_on_u1u2 - perp_projection up_intersection = NormalVector(up[0], up[1], up[2], is_polar=False) down_intersection = NormalVector(down[0], down[1], down[2], is_polar=False) return True, up_intersection, down_intersection
def visibility(self, posix_time): """Calculate the visibility function of the satellite and the site at a given time. Args: posix_time (float): The time to evaluate the visibility function at Returns: The value of the visibility function evaluated at the provided time. Note: This function assumes the FOV of the sensors on the satellite are 180 degrees """ # Since most helper functions don't play well with mpmath floats we have to perform a lossy # conversion. posix_time = float(posix_time) site_pos = np.array(self.site_ecef) * mp.mpf(1.0) site_normal_pos = site_pos / mp.norm(site_pos) sat_pos = self.sat_irp.interpolate(posix_time)[0] sat_site = np.subtract(sat_pos, site_pos) return mp.mpf(mp.fdot(sat_site, site_normal_pos) / mp.norm(sat_site))
def coherent_state(self, alpha, dtype=complex): from ..statevector import StateVector as sv x = numpy.empty(self.N1, dtype=dtype) x[0] = dtype("1") for n in range(1, self.N1): x[n] = x[n-1]*alpha/(n)**(0.5) if issubclass(dtype, complex): a = numpy.exp(-numpy.abs(alpha)**2/2.) else: import mpmath a = mpmath.exp(-mpmath.norm(alpha)**2/2) x = a*x[self.N0:self.N1] return sv(x, basis=self)
def cg(vec_x, mat_a, vec_b, rtol, atol, max_times): dim = vec_x.rows r = vec_b - mat_a * vec_x p = r init_norm_r = mpmath.norm(r) old_norm_r = init_norm_r # メインループ for times in range(max_times): ap = mat_a * p alpha = (r.T * p)[0] / (p.T * ap)[0] vec_x = vec_x + alpha * p r = r - alpha * ap new_norm_r = mpmath.norm(r) beta = new_norm_r * new_norm_r / (old_norm_r * old_norm_r) # 収束判定 print(times, mpmath.nstr(new_norm_r / init_norm_r)) if (new_norm_r <= (rtol * init_norm_r + atol)): break p = r + beta * p old_norm_r = new_norm_r return times, vec_x
def test_mev(): output("""\ reim:{$[0>type x;1 0*x;2=count x;x;'`]}; mc:{((x[0]*y 0)-x[1]*y 1;(x[0]*y 1)+x[1]*y 0)}; mmc:{((.qml.mm[x 0]y 0)-.qml.mm[x 1]y 1;(.qml.mm[x 0]y 1)+.qml.mm[x 1]y 0)}; mev_:{[b;x] if[2<>count wv:.qml.mev x;'`length]; if[not all over prec>=abs mmc[flip vc;flip(flip')(reim'')flip x]- flip(w:reim'[wv 0])mc'vc:(flip')(reim'')(v:wv 1);'`check]; / Normalize sign; LAPACK already normalized to real v*:1-2*0>{x a?max a:abs x}each vc[;0]; (?'[prec>=abs w[;1];w[;0];w];?'[b;v;0n])};""") for A in eigenvalue_subjects: if A.rows <= 3: V = [] for w, n, r in A.eigenvects(): w = sp.simplify(sp.expand_complex(w)) if len(r) == 1: r = r[0] r = sp.simplify(sp.expand_complex(r)) r = r.normalized() / sp.sign(max(r, key=abs)) r = sp.simplify(sp.expand_complex(r)) else: r = None V.extend([(w, r)] * n) V.sort(key=lambda (x, _): (-abs(x), -sp.im(x))) else: Am = mp.matrix(A) # extra precision for complex pairs to be equal in sort with mp.extradps(mp.mp.dps): W, R = mp.eig(Am) V = [] for w, r in zip(W, (R.column(i) for i in range(R.cols))): w = mp.chop(w) with mp.extradps(mp.mp.dps): _, S, _ = mp.svd(Am - w * mp.eye(A.rows)) if sum(x == 0 for x in mp.chop(S)) == 1: # nullity 1, so normalized eigenvector is unique r /= mp.norm(r) * mp.sign(max(r, key=abs)) r = mp.chop(r) else: r = None V.append((w, r)) V.sort(key=lambda (x, _): (-abs(x), -x.imag)) W, R = zip(*V) test("mev_[%sb" % "".join("0" if r is None else "1" for r in R), A, (W, [r if r is None else list(r) for r in R]), complex_pair=True)
def test_mev(): output("""\ reim:{$[0>type x;1 0*x;2=count x;x;'`]}; mc:{((x[0]*y 0)-x[1]*y 1;(x[0]*y 1)+x[1]*y 0)}; mmc:{((.qml.mm[x 0]y 0)-.qml.mm[x 1]y 1;(.qml.mm[x 0]y 1)+.qml.mm[x 1]y 0)}; mev_:{[b;x] if[2<>count wv:.qml.mev x;'`length]; if[not all over prec>=abs mmc[flip vc;flip(flip')(reim'')flip x]- flip(w:reim'[wv 0])mc'vc:(flip')(reim'')(v:wv 1);'`check]; / Normalize sign; LAPACK already normalized to real v*:1-2*0>{x a?max a:abs x}each vc[;0]; (?'[prec>=abs w[;1];w[;0];w];?'[b;v;0n])};""") for A in eigenvalue_subjects: if A.rows <= 3: V = [] for w, n, r in A.eigenvects(): w = sp.simplify(sp.expand_complex(w)) if len(r) == 1: r = r[0] r = sp.simplify(sp.expand_complex(r)) r = r.normalized() / sp.sign(max(r, key=abs)) r = sp.simplify(sp.expand_complex(r)) else: r = None V.extend([(w, r)]*n) V.sort(key=lambda (x, _): (-abs(x), -sp.im(x))) else: Am = mp.matrix(A) # extra precision for complex pairs to be equal in sort with mp.extradps(mp.mp.dps): W, R = mp.eig(Am) V = [] for w, r in zip(W, (R.column(i) for i in range(R.cols))): w = mp.chop(w) with mp.extradps(mp.mp.dps): _, S, _ = mp.svd(Am - w*mp.eye(A.rows)) if sum(x == 0 for x in mp.chop(S)) == 1: # nullity 1, so normalized eigenvector is unique r /= mp.norm(r) * mp.sign(max(r, key=abs)) r = mp.chop(r) else: r = None V.append((w, r)) V.sort(key=lambda (x, _): (-abs(x), -x.imag)) W, R = zip(*V) test("mev_[%sb" % "".join("0" if r is None else "1" for r in R), A, (W, [r if r is None else list(r) for r in R]), complex_pair=True)
def poincare_dist(x, y, c=1.0, precision=None): ''' The hyperbolic distance between points in the Poincare model with curvature -1/c Args: x, y: size 1xD mpmath matrix representing point in the D-dimensional ball |x| < 1 precision (int): bits of precision to use Returns: mpmath float object. Can be converted back to regular float ''' if precision is not None: mpm.mp.dps = precision x2 = mpm.fdot(x, x) y2 = mpm.fdot(y, y) xy = mpm.fdot(x, y) sqrt_c = mpm.sqrt(c) denom = 1 - 2 * c * xy + c**2 * x2 * y2 norm = mpm.norm( (-(1 - 2 * c * xy + c * y2) * x + (1. - c * x2) * y) / denom) return 2 / sqrt_c * mpm.atanh(sqrt_c * norm)
def solve_acos_bsin(a, b, c): # It solves the equation $ a cos(theta) + b sin(theta) = c $ for theta as the unknown. # This has either two or no answer. It is needed for the get_covered_phi function. # It always returns the larger answer first. from numpy.linalg import norm from math import acos Norm = norm((a, b)) if abs(c) > Norm: return None, None dot = c / Norm dtheta = acos(dot) if b >= 0: angle = acos(a / Norm) else: angle = -acos(a / Norm) upans = angle + dtheta downans = angle - dtheta return upans, downans
dtheta_values.append( d_theta(angle_v, paramv['k'], paramv['R'], paramv['alpha'], An)) beamshape = [ 20 * mpmath.log10(abs(each / dzero_value)) for each in dtheta_values ] beamshape_df = pd.DataFrame(data={ 'deg': np.degrees(np.float32(angles)), 'd0dthet': np.float32(beamshape) }) error = beamshape - ka5['relonaxis_db'] mean_error = np.float(np.mean(np.abs(error))) max_error = np.max(np.float32(np.abs(error))) matrixsolve_error = mpmath.norm(mpmath.residual(Mmn, An, bm)) #print(f'Decimal precision: {decimalprec} \n Ntrend: {Ntrend}') print(f'Matrix solve error : {matrixsolve_error }') print(f'Mean abs error: {mean_error}, max error: {max_error}\n') # # %% # an_candidate = mpmath.lu_solve(Mmn,bm) # res_mat = mpmath.residual(Mmn, an_candidate, bm) # res = mpmath.norm(res_mat) # print(f'matrix error is: {np.float64(res)}') # %% # an_candidate, res = mpmath.qr_solve(Mmn,bm) # print(res) # #%%
def run(self,**kwargs): """Run the microkinetic model. If recalculate is True then data which is re-loaded will be used as an initial guess; otherwise it will be assumed to be correct.""" for key in kwargs: setattr(self,key,kwargs[key]) #set numerical representation if self.numerical_representation == 'mpmath': import mpmath as mp mp.mp.dps = self.decimal_precision + 25 #pad decimal precision self._math = mp self._log_imports += "\nfrom mpmath import mpf \n\n" self._kB = mp.mpf('8.617332478e-5') #eV/K (from NIST) self._h = mp.mpf('4.135667516e-15') #eV s (from NIST) self._mpfloat = mp.mpf self._matrix = mp.matrix self._Axb_solver = mp.lu_solve self._math.infnorm = lambda x: mp.norm(x,'inf') elif self.numerical_representation in ['numpy','python']: self._log_imports += "\nfrom numpy import matrix \n\n" self._math = np self._math.infnorm = lambda x: np.linalg.norm(x,np.inf) self._mpfloat = float def matrixT(*args,**kwargs): array = np.array(args[0]) while 1 in array.shape: sum_idx = array.shape.index(1) array = array.sum(sum_idx) return array.T self._matrix = matrixT def Axb_solver(A,b): try: return np.linalg.solve(A,b.T) except np.linalg.linalg.LinAlgError: raise ZeroDivisionError self._Axb_solver = Axb_solver if self.decimal_precision > 15: print( 'Warning: Max precision with numpy/python is 16 digits') self.decimal_precision = 15 else: raise AttributeError( 'Numerical representation must be mpmath, numpy, or python.') #set up interaction model if self.adsorbate_interaction_model == 'first_order': interaction_model = catmap.thermodynamics.FirstOrderInteractions(self) response_func = interaction_model.interaction_response_function if not callable(response_func): int_function = getattr(interaction_model, response_func+'_response') interaction_model.interaction_response_function = int_function self.thermodynamics.__dict__['adsorbate_interactions'] = interaction_model elif self.adsorbate_interaction_model == 'second_order': interaction_model = catmap.thermodynamics.SecondOrderInteractions(self) response_func = interaction_model.interaction_response_function if not callable(response_func): int_function = getattr(interaction_model, response_func+'_response') interaction_model.interaction_response_function = int_function self.thermodynamics.__dict__['adsorbate_interactions'] = interaction_model elif self.adsorbate_interaction_model in ['ideal',None]: self.thermodynamics.adsorbate_interactions = None else: raise AttributeError( 'Invalid adsorbate_interaction_model specified.') self.compatibility_check() #determine whether or not to (re-)solve model has_all = True for v in self.output_variables: if not hasattr(self,v+'_map'): has_all = False if not hasattr(self,'stdout'): #any re-loaded model will have stdout has_all = False if self._solved == self._token(): #Do not solve the same model twice has_all = True elif has_all and not self.recalculate: #All data has been loaded and no verification => solved. self._solved = self._token() self.log('input_success') else: #Make "volcano plot" if hasattr(self,'descriptor_ranges') and hasattr(self,'resolution'): self.descriptor_space_analysis() #Get rates at single points if hasattr(self,'descriptors'): self.single_point_analysis(self.descriptors) #Get rates at multiple points if hasattr(self,'descriptor_values'): self.multi_point_analysis() #Save long attrs in data_file for attr in dir(self): if (not attr.startswith('_') and not callable(getattr(self,attr)) and attr not in self._classes): if (len(repr(getattr(self,attr))) > self._max_log_line_length): #line is too long for logfile -> put into pickle self._pickle_attrs.append(attr) pickled_data = {} for attr in self._pickle_attrs: pickled_data[attr] = getattr(self,attr) pickle.dump(pickled_data,open(self.data_file,'w')) #Make logfile log_txt = self._log_imports log_txt += self._header(exclude_outputs=self._pickle_attrs) self._stdout = '\n'.join(self._log_lines) log_txt += 'stdout = ' + '"'*3+self._stdout+'"'*3 #this construction means that self.stdout will only be set #for models which have been re-loaded. self._solved = self._token() if hasattr(self,'log_file'): logfile = self.log_file else: name,suffix = self.setup_file.rsplit('.',1) if suffix != 'log': suffix = 'log' else: suffix = 'out' logfile = '.'.join([name,suffix]) f = open(logfile,'w') f.write(log_txt) f.close() if getattr(self,'create_standalone',None): self.make_standalone()
from pylab import * import mpmath mpmath.mp.dps = 50 # higher precision for demonstration #Nv=100000 Nv=100000 a = [mpmath.sin(2.*mpmath.pi*n/Nv) for n in range(Nv)] b = array(a) print b.dot(b) - Nv/2 b32= array(a,dtype=float32) b64= array(a,dtype=float64) b128= array(a,dtype=float128) print b32.dot(b32) - Nv/2. print b64.dot(b64) - Nv/2. print b128.dot(b128) - Nv/2. print print mpmath.norm(b) - mpmath.sqrt(Nv/2) print norm(b32) - sqrt(Nv/2) print norm(b64) - sqrt(Nv/2) print norm(b128) -sqrt(Nv/2)
], 'agm': [ 'primitive', [lambda x, y: mp.agm(x) if y is None else mp.agm(x, y[0]), None] ], # 'matrix': [ 'primitive', [ lambda x, y: mp.matrix(x) if isa(x, Vector) else mp.matrix(x) if y is None else mp.matrix(x, y[0]), None ] ], 'matrix-ref': ['primitive', [lambda x, y: x[y[0], y[1], [0]], None]], 'matrix-set': [ 'primitive', [lambda x, y: matrix_set(x, y[0], y[1][0], y[1][1][0]), None] ], 'zeros': ['primitive', [lambda x, y: mp.zeros(x), None]], 'ones': ['primitive', [lambda x, y: mp.ones(x), None]], 'eye': ['primitive', [lambda x, y: mp.eye(x), None]], 'diag': ['primitive', [lambda x, y: mp.diag(x), None]], 'randmatrix': ['primitive', [lambda x, y: mp.randmatrix(x), None]], 'matrix-inv': ['primitive', [lambda x, y: x**(-1), None]], 'norm': [ 'primitive', [lambda x, y: mp.norm(x) if y is None else mp.norm(x, y[0]), None] ], 'mnorm': ['primitive', [lambda x, y: mp.mnorm(x, y[0]), None]], }
mat_a = mpmath.zeros(dim, dim) for i in range(dim): for j in range(dim): mat_a[i, j] = mpmath.mpf(dim - max(i, j)) mat_a = mat_a.T * mat_a # print(mat_a) # x = [1 2 ... dim] vec_true_x = mpmath.matrix([i for i in range(1, dim + 1)]) # nprint(vec_true_x) # b = A * x vec_b = mat_a * vec_true_x # CG法実行 # vec_x := 0 vec_x = mpmath.zeros(dim, 1) start_time1 = time.time() iterative_times, vec_x = cg(vec_x, mat_a, vec_b, 1.0e-20, 0.0, dim * 10) time1 = time.time() - start_time1 relerr = mpmath.norm(vec_x - vec_true_x) / mpmath.norm(vec_true_x) print('CG: iteration, time = ', iterative_times, time1, ', relerr(vec_x) = ', relerr) # ------------------------------------- # Copyright (c) 2021 Tomonori Kouya # All rights reserved. # -------------------------------------
def make_polar_coordinate(self, n, is_twisted=True, precision=30, log_scale=0): # This function distribute points with polar coordinate on sphere. This algorithm is O (n^2). # It also returns a phi above which we know north pole is a local maximum. from mpmath import mp, sin, cos, sqrt, pi, floor, mpf, asin from numpy import array, cross from numpy.linalg import norm from os import remove mp.dps = precision remove(self.points_address) if is_twisted: name = "twisted_polar_coordinates_" + str(n) self.point_set = PointSet(name=name, address=self.output_folder) else: name = "polar_coordinates_" + str(n) self.point_set = PointSet(name=name, address=self.output_folder) self.points_address = self.point_set.point_file_address if not float(Point._log_scale) == log_scale: Point.change_log_scale(log_scale) print("Point scale is", Point.get_scale()) if not Point._precision == precision: Point.change_precision(precision) phis = [0] * (n - 1) m = [0] * (n - 1) for j in range(n - 1): phis[j] = ((pi * (j + 1)) / n) - (pi / 2) m[j] = int(floor(mpf(".5") + sqrt(3) * n * cos(phis[j]))) for j in range(n - 1): for i in range(m[j]): if is_twisted: if j + 1 < n / 2: shift = (2 * pi * (j + 1)) / (n * m[j]) else: shift = (2 * pi * (1 - mpf(j + 1) / mpf(n))) / m[j] else: shift = 0 theta = ((2 * pi * i) / m[j]) + shift new_point = Point(theta=theta, phi=phis[j]) self.point_set.add_point(new_point) north_pole = Point(theta=0, phi=pi / 2) south_pole = Point(theta=0, phi=-pi / 2) self.point_set.add_point(north_pole) self.point_set.add_point(south_pole) self.min_discrepancy_distance = 1 / self.point_set.size # In below we get the confidence phi around the north pole highest_phi = -1 for i in range(int(n / 2) - 1, n - 2): phi1 = phis[i] phi2 = phis[i + 1] v1 = array([mpf(0), cos(phi1), mpf(0)]) v2 = array([2 * cos(phi1), mpf(0), sin(phi2) - sin(phi1)]) normal_vector = cross(v1, v2) normal_vector /= norm(normal_vector) highest_phi = max(highest_phi, asin(abs(normal_vector[2]))) return float(highest_phi)
db3 scaling coefficients Wavelet Analysis: The Scalable Structure of Information (2002) Howard L. Resnikoff, Raymond O.Jr. Wells Table 10.3 page 263 ''' db3 = [( _1 + sqrt10 + mp.sqrt(_5 + _2*sqrt10))/_16, ( _5 + sqrt10 + _3*mp.sqrt(_5 + _2*sqrt10))/_16, (_10 - _2*sqrt10 + _2*mp.sqrt(_5 + _2*sqrt10))/_16, (_10 - _2*sqrt10 - _2*mp.sqrt(_5 + _2*sqrt10))/_16, ( _5 + sqrt10 - _3*mp.sqrt(_5 + _2*sqrt10))/_16, ( _1 + sqrt10 - mp.sqrt(_5 + _2*sqrt10))/_16] db3 = np.array(db3) D6 = db3 for a in [D2, D4, D6]: norm = mpmath.norm(a) assert mpmath.almosteq(norm, mp.sqrt(_2)) def wavelet_coefficients(a): # TODO: is this just true for Daubechies wavelets? N = len(a) return np.array([(-1)**k*a[N-1-k] for k in range(N)]) # maps from genus (i.e. vanishing moments) to the scaling coefficients daubechies_wavelets = { 1: D2, 2: D4, 3: D6, }
def calc_ellipsoid_axes(coords, uvals, cell, probability=0.5, longest=True): """ This method calculates the principal axes of an ellipsoid as list of two fractional coordinate triples. Many thanks to R. W. Grosse-Kunstleve and P. D. Adams for their great publication on the handling of atomic anisotropic displacement parameters: R. W. Grosse-Kunstleve, P. D. Adams, J Appl Crystallogr 2002, 35, 477–480. F = ... * exp ( -2π²[ h²(a*)²U11 + k²(b*)²U22 + ... + 2hka*b*U12 ] ) SHELXL atom: Name type x y z occ U11 U22 U33 U23 U13 U12 F3 4 0.210835 0.104067 0.437922 21.00000 0.07243 0.03058 = 0.03216 -0.01057 -0.01708 0.03014 >>> import mpmath as mpm >>> cell = (10.5086, 20.9035, 20.5072, 90, 94.13, 90) >>> coords = [0.210835, 0.104067, 0.437922] >>> uvals = [0.07243, 0.03058, 0.03216, -0.01057, -0.01708, 0.03014] >>> l = calc_ellipsoid_axes(coords, uvals, cell, longest=True) >>> print(mpm.nstr(l)) [[0.24765096, 0.11383281, 0.43064756], [0.17401904, 0.09430119, 0.44519644]] >>> calc_ellipsoid_axes(coords, uvals, cell, longest=False) [[[0.24765096, 0.11383281, 0.43064756], [0.218406, 0.09626142, 0.43746127], [0.21924358, 0.10514684, 0.44886868]], [[0.17401904, 0.09430119, 0.44519644], [0.203264, 0.11187258, 0.43838273], [0.20242642, 0.10298716, 0.42697532]]] >>> cell = (10.5086, 20.9035, 20.5072, 90, 94.13, 90) >>> coords = [0.210835, 0.104067, 0.437922] >>> uvals = [0.07243, -0.03058, 0.03216, -0.01057, -0.01708, 0.03014] >>> calc_ellipsoid_axes(coords, uvals, cell, longest=True) <BLANKLINE> Ellipsoid is non positive definite! <BLANKLINE> False >>> uvals = [0.07243, 0.03058, 0.03216, -0.01057, -0.01708] >>> calc_ellipsoid_axes(coords, uvals, cell, longest=False) Traceback (most recent call last): ... Exception: 6 Uij values have to be supplied! >>> cell = (10.5086, 20.9035, 90, 94.13, 90) >>> coords = [0.210835, 0.104067, 0.437922] >>> uvals = [0.07243, 0.03058, 0.03216, -0.01057, -0.01708, 0.03014] >>> calc_ellipsoid_axes(coords, uvals, cell, longest=True) Traceback (most recent call last): ... Exception: cell needs six parameters! :param coords: coordinates of the respective atom in fractional coordinates :type coords: list :param uvals: Uij valiues of the respective ellipsoid on fractional basis like in cif and SHELXL format :type uvals: list :param cell: unit cell of the structure: a, b, c, alpha, beta, gamma :type cell: list :param probability: thermal probability of the ellipsoid :type probability: float or int :param longest: not always the length is important. make to False to get all three coordiantes of the ellipsoid axes. :type longest: boolean """ from misc import A probability += 1 # Uij is symmetric: if len(uvals) != 6: raise Exception('6 Uij values have to be supplied!') if len(cell) != 6: raise Exception('cell needs six parameters!') # orthogonalization matrix that transforms the fractional coordinates # with respect to a crystallographic basis system to coordinates # with respect to a Cartesian basis: A = A(cell).orthogonal_matrix Ucart = ufrac_to_ucart(A, cell, uvals) # print(Ucart) # E => eigenvalues, Q => eigenvectors: E, Q = mpm.eig(Ucart) # calculate vectors of ellipsoid axes try: sqrt(E[0]) sqrt(E[1]) sqrt(E[2]) except ValueError: print('\nEllipsoid is non positive definite!\n') return False v1 = mpm.matrix([Q[0, 0], Q[1, 0], Q[2, 0]]) v2 = mpm.matrix([Q[0, 1], Q[1, 1], Q[2, 1]]) v3 = mpm.matrix([Q[0, 2], Q[1, 2], Q[2, 2]]) v1i = v1 * (-1) v2i = v2 * (-1) v3i = v3 * (-1) # multiply probability (usually 50%) e1 = sqrt(E[0]) * probability e2 = sqrt(E[1]) * probability e3 = sqrt(E[2]) * probability # scale axis vectors to eigenvalues v1, v2, v3, v1i, v2i, v3i = v1 * e1, v2 * e2, v3 * e3, v1i * e1, v2i * e2, v3i * e3 # find out which vector is the longest: length = mpm.norm(v1) v = 0 if mpm.norm(v2) > length: length = mpm.norm(v2) v = 1 elif mpm.norm(v3) > length: length = mpm.norm(v3) v = 2 # move vectors back to atomic position atom = A * mpm.matrix(coords) v1, v1i = v1 + atom, v1i + atom v2, v2i = v2 + atom, v2i + atom v3, v3i = v3 + atom, v3i + atom # go back into fractional coordinates: a1 = cart_to_frac(v1, cell) a2 = cart_to_frac(v2, cell) a3 = cart_to_frac(v3, cell) a1i = cart_to_frac(v1i, cell) a2i = cart_to_frac(v2i, cell) a3i = cart_to_frac(v3i, cell) allvec = [[a1, a2, a3], [a1i, a2i, a3i]] if longest: # only the longest vector return [allvec[0][v], allvec[1][v]] else: # all vectors: return allvec
def test_left_eigen_vec(self): self.assertTrue(mp.norm(v - v*mp.mp.matrix(P), 'inf') <= TOL)
# chebyshev approximation start_2 = time.time() sv_vector = mp.matrix(12, 2) A_abs = mp.matrix(12) for i in range(12): for j in range(12): A_abs[i, j] = abs(A[i, j]) for i in range(12): sv_vector[i, 0] = A_abs[i, i] - sum(A_abs[i, :]) sv_vector[i, 1] = A_abs[i, i] - sum(A_abs[:, i]) s_min = min(max(sv_vector[:, 0]), max(sv_vector[:, 1])) s_max = mp.sqrt(mp.norm(A, p=1) * mp.norm(A, p=10)) # S = mp.svd_r(A, compute_uv=False) # delta = max(s_max, abs(1 - s_max)) m = 2 dim = 12 delta = s_min ** 2/ (s_max ** 2 + s_min ** 2) # delta_2 = min(S) ** 2/ (max(S) ** 2 + min(S) ** 2) # s_min, s_max = min(S), max(S) interval = [-1, 1] func = lambda x : mp.log(1 - ((1 - 2 * delta) * x + 1) / 2) coeffs = mp.chebyfit(func, interval, N=m) # B = mp.eye(12) - A B = 1/(s_max ** 2 + s_min ** 2) * A.T * A def Han_algorithm(B, m, dim): """
def run(self, **kwargs): """Run the microkinetic model. If recalculate is True then data which is re-loaded will be used as an initial guess; otherwise it will be assumed to be correct. :param recalculate: If True solve model again using previous results as initial guess :type recalculate: bool """ for key in kwargs: setattr(self, key, kwargs[key]) #ensure resolution has the proper dimensions if not hasattr(self.resolution, '__iter__'): self.resolution = [self.resolution] * len(self.descriptor_names) #set numerical representation if self.numerical_representation == 'mpmath': import mpmath as mp mp.mp.dps = self.decimal_precision + 25 #pad decimal precision self._math = mp self._log_imports += "\nfrom mpmath import mpf \n\n" self._kB = mp.mpf('8.617332478e-5') #eV/K (from NIST) self._h = mp.mpf('4.135667516e-15') #eV s (from NIST) self._mpfloat = mp.mpf self._matrix = mp.matrix self._Axb_solver = mp.lu_solve self._math.infnorm = lambda x: mp.norm(x, 'inf') elif self.numerical_representation in ['numpy', 'python']: self._log_imports += "\nfrom numpy import matrix \n\n" self._math = np self._math.infnorm = lambda x: np.linalg.norm(x, np.inf) self._mpfloat = float def matrixT(*args, **kwargs): array = np.array(args[0]) while 1 in array.shape: sum_idx = array.shape.index(1) array = array.sum(sum_idx) return array.T self._matrix = matrixT def Axb_solver(A, b): try: return np.linalg.solve(A, b.T) except np.linalg.linalg.LinAlgError: raise ZeroDivisionError self._Axb_solver = Axb_solver if self.decimal_precision > 15: print('Warning: Max precision with numpy/python is 16 digits') self.decimal_precision = 15 else: raise AttributeError( 'Numerical representation must be mpmath, numpy, or python.') #set up interaction model if self.adsorbate_interaction_model == 'first_order': interaction_model = catmap.thermodynamics.FirstOrderInteractions( self) interaction_model.get_interaction_info() response_func = interaction_model.interaction_response_function if not callable(response_func): int_function = getattr(interaction_model, response_func + '_response') interaction_model.interaction_response_function = int_function self.thermodynamics.__dict__[ 'adsorbate_interactions'] = interaction_model elif self.adsorbate_interaction_model == 'second_order': interaction_model = catmap.thermodynamics.SecondOrderInteractions( self) interaction_model.get_interaction_info() response_func = interaction_model.interaction_response_function if not callable(response_func): int_function = getattr(interaction_model, response_func + '_response') interaction_model.interaction_response_function = int_function self.thermodynamics.__dict__[ 'adsorbate_interactions'] = interaction_model elif self.adsorbate_interaction_model in ['ideal', None]: self.thermodynamics.adsorbate_interactions = None else: raise AttributeError( 'Invalid adsorbate_interaction_model specified.') self.compatibility_check() #determine whether or not to (re-)solve model has_all = True for v in self.output_variables: if not hasattr(self, v + '_map'): has_all = False if not hasattr(self, 'stdout'): #any re-loaded model will have stdout has_all = False if self._solved == self._token() and not getattr( self, 'recalculate', None): #Do not solve the same model twice has_all = True elif has_all and not getattr(self, 'recalculate', None): #All data has been loaded and no verification => solved. self._solved = self._token() self.log('input_success') else: ran_dsa = False #When no map exists, run descriptor space analysis first if not getattr(self, 'coverage_map', None): #Make "volcano plot" if getattr(self, 'descriptor_ranges', None) and getattr( self, 'resolution', None): self.descriptor_space_analysis() ran_dsa = True #Get rates at single points if getattr(self, 'descriptors', None): self.single_point_analysis(self.descriptors) #Get rates at multiple points if getattr(self, 'descriptor_values', None): self.multi_point_analysis() #If a map exists, run descriptor space analysis last (so that single-point guesses are #not discarded) if not ran_dsa and getattr(self, 'descriptor_ranges', None) and getattr( self, 'resolution', None): self.descriptor_space_analysis() #Save long attrs in data_file for attr in dir(self): if (not attr.startswith('_') and not callable(getattr(self, attr)) and attr not in self._classes): if (len(repr(getattr(self, attr))) > self._max_log_line_length): #line is too long for logfile -> put into pickle self._pickle_attrs.append(attr) pickled_data = {} for attr in self._pickle_attrs: pickled_data[attr] = getattr(self, attr) pickle.dump(pickled_data, open(self.data_file, 'w')) #Make logfile log_txt = self._log_imports log_txt += self._header(exclude_outputs=self._pickle_attrs) self._stdout = '\n'.join(self._log_lines) log_txt += 'stdout = ' + '"' * 3 + self._stdout + '"' * 3 #this construction means that self.stdout will only be set #for models which have been re-loaded. self._solved = self._token() if hasattr(self, 'log_file'): logfile = self.log_file else: name, suffix = self.setup_file.rsplit('.', 1) if suffix != 'log': suffix = 'log' else: suffix = 'out' logfile = '.'.join([name, suffix]) f = open(logfile, 'w') f.write(log_txt) f.close() if getattr(self, 'create_standalone', None): self.make_standalone()
def sarkar_embedding(tree, root, **kwargs): ''' Embed a tree in the Poincare disc using Sarkar's algorithm from "Low Distortion Delaunay Embedding of Trees in Hyperbolic Plane. Args: tree (networkx.Graph) : The tree represented with int node labels. Weighted trees should have the edge attribute "weight" root (int): The node to use as the root of the embedding Keyword Args: weighted (bool): True if the tree is weighted (default True) tau (float): the scaling factor for distances. By default it is calculated based on statistics of the tree. epsilon (float): parameter >0 controlling distortion bound (default 0.1). precision (int): number of bits of precision to use. By default it is calculated based on tau and epsilon. Returns: size N x 2 mpmath.matrix containing the coordinates of embedded nodes ''' eps = kwargs.get("epsilon",0.1) weighted = kwargs.get("weighted", True) tau = kwargs.get("tau") max_deg = max(tree.degree)[1] if tau is None: tau = (1+eps)/eps * mpm.log(2*max_deg/ mpm.pi) prc = kwargs.get("precision") if prc is None: prc = _embedding_precision(tree,root,eps) mpm.mp.dps = prc n = tree.order() emb = mpm.zeros(n,2) place = [] # place the children of root for i, v in enumerate(tree[root]): if weighted: r = mpm.tanh( tau*tree[root][v]["weight"]) else: r = mpm.tanh(tau) theta = 2*i*mpm.pi / tree.degree[root] emb[v,0] = r*mpm.cos(theta) emb[v,1] = r*mpm.sin(theta) place.append((root,v)) # TODO parallelize this while place: u, v = place.pop() # u is the parent of v p, x = emb[u,:], emb[v,:] rp = poincare_reflect0(x, p, precision=prc) arg = mpm.acos(rp[0]/mpm.norm(rp)) if rp[1] < 0: arg = 2*mpm.pi - arg theta = 2*mpm.pi / tree.degree[v] i=0 for w in tree[v]: if w == u: continue i+=1 if weighted: r = mpm.tanh(tau*tree[v][w]["weight"]) else: r = mpm.tanh(tau) w_emb = r * mpm.matrix([mpm.cos(arg+theta*i),mpm.sin(arg+theta*i)]).T w_emb = poincare_reflect0(x, w_emb, precision=prc) emb[w,:] = w_emb place.append((v,w)) return emb
def characterize_solution(ss, _matrix): residues = residues_calc(ss, _matrix) sae_residues = norm(residues, 1) sse_residues = norm(residues, 2) return sae_residues, sse_residues
def lyapunov_exponent(mathcalA, varphi, periodic_points, alg='basic', norm=2): k = max([len(word) for word in periodic_points]) if alg == 'basic': approx_basic = [] for n in range(1, k + 1): integral = sum([ mpmath.log(mpmath.norm(cocycle(word, mathcalA), p=norm)) * weight(word, varphi) for word in periodic_points if len(word) == n ]) normalization = sum([ weight(word, varphi) for word in periodic_points if len(word) == n ]) approx_basic.append(integral / (n * normalization)) return approx_basic elif alg == 'pollicott': #Compute the operator trace for each periodic point op_trace = { word: operator_trace(cocycle(word, mathcalA), 0)[0] for word in periodic_points } op_trace_der = { word: operator_trace(cocycle(word, mathcalA), 0)[1] for word in periodic_points } #Compute traces for products of transfer operator put in dictionary indexed by power trace = [ sum([(op_trace[word] * weight(word, varphi)) for word in periodic_points if len(word) == n]) for n in range(1, k + 1) ] trace_der = [ sum([(op_trace_der[word] * weight(word, varphi)) for word in periodic_points if len(word) == n]) for n in range(1, k + 1) ] coefficients = [mpmath.mpf(1)] coefficients_der = [mpmath.mpf(0)] for n in range(1, k + 1): M = mpmath.matrix(n) Der_M = mpmath.matrix(n) for i in range(0, n): for j in range(0, n): if j > i + 1: M[i, j] = 0 Der_M[i, j] = 0 elif j == i + 1: M[i, j] = n - j Der_M[i, j] = 0 else: M[i, j] = trace[i - j] Der_M[i, j] = trace_der[i - j] coefficients.append((((-1)**n) / mpmath.fac(n)) * mpmath.det(M)) if n == 1: coefficients_der.append( (((-1)**n) / mpmath.fac(n)) * trace_der[0]) else: #Use Jacobi's formula to compute derivative of coefficients coefficients_der.append( (((-1)**n) / mpmath.fac(n)) * trace_of(adj(M) * Der_M)) approximation = [] for n in range(1, k + 1): approximation.append( sum([coefficients_der[m] for m in range(1, n + 1)]) / sum([m * coefficients[m] for m in range(1, n + 1)])) return approximation else: return "Choices of algorithm are 'basic' and 'pollicott'"