def string2number(s): # a start to replace p2sage (used for the paramters in the FE) strs = str(s).replace(' ','') try: if 'e' in strs: # check for e(m/n) := exp(2*pi*i*m/n), used by Dirichlet characters, for example r = re.match(r'^\$?e\\left\(\\frac\{(?P<num>\d+)\}\{(?P<den>\d+)\}\\right\)\$?$',strs) if not r: r = re.match(r'^e\((?P<num>\d+)/(?P<den>\d+)\)$',strs) if r: q = Rational(r.groupdict()['num'])/Rational(r.groupdict()['den']) return CDF(exp(2*pi*I*q)) if 'I' in strs: return CDF(strs) elif (type(s) is list or type(s) is tuple) and len(s) == 2: return CDF(tuple(s)) elif '/' in strs: return Rational(strs) elif strs=='0.5': # Temporary fix because 0.5 in db for EC return Rational('1/2') elif '.' in strs: return float(strs) else: return Integer(strs) except: return s
def cross_ratio(theta0, theta1, theta2, theta3, rational=True): # WE NEED TO FIRST SIMPLIFY POSSIBLE DIVISION BY 0 # AND NaN (infinity) values num1 = theta0 - theta2 num2 = theta1 - theta2 denom1 = theta0 - theta3 denom2 = theta1 - theta3 #First come simplifications if isnan(num1) and isnan(num2): num1 = 1 num2 = 1 if isnan(denom1) and isnan(denom2): denom1 = 1 denom2 = 1 #print(num1, "/", denom1, " : ", num2, "/", denom2) #Then we calculate numerator and denominator finalNum = divide(num1, denom1) finalDen = divide(num2, denom2) if rational: return Rational(divide(finalNum, finalDen)) else: return divide(finalNum, finalDen)
def evalpolelt(label, gen, genlabel='a'): """ label is a compact polynomial expression in genlabel ( '*' and '**' are removed ) """ res = 0 import re regexp = r'([+-]?)([+-]?\d*o?\d*)(%s\d*)?' % genlabel for m in re.finditer(regexp, label): s, c, e = m.groups() if c == '' and e == None: break if c == '': c = 1 else: """ c may be an int or a rational a/b """ from sage.rings.rational import Rational c = str(c).replace('o', '/') c = Rational(c) if s == '-': c = -c if e == None: e = 0 elif e == genlabel: e = 1 else: e = int(e[1:]) res += c * gen**e return res
def test_nf(): from sage.all import NumberField, QQ, AA, Rational, polygen from pyeantic.sage_conversion import sage_nf_to_eantic x = polygen(QQ) # linear K = NumberField(x - 3, 'x', embedding=QQ(3)) L = sage_nf_to_eantic(K) # quadratic K = NumberField(2*x**2 - 3, 'A', embedding=AA(Rational((3,2)))**Rational((1,2))) L = sage_nf_to_eantic(K) # cubic p = x**3 - x**2 - x - 1 s = p.roots(AA, False)[0] K = NumberField(x**3 - x**2 - x - 1, 's', embedding=s) L = sage_nf_to_eantic(K)
def gauss_sum(self, val): val = int(val) mod, num = self.modulus, self.number g = self.chi.gauss_sum_numerical(val) g = complex2str(g) x = Rational('%s/%s' % (val, mod)) n = x.numerator() n = str(n) + "r" if not n == 1 else "r" d = x.denominator() Gtex = r'\Z/%s\Z' % mod chitex = self.char2tex(mod, num, tag=False) chitexr = self.char2tex(mod, num, 'r', tag=False) deftex = r'\sum_{r\in %s} %s e\left(\frac{%s}{%s}\right)'%(Gtex,chitexr,n,d) return r"\(\displaystyle \tau_{%s}(%s) = %s = %s \)" % (val, chitex, deftex, g)
def abstrace(x, deg): # absolute trace of a gp int / polmod / polmod pver polmod # trace of a t_POLMOD does what is expected but trace of an int # doubles it. Also we might see an int as one coefficient of a newform # most of whose coefficients are t_POLMODs. In this case we need to # multiply by the appropriate degree, so have to pass the degree as a # parameter. #print("abstrace({}) in degree {}".format(x,deg)) if deg == 1: return x.sage() if x in QQ: # miraculously this works for a GpElement #print("---returns(2) {}".format(deg*QQ(x))) return deg * Rational(x) try: #print("---returns(3) {}".format(x.trace().sage())) return x.trace().sage() except NameError: return x.trace().trace().sage()
def irr(self): """ Make the irreducible boundary. It will be returned with a coefficient of 1/2. :: sage: from strataalgebra import * sage: s = StrataAlgebra(QQ, 1, (1,2)) sage: s.irr() 1/2*D_irr """ # type: () -> object if self.g < 1: raise Exception("No irreducible boundaries for genus 0!") #G = StrataGraph(self.strataP._dstrata[0].keys()[0].M) G = StrataGraph(self.strataP.open_stratum().M) G.add_edge(1, 1) G.M[1, 0] -= 1 G.compute_invariant() return Rational((1, 2)) * self(G)
def boundary(self, g1, markings1=()): """ Return a boundary divisor with genus `g1` and `markings1` points on one component :param int g1: The genus on one component :param list markings1: A list or tuple of markings on the one component. Defaults to the empty list. :rtype: :class:`StrataAlgebraElement` Note that if the two components are the same, it will return the stratum with a coefficient of 1/2. :: sage: from strataalgebra import * sage: s = StrataAlgebra(QQ, 1, (1,2,3)) sage: s.boundary(0, (1,2)) Dg0m1_2 sage: s.boundary(1,[3]) Dg0m1_2 sage: s = StrataAlgebra(QQ, 2) sage: s.boundary(1) 1/2*Dg1 Each component must still be stable. :: sage: s.boundary(2) Traceback (most recent call last): ... KeyError: Dg0 """ markings2 = list(self.markings) for m in markings1: markings2.remove(m) g2 = self.g - g1 M = Matrix(StrataGraph.R, [[-1, 0] + list(markings1) + markings2, [g1, 1] + [1] * len(markings1) + [0] * len(markings2), [g2, 1] + [0] * len(markings1) + [1] * len(markings2)]) G = StrataGraph(M) G.compute_invariant() if self.g - g1 == g1 and len(self.markings) == 0: return Rational((1, 2)) * self(G) return self(G)
def basis_integrals(self, s=None): """ Return a list of numbers corresponding to the integrals of the basis elements in the top codimension. This is computed via the FZ relations, so it is probably not fast. However, it is a nice check. The value is cached, so you only have to compute it once per session. This is used by :meth:`~strataalgebra.StrataAlgebraElement.integrate` which is the more likely way you will want to use it. :: sage: from strataalgebra import * sage: s = StrataAlgebra(QQ,1,(1,)) sage: s.print_strata(1) **** i: 0 D_irr <BLANKLINE> **** i: 1 ka1 <BLANKLINE> **** i: 2 ps1 <BLANKLINE> sage: s.basis_integrals() [1, 1/24, 1/24] """ int_kappa = Rational((1, 24**self.g * factorial(self.g))) G = StrataGraph(self.strataP.open_stratum().M) G.M[1, 0] += StrataGraph.Xvar**self.moduli_dim kappa_index = self.strataP.index_from_graph_codim( G, self.moduli_dim) #._dstrata[self.moduli_dim][G] M = self.FZ_matrix(self.moduli_dim) ker = M.right_kernel() if ker.dimension() != 1: raise Exception("Something unexpected here!") return list(int_kappa / ker.gen(0)[kappa_index] * ker.gen(0))
def kappa_coeff(sigma,kappa_0,F): #maybe not optimal to compute the target_partition twice here... #global kappa_coeff_dict mmm = F.degree() target_partition = [] for i in range(1,mmm+1): for j in range(F[i]): target_partition.append(i) #key = (tuple(sigma),kappa_0,tuple(target_partition)) #if kappa_coeff_dict.has_key(key): # return kappa_coeff_dict[key] total = 0 num_ones = sum(1 for i in sigma if i == 1) for i in range(0,num_ones+1): for injection in Permutations(list(range(len(target_partition))),len(sigma)-i): term = binomial(num_ones,i)*binomial(kappa_0 + len(target_partition) + i-1, i)*factorial(i) for j in range(len(sigma)-i): term *= C_coeff(sigma[j+i],target_partition[injection[j]]) for j in range(len(target_partition)): if j in injection: continue term *= C_coeff(0,target_partition[j]) total += term return (-1)**(len(target_partition)+len(sigma))*total * Rational((1,aut(target_partition)))
def _invert_and_normalize(distances): geometric_mean = prod(distances)**Rational((1, len(distances))) return [geometric_mean / distance for distance in distances]
def div_ratio3(theta0, theta1, theta2, rational=True): aux = divide((theta1 - theta0), (theta2 - theta1)) if rational: return Rational(aux) else: return aux
def vecAsFractions(vec): return [Rational(x) for x in vec]
def replmon(n): ''' Return the result of application of :math:`\\mathcal{Z}`-operator to the monomial :math:`b_i^n`. ''' if n == 0: return 1 else: return factorial(n) * Rational(zeta(n + 1) / pi**(n + 1))
def _prod(self, ci1, ci2): """ Compute a product. You should probably not call this directly. Instead, just use the * operator. Values are cached in ``self._prod_dict``. INPUT: - ``ci1`` -- A tuple of (codim,index), where codim is the codimension of the basis element and index is its index in the list of classes. - ``ci2`` -- Ditto. OUTPUT: A dictionary mapping indexes of basis elements in codimension ci1[1]+ci2[1] to coefficients. """ #print ci1, ci2 if ci1[0] + ci2[0] > self.moduli_dim: #print "codim wrong!!" return dict() if ci1 > ci2: temp = ci1 ci1 = ci2 ci2 = temp if ci1 == (0, 0): #print "identity!" return {ci2[1]: 1} value = self._prod_dict.get((ci1, ci2), None) if value != None: #print "retrived value", value return value #print "computing!" #compute the value! G = self.strataP.get_stratum(*ci1) #[ci1[0]][ci1[1]] H = self.strataP.get_stratum(*ci2) #[ci2[0]][ci2[1]] # print "got stratum" prod_dict = dict() loop_coef = 2**(G.num_undecorated_loops() + H.num_undecorated_loops()) for A in self.strataP.common_degenerations(G, H): PsiKappaRing, kappa, psi, psi2 = PsiKappaVars(A) autA = graph_count_automorphisms(A) for Gs, Hs in genericGHstructures(G, H, A): #print "A:" #print A #print "Gs:" #print G #print Gs #print "Hs:" #print H #print Hs #print "psi", psi #print "psi2", psi2 prod_f_A_G = self._prod_f_A_G(Gs, kappa, psi, psi2) prod_f_A_H = self._prod_f_A_G(Hs, kappa, psi, psi2) excess = 1 for v1, v2, eind in shared_edges(Gs, Hs): #print "psi", psi #print "psi2", psi2 if v1 != v2: excess *= (-psi[(eind, v1)] - psi[(eind, v2)]) else: excess *= (-psi[(eind, v1)] - psi2[(eind, v2)]) #print "did excess" F_A_GH = prod_f_A_G * prod_f_A_H * excess #print prod_f_A_G, "*" , prod_f_A_H, "*", excess, "=", F_A_GH #print "F_A_GH", F_A_GH #print "A" #print A #print #print "aut", autA #print "loopc", loop_coef prod_codim = ci1[0] + ci2[0] #print prod_codim if F_A_GH in ZZ: if F_A_GH == 0: continue #print autA, loop_coef, F_A_GH/autA*loop_coef dict_plus_equals( prod_dict, self.strataP.index_from_graph_codim(A, prod_codim), Rational((F_A_GH * loop_coef, autA))) else: for m, c in F_A_GH.dict().items(): Ad = decorate_with_monomial(PsiKappaRing, A, m) Ad_index = self.strataP.index_from_graph_codim( Ad, prod_codim, None) #_dstrata[prod_codim].get(Ad, None) #print "Ad:" #print Ad #print "Ad_index", Ad_index, c/autA*loop_coef if not Ad_index is None: #print "!!!!!!!!!!!!!" #print autA dict_plus_equals(prod_dict, Ad_index, Rational((c * loop_coef, autA))) self._prod_dict[(ci1, ci2)] = prod_dict return prod_dict
def conreyangle(self, x): return Rational( pari("chareval(%s,znconreylog(%s,%d),%d)" % (self.G, self.G, self.number, x)))