def get_aut_P8(c_lst): ''' The double Segre surface S is isomorphic to P^1xP^1. The pair (A,B) of 2x2 matrices denotes an automorphism of P^1xP^1. We compute the representation of this automorphism in P^8 by using the parametrization as provided by ".get_pmz_lst". Since we consider the 2x2 matrices up to multiplication by a constant, it follows that the automorphism group is 6-dimensional. Formally, this method computes Sym^2(A)@Sym^2(B) where @ denotes the tensor product (otimes in tex). Parameters ---------- c_lst: list<MARing.FF> A list of length 8 with elements c0,...,c7 in "MARing.FF". We assume that the pair of matrices ( [ c0 c1 ] [ c4 c5 ] ) = (A,B) ( [ c2 c3 ] , [ c6 c7 ] ) represent an automorphism of P^1xP^1. Returns ------- sage_matrix A 9x9 matrix defined over "MARing.FF", which represents a (parametrized) automorphism of P^8 that preserves the double Segre surface S. ''' # obtain parametrization in order to compute Sym^2(?)@Sym^2(?) # pmz_lst = DSegre.get_pmz_lst() # compute automorphisms double Segre surface # c0, c1, c2, c3, c4, c5, c6, c7 = c_lst x0, x1, y0, y1 = ring('x0,x1,y0,y1') s, t, u, w = ring('s,t,u,w') # coordinates of P^1xP^1 dct1 = {} dct1.update({s: c0 * x0 + c1 * x1}) dct1.update({t: c2 * x0 + c3 * x1}) dct1.update({u: c4 * y0 + c5 * y1}) dct1.update({w: c6 * y0 + c7 * y1}) dct2 = {x0: s, x1: t, y0: u, y1: w} spmz_lst = [pmz.subs(dct1).subs(dct2) for pmz in pmz_lst] # compute matrix from reparametrization "spmz_lst" # this is a representation of element in Aut(P^1xP^1) # mat = [] for spmz in spmz_lst: row = [] for pmz in pmz_lst: row += [spmz.coefficient(pmz)] mat += [row] mat = sage_matrix(MARing.FF, mat) MATools.p('c_lst =', c_lst) MATools.p('mat =\n' + str(mat)) return mat
def test__diff_mat__a00b(self): mat = ring('matrix([(a,0),(0,1/a)])') a = ring('a') dmat = MARing.diff_mat(mat, a) print(mat) print(dmat) assert dmat == sage_matrix(MARing.FF, [(1, 0), (0, -1 / a**2)])
def get_aut_P5(c_lst): ''' Parameters ---------- c_lst : list A list of length 9 with elements c0,...,c8 in "MARing.FF". The matrix [ c0 c1 c2 ] M = [ c3 c4 c5 ] [ c6 c7 c8 ] represents an automorphism of P^2. Returns ------- sage_matrix This method returns a 6x6 matrix defined over "MARing.FF", which represents a (parametrized) automorphism of P^5 that preserves the Veronese surface V. Notes ----- The Veronese surface V is isomorphic to P^2. The automorphism M of P^2 is via the parametrization ".get_pmz_lst" represented as an automorphism of P^5. Algebraically this is the symmetric tensor Sym^2(M). ''' # obtain parametrization in order to compute Sym^2(M) # pmz_lst = Veronese.get_pmz_lst() # compute automorphisms double Segre surface # c0, c1, c2, c3, c4, c5, c6, c7, c8 = c_lst x0, x1, x2 = ring('x0,x1,x2') s, t, u = ring('s,t,u') # coordinates of P^2 dct1 = {} dct1.update({s: c0 * x0 + c1 * x1 + c2 * x2}) dct1.update({t: c3 * x0 + c4 * x1 + c5 * x2}) dct1.update({u: c6 * x0 + c7 * x1 + c8 * x2}) dct2 = {x0: s, x1: t, x2: u} spmz_lst = [pmz.subs(dct1).subs(dct2) for pmz in pmz_lst] # compute matrix from reparametrization "spmz_lst" # this is a representation of element in Aut(P^1xP^1) # mat = [] for spmz in spmz_lst: row = [] for pmz in pmz_lst: row += [spmz.coefficient(pmz)] mat += [row] mat = sage_matrix(MARing.FF, mat) MATools.p('c_lst =', c_lst) MATools.p('mat =\n' + str(mat)) return mat
def test__get_aut_P8__action_of_involution(self): ''' OUPUT: - We check how the action of the involution J: P^8---->P^8 acts on elements "c_lst" in Aut(P^1xP^1) by conjugation. See documentation "DSegre.change_basis()" and "DSegre.get_aut_P8()" for our internal implementation of J and "c_lst" respectively. ''' a, b, c, d, e, f, g, h = ring('a, b, c, d, e, f, g, h') # left-right involution # M = DSegre.get_aut_P8([a, b, c, d] + [e, f, g, h]) L = sage_matrix([(1, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 1, 0, 0, 0, 0, 0, 0), (0, 1, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 1, 0, 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, 0, 0, 0, 0, 1, 0), (0, 0, 0, 0, 0, 0, 1, 0, 0), (0, 0, 0, 0, 0, 1, 0, 0, 0)]) assert L == ~L LML = ~L * M * L LML_chk = DSegre.get_aut_P8([d, c, b, a] + [e, f, g, h]) assert LML_chk == LML # rotate # M = DSegre.get_aut_P8([a, b, c, d] + [e, f, g, h]) R = sage_matrix([(1, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 1, 0, 0, 0, 0, 0, 0), (0, 1, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 1, 0, 0, 0, 0), (0, 0, 0, 1, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 1, 0, 0), (0, 0, 0, 0, 0, 1, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 1), (0, 0, 0, 0, 0, 0, 0, 1, 0)]) assert R == ~R RMR = ~R * M * R RMR_chk = DSegre.get_aut_P8([d, c, b, a] + [h, g, f, e]) assert RMR_chk == RMR
def test__get_c_lst_lst_dct(self): k = ring('k') for key in Veronese.get_c_lst_lst_dct(): for c_lst in Veronese.get_c_lst_lst_dct()[key]: print('key =', key) print('c_lst =', c_lst) print('det =', sage_matrix(3, 3, c_lst).det()) n_lst = [] for c in c_lst: if c in sage_QQ: n_lst += [c] else: n_lst += [c.subs({k: 0})] print('n_lst =', n_lst) print if key != 'SO3(R)': assert sage_matrix(3, 3, c_lst).det() == 1 assert n_lst == [1, 0, 0, 0, 1, 0, 0, 0, 1]
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_sig(pol): ''' Parameters ---------- pol : MARing.R A quadratic form in the subring QQ[x0,...,x9] of the "MARing". Returns ------- int[] An ordered pair of integers which denotes the signature of the 9x9 Gramm matrix of the quadratic form. Example ------- >>>> get_sig(MARing.ring('-x0^2+x1^2+x2^2+x3^2+x4^2'))==[1,4] True The return value [1,4] means that the matrix is conjugate to matrix with diagonal either (1,-1,-1,-1,-1,0,0,0,0) or (-1,1,1,1,1,0,0,0,0). ''' x = MARing.x() M = sage_invariant_theory.quadratic_form( pol, x).as_QuadraticForm().matrix() M = sage_matrix(sage_QQ, M) D, V = M.eigenmatrix_right() # determine signature of quadric # num_neg = len([d for d in D.diagonal() if d < 0]) num_pos = len([d for d in D.diagonal() if d > 0]) return sorted([num_neg, num_pos])
def diff_mat(mat, var): ''' Parameters ---------- mat : sage_MATRIX A matrix defined over "MARing". var : MARing.R An indeterminate in "MARing". Returns ------- Returns a matrix whose entries are differentiated wrt. "var". ''' dmat = [] for row in mat: drow = [] for col in row: drow += [sage_diff(col, var)] dmat += [drow] return sage_matrix(dmat)
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 usecase__horn_and_spindle_cyclides(): ''' We consider the following cyclides with monomial parametrization determined by the following lattice polygons: [ * ] [ * ] [* * *] [ * ] [ * ] [* * *] spindle cyclide horn cyclide leftright leftright (2,4,3) (2,4,3) and 'leftright' involution act as a modular involution with vertical symmetry axis. We use the following numbering (see DSegre.get_ideal_lst() and DSegre.change_basis()): [8 3 5] [2 0 1] [6 4 7] ''' if True: # # G-invariant quadratic forms for spindle cyclide # (see usecase__invariant_quadratic_forms('243ss')): # # x0^2 - x3*x4 # x0^2 - x1^2 - x2^2 # # We send x3 |--> a*(x4-x3) # x4 |--> a*(x4+x3) # where a=sqrt(1/2) # followed by sending: x4 |--> x0, x0 |--> x4 a = ring('a') xv = x0, x1, x2, x3, x4 = ring('x0,x1,x2,x3,x4') y0, y1, y2, y3 = ring('y0,y1,y2,y3') m34 = sage_matrix(MARing.R, [[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, -a, a], [0, 0, 0, a, a]]) m04 = sage_matrix(MARing.R, [[0, 0, 0, 0, 1], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [1, 0, 0, 0, 0]]) m = m34 * m04 v = sage_vector(xv) g1 = ring('x0^2 - x3*x4') g2 = ring('x0^2 - x1^2 - x2^2') mat1 = sage_invariant_theory.quadratic_form( g1, xv).as_QuadraticForm().matrix() mat2 = sage_invariant_theory.quadratic_form( g2, xv).as_QuadraticForm().matrix() ng1 = v.row() * m.T * mat1 * m * v.column() ng2 = v.row() * m.T * mat2 * m * v.column() G1 = sage_SR(str(ng1[0])).subs({sage_SR('a'): 1 / sage_sqrt(2)}) G2 = sage_SR(str(ng2[0])).subs({sage_SR('a'): 1 / sage_sqrt(2)}) S = sage_PolynomialRing(sage_QQ, sage_var('x0,x1,x2,x3,x4,y0,y1,y2,y3')) x0, x1, x2, x3, x4, y0, y1, y2, y3 = S.gens() G1 = sage__eval(str(G1), S.gens_dict()) G2 = sage__eval(str(G2), S.gens_dict()) assert G1 in S assert G2 in S smap = [y0 - (x0 - x3), y1 - x1, y2 - x2, y3 - x4] prj_lst = S.ideal([G1, G2] + smap).elimination_ideal( [x0, x1, x2, x3, x4]).gens() eqn = str(prj_lst[0].subs({y0: 1})).replace('y1', 'x').replace( 'y2', 'y').replace('y3', 'z') MATools.p(80 * '-') MATools.p('SPINDLE CYCLIDE') MATools.p(80 * '-') MATools.p('We define a projective automorphism m:P^4--->P^4') MATools.p('\t a = 1/sqrt(2)') MATools.p('\t m34 =', list(m34)) MATools.p('\t m04 =', list(m04)) MATools.p('\t m = m34 * m04 =', list(m)) MATools.p('\t det(m) =', m.det()) MATools.p('\t v |--> m*v =', v, '|-->', m * v) MATools.p( 'Generators of ideal of cyclide in quadric of signature [1,4]:') MATools.p('\t g1 =', g1) MATools.p('\t g2 =', g2) MATools.p('Generators of ideal of cyclide in S^3 after applying m:') MATools.p('\t G1 =', G1) MATools.p('\t G2 =', G2) MATools.p('\t G2-2*G1 =', G2 - 2 * G1) MATools.p('Stereographic projection to circular quadratic cone:') MATools.p('\t smap =', smap, '(stereographic projection map)') MATools.p('\t prj_lst =', prj_lst) MATools.p('\t eqn =', eqn) MATools.p(80 * '-' + 2 * '\n') if True: # # G-invariant quadratic forms for horn cyclides # (see usecase__invariant_quadratic_forms('243st')): # # x0^2 - x3*x4 # x4^2 - x6^2 - x7^2 # a = ring('a') xv = x0, x3, x4, x6, x7 = ring('x0,x3,x4,x6,x7') y0, y1, y2, y3 = ring('y0,y1,y2,y3') m = sage_matrix(MARing.R, [[0, 0, a, 0, 0], [0, 1, 0, 0, 0], [-1, -1, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1]]) v = sage_vector(xv) g1 = ring('x0^2 - x3*x4') g2 = ring('x4^2 - x6^2 - x7^2') mat1 = sage_invariant_theory.quadratic_form( g1, xv).as_QuadraticForm().matrix() mat2 = sage_invariant_theory.quadratic_form( g2, xv).as_QuadraticForm().matrix() ng1 = v.row() * m.T * mat1 * m * v.column() ng2 = v.row() * m.T * mat2 * m * v.column() G1 = sage_SR(str(ng1[0])).subs({sage_SR('a'): 1 / sage_sqrt(2)}) G2 = sage_SR(str(ng2[0])).subs({sage_SR('a'): 1 / sage_sqrt(2)}) S = sage_PolynomialRing(sage_QQ, sage_var('x0,x3,x4,x6,x7,y0,y1,y2,y3')) x0, x3, x4, x6, x7, y0, y1, y2, y3 = S.gens() G1 = sage__eval(str(G1), S.gens_dict()) G2 = sage__eval(str(G2), S.gens_dict()) assert G1 in S assert G2 in S smap = [y0 - (x0 + x3), y1 - x4, y2 - x7, y3 - x6] prj_lst = S.ideal([G1, G2] + smap).elimination_ideal( [x0, x3, x4, x6, x7]).gens() eqn = str(prj_lst[0].subs({y0: 1})).replace('y1', 'x').replace( 'y2', 'y').replace('y3', 'z') MATools.p(80 * '-') MATools.p('HORN CYCLIDE') MATools.p(80 * '-') MATools.p('We define a projective automorphism m:P^4--->P^4') MATools.p('\t a = 1/sqrt(2)') MATools.p('\t m =', list(m)) MATools.p('\t det(m) =', m.det()) MATools.p('\t v |--> m*v =', v, '|-->', m * v) MATools.p( 'Generators of ideal of cyclide in quadric of signature [1,4]:') MATools.p('\t g1 =', g1) MATools.p('\t g2 =', g2) MATools.p('Generators of ideal of cyclide in S^3 after applying m:') MATools.p('\t G1 =', G1) MATools.p('\t G2 =', G2) MATools.p('\t G2-2*G1 =', G2 - 2 * G1) MATools.p('Stereographic projection to circular cylinder:') MATools.p('\t smap =', smap, '(stereographic projection map)') MATools.p('\t prj_lst =', prj_lst) MATools.p('\t eqn =', eqn) MATools.p(80 * '-' + 2 * '\n')
def usecase__invariant_quadratic_forms(case): ''' Let G be a subgroup of Aut(P^1xP^1) determined by the case-parameter. We output the vectors space of real G-invariant quadratic forms in the ideal of a (projection of) the double Segre surface obtained by the method: "DSegre.get_ideal_lst( exc_idx_lst )" The real structure is specified in terms of an involution. See "DSegre.change_basis()" for the specification of involutions. We also output signatures of random G-invariant quadratic forms. Parameters ---------- case : str Three numerical characters, which characterize the projection of a double Segre surface in S^n. For example '078', means #families=0, #n=7, #degree=8. If several examples are considered for the same triple then we extend with a character in [a-z]. These are currently implemented cases: ['087','287','365','265s','265t','443','243ss','243st'] Notes ----- See the source code below for a description of each of the cases of projections of double Segre surfaces that we consider. ''' # # obtain 1-parameter subgroups whose tangent vectors at the # identity generates the Lie algebra sl(2) # t, q, s, r, e, T = DSegre.get_gens_sl2() # # "involution" is in { 'identity', 'leftright', 'rotate', 'diagonal' } # # "c_lst_lst" represents a subgroup G of Aut(P^1xP^1) as a list of # 1-parameter subgroups that generate G. # if case == '087': descr = ''' This example shows that there exists a quadric of signature (4,5) that is invariant under the full automorphism group of S. ''' infoG = 'SL(2) x SL(2): [t + e, q + e, s + e, e + t, e + q, e + s ]' exc_idx_lst = [] c_lst_lst = [t + e, q + e, s + e, e + t, e + q, e + s] involution = 'identity' elif case == '287': descr = ''' This example shows quadrics of signatures (1,8), (1,6) and (1,4) in the ideal of the double Segre surface, that are invariant under a 2-dimensional group of toric Moebius automorphisms. ''' infoG = 'SO(2) x SO(2): [ s + e, e + s ]' exc_idx_lst = [] c_lst_lst = [s + e, e + s] involution = 'rotate' elif case == '365': descr = ''' This example shows that there exists a smooth sextic Del Pezzo surface in S^5 that is invariant under a 2-dimensional group of toric Moebius automorphisms. ''' infoG = 'SO(2) x SO(2): [ s + e, e + s ]' exc_idx_lst = [5, 6] c_lst_lst = [s + e, e + s] involution = 'rotate' elif case == '265s': descr = ''' This example shows that there exists a singular sextic Del Pezzo surface in S^5 that is invariant under a 1-dimensional group of toric Moebius automorphisms. Random signatures of type [1,n+1] with n>=3 found so far are: [1,4], [1,6]. If we extend the group with [e+s] then we obtain a quadric of signature [1,4]; this is the horn cyclide case with generators: x0^2 - x3*x4, x0^2 - x1^2 - x2^2, If we extend the group with [e+t] then we obtain a quadric of signature [1,4]; this is the spindle cyclide case with generators: x0^2 - x3*x4, x4^2 - x6^2 - x7^2. ''' infoG = 'SO(2): [ s + e ]' exc_idx_lst = [5, 8] c_lst_lst = [s + e] involution = 'leftright' elif case == '265t': descr = ''' This example indicates that there does not exists a singular sextic Del Pezzo surface in S^5 that is invariant under a 1-dimensional group of Moebius translations. Random signatures of type [1,n+1] with n>=3 found so far are: [1,4]. ''' infoG = 'SE(1): [ e + t ]' exc_idx_lst = [5, 8] c_lst_lst = [e + t] involution = 'leftright' elif case == '443': descr = ''' This example shows that the ring cyclide in S^3 admits a 2-dimensional family of toric Moebius automorphisms. ''' infoG = 'SO(2) x SO(2): [ s + e, e + s ]' exc_idx_lst = [5, 6, 7, 8] c_lst_lst = [s + e, e + s] involution = 'rotate' elif case == '243ss': descr = ''' This example shows that the spindle cyclide in S^3 admits a 2-dimensional family of Moebius automorphisms. ''' infoG = 'SO(2) x SX(1): [ s + e, e + s ]' exc_idx_lst = [5, 6, 7, 8] c_lst_lst = [s + e, e + s] involution = 'leftright' elif case == '243st': descr = ''' This example shows that the horn cyclide in S^3 admits a 2-dimensional family of Moebius automorphisms. ''' infoG = 'SO(2) x SE(1): [ s + e, e + t ]' exc_idx_lst = [1, 2, 5, 8] c_lst_lst = [s + e, e + t] involution = 'leftright' else: raise ValueError('Unknown case: ', case) # # compute vector space of invariant quadratic forms # iq_lst = DSegre.get_invariant_qf(c_lst_lst, exc_idx_lst) iq_lst = DSegre.change_basis(iq_lst, involution) iq_lst = MARing.replace_conj_pairs(iq_lst) # # computes signatures of random quadrics in # the vector space of invariant quadratic forms. # sig_lst = MARing.get_rand_sigs(iq_lst, 10) # # output results # while descr != descr.replace(' ', ' '): descr = descr.replace(' ', ' ') mat_str = str(sage_matrix([[8, 3, 5], [2, 0, 1], [6, 4, 7]])) new_mat_str = mat_str for ei in exc_idx_lst: new_mat_str = new_mat_str.replace(str(ei), ' ') for ei in range(0, 9): new_mat_str = new_mat_str.replace(str(ei), '*') MATools.p('\n' + 80 * '-') MATools.p('case :', case) MATools.p('description :\n', descr + '\n' + mat_str + '\n\n' + new_mat_str) MATools.p('G :', infoG) MATools.p('exc_idx_lst :', exc_idx_lst) MATools.p('involution :', involution) MATools.p('G-invariant quadratic forms:') for iq in iq_lst: MATools.p('\t', iq) MATools.p('random signatures:') MATools.p('\t', sig_lst) for sig in sig_lst: if 1 in sig: MATools.p('\t', sig) MATools.p('\n' + 80 * '-')
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)