def test__get_wmon_lst_1m4(self): if not self.mathematica_is_installed(): print( 'test__get_wmon_lst is not tested, since mathematica is not installed' ) return g_lst = ring('u0,u1,u2,u3,u4') w_lst = [(0, 1), (0, 1), (1, -3), (1, -2), (1, -2)] out = SERing.get_wmon_lst(g_lst, w_lst, 1, -4) print(out) assert out == []
def test__get_wmon_lst_2m4(self): if not self.mathematica_is_installed(): print( 'test__get_wmon_lst is not tested, since mathematica is not installed' ) return g_lst = ring('u0,u1,u2,u3,u4') w_lst = [(0, 1), (0, 1), (1, -3), (1, -2), (1, -2)] chk = ring( '[u3^2,u3*u4,u4^2,u0*u2*u3,u0*u2*u4,u1*u2*u3,u1*u2*u4,u0^2*u2^2,u0*u1*u2^2,u1^2*u2^2]' ) out = SERing.get_wmon_lst(g_lst, w_lst, 2, -4) print(out) assert out == sorted(chk)
def usecase_B5(): ''' We compute the projective isomorphism between two conic bundles that are parametrized by the birational maps ff: P2 ---> X and gg: P1xP1 ---> Y Further explanation of this example can be found in the accompanying arxiv article on projective isomorphisms between rational surfaces. ''' # we construct linear series associated to ff in order to determine # the generators of the graded coordinate ring of conic bundle X # basepoints in chart x0!=0; p1 = (0, 0) p2 = (0, 1) p3 = (1, 0) # 0f+p = e0-e1 PolyRing.reset_base_field() bp_tree = BasePointTree() bp_tree.add('z', p1, 1) f0p1 = SERing.conv(LinearSeries.get([1], bp_tree).pol_lst) SETools.p('f0p1 =', len(f0p1), f0p1) # 1f-3p = e0+e1-e2-e3 bp_tree = BasePointTree() bp_tree.add('z', p2, 1) bp_tree.add('z', p3, 1) f1m3 = SERing.conv(LinearSeries.get([1], bp_tree).pol_lst) SETools.p('f1m3 =', len(f1m3), f1m3) # 1f-2p = 2e0-e2-e3 bp_tree = BasePointTree() bp_tree.add('z', p2, 1) bp_tree.add('z', p3, 1) f1m2 = SERing.conv(LinearSeries.get([2], bp_tree).pol_lst) SETools.p('f1m2 =', len(f1m2), f1m2) # 1f-1p = 3e0-e1-e2-e3 bp_tree = BasePointTree() bp_tree.add('z', p1, 1) bp_tree.add('z', p2, 1) bp_tree.add('z', p3, 1) f1m1 = SERing.conv(LinearSeries.get([3], bp_tree).pol_lst) SETools.p('f1m1 =', len(f1m1), f1m1) # 1f-0p = 4e0-2e1-e2-e3 bp_tree = BasePointTree() bp_tree.add('z', p1, 2) bp_tree.add('z', p2, 1) bp_tree.add('z', p3, 1) f1m0 = SERing.conv(LinearSeries.get([4], bp_tree).pol_lst) SETools.p('f1m0 =', len(f1m0), f1m0) # 2f-4p = 4e0-2e2-2e3 bp_tree = BasePointTree() bp_tree.add('z', p2, 2) bp_tree.add('z', p3, 2) f2m4 = SERing.conv(LinearSeries.get([4], bp_tree).pol_lst) SETools.p('f2m4 =', len(f2m4), f2m4) # by inspection we recover the generators of graded ring of ff U = ring('x1'), ring('x2'), ring('x1+x2-x0'), ring('x1*x2'), ring( '(x1+x2-x0)^2') # compute bidegree (2,d) in order to find a relation between the generators u = u0, u1, u2, u3, u4 = ring('u0,u1,u2,u3,u4') SETools.p( 'Compare number of monomials of given bi-weight with dimension predicted by the Riemann-Roch formula...' ) for d in reversed([-i for i in range(8)]): w_lst = [(0, 1), (0, 1), (1, -3), (1, -2), (1, -2)] SETools.p('\tweight=', (2, d), ',\t#monomials=', len(SERing.get_wmon_lst(u, w_lst, 2, d)), ',\tRR=', 29 + 5 * d) # template for generators of coordinate ring for weight (2,-1) and (1,0) T2m4 = ring( '[u3^2,u3*u4,u4^2,u0*u2*u3,u0*u2*u4,u1*u2*u3,u1*u2*u4,u0^2*u2^2,u0*u1*u2^2,u1^2*u2^2]' ) T1m0 = ring( '[u1^2*u4,u1^2*u3,u1^3*u2,u0*u1*u4,u0*u1*u3,u0*u1^2*u2,u0^2*u4,u0^2*u3,u0^2*u1*u2,u0^3*u2]' ) SETools.p('T2m4 =', T2m4) SETools.p('T1m0 =', T1m0) # find linear relation for f2m4 a = a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = [ elt.subs({u[i]: U[i] for i in range(5)}) for elt in T2m4 ] # @UnusedVariable mata = sage_matrix(sage_QQ, SERing.get_matrix_P2(a)) kera = mata.transpose().right_kernel().matrix() SETools.p('kera =', kera) assert kera * sage_vector(a) == sage_vector([0]) assert a1 - a8 == 0 # construct map gg from ff # sage_Permutations(10).random_element().to_matrix().rows() ff = f1m0 matp = [(0, 0, 0, 0, 1, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 1, 0, 0), (0, 0, 0, 1, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 1), (0, 0, 0, 0, 0, 0, 1, 0, 0, 0), (0, 0, 0, 0, 0, 1, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 1, 0), (0, 0, 1, 0, 0, 0, 0, 0, 0, 0), (0, 1, 0, 0, 0, 0, 0, 0, 0, 0), (1, 0, 0, 0, 0, 0, 0, 0, 0, 0)] matp = sage_matrix(matp) x0, x1, x2, y0, y1, y2, y3 = ring( 'x0,x1,x2,y0,y1,y2,y3') # P2(x0:x1:x2) and P1xP1(y0:y1;y2:y3) gg = [comp.subs({x0: y1 * y3, x1: y0 * y2, x2: y1 * y2}) for comp in ff] gg = list(matp * sage_vector(gg)) gcd_gg = sage_gcd(gg) gg = [comp / gcd_gg for comp in gg] SETools.p('gcd_gg =', gcd_gg) SETools.p('ff =', len(ff), ff) SETools.p('gg =', len(gg), gg) # we construct linear series associated to gg in order to determine # the generators of the graded coordinate ring of conic bundle Y # determine and set basepoint tree ls = LinearSeries(SERing.conv(gg), PolyRing('x,y,v,w')) bp_tree = ls.get_bp_tree() SETools.p('bp_tree(gg) =', bp_tree) tree_211 = BasePointTree(['xv', 'xw', 'yv', 'yw']) tree_211.add('xw', (0, 0), 2).add('t', (1, 0), 1) tree_211.add('yv', (0, 1), 1) # 1g+0q = 4l0+2l1-2e1-e2-e3 g1m0 = SERing.conv(LinearSeries.get([4, 2], tree_211).pol_lst) SETools.p('g1m0 =', len(g1m0), g1m0) # 1g-3q = (l0+l1-e1-e2-e3) + (b-e1) g1m3 = SERing.conv(LinearSeries.get([1, 2], tree_211).pol_lst) SETools.p('g1m3 =', len(g1m3), g1m3) # 1g-2q = 2l0+2l1-2e1-e2-e3 g1m2 = SERing.conv(LinearSeries.get([2, 2], tree_211).pol_lst) SETools.p('g1m2 =', len(g1m2), g1m2) # 1g-1q = 3l0+2l1-2e1-e2-e3 g1m1 = SERing.conv(LinearSeries.get([3, 2], tree_211).pol_lst) SETools.p('g1m1 =', len(g1m1), g1m1) # 2g-4q = 4l0+4l1-4e1-2e2-2e3 tree_422 = BasePointTree(['xv', 'xw', 'yv', 'yw']) tree_422.add('xw', (0, 0), 4).add('t', (1, 0), 2) tree_422.add('yv', (0, 1), 2) g2m4 = SERing.conv(LinearSeries.get([4, 4], tree_422).pol_lst) SETools.p('g2m4 =', len(g2m4), g2m4) # by inspection we recover the generators of graded ring of gg V = ring('y0'), ring('y1'), ring('y0*y2^2+y1*y2^2-y1*y2*y3'), ring( 'y0*y1*y2^2'), ring('y0^2*y2^2+y1^2*y2^2-y1^2*y3^2') # find linear relation for g2m4 b = b0, b1, b2, b3, b4, b5, b6, b7, b8, b9 = [ elt.subs({u[i]: V[i] for i in range(5)}) for elt in T2m4 ] # @UnusedVariable matb = sage_matrix(sage_QQ, SERing.get_matrix_P1xP1(b)) kerb = matb.transpose().right_kernel().matrix() SETools.p('kerb =', kerb) assert kerb * sage_vector(b) == sage_vector([0]) assert 2 * b0 + b1 - 2 * b3 - 2 * b5 + b8 == 0 # compute inverse of G G = [elt.subs({u[i]: V[i] for i in range(5)}) for elt in T1m0] z = ring('z0,z1,z2,z3,z4,z5,z6,z7,z8,z9') t = ring('t') ide = [G[i] * z[0] - z[i] * G[0] for i in range(10)] + [t * G[0] - 1] I01 = sage_ideal(ide).elimination_ideal([t, y2, y3]).gens() I23 = sage_ideal(ide).elimination_ideal([t, y0, y1]).gens() I01 = [elt for elt in I01 if elt.degree(y0) == 1 and elt.degree(y1) == 1][0] I23 = [elt for elt in I23 if elt.degree(y2) == 1 and elt.degree(y3) == 1][0] Q0 = I01.coefficient(y1) Q1 = -I01.coefficient(y0) Q2 = I23.coefficient(y3) Q3 = -I23.coefficient(y2) Q = [Q0, Q1, Q2, Q3] SETools.p('Q =', Q) # [-z9, -z8, -z8, -z6 - 2*z7 + z8 + z9] # check the inverse QoG = [q.subs({z[i]: G[i] for i in range(10)}) for q in Q] gcd01 = sage_gcd(QoG[0], QoG[1]) gcd23 = sage_gcd(QoG[2], QoG[3]) QoG = [QoG[0] / gcd01, QoG[1] / gcd01, QoG[2] / gcd23, QoG[3] / gcd23] SETools.p('QoG =', QoG) assert QoG == [y0, y1, y2, y3] # compose F with projective isomorphism P c = c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12 = [ ring('c' + str(i)) for i in range(13) ] dctZ = {u[i]: z[i] for i in range(5)} dctP = { z[0]: c0 * u0 + c1 * u1, z[1]: c2 * u0 + c3 * u1, z[2]: c4 * u2, z[3]: c5 * u3 + c6 * u4 + c7 * u0 * u2 + c8 * u1 * u2, z[4]: c9 * u3 + c10 * u4 + c11 * u0 * u2 + c12 * u1 * u2 } PoF = [comp.subs(dctZ).subs(dctP) for comp in T1m0] PoF = [comp.subs({u[i]: U[i] for i in range(5)}) for comp in PoF] PoF = [comp / sage_gcd(PoF) for comp in PoF] SETools.p('PoF =', len(PoF), PoF) # compose PoF with Q QoPoF = [comp.subs({z[i]: PoF[i] for i in range(10)}) for comp in Q] gcd01 = sage_gcd(QoPoF[0], QoPoF[1]) gcd23 = sage_gcd(QoPoF[2], QoPoF[3]) QoPoF = [ QoPoF[0] / gcd01, QoPoF[1] / gcd01, QoPoF[2] / gcd23, QoPoF[3] / gcd23 ] SETools.p('QoPoF =', len(QoPoF), QoPoF) # create a list of equations for the ci b = T2m4 rel_g4m2 = 2 * b[0] + b[1] - 2 * b[3] - 2 * b[5] + b[8] SETools.p('rel_g4m2 =', rel_g4m2) rel_g4m2 = rel_g4m2.subs(dctZ).subs(dctP).subs( {u[i]: U[i] for i in range(5)}) SETools.p('rel_g4m2 =', rel_g4m2) rel_lst = [] x = ring('[x0,x1,x2]') for exp in sage_Compositions(4 + 3, length=3): rel_lst += [rel_g4m2.coefficient({x[i]: exp[i] - 1 for i in range(3)})] SETools.p('rel_lst =', len(rel_lst), rel_lst) t = ring('t') rel_lst += [(c0 * c3 - c1 * c2) * c4 * (c5 * c10 - c9 * c6) * t - 1] # solve for ci and put the solutions in dictionary form prime_lst = sage_ideal(rel_lst).elimination_ideal( t).primary_decomposition() SETools.p('prime_lst =', len(prime_lst)) for gen_lst in [prime.gens() for prime in prime_lst]: sol_dct = sage_solve([sage_SR(gen) for gen in gen_lst], [sage_SR(elt) for elt in c], solution_dict=True) assert len(sol_dct) == 1 SETools.p('\t gen_lst =', gen_lst) SETools.p('\t sol_dct =', sol_dct[0]) prime_lst2 = [] prime_lst2 += [prime_lst[0].gens() + [c0 - 1, c4 - 1]] prime_lst2 += [prime_lst[1].gens() + [c1 - 1, c4 - 1]] prime_lst2 += [prime_lst[2].gens() + [c1 - 1, c4 - 1]] prime_lst2 += [prime_lst[3].gens() + [c0 - 1, c4 - 1]] SETools.p('Added equations to prime_lst to simplify solutions:') for gen_lst in prime_lst2: sol_dct = sage_solve([sage_SR(gen) for gen in gen_lst], [sage_SR(elt) for elt in c], solution_dict=True) assert len(sol_dct) == 1 SETools.p('\t gen_lst =', gen_lst) SETools.p('\t sol_dct =', sol_dct[0]) r0, r1 = ring('r0,r1') sol0 = { c0: 1, c1: 0, c2: 0, c3: -r0 * r1, c4: 1, c5: 0, c6: r0, c7: 0, c8: 0, c9: r1, c10: -2 * r0, c11: 2, c12: -2 * r0 * r1 } sol1 = { c0: 0, c1: 1, c2: -r0 * r1, c3: 0, c4: 1, c5: 0, c6: r0, c7: 0, c8: 0, c9: r1, c10: -2 * r0, c11: -2 * r0 * r1, c12: 2 } sol2 = { c0: 0, c1: 1, c2: -r0 * r1, c3: 0, c4: 1, c5: r0, c6: 0, c7: 0, c8: 0, c9: -2 * r0, c10: r1, c11: -2 * r0 * r1, c12: 2 } sol3 = { c0: 1, c1: 0, c2: 0, c3: -r0 * r1, c4: 1, c5: r0, c6: 0, c7: 0, c8: 0, c9: -2 * r0, c10: r1, c11: 2, c12: -2 * r0 * r1 } sol_lst = [sol0, sol1, sol2, sol3] SETools.p('Simplified solutions by hand:') for sol in sol_lst: SETools.p('\t', sol) # compose compatible reparametrizations with gg y = ring('[y0,y1,y2,y3]') gr_lst = [] SETools.p('Computing (gg o r) for each sol in sol_lst...') for sol in sol_lst: gr = [ comp.subs({y[i]: QoPoF[i] for i in range(4)}).subs(sol) for comp in gg ] SETools.p('\t gr =', gr) gcd_gr = sage_gcd(gr) SETools.p('\t\t gcd_gr =', gcd_gr) gr_lst += [[comp / gcd_gr for comp in gr]] SETools.p('\t\t gr/gcd_gr =', gr_lst[-1]) SETools.p('gr_lst =', len(gr_lst)) for gr in gr_lst: SETools.p('\t gr =', gr) # get coefficient matrix of ff and its kernel mff = SERing.get_matrix_P2(ff) kff = mff.right_kernel_matrix().T SETools.p('mff =', mff.dimensions(), list(mff)) SETools.p('kff =', kff.dimensions(), list(kff)) assert (mff * kff).is_zero() # get implicit equations for image of gg z = ring('z0,z1,z2,z3,z4,z5,z6,z7,z8,z9') y = ring('y0,y1,y2,y3') igg = SERing.R.ideal([z[i] - gg[i] for i in range(10) ]).elimination_ideal([y[i] for i in range(4)]) SETools.p('igg =', list(igg.gens())) # Compute isomorphisms for each gr SETools.p('Compute projective isomorphism for each gr in gr_lst:') for gr in gr_lst: mgr = SERing.get_matrix_P2(gr) mgk = mgr * kff assert mgk.is_zero() # because the surfaces in P^9 are linearly normal Ef = sage_matrix(sage_QQ, mff.rows() + kff.T.rows()) Egr = sage_matrix(mgr.rows() + kff.T.rows()) UpI = Egr * Ef.inverse() assert (UpI.submatrix(10, 10) - sage_identity_matrix(5)).is_zero() U = UpI.submatrix(0, 0, 10, 10) SETools.p('\tU =', U.dimensions(), list(U)) # check if the answer is correct by substituting into the equations of Y Uff = list(U * sage_vector(ff)) iggs = igg.subs({z[i]: Uff[i] for i in range(10)}) assert iggs.is_zero()
def usecase_B4(): ''' We compute the projective automorphism of the rational normal scrolls that is parametrized the birational map f: P2 ---> X. Further explanation of this example can be found in the accompanying arxiv article on projective isomorphisms between rational surfaces. ''' # e0-e1 p1 = (0, 0) p2 = (1, 0) p3 = (0, 1) PolyRing.reset_base_field() bpt = BasePointTree() bpt.add('z', p1, 1) f0p1 = SERing.conv(LinearSeries.get([1], bpt).pol_lst) SETools.p('f0p1 =', len(f0p1), f0p1) # e0-e2-e3 bpt = BasePointTree() bpt.add('z', p2, 1) bpt.add('z', p3, 1) f1m2 = SERing.conv(LinearSeries.get([1], bpt).pol_lst) SETools.p('f1m2 =', len(f1m2), f1m2) # 2e0-e1-e2-e3 bpt = BasePointTree() bpt.add('z', p1, 1) bpt.add('z', p2, 1) bpt.add('z', p3, 1) f1m1 = SERing.conv(LinearSeries.get([2], bpt).pol_lst) SETools.p('f1m1 =', len(f1m1), f1m1) # 3e0-2e1-e2-e3 bpt = BasePointTree() bpt.add('z', p1, 2) bpt.add('z', p2, 1) bpt.add('z', p3, 1) f1m0 = SERing.conv(LinearSeries.get([3], bpt).pol_lst) SETools.p('f1m0 =', len(f1m0), f1m0) # set generators for the graded coordinate ring of f U = [ring('x1'), ring('x2'), ring('x1+x2-x0'), ring('x1*x2')] u = ring('u0,u1,u2,u3') # obtain monomials of weight (1,0) w_lst = [(0, 1), (0, 1), (1, -2), (1, -1)] M1m0 = SERing.get_wmon_lst(u, w_lst, 1, 0) SETools.p('M1m0 =', len(M1m0), M1m0) # compose F with projective isomorphism P z = [ring('z' + str(i)) for i in range(6)] c = [ring('c' + str(i)) for i in range(8)] dctZ = {u[i]: z[i] for i in range(4)} dctP = { z[0]: c[0] * u[0] + c[1] * u[1], z[1]: c[2] * u[0] + c[3] * u[1], z[2]: c[4] * u[2], z[3]: c[5] * u[3] + c[6] * u[0] * u[2] + c[7] * u[1] * u[2] } PoF = [comp.subs(dctZ).subs(dctP) for comp in M1m0] SETools.p('PoF wrt u =', len(PoF), PoF) PoF = [comp.subs({u[i]: U[i] for i in range(4)}) for comp in PoF] PoF = [comp / sage_gcd(PoF) for comp in PoF] SETools.p('PoF =', len(PoF), PoF) # recover matrix for automorphism P F = [comp.subs({u[i]: U[i] for i in range(4)}) for comp in M1m0] M = [] for pol in [comp.subs(dctZ).subs(dctP) for comp in M1m0]: row = [] for mon in M1m0: row += [pol.coefficient(mon)] M += [row] M = sage_matrix(M) SETools.p('M =', M.dimensions(), '\n' + str(M)) MF = list(M * sage_vector(F)) assert MF == PoF # compute the inverse Q of F t = ring('t') x = ring('x0,x1,x2') ide = [F[i] * z[0] - z[i] * F[0] for i in range(5)] + [t * F[0] - 1] I1 = sage_ideal(ide).elimination_ideal([t, x[2]]).gens() I2 = sage_ideal(ide).elimination_ideal([t, x[1]]).gens() I1 = [ elt for elt in I1 if elt.degree(x[0]) == 1 and elt.degree(x[1]) == 1 ][0] I2 = [ elt for elt in I2 if elt.degree(x[0]) == 1 and elt.degree(x[2]) == 1 ][0] Q0 = I1.coefficient(x[1]) Q1 = -I1.coefficient(x[0]) Q2 = I2.coefficient(x[0]) Q = [Q0, Q1, Q2] SETools.p('Q =', Q) QoF = [comp.subs({z[i]: F[i] for i in range(5)}) for comp in Q] QoF = [comp / sage_gcd(QoF) for comp in QoF] assert QoF == [x[0], x[1], x[2]] # compute the composition QoPoF = [comp.subs({z[i]: PoF[i] for i in range(5)}) for comp in Q] QoPoF = [comp / sage_gcd(QoPoF) for comp in QoPoF] SETools.p('QoPoF =', len(QoPoF), QoPoF) # from the compatible reparametrizations QoPoF we compute the # projective automorphisms U of X. f = f1m0 gr = [comp.subs({x[i]: QoPoF[i] for i in range(3)}) for comp in f] gcd_gr = sage_gcd(gr) gr = [comp / gcd_gr for comp in gr] Mf = SERing.get_matrix_P2(f) Mgr = SERing.get_matrix_P2(gr) Kf = Mf.right_kernel_matrix().T SETools.p('f =', len(f), f) SETools.p('gr =', len(gr), gr) SETools.p('\t gcd_gr =', gcd_gr) SETools.p('Mf =', Mf.dimensions(), list(Mf)) SETools.p('Mgr =', Mgr.dimensions(), list(Mgr)) SETools.p('Kf =', Kf.dimensions(), list(Kf)) assert (Mf * Kf).is_zero() assert (Mgr * Kf).is_zero() Ef = sage_matrix(sage_QQ, list(Mf) + list(Kf.T)) Egr = sage_matrix(list(Mgr) + list(Kf.T)) UpI = Egr * ~Ef assert (UpI.submatrix(5, 5) - sage_identity_matrix(5)).is_zero() U = UpI.submatrix(0, 0, 5, 5) SETools.p('UpI =', UpI.dimensions(), list(UpI)) SETools.p('U =', U.dimensions(), list(U), '\n' + str(U)) # verify whether U*f is a parametrization for X for all (c0,...,c7) Uf = list(U * sage_vector(f)) SETools.p('Uf =', len(Uf), Uf) eqX = sage_ideal([z[i] - f[i] for i in range(5)]).elimination_ideal([x[0], x[1], x[2]]).gens() eqXs = [eq.subs({z[i]: Uf[i] for i in range(5)}) for eq in eqX] SETools.p('eqX =', len(eqX), eqX) SETools.p('eqXs=', len(eqXs), eqXs) assert eqXs == [0, 0, 0]