def get_pmz_verify( o ): ''' Parameters ---------- o : OrbOutput Returns ------- Boolean * Return "None" if the test could not be performed because either parametrization or implicit equation was not available. * Return "True" if implicit equation of projected surface agrees with parametrization composed with projection. * Return "False" if both parametrization and implicit equation were available but do not agree. ''' if not o.input.do['pmz'] or not o.input.do['imp']: return None if o.prj_pol == -1 or o.gen == -2: return False OrbTools.p( 'Testing parametrization...' ) c0, s0, c1, s1 = OrbRing.coerce( 'c0,s0,c1,s1' ) x0, x1, x2, x3 = OrbRing.coerce( 'x0,x1,x2,x3' ) f = o.prj_pol p = o.prj_pmz_lst fp = o.prj_pol.subs( {x0:p[0], x1:p[1], x2:p[2], x3:p[3]} ) test = fp.reduce( [c0 * c0 + s0 * s0 - 1, c1 * c1 + s1 * s1 - 1] ) OrbTools.p( test ) if test != 0: return False return True
def get_genus( pol, plane = 'x1+2*x2+17*x3+11*x0' ): ''' The method requires that the maple-command is in "os.environ['PATH']". See [https://www.maplesoft.com]. Parameters ---------- pol : OrbRing.R A polynomial in QQ[x0,x1,x2,x3]. plane : string A String of a linear polynomial in QQ[x0,x1,x2,x3]. Returns ------- int An integer denoting the geometric genus of the curve given by the intersection of the surface defined by "pol", with the plane defined by "plane". If this geometric genus is not defined, then -2 is returned. If Maple is not installed then -3 is returned. ''' OrbTools.p( pol ) # obtain an equation for the curve defined # intersecting a plane with the zero-set of pol. plane = OrbRing.coerce( plane ) K = sage_ideal( pol, plane ).groebner_basis() P = K[0] if P.total_degree() <= 1: P = K[1] P = P.subs( {OrbRing.coerce( 'x3' ):1} ) # compute geometric genus with Maple. try: sage_maple.eval( 'with(algcurves);' ) except: return -3 sage_maple.eval( 'P := ' + str( P ) + ';' ) gen = sage_maple.eval( 'genus(P,x1,x2);' ) OrbTools.p( gen ) try: return int( gen ) except ValueError: return -2
def get_omat(o_str): ''' Parameters ---------- o_str : string A string with format: 'O****' where the *-symbol is a place holder for one of the following characters: r,s,m,p,a. Returns ------- sage_matrix A 9x9 matrix over "OrbRing.num_field" of the shape 1 0 0 0 0 0 0 0 0 0 * * 0 0 0 0 0 0 0 * * 0 0 0 0 0 0 0 0 0 * * 0 0 0 0 0 0 0 * * 0 0 0 0 0 0 0 0 0 * * 0 0 0 0 0 0 0 * * 0 0 0 0 0 0 0 0 0 * * 0 0 0 0 0 0 0 * * where each 2x2 matrix on the diagonal is of either one of the following shapes: 'r': c0 -s0 's': -c0 s0 s0 c0 -s0 -c0 'p': 1 0 'm': -1 0 'a': 1 0 0 1 0 -1 0 -1 ''' # parse input if o_str[0] != 'O' or len(o_str) != 5: raise ValueError('Incorrect input string: ', o_str) c0, s0 = OrbRing.coerce('c0,s0') br = [[c0, -s0], [s0, c0]] bs = [[-c0, s0], [-s0, -c0]] bp = [[1, 0], [0, 1]] bm = [[-1, 0], [0, -1]] ba = [[1, 0], [0, -1]] b_dct = {'r': br, 's': bs, 'p': bp, 'm': bm, 'a': ba} bmat_lst = [] for ch in o_str[1:]: bmat_lst += [b_dct.get(ch, 'error')] omat = sage_identity_matrix(OrbRing.R, 9) idx = 1 for bmat in bmat_lst: omat.set_block(idx, idx, sage_matrix(OrbRing.R, bmat)) idx = idx + 2 return omat
def test__get_project( self ): pol_lst = OrbRing.coerce( '[-x0^2+x1^2+x2^2+x3^2+x4^2+x5^2+x6^2+x7^2+x8^2, x8, x7, x6, x5, x1*x2-x0*x4]' ) pmat = get_pmat( False ) print( pmat ) out = get_project( pol_lst, pmat ) print( out ) assert str( out ) == '(x0^4 - x0^2*x1^2 - x0^2*x2^2 - x1^2*x2^2 - x0^2*x3^2, -x^2*y^2 - x^2 - y^2 - z^2 + 1)'
def get_pmz_value( pmz_lst, v0, v1, prec = 50 ): ''' Parameters ---------- pmz_lst : list<sage_POLY> A list of 4 polynomials in QQ[c0,s0,c1,s1]. v0 : sage_REALNUMBER A real number in [0,2*pi) v1 : sage_REALNUMBER A real number in [0,2*pi) prec : int Number of digits. scale : int A positive integer. Returns ------- list<float> Returns a point in R^3 represented by a list of 3 float values with precision "prec": F(a,b)=[ x, y, z ]. Here F(a,b) is represented by "pmz_lst" and has the following domain and range: F: [0,2*pi)X[0,2*pi) ---> R^3. The parametrization is a map in terms of cosine and sine. If F is not defined at the point it first looks at (v0-dv,v1-dv) where dv is very small. If that does not work, then we return None. ''' c0, s0, c1, s1, t0, t1 = OrbRing.coerce( 'c0,s0,c1,s1,t0,t1' ) dct = {c0:sage_cos( v0 ), s0:sage_sin( v0 ), c1:sage_cos( v1 ), s1:sage_sin( v1 ), t0:v0, t1:v1} if type( pmz_lst[0] ) == int: W = sage_QQ( pmz_lst[0] ) else: W = pmz_lst[0].subs( dct ) X = pmz_lst[1].subs( dct ) Y = pmz_lst[2].subs( dct ) Z = pmz_lst[3].subs( dct ) if W == 0: return None XW = round( X / W, prec ) YW = round( Y / W, prec ) ZW = round( Z / W, prec ) return [ XW, YW, ZW ]
def test__get_tmat(self): # # Setup inverse stereographic projection: # S: P^7 ---> S^7 # v = OrbRing.coerce('[v0,v1,v2,v3,v4,v5,v6,v7,v8]') d = v[1]**2 + v[2]**2 + v[3]**2 v0_2 = v[0]**2 vec_lst = [] vec_lst += [v0_2 + d] vec_lst += [2 * v[0] * v[1]] vec_lst += [2 * v[0] * v[2]] vec_lst += [2 * v[0] * v[3]] vec_lst += [2 * v[0] * v[4]] vec_lst += [2 * v[0] * v[5]] vec_lst += [2 * v[0] * v[6]] vec_lst += [2 * v[0] * v[7]] vec_lst += [-v0_2 + d] x = sage_vector(OrbRing.R, vec_lst) print(x) # # Setup Euclidean translation in S^7 # T:S^7--->S^7 # tmat = get_tmat(None) print(tmat) # # Setup stereographic projection # P:S^7--->P^7 # pmat = [] pmat += [[1, 0, 0, 0] + [0, 0, 0, 0, -1]] pmat += [[0, 1, 0, 0] + [0, 0, 0, 0, 0]] pmat += [[0, 0, 1, 0] + [0, 0, 0, 0, 0]] pmat += [[0, 0, 0, 1] + [0, 0, 0, 0, 0]] pmat += [[0, 0, 0, 0] + [1, 0, 0, 0, 0]] pmat += [[0, 0, 0, 0] + [0, 1, 0, 0, 0]] pmat += [[0, 0, 0, 0] + [0, 0, 1, 0, 0]] pmat += [[0, 0, 0, 0] + [0, 0, 0, 1, 0]] pmat = sage_matrix(pmat) print(pmat) # Check whether composition is an Euclidean # translation in P^7: # PoToS # tv = pmat * tmat * x tv = tv / (2 * v[0]) print(tv) assert str( tv ) == '(v0, v0*t1 + v1, v0*t2 + v2, v0*t3 + v3, v0*t4 + v4, v0*t5 + v5, v0*t6 + v6, v0*t7 + v7)'
def test__approx_QQ_coef__2(self): ring = PolyRing('x,y,v,w', True) ring.ext_num_field('t^2 - 3') ring.ext_num_field('t^2 + 1') ring.ext_num_field('t^2 + 2/7*a0*a1 + 3/7') ring.ext_num_field('t^2 - 2/7*a0*a1 + 3/7') a0, a1, a2, a3 = ring.root_gens() q2 = sage_QQ(1) / 2 a = 2 * a0 / 3 b = (-a0 * a1 / 3 - q2) * a3 c = (a0 * a1 / 3 - q2) * a2 d = (a1 / 2 - a0 / 3) * a3 e = (-a1 / 2 - a0 / 3) * a2 ci_idx = 5 # index for complex embedding C1 = -(b + c - d - e) C2 = -(b + c + d + e) for lbl, elt in [('a0', a0), ('C1', C1), ('C2', C2)]: print(lbl + ' = ' + str(elt.abs())) for ci in elt.complex_embeddings(): print('\t\t' + str(ci)) s = str(elt.complex_embeddings()[ci_idx]) print(lbl + '.complex_embedding()[' + str(ci_idx) + '] = ' + s) # C1 print('--- C1 ---') out = OrbRing.approx_QQ_coef(C1, ci_idx) print(out) print(sage_n(out)) chk = -sage_QQ(3687885631267691) / 2251799813685248 assert out == chk # C2 print('--- C2 ---') out = OrbRing.approx_QQ_coef(C2, ci_idx) print(out) print(sage_n(out)) chk = sage_QQ(2749869658604311) / 4503599627370496 assert out == chk
def test__get_pmz_verify__perseus( self ): o = OrbOutput( OrbInput() ) o.input.do['pmz'] = True o.input.do['imp'] = True o.prj_pmz_lst = '[-2*s1 + 3, 4/5*c0*c1 - 3/5*s0*c1 + 7/5*c0*s1 + 6/5*s0*s1 - 12/5*c0 - 11/5*s0 - 2*s1 + 3, 3/5*c0*c1 + 4/5*s0*c1 - 6/5*c0*s1 + 7/5*s0*s1 + 11/5*c0 - 12/5*s0, -2*s1 + 2]' o.prj_pmz_lst = OrbRing.coerce( o.prj_pmz_lst ) o.prj_pol = '25*x0^4 + 100*x0^3*x1 + 50*x0^2*x1^2 - 100*x0*x1^3 + 25*x1^4 - 50*x0^2*x2^2 - 100*x0*x1*x2^2 + 50*x1^2*x2^2 + 25*x2^4 - 24*x0^3*x3 - 40*x0^2*x1*x3 + 20*x0*x1^2*x3 + 20*x0*x2^2*x3 - 41*x0^2*x3^2 - 100*x0*x1*x3^2 + 50*x1^2*x3^2 + 50*x2^2*x3^2 + 20*x0*x3^3 + 25*x3^4' o.prj_pol = OrbRing.coerce( o.prj_pol ) o.gen = 1 print( o ) tst = get_pmz_verify( o ) print( tst ) assert tst == True
def test__get_orb_bp_tree( self ): pmz_lst = OrbRing.coerce( '[2,c0,s0,c1,s1,c0,s0,c1,s1]' ) bp_tree = get_orb_bp_tree( pmz_lst ) print( bp_tree ) out = str( bp_tree ) assert 'chart=xv, depth=0, mult=1, sol=(a0, (a0))' in out assert 'chart=xv, depth=0, mult=1, sol=(a0, (-a0))' in out assert 'chart=xv, depth=0, mult=1, sol=(-a0, (-a0))' in out assert 'chart=xv, depth=0, mult=1, sol=(-a0, (a0))' in out
def usecase_orb_product_implicit_circle(num=10): ''' Outputs "num" random surfaces in the projective n-sphere S^n, that are obtained by rotating or translating an implicit circle. The circle is obtained as a random hyperplane section. The hyperplane section is obtained by applying a random matrix in PGL(8+1) to the hyperplane section { x | x3=..=x8=0=-x0^2+x1^2+...+x8^2=0 }. Since the random matrix is not orthogonal we cannot use the matrix to compute parametric presentations for these examples. Notice that we can recover the OrbInput object from the short string output (see "usecase_orb_product_investigate_example()") Parameters ---------- num : int Number of times a random surface should be computed. ''' for idx in range(num): try: # compute random input ch_str = ''.join([ OrbRing.random_elt(['r', 's', 'p', 'm', 'a']) for i in range(4) ]) pmat = list(sage_MatrixSpace(sage_ZZ, 9, 9).random_element()) p_tup = ('P1', 'I', 'I') o_tup = ('I', 'O' + ch_str, 'I') v_tup = ('M' + str(pmat), 'I', 'I') input = OrbInput().set(p_tup, o_tup, v_tup) # compute only few attributes for key in input.do.keys(): input.do[key] = False input.do['imp'] = True input.do['dde'] = True o = orb_product(input) OrbTools.p('(deg, emb, dim ) =', (o.deg, o.emb, o.dim), ' short string =', o.get_short_str()) # output orbital product except BaseException as e: # continue with loop regardless of exceptions OrbTools.p('Exception occurred: ', e) OrbTools.p(input) OrbTools.p(o)
def random(self, bnd=10): ''' Sets attributes to random values. Parameters ---------- coef_bnd : int Positive integer. Returns ------- self Sets self.rota, self.trna, self.sa and self.rotb, self.trnb, self.sb with random values. ''' # OrbRing.random_int( coef_size ) q4 = sage_QQ(1) / 4 s_lst = [i * q4 for i in range(4 * bnd)] s_lst += [-s for s in s_lst] # circle A self.rota = [OrbRing.random_elt(range(360)) for i in range(6)] self.trna = [OrbRing.random_elt(range(360)) for i in range(3)] self.sa = OrbRing.random_elt(s_lst) # circle B self.rotb = [OrbRing.random_elt(range(360)) for i in range(6)] self.trnb = [OrbRing.random_elt(range(360)) for i in range(3)] self.sb = OrbRing.random_elt(s_lst) return self
def test__approx_QQ_pol_lst(self): ring = PolyRing('x,y,z', True).ext_num_field('t^2 - 3') x, y, z = ring.gens() a0 = ring.root_gens()[0] q2 = sage_QQ(1) / 2 pol_lst = [x * y * a0 + z**2 + q2 * y**2 - q2 - a0 * x, a0, -a0 * x] out_lst = OrbRing.approx_QQ_pol_lst(pol_lst, 1) c = sage_QQ(3900231685776981) / 2251799813685248 print(out_lst) assert out_lst[0] == x * y * c + z**2 + q2 * y**2 - q2 - c * x assert out_lst[1] == c assert out_lst[2] == -c * x
def test__approx_QQ_coef__1(self): ring = PolyRing('x,y,z', True).ext_num_field('t^2 - 3') a0 = ring.root_gens()[0] ci_idx = 1 for lbl, elt in [('a0', a0), ('-a0', -a0)]: print(lbl + ' = ' + str(elt.abs())) for ci in elt.complex_embeddings(): print('\t\t' + str(ci)) s = str(elt.complex_embeddings()[ci_idx]) print(lbl + '.complex_embedding()[' + str(ci_idx) + '] = ' + s) print('--- a0 ---') out = OrbRing.approx_QQ_coef(a0, ci_idx) chk = sage_QQ(3900231685776981) / 2251799813685248 print(out) print(sage_n(out)) assert out == chk print('--- (-a0) ---') out = OrbRing.approx_QQ_coef(-a0, ci_idx) print(out) print(sage_n(out)) assert out == -chk
def get_pmz( pmat, omat, vmat ): ''' Parameters ---------- pmat : sage_matrix A 4x9 invertible matrix with entries in QQ. A matrix represents a projection from a 7-sphere in projective 8-space to projective 3-space. omat : sage_matrix A 9x9 invertible matrix with entries in QQ[c1,s1]. This matrix represents a projective curve in the automorphism group of the projective 7-sphere. Thus "omat" represents a 1-parameter subgroup in Aut(S^7). vmat : sage_matrix A 9x9 invertible matrix with entries in QQ. This matrix represents an element in Aut(S^7), which transforms a standard circle (see below). Returns ------- list Two lists of elements in QQ[c0,s0,c1,s1]. The 1st list has length 9 and the 2nd list has length 4. The 1st list represent a parametrization S^1xS^1--->S^7 of a surface in S^7 and the 2nd list the parametrization S^1xS^1--->P^3 of the surface projected into P^3 (projective 3-space) using "pmat". Here (c0,s0) and (c1,s1) are points on S^1. Notes ----- The surface in S^7 is obtained by applying a 1-parameter subgroup to a circle C. Here C is the "vmat"-transform of the standard circle B in S^7 where B = { x | -x0^2+x1^2+x2^2==0 } and S^7 = { x | -x0^2+x1^2+...+x8^2==0 }. ''' c1, s1 = OrbRing.coerce( 'c1,s1' ) pmz_lst = list( omat * vmat * sage_vector( [1, c1, s1, 0, 0, 0, 0, 0, 0] ) ) prj_pmz_lst = list( pmat * omat * vmat * sage_vector( [1, c1, s1, 0, 0, 0, 0, 0, 0] ) ) return pmz_lst, prj_pmz_lst
def get_imp( omat, vmat ): ''' Parameters ---------- omat : sage_matrix A 9x9 invertible matrix with entries in QQ[c0,s0]. This matrix represents a projective curve in the automorphism group of the projective 7-sphere. Thus "omat" represents a 1-parameter subgroup in Aut(S^7). vmat : sage_matrix A 9x9 invertible matrix with entries in QQ. This matrix represents an element in Aut(S^7), which transforms a standard circle. Returns ------- list<OrbRing.R> A list of elements in QQ[x0,...,x8]. This list represent the generators of the ideal corresponding to the variety, which is obtained by applying a 1-parameter subgroup to a circle C. Here C is the "vmat"-transform of the standard circle B in S^7 where B = { x | -x0^2+x1^2+x2^2==0 } and S^7 = { x | -x0^2+x1^2+...+x8^2==0 }. ''' # declare list of coordinate variables v_lst = OrbRing.coerce( '[v0,v1,v2,v3,v4,v5,v6,v7,v8]' ) x_lst = OrbRing.coerce( '[x0,x1,x2,x3,x4,x5,x6,x7,x8]' ) c_lst = OrbRing.coerce( '[c0,s0]' ) # construct generators of ideal of orbital product g_lst = [] # v[i] coordinates of points on a circle C in S^7 vmatI = vmat.inverse() g_lst += list( vmatI * sage_vector( v_lst ) )[3:] g_lst += OrbRing.coerce( '[-v0^2+v1^2+v2^2+v3^2+v4^2+v5^2+v6^2+v7^2+v8^2]' ) # consider all point that are an orbit of C # the 1-parameter subgroup of Aut(S^7) # represented by the matrix omat e_lst = list( omat * sage_vector( v_lst ) ) g_lst += [ x_lst[i] - e_lst[i] for i in range( 0, 8 + 1 ) ] g_lst += OrbRing.coerce( '[-x0^2+x1^2+x2^2+x3^2+x4^2+x5^2+x6^2+x7^2+x8^2]' ) g_lst += OrbRing.coerce( '[s0^2+c0^2-1]' ) # compute the resulting variety by elimination g_ideal = OrbRing.R.ideal( g_lst ) imp_lst = list( g_ideal.elimination_ideal( v_lst + c_lst ).gens() ) return imp_lst
def test__get_sing_lst( self ): pol = OrbRing.coerce( '(x1^2+x2^2+x3^2+3*x0^2)^2-16*x0^2*(x1^2+x2^2)' ) print( pol ) os.environ['PATH'] += os.pathsep + '/home/niels/Desktop/n/app/magma/link' try: sage_magma.eval( 1 + 1 ) print( 'Magma is installed.' ) except: print( 'Magma is NOT installed.' ) sng_lst = get_sing_lst( pol ) print( sng_lst ) assert sng_lst == [] return sng_lst = get_sing_lst( pol ) print( sng_lst ) assert str( sng_lst ) == "[('[x0^2 + 1/3*x3^2,x1,x2]', 2), ('[x0,x1^2 + x2^2 + x3^2]', 2*t + 1)]"
def __str__(self): if OrbOutput.short_str: return self.get_short_str() s = '\n' s += 30 * '-' + '\n' s += str(self.input) + '\n' s += 'pmz_lst = ' + str(self.pmz_lst) + '\n' s += 'prj_pmz_lst = ' + str(self.prj_pmz_lst) + '\n' s += 'imp_lst = ' + str(self.imp_lst) + '\n' s += 'emb = ' + str(self.emb) + '\n' s += 'dim = ' + str(self.dim) + '\n' s += 'deg = ' + str(self.deg) + '\n' s += 'gen = ' + str(self.gen) + '\n' s += 'prj_pol = ' + str(self.prj_pol) + '\n' if self.prj_pol != None: s += 'prj_pol{x0:0} = ' + str( sage_factor(self.prj_pol.subs({OrbRing.coerce('x0'): 0 }))) + '\n' s += 'xyz_pol = ' + str(self.xyz_pol) + '\n' s += 'pmz_test = ' + str(self.pmz_test) + '\n' if self.fct_lst != None: s += 'fct_lst = ' + str(len(self.fct_lst)) + ' factors\n' if len(self.fct_lst) > 1: for fct in self.fct_lst: s += ' ~ ' + str(fct) + '\n' if self.sng_lst != None: s += 'sng_lst = ' + str(len(self.sng_lst)) + ' components\n' for sng in self.sng_lst: s += ' ~ ' + str(sng) + '\n' if self.bp_tree != None: s += 'bp_tree = ' + str(self.bp_tree) + '\n' s += 'short_str = ' s += self.get_short_str() + '\n' s += 30 * '-' + '\n' return s
def get_rmat(r_str): ''' Parameters ---------- r_str : string A string with the following format 'R****[%,%,%,%]' where: *-symbol is a place holder for a character in ['r','s','m','p','a'] %-symbol denotes an integer in [0,360] Returns ------- sage_matrix A 9x9 matrix over "OrbRing.num_field" of the same shape as "get_omat( 'O****' )" The "c0" and "s0" in each block are substituted with a rational approximation of cos(%) and sin(%) respectively. ''' omat = get_omat('O' + r_str[1:5]) cs_lst = sage__eval(r_str[5:]) c0, s0 = OrbRing.coerce('c0,s0') rmat = [] idx = -1 dct = {} for row in list(omat): if idx % 2 == 0: cv, sv = get_cs(cs_lst[idx / 2]) dct = {c0: cv, s0: sv} if cv**2 + sv**2 != 1: raise Exception('Expect cos(%)^2+sin(%)^2=1.') idx = idx + 1 rrow = [] for col in row: rrow += [col.subs(dct)] rmat += [rrow] return sage_matrix(rmat)
def test__get_genus( self ): pol = OrbRing.coerce( '(x1^2+x2^2+x3^2+3*x0^2)^2-16*(x1^2+x2^2)' ) print( pol ) os.environ['PATH'] += os.pathsep + '/home/niels/Desktop/n/app/maple/link/bin' try: sage_maple.eval( '1 + 1' ) print( 'Maple is installed.' ) except: print( 'Maple is NOT installed.' ) gen = get_genus( pol ) print( gen ) assert gen == -3 return gen = get_genus( pol ) print( gen ) assert gen == 1
def test__get_factor_lst( self ): pol = OrbRing.coerce( '(x1-x0)^3*(x1-3*x0)^2*(x2^2+x3^2)' ) print( pol ) os.environ['PATH'] += os.pathsep + '/home/niels/Desktop/n/app/maple/link/bin' try: sage_maple.eval( 'with(algcurves);' ) print( 'Maple is installed.' ) except: print( 'Maple is NOT installed.' ) fct_lst = get_factor_lst( pol ) print( fct_lst ) assert fct_lst == [] return fct_lst = get_factor_lst( pol ) print( fct_lst ) assert str( fct_lst ) == "[('x2-RootOf(_Z^2+1)*x3', '1'), ('x2+RootOf(_Z^2+1)*x3', '1'), ('x0-1/3*x1', '2'), ('x0-x1', '3')]"
def quadric_smooth(): ''' Construct povray image of rulings on hyperboloid of one sheet. ''' # construct the two rulings on the hyperboloid # by rotating lines L1 and L2 c0, s0, c1, s1, t0 = OrbRing.coerce('c0,s0,c1,s1,t0') P = sage_vector([-2, -1, -0.5]) Q = sage_vector([2, -1, -0.5]) L0 = t0 * P + (t0 - 1) * Q L1 = t0 * Q + (t0 - 1) * P M = sage_matrix([(c1, s1, 0), (-s1, c1, 0), (0, 0, 1)]) pmz_A_lst = [1] + list(M * L0) pmz_B_lst = [1] + list(M * L1) OrbTools.p('pmz_A_lst =', pmz_A_lst) for pmz in pmz_A_lst: OrbTools.p('\t\t', pmz) OrbTools.p('pmz_B_lst =', pmz_B_lst) for pmz in pmz_B_lst: OrbTools.p('\t\t', pmz) # PovInput ring cyclide # pin = PovInput() pin.path = './' + get_time_str() + '_quadric_smooth/' pin.fname = 'orb' pin.scale = 1 pin.cam_dct['location'] = (0, -10, 0) pin.cam_dct['lookat'] = (0, 0, 0) pin.cam_dct['rotate'] = (0, 0, 0) pin.shadow = True pin.light_lst = [(0, 0, -5), (0, -5, 0), (-5, 0, 0), (0, 0, 5), (0, 5, 0), (5, 0, 0)] pin.axes_dct['show'] = False pin.axes_dct['len'] = 1.2 pin.width = 400 pin.height = 800 pin.quality = 11 pin.ani_delay = 10 pin.impl = None pin.pmz_dct['A'] = (pmz_A_lst, 0) pin.pmz_dct['B'] = (pmz_B_lst, 0) pin.pmz_dct['FA'] = (pmz_A_lst, 0) pin.pmz_dct['FB'] = (pmz_B_lst, 0) v0_lst = [sage_QQ(i) / 10 for i in range(-15, 30, 5)] # -15, 35 v1_lst = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 36)] v1_lst_F = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 2)] pin.curve_dct['A'] = { 'step0': v0_lst, 'step1': v1_lst, 'prec': 10, 'width': 0.1 } pin.curve_dct['B'] = { 'step0': v0_lst, 'step1': v1_lst, 'prec': 10, 'width': 0.1 } pin.curve_dct['FA'] = { 'step0': v0_lst, 'step1': v1_lst_F, 'prec': 10, 'width': 0.01 } pin.curve_dct['FB'] = { 'step0': v0_lst, 'step1': v1_lst_F, 'prec': 10, 'width': 0.01 } col_A = (0.5, 0.0, 0.0, 0.0) # red col_B = rgbt2pov((28, 125, 154, 0)) # blue pin.text_dct['A'] = [True, col_A, 'phong 0.2 phong_size 5'] pin.text_dct['B'] = [True, col_B, 'phong 0.2 phong_size 5'] pin.text_dct['FA'] = [True, (0.1, 0.1, 0.1, 0.0), 'phong 0.2 phong_size 5'] pin.text_dct['FB'] = [True, (0.1, 0.1, 0.1, 0.0), 'phong 0.2 phong_size 5'] # raytrace image/animation create_pov(pin, ['A', 'B', 'FA', 'FB'])
def get_mat(A_str, B_str, C_str): ''' Parameters ---------- A_str : string A string of either one of the following forms: 'O****' 'tT' 'T[#,#,#,#,#,#,#]' 'R****[%,%,%,%]' 'I' 'P1' 'P0' 'M<list of a 9x9 matrix>' 'E[$,$,$,$,$,$,$,$]' 'E' 'X[%,%,%]' where: *-symbol is a place holder for one of the following characters: r,s,m,p,a #-symbol denotes an element of "OrbRing.num_field". %-symbol denotes an integer in [0,360]. $-symbol denotes an integer in [1,8] such that each integer occurs only once. For example 'E[2,1,3,4,5,6,7,8]' is correct, but 'E[1,1,3,4,5,6,7,8]' is incorrect. B_str : string Same specs as "A_str". C_str : string Same specs as "A_str". Returns ------- sage_matrix Let matrix A over QQ[c0,s0,c1,s1] be defined as follows, where we make a case distinction on "A_str": "A_str[0] == 'O' " : "A = get_omat( A_str )". "A_str[0] == 'T' " : "A = get_tmat( A_str )". "A_str[0] == 'E' " : "A = get_emat( A_str )". "A_str[0] == 'X' " : "A = get_xmat( A_str )". "A_str == 'tT'" : "A = get_tmat('tT')". "A_str[0] == 'R' " : "A = get_rmat( A_str )". "A_str == 'I' " : "A = sage_identity_matrix(9,9)". "A_str == 'P1'" : "A = get_pmat( True )". "A_str == 'P0'" : "A = get_pmat( False )". "A_str[0] == 'M' " : "A = sage_matrix(<list of a matrix>)". Similarly, we obtain matrices B and C. We return the matrix A*B*C. ''' M_lst = [] for M_str in [A_str, B_str, C_str]: if M_str[0] == 'O': M_lst += [get_omat(M_str)] elif M_str[0] == 'T': M_lst += [get_tmat(M_str)] elif M_str[0] == 'E': M_lst += [get_emat(M_str)] elif M_str[0] == 'X': M_lst += [get_xmat(M_str)] elif M_str == 'tT': M_lst += [get_tmat('tT')] elif M_str[0] == 'R': M_lst += [get_rmat(M_str)] elif M_str == 'I': M_lst += [sage_identity_matrix(OrbRing.num_field, 9, 9)] elif M_str == 'P1': M_lst += [get_pmat(True)] elif M_str == 'P0': M_lst += [get_pmat(False)] elif M_str[0] == 'M': mat_lst = OrbRing.coerce(M_str[1:]) M_lst += [sage_matrix(mat_lst)] return M_lst[0] * M_lst[1] * M_lst[2]
def get_tmat(t_str=None): ''' Parameters ---------- t_str : string A String with either one of the following 3 formats: * A string with format: 'T[#,#,#,#,#,#,#]' where # are in "OrbRing.num_field". * 'tT'. * "None". Returns ------- sage_matrix A 9x9 matrix defined over "OrbRing.num_field" representing an Euclidean translation of S^7. This map is obtained as the composition of a stereographic projection with center (1:0:0:0:0:0:0:0:1), an Euclidean translation in R^7, and the inverse stereographic projection. If "t_str==None", then the entries of the translation matrix are indeterminates t1,...,t7 in "OrbRing.R". If "t_str=='tT'", then the indeterminates are set to [c0,s0,0,0,0,0,0]. Thus the translations along a circle. ''' t = OrbRing.coerce('[t1,t2,t3,t4,t5,t6,t7]') # construct a translation matrix with undetermined # translations in t1,...,t7 a = (sage_QQ(1) / 2) * sum([ti**2 for ti in t]) mat = [] mat += [[1 + a] + list(t) + [-a]] for i in range(0, 7): mat += [[t[i]] + sage_identity_matrix(OrbRing.R, 7).row(i).list() + [-t[i]]] mat += [[a] + list(t) + [1 - a]] if t_str == None: # return matrix with indeterminates return sage_matrix(OrbRing.R, mat) elif t_str == 'tT': # translations along a circle c0, s0 = OrbRing.coerce('c0,s0') q = [c0, s0, 0, 0, 0, 0, 0] else: # Substitute coordinates [#,#,#,#,#,#,#] # for the t0,...,t7 variables. q = sage__eval(t_str[1:]) if len(q) != 7: raise ValueError('Expect 7 translation coordinates: ', t_str) # substitute q for t smat = [] for row in mat: srow = [] for col in row: srow += [col.subs({t[i]: q[i] for i in range(7)})] smat += [srow] if t_str == 'tT': return sage_matrix(OrbRing.R, smat) else: return sage_matrix(OrbRing.num_field, smat)
def get_curve_lst( pin, fam ): ''' Parameters ---------- pin : PovInput The following attributes of the PovInput object are used: * "pin.pmz_dct" * "pin.scale" * "pin.curve_dct" * "pin.curve_lst_dct" fam : string A key string for a family id (eg. 'A'). Returns ------- list Returns a list of lists of points. Each list of points defines points on a curve. v1_lstD Returns "pin.curve_lst_dct[<fam>]" if "pin.curve_lst_dct[<fam>]!=None". Otherwise let us assume w.l.o.g. that "fam=='A'" such that "pin.curve_lst_dct['A']==None". We set "pin.curve_lst_dct['A']" as follows: pin.curve_lst_dct['A'] = [ <curveA<0>>, <curveA<1>>, ... ] where * <curveA<n>> is a list of points [x,y,z] on a curve in family with id 'A', which are scaled with "pin.scale". * The space between points in <curveA<n>> is determined by "pin.curve_dct['A']['step0']". * The space between <curveA<n>> and <curveA<n+1>> is determined by values in "pin.curve_dct['A']['step1']". * The precision of points in <curveA<n>> is determined by values in "pin.curve_dct['A']['prec']". Returns pin.curve_lst_dct['A']. ''' OrbTools.p( fam ) if fam in pin.curve_lst_dct and pin.curve_lst_dct[fam] != None: OrbTools.p( 'Already computed ', fam ) return pin.curve_lst_dct[fam] pmz_lst, fam_id = pin.pmz_dct[fam] pmz_lst = OrbRing.coerce( pmz_lst ) # loop through lists of parameter values pin.curve_lst_dct[fam] = [] for v1 in pin.curve_dct[fam]['step1']: curve = [] for v0 in pin.curve_dct[fam]['step0']: if fam_id == 0: point = get_pmz_value( pmz_lst, v0, v1, pin.curve_dct[fam]['prec'] ) elif fam_id == 1: point = get_pmz_value( pmz_lst, v1, v0, pin.curve_dct[fam]['prec'] ) else: raise ValueError( 'Expect pin.pmz_dct[fam][1] in [0,1]: ', fam_id ) # add points to curve if map is defined if point != None: point = [ coord * pin.scale for coord in point ] curve += [point] # need at least 3 points for cubic interpolation if len( curve ) >= 3: # add curve to family pin.curve_lst_dct[fam] += [curve] return pin.curve_lst_dct[fam]
def test__get_deg_dim_3( self ): imp_lst = OrbRing.coerce( '[-x0^2+x1^2+x2^2+x3^2+x4^2+x5^2+x6^2+x7^2+x8^2, x8, x7, x6, x5, x1*x2-x0*x4]' ) deg_dim = get_deg_dim( imp_lst ) print( deg_dim ) assert deg_dim == ( 4, 2 )
def perseus_cyclide(): ''' Creates povray image of the Perseus cyclide. ''' # We first construct a trigonometric parametrization # by rotating a circle. # cos(pi/3) = 1/2 # sin(pi/3) = sqrt(3)/2 # r, R = 1, 2 c0, s0, c1, s1 = sage_var('c0,s0,c1,s1') x, y, v, w, a0 = sage_var('x,y,v,w,a0') q2 = sage_QQ(1) / 2 MZ = sage_matrix([(c1, s1, 0), (-s1, c1, 0), (0, 0, 1)]) MZc = MZ.subs({c1: q2, s1: q2 * a0}) V = sage_vector([r * c0, 0, r * s0]) V = MZc * V V[0] = V[0] + R pmz_AB_lst = list(MZ * V) OrbTools.p('V =', V) OrbTools.p('pmz_AB_lst =', pmz_AB_lst) for pmz in pmz_AB_lst: OrbTools.p('\t\t', sage_factor(pmz)) # We convert the trigonometric parametrization to a # rational parametrization, via the following formulas: # # cos(s) = (y^2-x^2) / (y^2+x^2) # sin(s) = 2*x*y / (y^2+x^2) # y=1; x = arctan( s/2 ) # C0 = (y**2 - x**2) / (y**2 + x**2) S0 = 2 * x * y / (y**2 + x**2) C1 = (w**2 - v**2) / (w**2 + v**2) S1 = 2 * v * w / (w**2 + v**2) den = (y**2 + x**2) * (w**2 + v**2) dct = {c0: C0, s0: S0, c1: C1, s1: S1} pmz_lst = [den] + [(elt.subs(dct) * den).simplify_full() for elt in list(MZ * V)] OrbTools.p('pmz_lst =', pmz_lst) for pmz in pmz_lst: OrbTools.p('\t\t', sage_factor(pmz)) # do a basepoint analysis on the rational parametrization # ring = PolyRing('x,y,v,w', True).ext_num_field('t^2-3') ls = LinearSeries([str(pmz) for pmz in pmz_lst], ring) OrbTools.p(ls.get_bp_tree()) # construct linear series for families of conics # ring = PolyRing( 'x,y,v,w') # construct polynomial ring over new ground field OrbTools.p(ring) x, y, v, w = ring.gens() a0, a1, a2, a3 = ring.root_gens() p1 = ['xv', (-a3, a1)] p2 = ['xv', (-a2, -a1)] p3 = ['xv', (a3, a1)] p4 = ['xv', (a2, -a1)] bpt_1234 = BasePointTree(['xv', 'xw', 'yv', 'yw']) bpt_1234.add(p1[0], p1[1], 1) bpt_1234.add(p2[0], p2[1], 1) bpt_1234.add(p3[0], p3[1], 1) bpt_1234.add(p4[0], p4[1], 1) bpt_12 = BasePointTree(['xv', 'xw', 'yv', 'yw']) bpt_12.add(p1[0], p1[1], 1) bpt_12.add(p2[0], p2[1], 1) bpt_34 = BasePointTree(['xv', 'xw', 'yv', 'yw']) bpt_34.add(p3[0], p3[1], 1) bpt_34.add(p4[0], p4[1], 1) ls_22 = LinearSeries.get([2, 2], bpt_1234) ls_21 = LinearSeries.get([2, 1], bpt_1234) ls_12 = LinearSeries.get([1, 2], bpt_1234) ls_11a = LinearSeries.get([1, 1], bpt_12) ls_11b = LinearSeries.get([1, 1], bpt_34) OrbTools.p('linear series 22 =\n', ls_22) OrbTools.p('linear series 21 =\n', ls_21) OrbTools.p('linear series 12 =\n', ls_12) OrbTools.p('linear series 11a =\n', ls_11a) OrbTools.p('linear series 11b =\n', ls_11b) # compute reparametrization from the linear series of families ring = PolyRing('x,y,v,w,c0,s0,c1,s1') OrbTools.p(ring) x, y, v, w, c0, s0, c1, s1 = ring.gens() a0, a1, a2, a3 = ring.root_gens() pmz_AB_lst = [1] + ring.coerce(pmz_AB_lst) pmz_lst = ring.coerce(pmz_lst) q2 = sage_QQ(1) / 2 a = 2 * a0 / 3 b = (-a0 * a1 / 3 - q2) * a3 c = (a0 * a1 / 3 - q2) * a2 d = (a1 / 2 - a0 / 3) * a3 e = (-a1 / 2 - a0 / 3) * a2 bc = b + c de = d + e X = 1 - s0 Y = c0 V = 1 - s1 W = c1 CB_dct = { x: X, y: Y, v: W * X + bc * W * Y - de * V * Y, w: V * X + bc * V * Y + de * W * Y } DB_dct = { x: X, y: Y, v: W * X - bc * W * Y + de * V * Y, w: V * X - bc * V * Y - de * W * Y } EB_dct = { x: X, y: Y, v: W * X**2 + W * Y**2 - a * V * Y**2, w: V * X**2 + V * Y**2 + a * W * Y**2 } pmz_CB_lst = [pmz.subs(CB_dct) for pmz in pmz_lst] # CB 11a pmz_DB_lst = [pmz.subs(DB_dct) for pmz in pmz_lst] # CB 11b pmz_EB_lst = [pmz.subs(EB_dct) for pmz in pmz_lst] # CB 21 # output OrbTools.p('pmz_AB_lst =\n', pmz_AB_lst) OrbTools.p('pmz_CB_lst =\n', pmz_CB_lst) OrbTools.p('pmz_DB_lst =\n', pmz_DB_lst) OrbTools.p('pmz_EB_lst =\n', pmz_EB_lst) # approximate by map defined over rational numbers ci_idx = 5 # index defining the complex embedding pmz_AB_lst = OrbRing.approx_QQ_pol_lst(pmz_AB_lst, ci_idx) pmz_CB_lst = OrbRing.approx_QQ_pol_lst(pmz_CB_lst, ci_idx) pmz_DB_lst = OrbRing.approx_QQ_pol_lst(pmz_DB_lst, ci_idx) pmz_EB_lst = OrbRing.approx_QQ_pol_lst(pmz_EB_lst, ci_idx) # mathematica input ms = '' for pmz, AB in [(pmz_lst, 'ZZ'), (pmz_AB_lst, 'AB'), (pmz_CB_lst, 'CB'), (pmz_DB_lst, 'DB'), (pmz_EB_lst, 'EB')]: s = 'pmz' + AB + '=' + str(pmz) + ';' s = s.replace('[', '{').replace(']', '}') ms += '\n' + s OrbTools.p('Mathematica input =', ms) # PovInput ring cyclide # pin = PovInput() pin.path = './' + get_time_str() + '_perseus_cyclide/' pin.fname = 'orb' pin.scale = 1 pin.cam_dct['location'] = (0, 7, 0) pin.cam_dct['lookat'] = (0, 0, 0) pin.cam_dct['rotate'] = (45, 0, 0) pin.shadow = True pin.light_lst = [(0, 0, -10), (0, -10, 0), (-10, 0, 0), (0, 0, 10), (0, 10, 0), (10, 0, 0)] pin.axes_dct['show'] = False pin.axes_dct['len'] = 1.2 pin.height = 400 pin.width = 800 pin.quality = 11 pin.ani_delay = 10 pin.impl = None pin.pmz_dct['A'] = (pmz_AB_lst, 0) pin.pmz_dct['B'] = (pmz_AB_lst, 1) pin.pmz_dct['C'] = (pmz_CB_lst, 0) pin.pmz_dct['D'] = (pmz_DB_lst, 0) pin.pmz_dct['E'] = (pmz_EB_lst, 0) pin.pmz_dct['FA'] = (pmz_AB_lst, 0) pin.pmz_dct['FB'] = (pmz_AB_lst, 1) pin.pmz_dct['FC'] = (pmz_CB_lst, 0) pin.pmz_dct['FD'] = (pmz_DB_lst, 0) pin.pmz_dct['FE'] = (pmz_EB_lst, 0) v0_lst = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 10)] v1_lst_A = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 10)] # 5 v1_lst_B = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 15)] v1_lst_C = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 36)] v1_lst_D = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 36)] v1_lst_E = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 10)] # 5 v1_lst_F = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 1)] prec = 50 pin.curve_dct['A'] = { 'step0': v0_lst, 'step1': v1_lst_A, 'prec': prec, 'width': 0.04 } pin.curve_dct['B'] = { 'step0': v0_lst, 'step1': v1_lst_B, 'prec': prec, 'width': 0.04 } pin.curve_dct['C'] = { 'step0': v0_lst, 'step1': v1_lst_C, 'prec': prec, 'width': 0.05 } pin.curve_dct['D'] = { 'step0': v0_lst, 'step1': v1_lst_D, 'prec': prec, 'width': 0.05 } pin.curve_dct['E'] = { 'step0': v0_lst, 'step1': v1_lst_E, 'prec': prec, 'width': 0.04 } pin.curve_dct['FA'] = { 'step0': v0_lst, 'step1': v1_lst_F, 'prec': prec, 'width': 0.01 } pin.curve_dct['FB'] = { 'step0': v0_lst, 'step1': v1_lst_F, 'prec': prec, 'width': 0.01 } pin.curve_dct['FC'] = { 'step0': v0_lst, 'step1': v1_lst_F, 'prec': prec, 'width': 0.01 } pin.curve_dct['FD'] = { 'step0': v0_lst, 'step1': v1_lst_F, 'prec': prec, 'width': 0.01 } pin.curve_dct['FE'] = { 'step0': v0_lst, 'step1': v1_lst_F, 'prec': prec, 'width': 0.01 } col_A = (0.6, 0.0, 0.0, 0.0) # red col_B = (0.8, 0.6, 0.2, 0.0) # beige col_C = (0.6, 0.0, 0.0, 0.0 ) # red *** rgbt2pov( ( 74, 33, 0, 0 ) ) # brown col_D = (0.2, 0.6, 0.0, 0.0 ) # green *** rgbt2pov( ( 28, 125, 154, 0 ) ) # blue col_E = (0.2, 0.6, 0.0, 0.0) # green colFF = (0.1, 0.1, 0.1, 0.0) pin.text_dct['A'] = [True, col_A, 'phong 0.2 phong_size 5'] pin.text_dct['B'] = [True, col_B, 'phong 0.2 phong_size 5'] pin.text_dct['C'] = [True, col_C, 'phong 0.2 phong_size 5'] pin.text_dct['D'] = [True, col_D, 'phong 0.2 phong_size 5'] pin.text_dct['E'] = [True, col_E, 'phong 0.2 phong_size 5'] pin.text_dct['FA'] = [True, colFF, 'phong 0.2 phong_size 5'] pin.text_dct['FB'] = [True, colFF, 'phong 0.2 phong_size 5'] pin.text_dct['FC'] = [True, colFF, 'phong 0.2 phong_size 5'] pin.text_dct['FD'] = [True, colFF, 'phong 0.2 phong_size 5'] pin.text_dct['FE'] = [True, colFF, 'phong 0.2 phong_size 5'] # raytrace image/animation create_pov(pin, ['C', 'D', 'FC', 'FD']) create_pov(pin, ['A', 'B', 'FC', 'FD']) create_pov(pin, ['E', 'B', 'FC', 'FD'])
def CH1_cyclide(): ''' Creates povray image of a CH1 cyclide, which is an inversion of a Circular Hyperboloid of 1 sheet. ''' # Construct a trigonometric parametrization by rotating a circle. r, R = 1, 1 c0, s0, c1, s1 = sage_var('c0,s0,c1,s1') x, y, v, w, a0 = sage_var('x,y,v,w,a0') q2 = sage_QQ(1) / 2 MX = sage_matrix([(1, 0, 0), (0, c1, s1), (0, -s1, c1)]) MXc = MX.subs({c1: a0, s1: a0}) # a0=1/sqrt(2)=cos(pi/4)=sin(pi/4) MZ = sage_matrix([(c1, s1, 0), (-s1, c1, 0), (0, 0, 1)]) V = sage_vector([r * c0, 0, r * s0]) V = MXc * V V[0] = V[0] + R pmz_AB_lst = list(MZ * V) OrbTools.p('V =', V) OrbTools.p('pmz_AB_lst =', pmz_AB_lst) for pmz in pmz_AB_lst: OrbTools.p('\t\t', sage_factor(pmz)) # Convert the trigonometric parametrization to a rational parametrization # We convert via the following formulas, # # cos(s) = (y^2-x^2) / (y^2+x^2) # sin(s) = 2*x*y / (y^2+x^2) # y=1; x = arctan( s/2 ) # C0 = (y**2 - x**2) / (y**2 + x**2) S0 = 2 * x * y / (y**2 + x**2) C1 = (w**2 - v**2) / (w**2 + v**2) S1 = 2 * v * w / (w**2 + v**2) den = (y**2 + x**2) * (w**2 + v**2) dct = {c0: C0, s0: S0, c1: C1, s1: S1} pmz_lst = [den] + [(elt.subs(dct) * den).simplify_full() for elt in list(MZ * V)] OrbTools.p('pmz_lst =', pmz_lst) for pmz in pmz_lst: OrbTools.p('\t\t', sage_factor(pmz)) # do a basepoint analysis on the rational parametrization # The True argument is for resetting the number field to QQ! ring = PolyRing('x,y,v,w', True).ext_num_field('t^2-1/2') ls = LinearSeries([str(pmz) for pmz in pmz_lst], ring) OrbTools.p(ls.get_bp_tree()) # construct linear series for families of conics ring = PolyRing( 'x,y,v,w') # construct polynomial ring over new ground field OrbTools.p(ring) x, y, v, w = ring.gens() a0, a1 = ring.root_gens() p1 = ['xv', (0, 2 * a0 * a1)] p2 = ['xv', (0, -2 * a0 * a1)] p3 = ['xv', (a1, 2 * a0 * a1)] p4 = ['xv', (-a1, -2 * a0 * a1)] bpt_1234 = BasePointTree(['xv', 'xw', 'yv', 'yw']) bpt_1234.add(p1[0], p1[1], 1) bpt_1234.add(p2[0], p2[1], 1) bpt_1234.add(p3[0], p3[1], 1) bpt_1234.add(p4[0], p4[1], 1) bpt_12 = BasePointTree(['xv', 'xw', 'yv', 'yw']) bpt_12.add(p1[0], p1[1], 1) bpt_12.add(p2[0], p2[1], 1) bpt_34 = BasePointTree(['xv', 'xw', 'yv', 'yw']) bpt_34.add(p3[0], p3[1], 1) bpt_34.add(p4[0], p4[1], 1) ls_22 = LinearSeries.get([2, 2], bpt_1234) # |2(l1+l2)-e1-e2-e3-e4| ls_21 = LinearSeries.get([2, 1], bpt_1234) ls_12 = LinearSeries.get([1, 2], bpt_1234) ls_11a = LinearSeries.get([1, 1], bpt_12) ls_11b = LinearSeries.get([1, 1], bpt_34) OrbTools.p('linear series 22 =\n', ls_22) OrbTools.p('linear series 21 =\n', ls_21) OrbTools.p('linear series 12 =\n', ls_12) OrbTools.p('linear series 11a =\n', ls_11a) OrbTools.p('linear series 11b =\n', ls_11b) # compute reparametrization from the linear series of families ring = PolyRing( 'x,y,v,w,c0,s0,c1,s1') # construct polynomial ring with new generators OrbTools.p(ring) x, y, v, w, c0, s0, c1, s1 = ring.gens() a0, a1 = ring.root_gens() pmz_AB_lst = [1] + ring.coerce(pmz_AB_lst) pmz_lst = ring.coerce(pmz_lst) X = 1 - s0 Y = c0 V = 1 - s1 W = c1 CB_dct = { x: X, y: Y, v: W * X - 2 * a0 * V * Y, w: V * X + 2 * a0 * W * Y } pmz_CB_lst = [pmz.subs(CB_dct) for pmz in pmz_lst] # CB 11b # output OrbTools.p('pmz_AB_lst =\n', pmz_AB_lst) OrbTools.p('pmz_CB_lst =\n', pmz_CB_lst) # approximate by map defined over rational numbers ci_idx = 0 # index defining the complex embedding OrbTools.p('complex embeddings =') for i in range(len(a0.complex_embeddings())): a0q = OrbRing.approx_QQ_coef(a0, i) OrbTools.p('\t\t' + str(i) + ' =', a0q, sage_n(a0q)) pmz_AB_lst = OrbRing.approx_QQ_pol_lst(pmz_AB_lst, ci_idx) pmz_CB_lst = OrbRing.approx_QQ_pol_lst(pmz_CB_lst, ci_idx) # mathematica input ms = '' for pmz, AB in [(pmz_lst, 'ZZ'), (pmz_AB_lst, 'AB'), (pmz_CB_lst, 'CB')]: s = 'pmz' + AB + '=' + str(pmz) + ';' s = s.replace('[', '{').replace(']', '}') ms += '\n' + s OrbTools.p('Mathematica input =', ms) # PovInput ring cyclide # pin = PovInput() pin.path = './' + get_time_str() + '_CH1_cyclide/' pin.fname = 'orb' pin.scale = 1 pin.cam_dct['location'] = (0, -5, 0) pin.cam_dct['lookat'] = (0, 0, 0) pin.cam_dct['rotate'] = (20, 0, 0) pin.shadow = True pin.light_lst = [(1, 0, 0), (0, 1, 0), (0, 0, 1), (-1, 0, 0), (0, -1, 0), (0, 0, -1), (10, 0, 0), (0, 10, 0), (0, 0, 10), (-10, 0, 0), (0, -10, 0), (0, 0, -10)] pin.axes_dct['show'] = False pin.axes_dct['len'] = 1.2 pin.height = 400 pin.width = 800 pin.quality = 11 pin.ani_delay = 10 pin.impl = None pin.pmz_dct['A'] = (pmz_AB_lst, 0) pin.pmz_dct['B'] = (pmz_AB_lst, 1) pin.pmz_dct['C'] = (pmz_CB_lst, 0) pin.pmz_dct['FA'] = (pmz_AB_lst, 0) pin.pmz_dct['FB'] = (pmz_AB_lst, 1) pin.pmz_dct['FC'] = (pmz_CB_lst, 0) v0_lst = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 10)] v1_lst_A = [(sage_QQ(i) / 180) * sage_pi for i in range(180, 360, 10)] v1_lst_B = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 180, 10)] v1_lst_C = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 180, 10)] v1_lst_FA = [(sage_QQ(i) / 180) * sage_pi for i in range(180, 360, 2)] v1_lst_FB = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 180, 2)] v1_lst_FC = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 180, 2)] prec = 50 pin.curve_dct['A'] = { 'step0': v0_lst, 'step1': v1_lst_A, 'prec': prec, 'width': 0.03 } pin.curve_dct['B'] = { 'step0': v0_lst, 'step1': v1_lst_B, 'prec': prec, 'width': 0.03 } pin.curve_dct['C'] = { 'step0': v0_lst, 'step1': v1_lst_C, 'prec': prec, 'width': 0.03 } pin.curve_dct['FA'] = { 'step0': v0_lst, 'step1': v1_lst_FA, 'prec': prec, 'width': 0.02 } pin.curve_dct['FB'] = { 'step0': v0_lst, 'step1': v1_lst_FB, 'prec': prec, 'width': 0.02 } pin.curve_dct['FC'] = { 'step0': v0_lst, 'step1': v1_lst_FC, 'prec': prec, 'width': 0.02 } col_A = (0.6, 0.4, 0.1, 0.0) col_B = (0.1, 0.15, 0.0, 0.0) col_C = (0.2, 0.3, 0.2, 0.0) colFF = (0.1, 0.1, 0.1, 0.0) pin.text_dct['A'] = [True, col_A, 'phong 0.2 phong_size 5'] pin.text_dct['B'] = [True, col_B, 'phong 0.2 phong_size 5'] pin.text_dct['C'] = [True, col_C, 'phong 0.2 phong_size 5'] pin.text_dct['FA'] = [True, colFF, 'phong 0.2 phong_size 5'] pin.text_dct['FB'] = [True, colFF, 'phong 0.2 phong_size 5'] pin.text_dct['FC'] = [True, colFF, 'phong 0.2 phong_size 5'] # raytrace image/animation create_pov(pin, ['A', 'B', 'C']) create_pov(pin, ['A', 'B', 'C', 'FA', 'FB', 'FC']) create_pov(pin, ['A', 'B', 'FA', 'FB']) create_pov(pin, ['B', 'C', 'FA', 'FB'])
def test__get_emb_dim( self ): imp_lst = OrbRing.coerce( '[-x0^2+x1^2+x2^2+x3^2+x4^2+x5^2+x6^2+x7^2+x8^2, x8, x7, x6, x5, x1*x2-x0*x4]' ) emb = get_emb_dim( imp_lst ) print( emb ) assert emb == 3
def get_imp(A, B, prj, sng, snp): ''' Computes implicit equation of a stereographic projection S of the pointwise Hamiltonian product of circles in the sphere S^3 defined by transformations of the standard circle [1,cos(a),sin(a),0,0] by A and B respectively. Parameters ---------- A : sage_Matrix<sage_QQ> Represents a linear transformation S^3--->S^3 B : sage_Matrix<sage_QQ> Represents a linear transformation S^3--->S^3 prj : int Choice for stereographic projection S^3--->P^3: 0: (x0:x1:x2:x3:x4) |--> (x0-x4:x1:x2:x3) 1: (x0:x1:x2:x3:x4) |--> (x0-x1:x4:x2:x3) 2: (x0:x1:x2:x3:x4) |--> (x0-x2:x1:x4:x3) 3: (x0:x1:x2:x3:x4) |--> (x0-x3:x1:x2:x4) sng : boolean If true computes singular locus of S. Needs Magma path set in os.environ['PATH']. Otherwise the empty-list is returned. snp : boolean If true and if sng is True, then the singular locus is computed with a probablistic method, which is faster but the correctness of the output is not guaranteed. Returns ------- dict { 'Agreat' : boolean If True, then circle A is great. 'Bgreat' : boolean If True, then circle B is great. 'eqn_x' : sage_PolynomialRing Equation of S in x0,...,x3 'eqn_str': Formatted equation in x0,...,x3 of the form f(x1:x2:x3)+x0*g(x0:x1:x2:x3). 'eqn_xyz': Equation of S in x,y,z 'sng_lst': Empty-list if Magma is not installed or list of singularities of S otherwise. } ''' dct = {} # output # create polynomial ring # R = sage_PolynomialRing(sage_QQ, 'x0,x1,x2,x3,a0,a1,a2,a3,a4,b0,b1,b2,b3,b4') x0, x1, x2, x3, a0, a1, a2, a3, a4, b0, b1, b2, b3, b4 = R.gens() # construct ideal for A # sv = [0, 0, 0, 1, 0] tv = [0, 0, 0, 0, 1] u0, u1, u2, u3, u4 = list(A * sage_vector(sv)) v0, v1, v2, v3, v4 = list(A * sage_vector(tv)) eqA = [-a0**2 + a1**2 + a2**2 + a3**2 + a4**2] eqA += [u0 * a0 + u1 * a1 + u2 * a2 + u3 * a3 + u4 * a4] eqA += [v0 * a0 + v1 * a1 + v2 * a2 + v3 * a3 + v4 * a4] dct['Agreat'] = u0 == v0 == 0 # construct ideal for B # u0, u1, u2, u3, u4 = list(B * sage_vector(sv)) v0, v1, v2, v3, v4 = list(B * sage_vector(tv)) eqB = [-b0**2 + b1**2 + b2**2 + b3**2 + b4**2] eqB += [u0 * b0 + u1 * b1 + u2 * b2 + u3 * b3 + u4 * b4] eqB += [v0 * b0 + v1 * b1 + v2 * b2 + v3 * b3 + v4 * b4] dct['Bgreat'] = u0 == v0 == 0 # stereographic projection # if prj == 0: j, i_lst = 4, [1, 2, 3] if prj == 1: j, i_lst = 1, [4, 2, 3] if prj == 2: j, i_lst = 2, [1, 4, 3] if prj == 3: j, i_lst = 3, [1, 2, 4] # construct equation of for projection of A*B # c = c0, c1, c2, c3, c4 = get_hp_P4([a0, a1, a2, a3, a4], [b0, b1, b2, b3, b4]) x = [x0, x1, x2, x3] i1, i2, i3 = i_lst id = [x[0] - (c[0] - c[j]), x[1] - c[i1], x2 - c[i2], x3 - c[i3]] + eqA + eqB dct['eqn_x'] = eqn_x = R.ideal(id).elimination_ideal( [a0, a1, a2, a3, a4, b0, b1, b2, b3, b4]).gens()[0] # get equation in string form # f = eqn_x.subs({x0: 0}) dct['eqn_str'] = str(sage_factor(f)) + '+' + str(sage_factor(eqn_x - f)) xs, ys, zs = sage_var('x,y,z') dct['eqn_xyz'] = sage_SR(eqn_x.subs({x0: 1, x1: xs, x2: ys, x3: zs})) # compute singular locus # dct['sng_lst'] = [] if sng: dct['sng_lst'] = get_sing_lst(OrbRing.coerce(eqn_x), snp) return dct
def test__get_deg_dim_2( self ): imp_lst = OrbRing.coerce( '[-x0^2+x1^2+x2^2+x3^2+x4^2+x5^2+x6^2+x7^2+x8^2, x8, x7, x6, x5, x4, x3]' ) deg_dim = get_deg_dim( imp_lst ) print( deg_dim ) assert deg_dim == ( 2, 1 )