def test__qmat__qpol(self): x = MARing.x() q = MARing.q() g_lst = DSegre.get_ideal_lst() chk_qpol = 0 for i in range(len(g_lst)): chk_qpol += q[i] * g_lst[i] qmat = DSegre.get_qmat() qpol = list(sage_vector(x).row() * qmat * sage_vector(x).column())[0][0] assert qpol == chk_qpol
def get_qmat(exc_idx_lst=[]): ''' Parameters ---------- exc_idx_lst : list<int> A list of integers in [0,8]. Returns ------- sage_matrix<MARing.R> A symmetric 9x9 matrix with entries in the ring QQ[q0,...,q19] which is a subring of "MARing.R". It represents the Gramm matrix of a quadratic form in the ideal of the double Segre surface or a projection of the double Segre surface with ideal defined by "get_ideal_lst( exc_idx_lst )". Method ------ We obtain generators of the ideal of the (projection of) the double Segre surface with the method "get_ideal_lst( exc_idx_lst )". If the ideal is of a projection of the double Segre surface, then the returned matrix with parameters q0,...,q19 is not of full rank. ''' x = MARing.x() q = MARing.q() g_lst = DSegre.get_ideal_lst(exc_idx_lst) qpol = 0 for i in range(len(g_lst)): qpol += q[i] * g_lst[i] qmat = sage_invariant_theory.quadratic_form( qpol, x).as_QuadraticForm().matrix() qmat = sage_matrix(MARing.R, qmat) return qmat
def get_qmat(): ''' Returns ------- sage_matrix A symmetric 5x5 matrix with entries in the ring QQ[q0,...,q5] which is a subring of "MARing.R". It represents the Gramm matrix of a quadratic form in the ideal of the Veronese with ideal defined by ".get_ideal_lst()". ''' x = MARing.x()[:6] q = MARing.q()[:6] g_lst = Veronese.get_ideal_lst() qpol = 0 for i in range(len(g_lst)): qpol += q[i] * g_lst[i] qmat = sage_invariant_theory.quadratic_form( qpol, x).as_QuadraticForm().matrix() qmat = sage_matrix(MARing.R, qmat) return qmat
def get_invariant_qf(c_lst_lst, exc_idx_lst=[]): ''' Computes quadratic forms in the ideal of the double Segre surface that are invariant under a given subgroup of Aut(P^1xP^1). Parameters ---------- c_lst_lst : list<list<MARing.FF>> A list of "c_lst"-lists. A c_lst is a list of length 8 with elements c0,...,c7 in QQ(k), where QQ(k) is a subfield of "MARing.FF". If we substitute k:=0 in the entries of "c_lst" then we should obtain the list: [1,0,0,1,1,0,0,1]. A c_lst represents a pair of two matrices: ( [ c0 c1 ] [ c4 c5 ] ) ( [ c2 c3 ] , [ c6 c7 ] ) with the property that c0*c3-c1*c2!=0 and c4*c7-c5*c6!=0. If the two matrices are not normalized to have determinant 1 then the method should be taken with care (it should be checked that the tangent vectors at the identity generate the correct Lie algebra). exc_idx_lst : list<int> A list of integers in [0,8]. Returns ------- A list of quadratic forms in the ideal of (a projection of) the double Segre surface S: ".get_ideal_lst( exc_idx_lst )" such that the quadratic forms are invariant under the automorphisms of S as defined by "c_lst_lst" and such that the quadratic forms generate the module of all invariant quadratic forms. Note that Aut(S)=Aut(P^1xP^1). ''' # for verbose output # mt = MATools() sage_set_verbose(-1) # initialize vectors for indeterminates of "MARing.R" # x = MARing.x() q = MARing.q() r = MARing.r() # obtain algebraic conditions on q0,...,q19 # so that the associated quadratic form is invariant # wrt. the automorphism defined by input "c_lst_lst" # iq_lst = [] for c_lst in c_lst_lst: iq_lst += DSegre.get_invariant_q_lst(c_lst, exc_idx_lst) iq_lst = list(MARing.R.ideal(iq_lst).groebner_basis()) # solve the ideal defined by "iq_lst" # sol_dct = MARing.solve(iq_lst, q) # substitute the solution in the quadratic form # associated to the symmetric matrix qmat. # qmat = DSegre.get_qmat(exc_idx_lst) qpol = list(sage_vector(x).row() * qmat * sage_vector(x).column())[0][0] sqpol = qpol.subs(sol_dct) mt.p('sqpol =', sqpol) mt.p('r =', r) assert sqpol.subs({ri: 0 for ri in r}) == 0 iqf_lst = [] # iqf=invariant quadratic form for i in range(len(r)): coef = sqpol.coefficient(r[i]) if coef != 0: iqf_lst += [coef] mt.p('iqf_lst =', iqf_lst) return iqf_lst
def change_basis(iqf_lst, involution='identity'): ''' This method allows us to change coordinates of the ideal generated by "iqf_lst" so that the antiholomorphic involution defined by "involution" becomes complex conjugation. Parameters ---------- iqf_lst: list<MARing> A list of elements in the subring NF[x0,...,x8] of "MARing.R" where NF denotes the Gaussian rationals QQ(I) with I^2=-1. involution: str Either one of the following strings: 'identity', 'leftright', 'rotate', 'diagonal'. Returns ------- We consider the input "iqf_lst" as a map. We compose this map composed with the map corresponding to <identity>, <leftright>, <rotate> or <diagonal>. We return a list of elements in NF[x0,...,x8] that represents the composition. Notes ----- A double Segre surface in projective 8-space P^8 is represented by a toric parametrization whose completion to P^1xP^1 is provided by "get_pmz_lst": (s,u) |--> (1:s:s^{-1}:u:u^{-1}:s*u:s^{-1}*u^{-1}:s*u^{-1}:s^{-1}*u) = (x0:x1:x2:x3:x4:x5:x6:x7:x8) We can put the exponents of the monomials in a lattice where x0 corresponds to coordinate (0,0), x6 to (-1,-1) x5 to (1,1) and x8 to (-1,1): x8 x3 x5 x2 x0 x1 x6 x4 x7 An antiholomorphic involution, that preserves the toric structure, acts on the above lattice as a unimodular involution: identity_*: ( a, b ) |--> ( a, b) leftright_*: ( a, b ) |--> (-a, b) rotate_*: ( a, b ) |--> (-a,-b) diagonal_*: ( a, b ) |--> ( b, a) These unimodular lattice involutions induce an involution on P^8. We compose the toric parametrization of the double Segre surface with the one of the following maps in order to make the antiholomorphic involution that acts on P^8, equal to complex conjugation. identity: (x0:...:x8) |--> (x0:...:x8) leftright: x3 |--> x3, x0 |--> x0, x4 |--> x4, x1 |--> x1 + I*x2, x2 |--> x1 - I*x2, x5 |--> x5 + I*x8, x8 |--> x5 - I*x8, x7 |--> x7 + I*x6, x6 |--> x7 - I*x6 rotate: x0 |--> x0, x1 |--> x1 + I*x2, x2 |--> x1 - I*x2, x3 |--> x3 + I*x4, x4 |--> x3 - I*x4, x5 |--> x5 + I*x6, x6 |--> x5 - I*x6, x7 |--> x7 + I*x8, x8 |--> x7 - I*x8 diagonal: x5 |--> x5, x0 |--> x0, x6 |--> x6, x3 |--> x3 + I*x1, x1 |--> x3 - I*x1, x8 |--> x8 + I*x7, x7 |--> x8 - I*x7, x2 |--> x2 + I*x4, x4 |--> x2 - I*x4 ''' I = ring('I') x = x0, x1, x2, x3, x4, x5, x6, x7, x8 = MARing.x() z = z0, z1, z2, z3, z4, z5, z6, z7, z8 = MARing.z() dct = {} dct['identity'] = {x[i]: z[i] for i in range(9)} dct['rotate'] = { x0: z0, x1: z1 + I * z2, x2: z1 - I * z2, x3: z3 + I * z4, x4: z3 - I * z4, x5: z5 + I * z6, x6: z5 - I * z6, x7: z7 + I * z8, x8: z7 - I * z8 } dct['leftright'] = { x0: z0, x3: z3, x4: z4, x5: z5 + I * z8, x8: z5 - I * z8, x1: z1 + I * z2, x2: z1 - I * z2, x7: z7 + I * z6, x6: z7 - I * z6 } dct['diagonal'] = { x0: z0, x6: z6, x5: z5, x3: z3 + I * z1, x1: z3 - I * z1, x8: z8 + I * z7, x7: z8 - I * z7, x2: z2 + I * z4, x4: z2 - I * z4 } zx_dct = {z[i]: x[i] for i in range(9)} new_lst = [iqf.subs(dct[involution]).subs(zx_dct) for iqf in iqf_lst] return new_lst
def change_basis(iqf_lst): ''' Parameters ---------- iqf_lst : list A list of elements in the subring NF[x0,...,x5] of "MARing.R" where NF denotes the Gaussian rationals QQ(I) with I^2=-1. Returns ------- list The input "iqf_lst" where we make the following substitution for each polynomial x0 |--> x0, x1 |--> x1, x2 |--> x2 + I*x3, x3 |--> x2 - I*x3, x4 |--> x4 + I*x5, x5 |--> x4 - I*x5. Notes ----- We consider a toric parametrization of the Veronese surface: (s,t) |--> (1 : s*t : s : t : s^2 : t^2 ) = (x0 : x1 : x2 : x3 : x4 : x5 ) We can put the exponents of the monomials in a lattice where x0 corresponds to coordinate (0,0), x4 to (2,0) and x5 to (0,2): x5 x7 x8 x3 x1 x6 x0 x2 x4 The monomial parametrization of the Veronese corresponds to the following lattice polygon: * * * * * * An antiholomorphic involution acts on the above lattice polygon as a unimodular involution: ( a, b ) |--> ( b, a) This unimodular lattice involutions induce an involution on P^5: x0 |--> x0, x1 |--> x1, x2 |--> x2 + I*x3, x3 |--> x2 - I*x3, x4 |--> x4 + I*x5, x5 |--> x4 - I*x5, ''' I = ring('I') x = x0, x1, x2, x3, x4, x5 = MARing.x()[:6] z = z0, z1, z2, z3, z4, z5 = MARing.z()[:6] dct = { x0: z0, x1: z1, x2: z2 + I * z3, x3: z2 - I * z3, x4: z4 + I * z5, x5: z4 - I * z5 } zx_dct = {z[i]: x[i] for i in range(6)} new_lst = [iqf.subs(dct).subs(zx_dct) for iqf in iqf_lst] return new_lst
def get_invariant_qf(c_lst_lst): ''' Parameters ---------- c_lst_lst : list A list of "c_lst"-lists. A c_lst is a list of length 9 with elements c0,...,c8 in the subring in QQ(k) of "MARing.FF". The matrix [ c0 c1 c2 ] M = [ c3 c4 c5 ] [ c6 c7 c8 ] represents---for each value of k---an automorphism of P^2. If we set k:=0 then "c_lst" must correspond to the identity matrix: [ 1,0,0, 0,1,0, 0,0,1 ]. If M is not normalized to have determinant 1 then the method should be taken with care (see doc. ".get_c_lst_lst_dct"). Returns ------- list<MARing.R> A list of quadratic forms in the ideal of the Veronese surface V (see ".get_ideal_lst()"), such that the quadratic forms are invariant under the automorphisms of V as defined by "c_lst_lst" and such that the quadratic forms generate the module of all invariant quadratic forms. Note that Aut(V)=Aut(P^2). ''' # for verbose output # mt = MATools() # initialize vectors for indeterminates of "MARing.R" # x = MARing.x()[:6] q = MARing.q()[:6] r = MARing.r()[:6] # obtain algebraic conditions on q0,...,q19 # so that the associated quadratic form is invariant # wrt. the automorphism defined by input "c_lst_lst" # iq_lst = [] for c_lst in c_lst_lst: iq_lst += Veronese.get_invariant_q_lst(c_lst) iq_lst = list(MARing.R.ideal(iq_lst).groebner_basis()) # solve the ideal defined by "iq_lst" # sol_dct = MARing.solve(iq_lst, q) # substitute the solution in the quadratic form # associated to the symmetric matrix qmat. # qmat = Veronese.get_qmat() qpol = list(sage_vector(x).row() * qmat * sage_vector(x).column())[0][0] sqpol = qpol.subs(sol_dct) mt.p('sqpol =', sqpol) mt.p('r =', r) assert sqpol.subs({ri: 0 for ri in r}) == 0 iqf_lst = [] # iqf=invariant quadratic form for i in range(len(r)): coef = sqpol.coefficient(r[i]) if coef != 0: iqf_lst += [coef] mt.p('iqf_lst =', iqf_lst) return iqf_lst
def test__get_aut_P8__rotation_matrix(self): ''' OUTPUT: - We verify that for the 1-parameter subgroup of rotations with matrix [ cos(k) -sin(k) ] [ sin(k) cos(k) ] it is for our Lie algebra methods sufficient to consider 1-parameter subgroups that have the same tangent vector at the identity. Note that for k=0 we need to get the identity and the determinant should be 1. ''' k = ring('k') I = ring('I') a, b, c, d, e, f, g, h = ring('a, b, c, d, e, f, g, h') x = MARing.x() q = MARing.q() r = MARing.r() # # We consider the representation of the # following matrix into P^8 # # ( [ 1 -k ] , [ 1 0 ] ) # ( [ k 1 ] [ 0 1 ] ) # # We define A to be the tangent vector at the # identity of this representation # N = DSegre.get_aut_P8([1, -k, k, 1] + [1, 0, 0, 1]) A = MARing.diff_mat(N, k).subs({k: 0}) # # We consider the representation of the # following matrix into P^8 # # ( [ cos(k) -sin(k) ] , [ 1 0 ] ) # ( [ sin(k) cos(k) ] [ 0 1 ] ) # # We define B to be the tangent vector at the # identity of this representation # M = DSegre.get_aut_P8([a, b, c, d] + [e, f, g, h]) a, b, c, d, e, f, g, h = sage_var('a, b, c, d, e, f, g, h') k = sage_var('k') M = sage__eval(str(list(M)), { 'a': a, 'b': b, 'c': c, 'd': d, 'e': e, 'f': f, 'g': g, 'h': h, 'k': k }) M = sage_matrix(M) M = M.subs({ a: sage_cos(k), b: -sage_sin(k), c: sage_sin(k), d: sage_cos(k), e: 1, f: 0, g: 0, h: 1 }) # differentiate the entries of M wrt. k dmat = [] for row in M: drow = [] for col in row: drow += [sage_diff(col, k)] dmat += [drow] M = sage_matrix(dmat) B = M.subs({k: 0}) assert str(A) == str(B)