def xseries(self, all_conjugates=True): r"""Returns the corresponding x-series. Parameters ---------- all_conjugates : bool (default: True) If ``True``, returns all conjugates x-representations of this Puiseux t-series. If ``False``, only returns one representative. Returns ------- list List of PuiseuxXSeries representations of this PuiseuxTSeries. """ # obtain relevant rings: # o R = parent ring of curve # o L = parent ring of T-series # o S = temporary polynomial ring over base ring of T-series # o P = Puiseux series ring L = self.ypart.parent() t = L.gen() S = L.base_ring()['z'] z = S.gen() R = self.f.parent() x,y = R.gens() P = PuiseuxSeriesRing(L.base_ring(), str(x)) x = P.gen() # given x = alpha + lambda*t^e solve for t. this involves finding an # e-th root of either (1/lambda) or of lambda, depending on e's sign ## (A sign on a ramification index ? hm) e = self.ramification_index abse = abs(e) lamb = S(self.xcoefficient) order = self.order if e > 0: phi = lamb*z**e - 1 else: phi = z**abse - lamb mu = phi.roots(QQbar, multiplicities=False)[0] if all_conjugates: zeta_e=QQbar.zeta(abse) conjugates = [mu*zeta_e**k for k in range(abse)] else: conjugates = [mu] map(lambda x: x.exactify(), conjugates) # determine the resulting x-series xseries = [] for c in conjugates: t = self.ypart.parent().gen() fconj = self.ypart(c*t) p = P(fconj(x**(QQ(1)/e))) p = p.add_bigoh(QQ(order+1)/abse) xseries.append(p) return xseries
def compute_bd(f, b, df, r, alpha): """Determine the next integral basis element form those already computed.""" # obtain the ring of Puiseux series in which the truncated series # live. these should already be such that the base ring is SR, the symbolic # ring. (below we will have to introduce symbolic indeterminants) R = f.parent() F = R.fraction_field() x, y = R.gens() # construct a list of indeterminants and a guess for the next integral # basis element. to make computations uniform in the univariate and # multivariate cases an additional generator of the underlying polynomial # ring is introduced. d = len(b) Q = PolynomialRing(QQbar, ['a%d' % n for n in range(d)] + ['dummy']) a = tuple(Q.gens()) b = tuple(b) P = PuiseuxSeriesRing(Q, str(x)) xx = P.gen() bd = F(y * b[-1]) # XXX HACK for l in range(len(r)): for k in range(len(r[l])): r[l][k] = r[l][k].change_ring(Q) # sufficiently singularize the current integral basis element guess at each # of the singular points of df for l in range(len(df)): k = df[l] # factor alphak = alpha[l] # point at which the truncated series are centered rk = r[l] # truncated puiseux series # singularize the current guess at the current point using each # truncated Puiseux seriesx sufficiently_singular = False while not sufficiently_singular: # from each puiseux series, rki, centered at alphak construct a # system of equations from the negative exponent terms appearing in # the expression A(x,rki)) equations = [] for rki in rk: # A = sum(a[j] * b[j](xx,rki) for j in range(d)) A = evaluate_A(a, b, xx, rki, d) A += bd(xx, rki) # implicit division by x-alphak, hence truncation to x^1 terms = A.truncate(1).coefficients() equations.extend(terms) # attempt to solve this linear system of equations. if a (unique) # solution exists then the integral basis element is not singular # enough at alphak sols = solve_coefficient_system(Q, equations, a) if not sols is None: bdm1 = sum(F(sols[i][0]) * b[i] for i in range(d)) bd = F(bdm1 + bd) / F(k) else: sufficiently_singular = True return bd
def compute_bd(f, b, df, r, alpha): """Determine the next integral basis element form those already computed.""" # obtain the ring of Puiseux series in which the truncated series # live. these should already be such that the base ring is SR, the symbolic # ring. (below we will have to introduce symbolic indeterminants) R = f.parent() F = R.fraction_field() x,y = R.gens() # construct a list of indeterminants and a guess for the next integral # basis element. to make computations uniform in the univariate and # multivariate cases an additional generator of the underlying polynomial # ring is introduced. d = len(b) Q = PolynomialRing(QQbar, ['a%d'%n for n in range(d)] + ['dummy']) a = tuple(Q.gens()) b = tuple(b) P = PuiseuxSeriesRing(Q, str(x)) xx = P.gen() bd = F(y*b[-1]) # XXX HACK for l in range(len(r)): for k in range(len(r[l])): r[l][k] = r[l][k].change_ring(Q) # sufficiently singularize the current integral basis element guess at each # of the singular points of df for l in range(len(df)): k = df[l] # factor alphak = alpha[l] # point at which the truncated series are centered rk = r[l] # truncated puiseux series # singularize the current guess at the current point using each # truncated Puiseux seriesx sufficiently_singular = False while not sufficiently_singular: # from each puiseux series, rki, centered at alphak construct a # system of equations from the negative exponent terms appearing in # the expression A(x,rki)) equations = [] for rki in rk: # A = sum(a[j] * b[j](xx,rki) for j in range(d)) A = evaluate_A(a,b,xx,rki,d) A += bd(xx, rki) # implicit division by x-alphak, hence truncation to x^1 terms = A.truncate(1).coefficients() equations.extend(terms) # attempt to solve this linear system of equations. if a (unique) # solution exists then the integral basis element is not singular # enough at alphak sols = solve_coefficient_system(Q, equations, a) if not sols is None: bdm1 = sum(F(sols[i][0])*b[i] for i in range(d)) bd = F(bdm1 + bd)/ F(k) else: sufficiently_singular = True return bd
def test_change_ring(self): R = PuiseuxSeriesRing(QQ, 'x') S = R.change_ring(QQbar) self.assertEqual(R.base_ring(), QQ) self.assertEqual(S.base_ring(), QQbar) T = R.change_ring(SR) self.assertEqual(T.base_ring(), SR) B = QQ['a,b'] U = R.change_ring(B) self.assertEqual(U.base_ring(), B)
def test_sub(self): R = PuiseuxSeriesRing(QQ, 't') t = R.gen() half = QQ(1)/QQ(2) p = 1 + t q = 1 + t + t**2 r = t**2 self.assertEqual(q - p, r) p = 1 + t**half q = 1 + t**half + t r = t self.assertEqual(q - p, r)
def test_sub(self): R = PuiseuxSeriesRing(QQ, 't') t = R.gen() half = QQ(1) / QQ(2) p = 1 + t q = 1 + t + t**2 r = t**2 self.assertEqual(q - p, r) p = 1 + t**half q = 1 + t**half + t r = t self.assertEqual(q - p, r)
def test_bigoh(self): R = PuiseuxSeriesRing(QQ, 'x') x = R.gen() half = QQ(1)/QQ(2) p = x**(3*half) q = p.add_bigoh(half) self.assertEqual(q.prec(), half) self.assertEqual(q.laurent_part.prec(), 1) p = x**(3*half) q = p.add_bigoh(4) self.assertEqual(q.prec(), 4) self.assertEqual(q.laurent_part.prec(), 8)
def test_bigoh(self): R = PuiseuxSeriesRing(QQ, 'x') x = R.gen() half = QQ(1) / QQ(2) p = x**(3 * half) q = p.add_bigoh(half) self.assertEqual(q.prec(), half) self.assertEqual(q.laurent_part.prec(), 1) p = x**(3 * half) q = p.add_bigoh(4) self.assertEqual(q.prec(), 4) self.assertEqual(q.laurent_part.prec(), 8)
def test_change_ring(self): R = PuiseuxSeriesRing(QQ, 'x') x = R.gen() half = QQ(1)/2 p = x**(-half) + 1 + x + half*x**(5*half) S = PuiseuxSeriesRing(CC, 'x') q = p.change_ring(CC) self.assertEqual(q.parent(), S) T = PuiseuxSeriesRing(SR, 'x') r = p.change_ring(SR) self.assertEqual(r.parent(), T) B = QQ['a,b'] U = PuiseuxSeriesRing(B, 'x') s = p.change_ring(B) self.assertEqual(s.parent(), U)
def test_mul(self): R = PuiseuxSeriesRing(QQ, 't') t = R.gen() half = QQ(1) / QQ(2) p = t**half q = t**half r = t self.assertEqual(p * q, r) p = 1 + t q = 1 + t + t**2 r = 1 + 2 * t + 2 * t**2 + t**3 self.assertEqual(p * q, r) p = 1 + t**half q = 1 + t**half + t r = 1 + 2 * t**half + 2 * t + t**(half + 1) self.assertEqual(p * q, r)
def test_mul(self): R = PuiseuxSeriesRing(QQ, 't') t = R.gen() half = QQ(1)/QQ(2) p = t**half q = t**half r = t self.assertEqual(p * q, r) p = 1 + t q = 1 + t + t**2 r = 1 + 2*t + 2*t**2 + t**3 self.assertEqual(p * q, r) p = 1 + t**half q = 1 + t**half + t r = 1 + 2*t**half + 2*t + t**(half+1) self.assertEqual(p * q, r)
def test_repr(self): R = PuiseuxSeriesRing(QQ, 't') t = R.gen() p = R(1) s = '1' self.assertEqual(str(p), s) p = t s = 't' self.assertEqual(str(p), s) p = t**2 s = 't^2' self.assertEqual(str(p), s) half = QQ(1) / QQ(2) p = t**half s = 't^(1/2)' self.assertEqual(str(p), s) p = t**(-half) s = 't^(-1/2)' self.assertEqual(str(p), s)
def test_laurent_ramification(self): R = PuiseuxSeriesRing(QQ, 'x') x = R.gen() y = R.laurent_series_ring().gen() p = x self.assertEqual(p.laurent_part, y) self.assertEqual(p.ramification_index, 1) p = x**2 self.assertEqual(p.laurent_part, y**2) self.assertEqual(p.ramification_index, 1) p = x**(QQ(1) / 2) self.assertEqual(p.laurent_part, y) self.assertEqual(p.ramification_index, 2) p = x**(QQ(2) / 3) self.assertEqual(p.laurent_part, y**2) self.assertEqual(p.ramification_index, 3) p = 1 + 42 * x**(QQ(1) / 2) + 99 * x**(QQ(1) / 3) self.assertEqual(p.laurent_part, 1 + 99 * y**2 + 42 * y**3) self.assertEqual(p.ramification_index, 6)
def test_add(self): R = PuiseuxSeriesRing(QQ, 't') t = R.gen() half = QQ(1)/QQ(2) p = 1 q = t r = 1 + t self.assertEqual(p + q, r) p = 1 q = t**half r = 1 + t**half self.assertEqual(p + q, r) p = 1 + t q = 1 + t + t**2 r = 2 + 2*t + t**2 self.assertEqual(p + q, r) p = 1 + t**(QQ(1)/2) q = 1 + t**(QQ(1)/2) + t r = 2 + 2*t**(QQ(1)/2) + t self.assertEqual(p + q, r)
def test_laurent_ramification(self): R = PuiseuxSeriesRing(QQ, 'x') x = R.gen() y = R.laurent_series_ring().gen() p = x self.assertEqual(p.laurent_part, y) self.assertEqual(p.ramification_index, 1) p = x**2 self.assertEqual(p.laurent_part, y**2) self.assertEqual(p.ramification_index, 1) p = x**(QQ(1)/2) self.assertEqual(p.laurent_part, y) self.assertEqual(p.ramification_index, 2) p = x**(QQ(2)/3) self.assertEqual(p.laurent_part, y**2) self.assertEqual(p.ramification_index, 3) p = 1 + 42*x**(QQ(1)/2) + 99*x**(QQ(1)/3) self.assertEqual(p.laurent_part, 1 + 99*y**2 + 42*y**3) self.assertEqual(p.ramification_index, 6)
def test_add(self): R = PuiseuxSeriesRing(QQ, 't') t = R.gen() half = QQ(1) / QQ(2) p = 1 q = t r = 1 + t self.assertEqual(p + q, r) p = 1 q = t**half r = 1 + t**half self.assertEqual(p + q, r) p = 1 + t q = 1 + t + t**2 r = 2 + 2 * t + t**2 self.assertEqual(p + q, r) p = 1 + t**(QQ(1) / 2) q = 1 + t**(QQ(1) / 2) + t r = 2 + 2 * t**(QQ(1) / 2) + t self.assertEqual(p + q, r)
def test_repr(self): R = PuiseuxSeriesRing(QQ, 't') t = R.gen() p = R(1) s = '1' self.assertEqual(str(p), s) p = t s = 't' self.assertEqual(str(p), s) p = t**2 s = 't^2' self.assertEqual(str(p), s) half = QQ(1)/QQ(2) p = t**half s = 't^(1/2)' self.assertEqual(str(p), s) p = t**(-half) s = 't^(-1/2)' self.assertEqual(str(p), s)
def test_change_ring(self): R = PuiseuxSeriesRing(QQ, 'x') x = R.gen() half = QQ(1) / 2 p = x**(-half) + 1 + x + half * x**(5 * half) S = PuiseuxSeriesRing(CC, 'x') q = p.change_ring(CC) self.assertEqual(q.parent(), S) T = PuiseuxSeriesRing(SR, 'x') r = p.change_ring(SR) self.assertEqual(r.parent(), T) B = QQ['a,b'] U = PuiseuxSeriesRing(B, 'x') s = p.change_ring(B) self.assertEqual(s.parent(), U)
def test_construction_SR(self): R = PuiseuxSeriesRing(SR, 'x') x = R.gen()
def test_construction_QQbar(self): R = PuiseuxSeriesRing(QQbar, 'x') x = R.gen()