def test__get_proj( self ): # construct dct a0 = PolyRing( 'x,y,v,w', True ).ext_num_field( 't^2 + 1' ).root_gens()[0] # i bp_tree = BasePointTree( ['xv', 'xw', 'yv', 'yw'] ) bp = bp_tree.add( 'xv', ( -a0, a0 ), 1 ) # e1 bp = bp_tree.add( 'xv', ( a0, -a0 ), 1 ) # e2 ls = LinearSeries.get( [2, 2], bp_tree ) # |2(l1+l2)-e1-e2| sig = ( 6, 1 ) coef_lst = [-1, -1, 0, 0, 0, -1, 1, 0, -1, -1, -1] prv_Q = None dct = get_surf( ls, sig, coef_lst, prv_Q ) # construct projection matrix P U, J = dct['UJ'] U.swap_rows( 0, 6 ) J.swap_columns( 0, 6 ) J.swap_rows( 0, 6 ) assert dct['M'] == approx_QQ( U.T * J * U ) approxU = approx_QQ( U ) P = get_prj_mat( 4, 7, 0 ) P[0, 6] = -1;P[3, 3] = 0;P[3, 4] = 1 P = P * approxU # call get_proj f_xyz, pmz_AB_lst = get_proj( dct['imp_lst'], dct['pmz_lst'], P ) print( f_xyz ) print( pmz_AB_lst ) assert str( f_xyz ).startswith( '232136158126691416007724114435018582183550370830165237' ) assert str( pmz_AB_lst ).startswith( '[3687965761301911367110366337978449028075575/' )
def test__get_surf( self ): a0 = PolyRing( 'x,y,v,w', True ).ext_num_field( 't^2 + 1' ).root_gens()[0] # i bp_tree = BasePointTree( ['xv', 'xw', 'yv', 'yw'] ) bp = bp_tree.add( 'xv', ( -a0, a0 ), 1 ) # e1 bp = bp_tree.add( 'xv', ( a0, -a0 ), 1 ) # e2 ls = LinearSeries.get( [2, 2], bp_tree ) # |2(l1+l2)-e1-e2| sig = ( 5, 1 ) coef_lst = [-1, 1, -1, 1, 0, 1, 1, -1] prv_Q = [( 1, 0, 0, 1, 0, 1, 1 ), ( 1, 0, 1, 0, 0, 1, 0 ), ( 1, 0, 0, 1, 0, 0, 0 ), ( 1, 0, 0, 0, 0, 1, 1 ), ( 1, 0, 0, 0, 0, 0, 1 ), ( 0, 1, 1, 0, 1, 1, 0 )] dct = get_surf( ls, sig, coef_lst, prv_Q ) print( list( dct['Q'] ) ) print( dct['pmz_lst'] ) print( dct['imp_lst'] ) print( list( dct['M'] ) ) print( list( dct['UJ'][0] ) ) print( list( dct['UJ'][1] ) ) assert str( list( dct['Q'] ) ) == str( prv_Q ) assert str( dct['pmz_lst'] ) == '[-c0*s0*c1^2 + c0^2*s1^2 - c0*s0*s1^2 + s0^2*s1^2 + c0*c1^2 - 2*c0^2*s1 + 2*c0*s0*s1 - 2*s0^2*s1 + c0*s1^2 - 2*s0*s1^2 + c0^2 - c0*s0 + s0^2 - 2*c0*s1 + 4*s0*s1 + s1^2 + c0 - 2*s0 - 2*s1 + 1, -c0*s0*c1^2 + s0^2*c1^2 - c0^2*c1*s1 + s0^2*s1^2 + c0^2*c1 + c0*c1^2 - 2*s0*c1^2 - 2*s0^2*s1 - 2*s0*s1^2 + s0^2 + c1^2 + 4*s0*s1 + s1^2 - 2*s0 - 2*s1 + 1, -c0^2*c1^2 + c0^2*c1*s1 - c0*s0*s1^2 + s0^2*s1^2 - c0^2*c1 + 2*c0*s0*s1 - 2*s0^2*s1 + c0*s1^2 - 2*s0*s1^2 - c0*s0 + s0^2 - 2*c0*s1 + 4*s0*s1 + s1^2 + c0 - 2*s0 - 2*s1 + 1, -c0*s0*c1^2 - c0^2*c1*s1 + c0^2*s1^2 + s0^2*s1^2 + c0^2*c1 + c0*c1^2 - 2*c0^2*s1 - 2*s0^2*s1 - 2*s0*s1^2 + c0^2 + s0^2 + 4*s0*s1 + s1^2 - 2*s0 - 2*s1 + 1, c0^2*s1^2 + s0^2*s1^2 - 2*c0^2*s1 - 2*s0^2*s1 - 2*s0*s1^2 + c0^2 + s0^2 + 4*s0*s1 + s1^2 - 2*s0 - 2*s1 + 1, -c0*s0*c1^2 + s0^2*c1^2 - 2*c0^2*c1*s1 + c0*s0*c1*s1 - s0^2*c1*s1 + 2*c0^2*c1 - c0*s0*c1 + s0^2*c1 + c0*c1^2 - 2*s0*c1^2 - c0*c1*s1 + 2*s0*c1*s1 + c0*c1 - 2*s0*c1 + c1^2 - c1*s1 + c1]' assert str( dct['imp_lst'] ) == '[2*x1^2 + x0*x2 - x1*x2 - x2*x3 - 4*x0*x4 - 5*x1*x4 + 4*x2*x4 + 3*x3*x4 + x4^2 - x0*x5 - 4*x1*x5 + x2*x5 + x3*x5 + 3*x4*x5 + 2*x5^2, 2*x0*x1 - x0*x2 - x1*x2 - 6*x0*x3 - 2*x1*x3 + 3*x2*x3 + 4*x3^2 + 6*x0*x4 + x1*x4 - 2*x2*x4 - 5*x3*x4 + x4^2 + x0*x5 - x2*x5 - x3*x5 + x4*x5, 2*x0^2 - x0*x2 + x1*x2 - 4*x0*x3 + x2*x3 + 2*x3^2 - x1*x4 - x3*x4 + x4^2 + x0*x5 - x2*x5 - x3*x5 + x4*x5, 4*x1*x3^2 - x2*x3^2 + x3^3 + x0*x2*x4 + x1*x2*x4 - x2^2*x4 + x0*x3*x4 - 11*x1*x3*x4 + x2*x3*x4 - 10*x3^2*x4 - 2*x0*x4^2 + 6*x1*x4^2 + 22*x3*x4^2 - 12*x4^3 - x0*x3*x5 + 2*x2*x3*x5 - 4*x3^2*x5 - x0*x4*x5 + 15*x3*x4*x5 - 11*x4^2*x5 - 2*x0*x5^2 - x2*x5^2 + 2*x3*x5^2 + x4*x5^2, 4*x0*x3^2 - x2*x3^2 - 3*x3^3 + x0*x2*x4 + x1*x2*x4 - x2^2*x4 - 11*x0*x3*x4 + x1*x3*x4 + x2*x3*x4 + 10*x3^2*x4 + 6*x0*x4^2 - 2*x1*x4^2 - 10*x3*x4^2 + 4*x4^3 - 5*x0*x3*x5 + 2*x2*x3*x5 + 4*x3^2*x5 + 7*x0*x4*x5 - 4*x2*x4*x5 - 9*x3*x4*x5 + 5*x4^2*x5 + 2*x0*x5^2 - x2*x5^2 - 2*x3*x5^2 + x4*x5^2, 4*x1*x2*x3 - x2*x3^2 + x3^3 - 3*x0*x2*x4 - 7*x1*x2*x4 + 3*x2^2*x4 - 3*x0*x3*x4 - 3*x1*x3*x4 + 5*x2*x3*x4 - 2*x3^2*x4 + 6*x0*x4^2 + 6*x1*x4^2 - 4*x2*x4^2 + 2*x3*x4^2 - 4*x4^3 - 2*x0*x2*x5 - 2*x1*x2*x5 - x0*x3*x5 + 3*x0*x4*x5 + 2*x1*x4*x5 + 4*x2*x4*x5 + x3*x4*x5 - 5*x4^2*x5 + x2*x5^2 - x4*x5^2, 4*x0*x2*x3 - 5*x2*x3^2 + x3^3 - 7*x0*x2*x4 - 3*x1*x2*x4 + 3*x2^2*x4 - 3*x0*x3*x4 - 3*x1*x3*x4 + 17*x2*x3*x4 - 2*x3^2*x4 + 6*x0*x4^2 + 6*x1*x4^2 - 12*x2*x4^2 + 2*x3*x4^2 - 4*x4^3 - 2*x0*x2*x5 + 2*x1*x2*x5 + 7*x0*x3*x5 - 4*x3^2*x5 - 9*x0*x4*x5 - 2*x1*x4*x5 + 4*x2*x4*x5 + 9*x3*x4*x5 - 5*x4^2*x5 - 4*x0*x5^2 + x2*x5^2 + 4*x3*x5^2 - x4*x5^2, 2*x2^2*x3^2 - 4*x2*x3^3 + 2*x3^4 - 2*x0*x2^2*x4 - 2*x1*x2^2*x4 + 2*x2^3*x4 + 4*x2^2*x3*x4 + 19*x2*x3^2*x4 - 7*x3^3*x4 - x0*x2*x4^2 - x1*x2*x4^2 - 3*x2^2*x4^2 - 3*x0*x3*x4^2 - 3*x1*x3*x4^2 - 25*x2*x3*x4^2 + 4*x3^2*x4^2 + 6*x0*x4^3 + 6*x1*x4^3 + 8*x2*x4^3 + 10*x3*x4^3 - 12*x4^4 - 4*x2^2*x3*x5 + 4*x2*x3^2*x5 - 4*x0*x2*x4*x5 + 4*x2^2*x4*x5 + 3*x0*x3*x4*x5 - 2*x2*x3*x4*x5 - 4*x3^2*x4*x5 - 3*x0*x4^2*x5 + 6*x2*x4^2*x5 + 13*x3*x4^2*x5 - 13*x4^3*x5 + x0*x2*x5^2 - x1*x2*x5^2 + 2*x2^2*x5^2 - x2*x3*x5^2 - 6*x0*x4*x5^2 + x1*x4*x5^2 - x2*x4*x5^2 + 7*x3*x4*x5^2 - 2*x4^2*x5^2 - x0*x5^3 + x2*x5^3 + x3*x5^3 - x4*x5^3]' assert str( list( dct['M'] ) ) == '[(-2, 1, -1/2, -1, 5, 1/2), (1, -2, -1/2, -1, 7/2, 2), (-1/2, -1/2, 0, 3/2, -3, -1/2), (-1, -1, 3/2, 2, -7/2, -1/2), (5, 7/2, -3, -7/2, -1, -3/2), (1/2, 2, -1/2, -1/2, -3/2, -2)]' assert str( list( dct['UJ'][0] ) ) == '[(1.35786975221142?, 1.07346104931619?, -0.55476539365996?, -0.40827309297366?, -2.0166161907848?, -0.97578089340802?), (1.164220993205174?, -1.238241275959885?, -0.069749665334111?, -0.0755220593640689?, -0.253358176151464?, 0.852764409706635?), (0.2374970415389016?, 0.06861265576467416?, 0.8393349903238033?, -0.2501991469577176?, 0.08951234160953201?, -0.1515231571929268?), (0.05097640435508013?, -0.3562824973464569?, -0.0953003146422521?, 0.01449254245924731?, 0.1356081690977796?, -0.5531500949878551?), (0.0804899878314170?, 0.04919673465402113?, 0.00930980680657234?, 0.1455320285330222?, 0.0527745414065528?, -0.00912281285573814?), (1.1245900860635?, 0.9053316050139?, -1.0130556284196?, -1.5021250674132?, 1.7776721895235?, 0.0915041576522?)]' assert str( list( dct['UJ'][1] ) ) == '[(-1.000000000000000?, 0, 0, 0, 0, 0), (0, -1.000000000000000?, 0, 0, 0, 0), (0, 0, -1.000000000000000?, 0, 0, 0), (0, 0, 0, -1.000000000000000?, 0, 0), (0, 0, 0, 0, -1.000000000000000?, 0), (0, 0, 0, 0, 0, 1.000000000000000?)]'
def test__get_linear_series__1(self): # Example from phd thesis of Niels Lubbes (page 159). PolyRing.reset_base_field() bp_tree = BasePointTree() bp = bp_tree.add('z', (0, 0), 1) bp = bp.add('t', (0, 0), 1) bp = bp.add('t', (-1, 0), 1) bp = bp.add('t', (0, 0), 1) ls = LinearSeries.get([2], bp_tree) assert str(ls) == '{ 2, <<x^2, y^2 + x*z>>, QQ[x, y, z] }'
def test__get_linear_series__7(self): ring = PolyRing('x,y,z', True) # checks that 2 infinitly near base points and # a simple base point is not collinear. # bp_tree = BasePointTree() bp_tree.add('z', (1, 0), 1) bp = bp_tree.add('z', (0, 1), 1) bp.add('t', (1, 0), 1) ls = LinearSeries.get([1], bp_tree) assert ls.pol_lst == []
def test__get_linear_series__8(self): a0 = PolyRing('x,y,v,w').ext_num_field('t^2 + 1').root_gens()[0] # i bp_tree_1 = BasePointTree(['xv', 'xw', 'yv', 'yw']) bp_tree_1.add('xv', (-2 * a0, a0), 1) # e2 bp_tree_1.add('xv', (2 * a0, -a0), 1) # e3 bp_tree_1.add('xv', (a0, -a0), 1) # e4 bp_tree_1.add('xv', (-a0, a0), 1) # e5 ls = LinearSeries.get([2, 1], bp_tree_1) # |2e0+1e1-e2-e3-e4-e5| print(ls) print(bp_tree_1) bp_tree_2 = ls.get_bp_tree() print(bp_tree_2) bp_tree_2_str = bp_tree_2.alt_str() bp_tree_2_str = bp_tree_2_str.replace('(a0)', 'a0') bp_tree_2_str = bp_tree_2_str.replace('(-a0)', '-a0') print(bp_tree_1.alt_str()) print(bp_tree_2.alt_str()) assert self.equal_output_strings(bp_tree_1.alt_str(), bp_tree_2_str)
def test__get_linear_series__6(self): ring = PolyRing('x,y,v,w', True) ring.ext_num_field('t^2 + 1') a0 = ring.root_gens()[0] bp_tree_1 = BasePointTree(['xv', 'xw', 'yv', 'yw']) bp = bp_tree_1.add('xv', (a0, -a0), 2) bp_tree_2 = LinearSeries.get([2, 2], bp_tree_1).get_bp_tree() bp_tree_2_str = bp_tree_2.alt_str() bp_tree_2_str = bp_tree_2_str.replace('(a0)', 'a0') bp_tree_2_str = bp_tree_2_str.replace('(-a0)', '-a0') assert self.equal_output_strings(bp_tree_1.alt_str(), bp_tree_2_str)
def test__BasePointTree(self): bp_tree = BasePointTree() bp = bp_tree.add('z', (0, 0), 1) bp = bp.add('t', (0, 0), 1) bp = bp.add('t', (-1, 0), 1) bp = bp.add('t', (0, 0), 1) out = str(bp_tree) chk = """ chart=z, depth=0, mult=1, sol=(0, 0), None chart=t, depth=1, mult=1, sol=(0, 0), None chart=t, depth=2, mult=1, sol=(-1, 0), None chart=t, depth=3, mult=1, sol=(0, 0), None """ assert self.equal_output_strings(out, chk)
def test__verify_get_surf( self ): a0 = PolyRing( 'x,y,v,w', True ).ext_num_field( 't^2 + 1' ).root_gens()[0] # i bp_tree = BasePointTree( ['xv', 'xw', 'yv', 'yw'] ) bp = bp_tree.add( 'xv', ( -a0, a0 ), 1 ) # e1 bp = bp_tree.add( 'xv', ( a0, -a0 ), 1 ) # e2 ls = LinearSeries.get( [2, 2], bp_tree ) # |2(l1+l2)-e1-e2| sig = ( 6, 1 ) coef_lst = [-1, -1, 0, 0, 0, -1, 1, 0, -1, -1, -1] prv_Q = None dct = get_surf( ls, sig, coef_lst, prv_Q ) test_dct = verify_get_surf( dct ) print( test_dct ) assert test_dct['all']
def test__rand_surf_prj( self ): a0 = PolyRing( 'x,y,v,w', True ).ext_num_field( 't^2 + 1' ).root_gens()[0] # i bp_tree = BasePointTree( ['xv', 'xw', 'yv', 'yw'] ) bp = bp_tree.add( 'xv', ( -a0, a0 ), 1 ) # e1 bp = bp_tree.add( 'xv', ( a0, -a0 ), 1 ) # e2 ls = LinearSeries.get( [2, 2], bp_tree ) # |2(l1+l2)-e1-e2| prj_dim = 5 prv_Q = sage_matrix( sage_QQ, [( 1, 1, 1, 1, 1, 0, 1 ), ( 0, 1, 0, 1, 0, 0, 0 ), ( 1, 0, 0, 1, 0, 1, 1 ), ( 1, 0, 1, 1, 0, 1, 0 ), ( 0, 0, 1, 0, 1, 0, 1 ), ( 0, 1, 1, 0, 1, 1, 1 )] ) Q, pmz_lst, imp_lst = rand_surf_prj( ls, prj_dim, prv_Q ) print( 'Q =\n' + str( list( Q ) ) ) print( '\npmz_lst =\n' + str( pmz_lst ) ) print( '\nimp_lst =\n' + str( imp_lst ) ) assert Q == prv_Q assert str( pmz_lst ) == '[s0^2*c1^2 + c0*s0*c1*s1 - s0^2*c1*s1 + c0^2*s1^2 - c0*s0*s1^2 + s0^2*s1^2 - c0*s0*c1 + s0^2*c1 - 2*s0*c1^2 - 2*c0^2*s1 + 2*c0*s0*s1 - 2*s0^2*s1 - c0*c1*s1 + 2*s0*c1*s1 + c0*s1^2 - 2*s0*s1^2 + c0^2 - c0*s0 + s0^2 + c0*c1 - 2*s0*c1 + c1^2 - 2*c0*s1 + 4*s0*s1 - c1*s1 + s1^2 + c0 - 2*s0 + c1 - 2*s1 + 1, -s0^2*c1*s1 - c0*s0*s1^2 + s0^2*c1 + 2*c0*s0*s1 + 2*s0*c1*s1 + c0*s1^2 - c0*s0 - 2*s0*c1 - 2*c0*s1 - c1*s1 + c0 + c1, -c0*s0*c1^2 + c0^2*s1^2 - c0*s0*s1^2 + s0^2*s1^2 + c0*c1^2 - 2*c0^2*s1 + 2*c0*s0*s1 - 2*s0^2*s1 + c0*s1^2 - 2*s0*s1^2 + c0^2 - c0*s0 + s0^2 - 2*c0*s1 + 4*s0*s1 + s1^2 + c0 - 2*s0 - 2*s1 + 1, -c0*s0*c1^2 + s0^2*c1^2 - c0*s0*s1^2 + s0^2*s1^2 + c0*c1^2 - 2*s0*c1^2 + 2*c0*s0*s1 - 2*s0^2*s1 + c0*s1^2 - 2*s0*s1^2 - c0*s0 + s0^2 + c1^2 - 2*c0*s1 + 4*s0*s1 + s1^2 + c0 - 2*s0 - 2*s1 + 1, c0^2*c1^2 + s0^2*c1^2 + c0*s0*c1*s1 + c0^2*s1^2 - c0*s0*c1 - 2*s0*c1^2 - 2*c0^2*s1 - c0*c1*s1 + c0^2 + c0*c1 + c1^2, c0^2*c1^2 - c0*s0*c1^2 + s0^2*c1^2 - 2*c0^2*c1*s1 + c0*s0*c1*s1 - s0^2*c1*s1 + c0^2*s1^2 + 2*c0^2*c1 - c0*s0*c1 + s0^2*c1 + c0*c1^2 - 2*s0*c1^2 - 2*c0^2*s1 - c0*c1*s1 + 2*s0*c1*s1 + c0^2 + c0*c1 - 2*s0*c1 + c1^2 - c1*s1 + c1]' assert str( imp_lst ) == '[5*x0*x1 - 5*x1^2 + 12*x0*x2 - 13*x1*x2 + 4*x2^2 - 9*x0*x3 + 8*x1*x3 - 12*x2*x3 + 5*x3^2 - 8*x0*x4 - 5*x1*x4 - 8*x2*x4 + 13*x3*x4 + 4*x4^2 + 2*x0*x5 + 8*x1*x5 - 2*x2*x5 - 3*x3*x5 - 8*x4*x5 + 4*x5^2, 5*x0^2 - 5*x1^2 + 32*x0*x2 - 28*x1*x2 + 19*x2^2 - 34*x0*x3 + 28*x1*x3 - 47*x2*x3 + 25*x3^2 - 33*x0*x4 - 5*x1*x4 - 23*x2*x4 + 38*x3*x4 + 14*x4^2 + 7*x0*x5 + 28*x1*x5 - 7*x2*x5 - 8*x3*x5 - 28*x4*x5 + 14*x5^2, 8*x1^2*x4 - 46*x0*x2*x4 + 44*x1*x2*x4 - 38*x2^2*x4 + 42*x0*x3*x4 - 44*x1*x3*x4 + 83*x2*x3*x4 - 41*x3^2*x4 + 49*x0*x4^2 + 11*x1*x4^2 + 35*x2*x4^2 - 53*x3*x4^2 - 21*x4^3 - 8*x1^2*x5 + 20*x0*x2*x5 - 18*x1*x2*x5 + 12*x2^2*x5 - 16*x0*x3*x5 + 18*x1*x3*x5 - 31*x2*x3*x5 + 15*x3^2*x5 - 24*x0*x4*x5 - 58*x1*x4*x5 - 8*x2*x4*x5 + 31*x3*x4*x5 + 50*x4^2*x5 + x0*x5^2 + 21*x1*x5^2 - x2*x5^2 - 4*x3*x5^2 - 37*x4*x5^2 + 8*x5^3, 5*x0*x2*x3 - 5*x1*x2*x3 + 5*x2^2*x3 - 5*x0*x3^2 + 5*x1*x3^2 - 10*x2*x3^2 + 5*x3^3 + 6*x0*x2*x4 - 4*x1*x2*x4 + 2*x2^2*x4 - 12*x0*x3*x4 + 4*x1*x3*x4 - 11*x2*x3*x4 + 10*x3^2*x4 - 4*x0*x4^2 - 4*x2*x4^2 + 9*x3*x4^2 + 2*x4^3 - 6*x0*x2*x5 + 4*x1*x2*x5 - 2*x2^2*x5 + 7*x0*x3*x5 + x1*x3*x5 + 6*x2*x3*x5 - 5*x3^2*x5 + 5*x0*x4*x5 + 4*x1*x4*x5 + 3*x2*x4*x5 - 13*x3*x4*x5 - 6*x4^2*x5 - x0*x5^2 - 4*x1*x5^2 + x2*x5^2 + 4*x3*x5^2 + 6*x4*x5^2 - 2*x5^3, 40*x1^2*x3 - 10*x1*x2*x3 + 40*x2^2*x3 - 20*x0*x3^2 + 10*x1*x3^2 - 45*x2*x3^2 + 25*x3^3 + 276*x0*x2*x4 - 184*x1*x2*x4 + 92*x2^2*x4 - 307*x0*x3*x4 + 239*x1*x3*x4 - 331*x2*x3*x4 + 195*x3^2*x4 - 184*x0*x4^2 - 184*x2*x4^2 + 309*x3*x4^2 + 92*x4^3 - 120*x0*x2*x5 + 80*x1*x2*x5 - 40*x2^2*x5 + 135*x0*x3*x5 - 85*x1*x3*x5 + 125*x2*x3*x5 - 80*x3^2*x5 + 126*x0*x4*x5 + 184*x1*x4*x5 + 34*x2*x4*x5 - 219*x3*x4*x5 - 224*x4^2*x5 - 20*x0*x5^2 - 80*x1*x5^2 + 20*x2*x5^2 + 40*x3*x5^2 + 172*x4*x5^2 - 40*x5^3, 400*x2^3 - 80*x1*x2*x3 - 640*x2^2*x3 - 60*x0*x3^2 + 80*x1*x3^2 + 335*x2*x3^2 - 35*x3^3 - 792*x0*x2*x4 + 228*x1*x2*x4 - 264*x2^2*x4 + 419*x0*x3*x4 - 403*x1*x3*x4 + 637*x2*x3*x4 - 255*x3^2*x4 + 328*x0*x4^2 + 428*x2*x4^2 - 493*x3*x4^2 - 164*x4^3 + 352*x0*x2*x5 + 32*x1*x2*x5 - 16*x2^2*x5 - 159*x0*x3*x5 + 223*x1*x3*x5 - 187*x2*x3*x5 + 70*x3^2*x5 - 150*x0*x4*x5 - 428*x1*x4*x5 - 386*x2*x4*x5 + 441*x3*x4*x5 + 412*x4^2*x5 - 8*x0*x5^2 + 168*x1*x5^2 + 108*x2*x5^2 - 98*x3*x5^2 - 332*x4*x5^2 + 84*x5^3, 100*x1*x2^2 - 140*x1*x2*x3 - 70*x2^2*x3 + 20*x0*x3^2 + 40*x1*x3^2 + 105*x2*x3^2 - 55*x3^3 - 236*x0*x2*x4 + 224*x1*x2*x4 - 312*x2^2*x4 + 277*x0*x3*x4 - 249*x1*x3*x4 + 596*x2*x3*x4 - 290*x3^2*x4 + 349*x0*x4^2 + 75*x1*x4^2 + 199*x2*x4^2 - 294*x3*x4^2 - 137*x4^3 + 166*x0*x2*x5 - 144*x1*x2*x5 + 122*x2^2*x5 - 147*x0*x3*x5 + 109*x1*x3*x5 - 296*x2*x3*x5 + 135*x3^2*x5 - 200*x0*x4*x5 - 474*x1*x4*x5 - 88*x2*x4*x5 + 228*x3*x4*x5 + 346*x4^2*x5 + 11*x0*x5^2 + 219*x1*x5^2 - 11*x2*x5^2 - 34*x3*x5^2 - 281*x4*x5^2 + 72*x5^3, 400*x0*x2^2 - 480*x1*x2*x3 - 40*x2^2*x3 - 260*x0*x3^2 + 480*x1*x3^2 - 315*x2*x3^2 + 215*x3^3 + 288*x0*x2*x4 - 92*x1*x2*x4 - 704*x2^2*x4 - 791*x0*x3*x4 + 167*x1*x3*x4 + 407*x2*x3*x4 + 395*x3^2*x4 + 208*x0*x4^2 + 200*x1*x4^2 - 92*x2*x4^2 + 577*x3*x4^2 - 4*x4^3 - 328*x0*x2*x5 + 352*x1*x2*x5 + 24*x2^2*x5 + 451*x0*x3*x5 + 53*x1*x3*x5 - 57*x2*x3*x5 - 230*x3^2*x5 + 150*x0*x4*x5 - 508*x1*x4*x5 - 46*x2*x4*x5 - 949*x3*x4*x5 - 68*x4^2*x5 - 88*x0*x5^2 + 48*x1*x5^2 + 188*x2*x5^2 + 322*x3*x5^2 + 148*x4*x5^2 - 76*x5^3, 100*x1^2*x2 - 40*x1*x2*x3 + 80*x2^2*x3 - 30*x0*x3^2 + 40*x1*x3^2 - 95*x2*x3^2 + 45*x3^3 + 754*x0*x2*x4 - 536*x1*x2*x4 + 618*x2^2*x4 - 903*x0*x3*x4 + 711*x1*x3*x4 - 1444*x2*x3*x4 + 810*x3^2*x4 - 811*x0*x4^2 - 125*x1*x4^2 - 561*x2*x4^2 + 916*x3*x4^2 + 343*x4^3 + 50*x1^2*x5 - 344*x0*x2*x5 + 246*x1*x2*x5 - 248*x2^2*x5 + 373*x0*x3*x5 - 281*x1*x3*x5 + 564*x2*x3*x5 - 315*x3^2*x5 + 480*x0*x4*x5 + 936*x1*x4*x5 + 112*x2*x4*x5 - 622*x3*x4*x5 - 834*x4^2*x5 - 49*x0*x5^2 - 371*x1*x5^2 + 49*x2*x5^2 + 106*x3*x5^2 + 639*x4*x5^2 - 148*x5^3, 800*x1^3 + 10*x1*x2*x3 + 280*x2^2*x3 - 80*x0*x3^2 - 10*x1*x3^2 - 295*x2*x3^2 + 95*x3^3 + 2444*x0*x2*x4 - 2296*x1*x2*x4 - 1052*x2^2*x4 - 1733*x0*x3*x4 + 1221*x1*x3*x4 + 91*x2*x3*x4 - 15*x3^2*x4 + 104*x0*x4^2 + 600*x1*x4^2 - 1496*x2*x4^2 + 2351*x3*x4^2 + 348*x4^3 - 100*x1^2*x5 - 1024*x0*x2*x5 + 816*x1*x2*x5 + 192*x2^2*x5 + 833*x0*x3*x5 - 551*x1*x3*x5 + 119*x2*x3*x5 - 40*x3^2*x5 + 190*x0*x4*x5 + 196*x1*x4*x5 + 642*x2*x4*x5 - 1977*x3*x4*x5 - 904*x4^2*x5 - 104*x0*x5^2 - 216*x1*x5^2 + 104*x2*x5^2 + 376*x3*x5^2 + 764*x4*x5^2 - 208*x5^3]'
def test__get_linear_series__3(self): PolyRing.reset_base_field() bp_tree_1 = BasePointTree() bp_tree_1.add('z', (0, 0), 2).add('t', (1, 0), 1) bp_tree_1.add('z', (2, 3), 1) bp_tree_2 = LinearSeries.get([3], bp_tree_1).get_bp_tree() assert self.equal_output_strings(bp_tree_1.alt_str(), bp_tree_2.alt_str())
def usecase__construct_surfaces(): ''' We construct a surface parametrization and its Neron-Severi lattice. Requires the linear_series package. ''' # Blowup of projective plane in 3 colinear points # and 2 infinitely near points. The image of the # map associated to the linear series is a quartic # del Pezzo surface with 5 families of conics. # Moreover the surface contains 8 straight lines. # ring = PolyRing('x,y,z', True) p1 = (-1, 0) p2 = (0, 0) p3 = (1, 0) p4 = (0, 1) p5 = (2, 0) bp_tree = BasePointTree() bp_tree.add('z', p1, 1) bp_tree.add('z', p2, 1) bp_tree.add('z', p3, 1) bp = bp_tree.add('z', p4, 1) bp.add('t', p5, 1) ls = LinearSeries.get([3], bp_tree) NSTools.p(ls.get_bp_tree()) NSTools.p('implicit equation =\n\t', ls.get_implicit_image()) # construct NS-lattice where p1=e1,...,p5=e5 rank = 6 d_lst = ['e0-e1-e2-e3', 'e4-e5'] # basepoint p5 is infinitely near to p4 Md_lst = [] M = sage_identity_matrix(6) d_lst = [Div.new(d, rank) for d in d_lst] Md_lst = [Div.new(Md, rank) for Md in Md_lst] M = sage_matrix(M) dpl = DPLattice(d_lst, Md_lst, M) NSTools.p('Neron-Severi lattice =', dpl) # search representative for the equivalence class in classification assert dpl in DPLattice.get_cls(rank)
def usecase_celestial_types(): ''' Let surface X in P^m be the blowups of P^1xP^1 in either 0 or 2 complex conjugate points so that m=8 and m=6 respectively. Here P^1xP^1 denotes the fiber product of the projective line with itself. We verify for n in [3,4,5,6,7] whether X can be linearly projected into the projective n-sphere S^n. If m=8, then the celestial type is (2,8,n), where the first entry denotes the number of conics contained in X through (almost) every point. If m=6, then the celestial type is (3,6,n) or (2,6,n). If X in S^5 has celestial type (2,6,5), then X has a real isolated singularity (see dp6_sing() for a visualization)). ''' # We provide certificates "c_lst" and "prv_Q" for "get_surf()", # which were obtained by a previous (long) computation. # # P^1xP^1 # # We construct a parametrization of the double Segre surface dP8 in # projective 8-space. This surface contains 2 conics through each point # ring = PolyRing('x,y,v,w', True) ls_dP8 = LinearSeries(get_mon_lst([2, 2], ring.gens()), ring) OrbTools.p('ls_dP8 =', ls_dP8) get_surf(ls_dP8, (7 + 1, 1), [ -8, -8, -10, -6, -7, 6, 5, 6, 0, -8, -2, -7, -7, 7, -1, 0, -9, 7, 1, -9 ]) prv_Q = sage_matrix([(0, 0, 0, 1, 1, 1, 0, 0, 0), (0, 1, 0, 0, 0, 0, 0, 0, 0), (1, 0, 1, 1, 0, 0, 0, 1, 0), (1, 0, 0, 1, 0, 0, 1, 0, 0), (0, 0, 0, 0, 0, 0, 1, 0, 1), (0, 1, 0, 0, 1, 0, 1, 0, 1), (0, 0, 0, 1, 1, 0, 1, 0, 1), (1, 0, 0, 1, 0, 0, 1, 1, 0)]) get_surf( ls_dP8, (6 + 1, 1), [3, -3, 3, -7, 7, 1, -4, 3, -10, 6, -4, -6, -6, 4, -9, 3, -6, -4, 1], prv_Q) prv_Q = sage_matrix([(0, 1, 0, 0, 1, 0, 1, 0, 1), (1, 1, 1, 1, 0, 1, 0, 0, 1), (1, 1, 0, 1, 1, 1, 1, 0, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 0, 1, 0, 1, 0, 1, 0, 0), (0, 0, 1, 0, 1, 0, 0, 1, 0), (0, 0, 0, 0, 0, 0, 1, 1, 1)]) get_surf(ls_dP8, (5 + 1, 1), [ -7, -2, -1, -5, -4, 6, -2, -2, -2, 2, 9, -4, -9, -4, 2, -10, 9, -6, -1 ], prv_Q) prv_Q = sage_matrix([(0, 1, 0, 1, 1, 1, 0, 1, 1), (1, 0, 0, 0, 1, 1, 0, 1, 1), (1, 0, 0, 0, 1, 0, 0, 0, 1), (0, 1, 1, 0, 0, 0, 1, 1, 0), (1, 1, 1, 0, 0, 0, 1, 1, 0), (0, 1, 1, 1, 0, 1, 1, 1, 0)]) get_surf(ls_dP8, (4 + 1, 1), [-2, -3, 6, 7, -10, -2, -4, -8, -3, -4, 4, -6], prv_Q) # # P^1xP^1 blown up in two general complex conjugate points # # We construct a parametrization of a sextic del Pezzo surface dP6 # in projective 6-space, that contains 3 conics through each point. # We show that dP6 can be projected into S^5 and S^4. # a0 = PolyRing('x,y,v,w', True).ext_num_field('t^2 + 1').root_gens()[0] bp_tree = BasePointTree(['xv', 'xw', 'yv', 'yw']) bp_tree.add('xv', (-a0, a0), 1) bp_tree.add('xv', (a0, -a0), 1) ls_dP6 = LinearSeries.get([2, 2], bp_tree) OrbTools.p('ls_dP6 =', ls_dP6) get_surf(ls_dP6, (5 + 1, 1), [-9, -6, 1, 4, -1, -8, -5, -5, -4, 8, 1]) prv_Q = sage_matrix([(0, 0, 0, 1, 0, 1, 1), (1, 1, 0, 1, 0, 0, 0), (0, 1, 1, 0, 1, 0, 1), (1, 1, 0, 0, 1, 0, 0), (1, 1, 1, 1, 1, 1, 0), (1, 0, 0, 1, 0, 1, 1)]) get_surf(ls_dP6, (4 + 1, 1), [-1, -9, -10, -7, -10, -8, 0], prv_Q) # # P^1xP^1 blown up in two complex conjugate points that lie in the same fiber # # We construct a parametrization of a sextic weak del Pezzo surface wdP6 # in projective 6-space, that contains 2 conics through each point. # We show that wdP6 can be projected into S^5 and S^4. # a0 = PolyRing('x,y,v,w', True).ext_num_field('t^2 + 1').root_gens()[0] bp_tree = BasePointTree(['xv', 'xw', 'yv', 'yw']) bp_tree.add('xv', (a0, 0), 1) # the complex conjugate base points lie in the same fiber bp_tree.add('xv', (-a0, 0), 1) ls_wdP6 = LinearSeries.get([2, 2], bp_tree) OrbTools.p('ls_wdP6 =', ls_wdP6) get_surf(ls_wdP6, (5 + 1, 1), [-6, 8, -7, -8, 0, -8, 2, -5, -8]) prv_Q = sage_matrix([(1, 0, 0, 1, 1, 1, 0), (1, 0, 0, 1, 0, 1, 1), (0, 1, 1, 1, 0, 1, 0), (0, 0, 0, 0, 1, 0, 0), (0, 1, 0, 1, 1, 1, 0), (0, 0, 0, 1, 1, 1, 0)]) get_surf(ls_wdP6, (4 + 1, 1), [-2, -7, -6, -10, -2, -4, 4], prv_Q)
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 ring_cyclide(): ''' Creates povray image of 4 families of circles on a ring cyclide. ''' # We construct a trigonometric parametrization of the ring cyclide, # by rotating a circle of radius r along a circle of radius R. R = 2 r = 1 x, y, v, w, c0, s0, c1, s1 = sage_var('x,y,v,w,c0,s0,c1,s1') V = sage_vector([r * c0 + R, 0, r * s0]) M = sage_matrix([(c1, -s1, 0), (s1, c1, 0), (0, 0, 1)]) pmz_AB_lst = [1] + list(M * V) OrbTools.p('pmz_AB_lst =', pmz_AB_lst) for pmz in pmz_AB_lst: OrbTools.p('\t\t', sage_factor(pmz)) # convert pmz_AB_lst to rational parametrization pmz_lst 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(M * V)] OrbTools.p('pmz_lst =', pmz_lst) # find basepoints ls = LinearSeries(pmz_lst, PolyRing('x,y,v,w', True)) OrbTools.p(ls.get_bp_tree()) # construct linear series for families of conics a0, a1 = PolyRing('x,y,v,w').ext_num_field('t^2+1/3').ext_num_field( 't^2+1').root_gens() p1 = ['xv', (-a0, a1)] p2 = ['xv', (a0, -a1)] p3 = ['xv', (-a0, -a1)] p4 = ['xv', (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 ring = PolyRing( 'x,y,v,w,c0,s0,c1,s1') # construct polynomial ring with new generators pmz_lst = ring.coerce(pmz_lst) x, y, v, w, c0, s0, c1, s1 = ring.gens() X = 1 - s0 Y = c0 # see get_S1xS1_pmz() V = 1 - s1 W = c1 q = sage_n(sage_sqrt(3)).exact_rational() # approximation of sqrt(3) CB_dct = {x: X, y: Y, v: W * X + q * V * Y, w: V * X - q * W * Y} DB_dct = {x: X, y: Y, v: W * X - q * V * Y, w: V * X + q * W * Y} pmz_CB_lst = [pmz.subs(CB_dct) for pmz in pmz_lst] pmz_DB_lst = [pmz.subs(DB_dct) for pmz in pmz_lst] # 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) # mathematica for pmz, AB in [(pmz_AB_lst, 'AB'), (pmz_CB_lst, 'CB'), (pmz_DB_lst, 'DB')]: s = 'pmz' + AB + '=' + str(pmz) + ';' s = s.replace('[', '{').replace(']', '}') print(s) # PovInput ring cyclide # pin = PovInput() pin.path = './' + get_time_str() + '_ring_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'] = (55, 0, 0) # 45 pin.shadow = True pin.light_lst = [(0, 0, -5), (0, -5, 0), (-5, 0, 0), (0, 0, 5), (0, 5, 0), (5, 0, 0), (-5, -5, -5), (5, -5, 5), (-5, -5, 5), (5, -5, -5)] pin.axes_dct['show'] = False pin.axes_dct['len'] = 1.2 pin.width = 800 pin.height = 400 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['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['WA'] = (pmz_AB_lst, 0) pin.pmz_dct['WB'] = (pmz_AB_lst, 1) pin.pmz_dct['WC'] = (pmz_CB_lst, 0) pin.pmz_dct['WD'] = (pmz_DB_lst, 0) v0_lst = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 10)] v1_lst = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 24)] v1_lst_A = [ sage_pi / 2 + (sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 12) ] v1_lstFF = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 1)] v1_lst_WA = [ 0.1, 0.52, 0.94, 1.36, 1.78, 2.2, 2.61, 3.04, 3.45, 3.88, 4.3, 4.712, 5.13, 5.55, 5.965 ] v1_lst_WB = [ 0, 0.7, 1.31, 1.8, 2.18, 2.5, 2.77, 3.015, 3.26, 3.51, 3.78, 4.099, 4.49, 4.97, 5.579 ] v1_lst_WD = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 24)] v1_lst_WC = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 24)] pin.curve_dct['A'] = { 'step0': v0_lst, 'step1': v1_lst_A, 'prec': 10, 'width': 0.05 } pin.curve_dct['B'] = { 'step0': v0_lst, 'step1': v1_lst, 'prec': 10, 'width': 0.05 } pin.curve_dct['C'] = { 'step0': v0_lst, 'step1': v1_lst, 'prec': 10, 'width': 0.05 } pin.curve_dct['D'] = { 'step0': v0_lst, 'step1': v1_lst, 'prec': 10, 'width': 0.05 } pin.curve_dct['FA'] = { 'step0': v0_lst, 'step1': v1_lstFF, 'prec': 10, 'width': 0.02 } pin.curve_dct['FB'] = { 'step0': v0_lst, 'step1': v1_lstFF, 'prec': 10, 'width': 0.02 } pin.curve_dct['FC'] = { 'step0': v0_lst, 'step1': v1_lstFF, 'prec': 10, 'width': 0.02 } pin.curve_dct['FD'] = { 'step0': v0_lst, 'step1': v1_lstFF, 'prec': 10, 'width': 0.02 } pin.curve_dct['WA'] = { 'step0': v0_lst, 'step1': v1_lst_WA, 'prec': 10, 'width': 0.05 } pin.curve_dct['WB'] = { 'step0': v0_lst, 'step1': v1_lst_WB, 'prec': 10, 'width': 0.05 } pin.curve_dct['WC'] = { 'step0': v0_lst, 'step1': v1_lst_WC, 'prec': 10, 'width': 0.05 } pin.curve_dct['WD'] = { 'step0': v0_lst, 'step1': v1_lst_WD, 'prec': 10, 'width': 0.05 } # A = | rotated circle # B = - horizontal circle # C = / villarceau circle # D = \ villarceau circle col_A = rgbt2pov((28, 125, 154, 0)) # blue col_B = rgbt2pov((74, 33, 0, 0)) # brown col_C = rgbt2pov((75, 102, 0, 0)) # green col_D = rgbt2pov((187, 46, 0, 0)) # red/orange colFF = rgbt2pov((179, 200, 217, 0)) # light 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['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['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['WA'] = [True, col_A, 'phong 0.2 phong_size 5'] pin.text_dct['WB'] = [True, col_B, 'phong 0.2 phong_size 5'] pin.text_dct['WC'] = [True, col_C, 'phong 0.2 phong_size 5'] pin.text_dct['WD'] = [True, col_D, 'phong 0.2 phong_size 5'] # raytrace image/animation create_pov(pin, ['A', 'C', 'D']) create_pov(pin, ['A', 'C', 'D'] + ['FA', 'FC', 'FD']) create_pov(pin, ['WA', 'WB', 'WC', 'WD']) create_pov(pin, ['WA', 'WB', 'WC', 'WD'] + ['FA', 'FC', 'FD']) create_pov(pin, ['WA', 'WB', 'WD']) create_pov(pin, ['WA', 'WB', 'WD'] + ['FA', '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 dp6_smooth(): ''' Creates povray image of the projection of a smooth sextic del Pezzo surface in S^5. This surface contains 3 families of conics that form a hexagonal web. ''' # compute parametrizations of canonical model a0 = PolyRing('x,y,v,w', True).ext_num_field('t^2 + 1').root_gens()[0] bp_tree = BasePointTree(['xv', 'xw', 'yv', 'yw']) bp = bp_tree.add('xv', (-a0, a0), 1) bp = bp_tree.add('xv', (a0, -a0), 1) ls_AB = LinearSeries.get([2, 2], bp_tree) ls_CB = LinearSeries.get([1, 1], bp_tree) # compute surface in quadric of signature (6,1) c_lst = [-1, -1, 0, 0, 0, -1, 1, 0, -1, -1, -1] dct = get_surf(ls_AB, (6, 1), c_lst) # compute projection to P^3 U, J = dct['UJ'] U.swap_rows(0, 6) J.swap_columns(0, 6) J.swap_rows(0, 6) approxU = approx_QQ(U) P = get_prj_mat(4, 7, 0) P[0, 6] = -1 P[3, 3] = 0 P[3, 4] = 1 P = P * approxU f_xyz, pmz_AB_lst = get_proj(dct['imp_lst'], dct['pmz_lst'], P) # compute reparametrization ring = PolyRing( 'x,y,v,w,c0,s0,c1,s1') # construct polynomial ring with new generators x, y, v, w, c0, s0, c1, s1 = ring.gens() X = 1 - s0 Y = c0 # see get_S1xS1_pmz() V = 1 - s1 W = c1 CB_dct = {x: X, y: Y, v: X * W + Y * V, w: X * V - Y * W} pmz_CB_lst = [p.subs(CB_dct) for p in ring.coerce(ls_AB.pol_lst)] pmz_CB_lst = list(P * dct['Q'] * sage_vector(pmz_CB_lst)) # set PovInput as container # put very low quality for testing purposes pin = PovInput() pin.path = './' + get_time_str() + '_dp6_smooth/' pin.fname = 'orb' pin.scale = 1 pin.cam_dct['location'] = (0, 0, sage_QQ(-21) / 10) pin.cam_dct['lookat'] = (0, 0, 0) pin.cam_dct['rotate'] = (310, 0, 0) pin.shadow = True pin.light_lst = [(0, 0, -4), (0, -4, 0), (-4, 0, 0), (0, 4, 0), (4, 0, 0), (-5, -5, -5), (5, 5, -5), (-5, 5, -5), (5, -5, -5)] pin.axes_dct['show'] = False pin.axes_dct['len'] = 1.2 pin.height = 400 pin.width = 800 pin.quality = 11 pin.ani_delay = 1 pin.impl = None v0_lst = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 10)] v1_lst = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 15)] v1_F_lst = [(sage_QQ(i) / 180) * sage_pi for i in range(0, 360, 1)] 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) pin.curve_dct['A'] = { 'step0': v0_lst, 'step1': v1_lst, 'prec': 10, 'width': 0.018 } pin.curve_dct['B'] = { 'step0': v0_lst, 'step1': v1_lst, 'prec': 10, 'width': 0.018 } pin.curve_dct['C'] = { 'step0': v0_lst, 'step1': v1_lst, 'prec': 10, 'width': 0.018 } pin.curve_dct['FA'] = { 'step0': v0_lst, 'step1': v1_F_lst, 'prec': 10, 'width': 0.003 } pin.curve_dct['FB'] = { 'step0': v0_lst, 'step1': v1_F_lst, 'prec': 10, 'width': 0.003 } pin.curve_dct['FC'] = { 'step0': v0_lst, 'step1': v1_F_lst, 'prec': 10, 'width': 0.003 } # ( 0.4, 0.0, 0.0, 0.0 ), ( 0.2, 0.3, 0.2, 0.0 ), ( 0.8, 0.6, 0.2, 0.0 ) col_A = rgbt2pov((75, 102, 0, 0)) # green / col_B = rgbt2pov((74, 33, 0, 0)) # brown - col_C = rgbt2pov((28, 125, 154, 0)) # blue \ colFF = rgbt2pov((179, 200, 217, 0)) # light blue pin.text_dct['A'] = [True, col_A, 'phong 0.2'] pin.text_dct['B'] = [True, col_B, 'phong 0.2'] pin.text_dct['C'] = [True, col_C, 'phong 0.2'] pin.text_dct['FA'] = [True, colFF, 'phong 0.8'] pin.text_dct['FB'] = [True, colFF, 'phong 0.8'] pin.text_dct['FC'] = [True, colFF, 'phong 0.8'] # raytrace image/animation create_pov(pin, ['A', 'B', 'C']) create_pov(pin, ['A', 'B', 'C', 'FA', 'FB', 'FC']) create_pov(pin, ['A', 'FA', 'FB', 'FC']) create_pov(pin, ['B', 'FA', 'FB', 'FC']) create_pov(pin, ['C', 'FA', 'FB', 'FC'])
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]
def blum_cyclide(): ''' Construct a povray image of 6 families of circles on a smooth Darboux cyclide. This surface is also known as the Blum cyclide. ''' # construct dct a0 = PolyRing( 'x,y,v,w', True ).ext_num_field( 't^2 + 1' ).root_gens()[0] # i bpt_1234 = BasePointTree( ['xv', 'xw', 'yv', 'yw'] ) bpt_1234.add( 'xv', ( -1 * a0, 1 * a0 ), 1 ) # e1 bpt_1234.add( 'xv', ( 1 * a0, -1 * a0 ), 1 ) # e2 bpt_1234.add( 'xw', ( -2 * a0, 2 * a0 ), 1 ) # e3 bpt_1234.add( 'xw', ( 2 * a0, -2 * a0 ), 1 ) # e4 bpt_12 = BasePointTree( ['xv', 'xw', 'yv', 'yw'] ) bpt_12.add( 'xv', ( -1 * a0, 1 * a0 ), 1 ) # e1 bpt_12.add( 'xv', ( 1 * a0, -1 * a0 ), 1 ) # e2 bpt_34 = BasePointTree( ['xv', 'xw', 'yv', 'yw'] ) bpt_34.add( 'xw', ( -2 * a0, 2 * a0 ), 1 ) # e3 bpt_34.add( 'xw', ( 2 * a0, -2 * a0 ), 1 ) # e4 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 ) sig = ( 4, 1 ) pol_lst = ls_22.get_implicit_image() # determine signature x_lst = sage_PolynomialRing( sage_QQ, [ 'x' + str( i ) for i in range( sum( sig ) )] ).gens() for pol in pol_lst: if pol.degree() == 2: M = sage_invariant_theory.quadratic_form( pol, x_lst ).as_QuadraticForm().matrix() D, V = sage_matrix( sage_QQ, M ).eigenmatrix_right() # D has first all negative values on diagonal cur_sig = ( len( [ d for d in D.diagonal() if d < 0 ] ), len( [ d for d in D.diagonal() if d > 0 ] ) ) else: cur_sig = '[no signature]' OrbTools.p( '\t\t', pol, cur_sig ) # obtain surface in sphere coef_lst = [0, -1, -1] dct = get_surf( ls_22, sig, coef_lst ) # construct projection matrix P U, J = dct['UJ'] U.swap_rows( 0, 4 ) J.swap_columns( 0, 4 ) J.swap_rows( 0, 4 ) assert dct['M'] == approx_QQ( U.T * J * U ) approxU = approx_QQ( U ) P = sage_identity_matrix( 5 ).submatrix( 0, 0, 4, 5 ) P[0, 4] = -1; P = P * approxU OrbTools.p( ' approx_QQ( U ) =', list( approx_QQ( U ) ) ) OrbTools.p( ' approx_QQ( J ) =', list( approx_QQ( J ) ) ) OrbTools.p( ' P =', list( P ) ) # call get_proj f_xyz, pmz_AB_lst = get_proj( dct['imp_lst'], dct['pmz_lst'], P ) f_xyz_deg_lst = [f_xyz.degree( sage_var( v ) ) for v in ['x', 'y', 'z']] # compute reparametrization ring = PolyRing( 'x,y,v,w,c0,s0,c1,s1' ) # construct polynomial ring with new generators p_lst = ring.coerce( ls_22.pol_lst ) x, y, v, w, c0, s0, c1, s1 = ring.gens() X = 1 - s0; Y = c0; # see get_S1xS1_pmz() V = 1 - s1; W = c1; CB_dct = { x:X, y:Y, v:X * W + Y * V, w: X * V - Y * W } DB_dct = { x:X, y:Y, v:4 * X * W - Y * V, w: X * V + Y * W } EB_dct = { x:X, y:Y, v:40 * W * X ** 2 + 25 * W * Y ** 2 + 24 * V * X * Y, w:40 * V * X ** 2 + 16 * V * Y ** 2 - 15 * W * X * Y } AF_dct = { x:-10 * Y * V ** 2 - 25 * Y * W ** 2 + 9 * X * V * W, y:15 * X * V ** 2 + 24 * X * W ** 2 - 15 * Y * V * W, v:V, w:W } pmz_CB_lst = list( P * sage_vector( [ p.subs( CB_dct ) for p in p_lst] ) ) pmz_DB_lst = list( P * sage_vector( [ p.subs( DB_dct ) for p in p_lst] ) ) pmz_EB_lst = list( P * sage_vector( [ p.subs( EB_dct ) for p in p_lst] ) ) pmz_AF_lst = list( P * sage_vector( [ p.subs( AF_dct ) for p in p_lst] ) ) # output OrbTools.p( 'f_xyz =', f_xyz_deg_lst, '\n', f_xyz ) 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 ) OrbTools.p( 'pmz_AF_lst =\n', pmz_AF_lst ) # mathematica pmz_lst = [ ( pmz_AB_lst, 'AB' ), ( pmz_CB_lst, 'CB' ), ( pmz_DB_lst, 'DB' ), ( pmz_EB_lst, 'EB' ), ( pmz_AF_lst, 'AF' )] OrbTools.p( 'Mathematica input for ParametricPlot3D:' ) for pmz, AB in pmz_lst: s = 'pmz' + AB + '=' + str( pmz ) s = s.replace( '[', '{' ).replace( ']', '}' ) print( s ) # PovInput for Blum cyclide # pin = PovInput() pin.path = './' + get_time_str() + '_blum_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'] = ( 20, 180, 20 ) pin.shadow = True pin.light_lst = [( 0, 0, -5 ), ( 0, -5, 0 ), ( -5, 0, 0 ), ( 0, 0, 5 ), ( 0, 5, 0 ), ( 5, 0, 0 ), ( -5, -5, -5 ), ( 5, -5, 5 ), ( -5, -5, 5 ), ( 5, -5, -5 ) ] 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 start0 = sage_QQ( 1 ) / 10 # step0=10 step1=15 v0_lst = [ start0 + ( sage_QQ( i ) / 180 ) * sage_pi for i in range( 0, 360, 10 )] v1_lst = [ ( sage_QQ( i ) / 180 ) * sage_pi for i in range( 0, 360, 15 )] v1_lst_F = [ start0 + ( sage_QQ( i ) / 360 ) * sage_pi for i in range( 0, 720, 1 )] v1_lst_WE = [1.8, 2.3, 2.7, 3.1, 3.5, 3.8, 4.134, 4.31, 4.532, 4.7, 4.9, 5.08, 5.25, 5.405, 5.553, 5.7, 5.84] v1_lst_WF = [1.69, 1.87, 2.07, 2.26, 2.5, 2.72, 2.96, 3.2, 3.42, 3.65, 3.81] v1_lst_WD = [ 5.44, 5.56, 5.68, 5.81, 5.95, 6.1, 6.27, 6.474] # [5.01, 5.12, 5.22, 5.32, v1_lst_SA = [6.5]; v1_lst_SE = [5.4]; v1_lst_SB = [5.95]; v1_lst_SF = [2.28]; v1_lst_SC = [4.83]; v1_lst_SD = [5.55]; 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['F'] = ( pmz_AF_lst, 1 ) pin.pmz_dct['WD'] = ( pmz_DB_lst, 0 ) pin.pmz_dct['WE'] = ( pmz_EB_lst, 0 ) pin.pmz_dct['WF'] = ( pmz_AF_lst, 1 ) pin.pmz_dct['SA'] = ( pmz_AB_lst, 0 ) pin.pmz_dct['SB'] = ( pmz_AB_lst, 1 ) pin.pmz_dct['SC'] = ( pmz_CB_lst, 0 ) pin.pmz_dct['SD'] = ( pmz_DB_lst, 0 ) pin.pmz_dct['SE'] = ( pmz_EB_lst, 0 ) pin.pmz_dct['SF'] = ( pmz_AF_lst, 1 ) 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 ) pin.pmz_dct['FF'] = ( pmz_AF_lst, 1 ) pin.curve_dct['A'] = {'step0':v0_lst, 'step1':v1_lst, 'prec':10, 'width':0.05} pin.curve_dct['B'] = {'step0':v0_lst, 'step1':v1_lst, 'prec':10, 'width':0.05} pin.curve_dct['C'] = {'step0':v0_lst, 'step1':v1_lst, 'prec':10, 'width':0.05} pin.curve_dct['D'] = {'step0':v0_lst, 'step1':v1_lst, 'prec':10, 'width':0.05} pin.curve_dct['E'] = {'step0':v0_lst, 'step1':v1_lst, 'prec':10, 'width':0.05} pin.curve_dct['F'] = {'step0':v0_lst, 'step1':v1_lst, 'prec':10, 'width':0.05} pin.curve_dct['WD'] = {'step0':v0_lst, 'step1':v1_lst_WD, 'prec':10, 'width':0.05} pin.curve_dct['WE'] = {'step0':v0_lst, 'step1':v1_lst_WE, 'prec':10, 'width':0.05} pin.curve_dct['WF'] = {'step0':v0_lst, 'step1':v1_lst_WF, 'prec':10, 'width':0.05} pin.curve_dct['SA'] = {'step0':v0_lst, 'step1':v1_lst_SA, 'prec':10, 'width':0.05} pin.curve_dct['SB'] = {'step0':v0_lst, 'step1':v1_lst_SB, 'prec':10, 'width':0.05} pin.curve_dct['SC'] = {'step0':v0_lst, 'step1':v1_lst_SC, 'prec':10, 'width':0.05} pin.curve_dct['SD'] = {'step0':v0_lst, 'step1':v1_lst_SD, 'prec':10, 'width':0.06} pin.curve_dct['SE'] = {'step0':v0_lst, 'step1':v1_lst_SE, 'prec':10, 'width':0.05} pin.curve_dct['SF'] = {'step0':v0_lst, 'step1':v1_lst_SF, 'prec':10, 'width':0.05} 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} pin.curve_dct['FC'] = {'step0':v0_lst, 'step1':v1_lst_F, 'prec':10, 'width':0.01} pin.curve_dct['FD'] = {'step0':v0_lst, 'step1':v1_lst_F, 'prec':10, 'width':0.01} pin.curve_dct['FE'] = {'step0':v0_lst, 'step1':v1_lst_F, 'prec':10, 'width':0.01} pin.curve_dct['FF'] = {'step0':v0_lst, 'step1':v1_lst_F, 'prec':10, 'width':0.01} col_A = rgbt2pov( ( 28, 125, 154, 0 ) ) # blue col_B = rgbt2pov( ( 74, 33, 0, 0 ) ) # brown col_C = rgbt2pov( ( 75, 102, 0, 0 ) ) # green col_E = col_A col_F = col_B col_D = col_C colFF = rgbt2pov( ( 179, 200, 217, 0 ) ) # light blue pin.text_dct['A'] = [True, col_A, 'phong 0.2' ] pin.text_dct['B'] = [True, col_B, 'phong 0.2' ] pin.text_dct['C'] = [True, col_C, 'phong 0.2' ] pin.text_dct['E'] = [True, col_E, 'phong 0.2' ] pin.text_dct['F'] = [True, col_F, 'phong 0.2' ] pin.text_dct['D'] = [True, col_D, 'phong 0.2' ] pin.text_dct['WE'] = [True, col_E, 'phong 0.2' ] pin.text_dct['WF'] = [True, col_F, 'phong 0.2' ] pin.text_dct['WD'] = [True, col_D, 'phong 0.2' ] pin.text_dct['SA'] = [True, col_A, 'phong 0.2' ] pin.text_dct['SB'] = [True, col_B, 'phong 0.2' ] pin.text_dct['SC'] = [True, col_C, 'phong 0.2' ] pin.text_dct['SE'] = [True, col_E, 'phong 0.2' ] pin.text_dct['SF'] = [True, col_F, 'phong 0.2' ] pin.text_dct['SD'] = [True, col_D, 'phong 0.2' ] pin.text_dct['FA'] = [True, colFF, 'phong 0.2' ] pin.text_dct['FB'] = [True, colFF, 'phong 0.2' ] pin.text_dct['FC'] = [True, colFF, 'phong 0.2' ] pin.text_dct['FE'] = [True, colFF, 'phong 0.2' ] pin.text_dct['FF'] = [True, colFF, 'phong 0.2' ] pin.text_dct['FD'] = [True, colFF, 'phong 0.2' ] # raytrace image/animation F_lst = ['FA', 'FB', 'FC'] S_lst = ['SA', 'SB', 'SC', 'SD', 'SE', 'SF'] create_pov( pin, ['A', 'B', 'C'] ) create_pov( pin, ['A', 'B', 'C'] + F_lst ) create_pov( pin, ['WD', 'WE', 'WF'] ) create_pov( pin, ['WD', 'WE', 'WF'] + F_lst ) create_pov( pin, S_lst + F_lst ) # ABC - EFD create_pov( pin, ['A', 'B'] + F_lst ) create_pov( pin, ['E', 'F'] + F_lst )
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 usecase__roman_circles(): ''' We compute circles on a Roman surface. ''' # parametrization of the Roman surface # p_lst = '[ z^2+x^2+y^2, -z*x, -x*y, z*y ]' # we consider the stereographic projection from # S^3 = { x in P^4 | -x0^2+x1^2+x2^2+x3^2+x4^2 = 0 } # where the center of projection is (1:0:0:0:1): # (x0:x1:x2:x3:x4) |---> (x0-x4:x1:x2:x3) # inverse stereographic projection into 3-sphere # s_lst = '[ y0^2+y1^2+y2^2+y3^2, 2*y0*y1, 2*y0*y2, 2*y0*y3, -y0^2+y1^2+y2^2+y3^2 ]' # compose p_lst with s_lst # ring = PolyRing('x,y,z,y0,y1,y2,y3') x, y, z, y0, y1, y2, y3 = ring.gens() p_lst = ring.coerce(p_lst) s_lst = ring.coerce(s_lst) dct = {y0: p_lst[0], y1: p_lst[1], y2: p_lst[2], y3: p_lst[3]} sp_lst = [s.subs(dct) for s in s_lst] NSTools.p('sp_lst =') for sp in sp_lst: NSTools.p('\t\t', sage_factor(sp)) NSTools.p('gcd(sp_lst) =', sage_gcd(sp_lst)) # determine base points # ring = PolyRing('x,y,z', True) sp_lst = ring.coerce(sp_lst) ls = LinearSeries(sp_lst, ring) NSTools.p(ls.get_bp_tree()) # We expect that the basepoints come from the intersection # of the Roman surface with the absolute conic: # A = { (y0:y1:y2:y3) in P^3 | y0=y1^2+y2^2+y3^2 = 0 } # # Circles are the image via p_lst of lines that pass through # complex conjugate points. # ring = PolyRing('x,y,z', False) # reinitialize ring with updated numberfield a0, a1, a2, a3 = ring.root_gens() # a0=(1-I*sqrt(3)) with conjugate a0-1 and minimal polynomial t^2-t+1 # we compute candidate classes of circles # h = Div.new('4e0-e1-e2-e3-e4-e5-e6-e7-e8') div_lst = get_divs(h, 2, -2, False) + get_divs(h, 2, -1, False) NSTools.p('Classes of circles up to permutation:') for c in div_lst: NSTools.p('\t\t', c) # We recover the preimages of circles in the Roman surface # under the map p_lst, by constructing for each candidate # class the corresponding linear series. # 2e0-e1-e2-e3-e4-e5-e6-e7-e8 b = [(a0 - 1, -a0), (-a0, a0 - 1)] b += [(-a0 + 1, a0), (a0, -a0 + 1)] b += [(a0 - 1, a0), (-a0, -a0 + 1)] b += [(-a0 + 1, -a0), (a0, a0 - 1)] bp_tree = BasePointTree() for i in range(6): bp_tree.add('z', b[i], 1) NSTools.p('basepoints =', b) NSTools.p(LinearSeries.get([2], bp_tree)) # e0-e1-e2 b = [(a0 - 1, -a0), (-a0, a0 - 1)] bp_tree = BasePointTree() bp = bp_tree.add('z', b[0], 1) bp = bp_tree.add('z', b[1], 1) NSTools.p('basepoints =', b) NSTools.p(LinearSeries.get([1], bp_tree)) # e0-e3-e4 b = [(-a0 + 1, a0), (a0, -a0 + 1)] bp_tree = BasePointTree() bp = bp_tree.add('z', b[0], 1) bp = bp_tree.add('z', b[1], 1) NSTools.p('basepoints =', b) NSTools.p(LinearSeries.get([1], bp_tree)) # e0-e5-e6 b = [(a0 - 1, a0), (-a0, -a0 + 1)] bp_tree = BasePointTree() bp = bp_tree.add('z', b[0], 1) bp = bp_tree.add('z', b[1], 1) NSTools.p('basepoints =', b) NSTools.p(LinearSeries.get([1], bp_tree)) # e0-e7-e8 b = [(-a0 + 1, -a0), (a0, a0 - 1)] bp_tree = BasePointTree() bp = bp_tree.add('z', b[0], 1) bp = bp_tree.add('z', b[1], 1) NSTools.p('basepoints =', b) NSTools.p(LinearSeries.get([1], bp_tree)) return
def usecase_B2(): ''' We compute the projective isomorphisms between the images of birational maps: f:P2--->X and g:P1xP1--->Y Further explanation of this example can be found in the accompanying arxiv article on projective isomorphisms between rational surfaces. ''' x = [ring('x' + str(i)) for i in range(3)] y = [ring('y' + str(i)) for i in range(4)] z = [ring('z' + str(i)) for i in range(4)] c = [ring('c' + str(i)) for i in range(8)] # the maps f and g are parametrizations of (linear projections of) toric surfaces f = ring( '[x0^6*x1^2,x0*x1^5*x2^2,x1^3*x2^5,x0^5*x2^3+x0^5*x2^3+x0^5*x1*x2^2]') g = ring( '[y0^3*y1^2*y2^5,y1^5*y2^3*y3^2,y0^2*y1^3*y3^5,y0^5*y2^2*y3^3+y0^4*y1*y2^3*y3^2]' ) g = [g[0], g[1] + g[0], g[2], g[3] + g[2]] SETools.p('f =', len(f), f) SETools.p('g =', len(g), g) assert sage_gcd(f) == 1 assert sage_gcd(g) == 1 # we compute the implicit equations of the images of the maps f and g eqf = sage_ideal([z[i] - f[i] for i in range(4)]).elimination_ideal(x).gens() SETools.p('eqf =', eqf) assert len(eqf) == 1 assert eqf[0].degree() == 26 eqg = sage_ideal([z[i] - g[i] for i in range(4)]).elimination_ideal(y).gens() SETools.p('eqg =', eqg) assert len(eqg) == 1 assert eqg[0].degree() == 26 # We compute the coefficient matrix Mf and its kernel Kf Mf = SERing.get_matrix_P2(f) Kf = Mf.right_kernel_matrix().T SETools.p('Mf =', Mf.dimensions(), list(Mf)) SETools.p('Kf =', Kf.dimensions(), list(Kf)) assert (Mf * Kf).is_zero() # we do a basepoint analysis for f and g bf = LinearSeries(SERing.conv(f), PolyRing('x,y,z', True)).get_bp_tree() SETools.p('bf =', bf) bg = LinearSeries(SERing.conv(g), PolyRing('x,y,v,w', True)).get_bp_tree() SETools.p('bg =', bg) ################################################### # Computing compatible reductions of f and g # ################################################### # r0-reduction of f and g hf = LinearSeries.get([8], bf) hg = LinearSeries.get([5, 5], bg) SETools.p(len(hf.pol_lst), SERing.conv(hf.pol_lst)) SETools.p(len(hg.pol_lst), SERing.conv(hg.pol_lst)) assert len(hf.pol_lst) == len(hg.pol_lst) == 16 # r1-reduction of hf and hg hft = BasePointTree() hft.add('x', (0, 0), 2).add('t', (0, 0), 1) hft.add('y', (0, 0), 2).add('t', (0, 0), 1) hft.add('z', (0, 0), 1) hf = LinearSeries.get([5], hft) hgt = BasePointTree(['xv', 'xw', 'yv', 'yw']) hgt.add('xv', (0, 0), 1) hgt.add('xw', (0, 0), 1) hgt.add('yv', (0, 0), 1) hgt.add('yw', (0, 0), 1) hg = LinearSeries.get([3, 3], hgt) SETools.p(len(hf.pol_lst), SERing.conv(hf.pol_lst)) SETools.p(len(hg.pol_lst), SERing.conv(hg.pol_lst)) assert len(hf.pol_lst) == len(hg.pol_lst) == 12 # second r1-reduction of hf and hg hft = BasePointTree() hft.add('x', (0, 0), 1) hft.add('y', (0, 0), 1) hf = LinearSeries.get([2], hft) hg = LinearSeries(['x', 'y', 'v', 'w'], PolyRing('x,y,v,w')) SETools.p(len(hf.pol_lst), SERing.conv(hf.pol_lst)) SETools.p(len(hg.pol_lst), SERing.conv(hg.pol_lst)) assert len(hf.pol_lst) == len(hg.pol_lst) == 4 ################################################### # Computing the projective isomorphisms # ################################################### # we compute maps to P1xP1 from two pencils PolyRing.reset_base_field() bpt = BasePointTree() bpt.add('y', (0, 0), 1) pen1 = SERing.conv(LinearSeries.get([1], bpt).pol_lst) SETools.p('pen1 =', pen1) assert set([x[0], x[1]]) == set(pen1) # thus the first pencil defines a map pen1: (x0:x1:x2) |--> (x0:x1) bpt = BasePointTree() bpt.add('x', (0, 0), 1) pen2 = SERing.conv(LinearSeries.get([1], bpt).pol_lst) SETools.p('pen2 =', pen2) assert set([x[0], x[2]]) == set(pen2) # thus the second pencil defines a map pen2: (x0:x1:x2) |--> (x0:x2) # We find that # pen1 x pen2: P2-->P1xP1, (x0:x1:x2) |--> (x0:x1;x0:x2) and # pen2 x pen1: P2-->P1xP1, (x0:x1:x2) |--> (x0:x2;x0:x1) # we find the following compatible reparametrizations # by composing the maps pen1 x pen2 and pen2 x pen1 # with a parametrized map in the identity component of Aut(P1xP1). r0 = { y[0]: c[0] * x[0] + c[1] * x[1], y[1]: c[2] * x[0] + c[3] * x[1], y[2]: c[4] * x[0] + c[5] * x[2], y[3]: c[6] * x[0] + c[7] * x[2] } r1 = { y[0]: c[0] * x[0] + c[1] * x[2], y[1]: c[2] * x[0] + c[3] * x[2], y[2]: c[4] * x[0] + c[5] * x[1], y[3]: c[6] * x[0] + c[7] * x[1] } # Remark: all substitutions with .subs(...) are performed at the same time. ################################################### # reparametrization r0 # ################################################### # compose g with reparametrization r0 gcd0 = sage_gcd([comp.subs(r0) for comp in g]) assert gcd0 == 1 gr0 = [comp.subs(r0) / gcd0 for comp in g] SETools.p('gr0 =', len(gr0), gcd0, gr0) assert SERing.get_degree(gr0) == 10 assert SERing.get_degree(f) == 8 # find conditions on c so that gr0 has the same basepoints as f eqn0_lst = usecase_B2_helper_bp(gr0) eqn0_lst += [ring('(c0*c3-c1*c2)*(c4*c7-c5*c6)*t-1')] prime0_lst = sage_ideal(eqn0_lst).elimination_ideal( ring('t')).primary_decomposition() SETools.p('eqn0_lst =', len(eqn0_lst), eqn0_lst) for prime0 in prime0_lst: SETools.p('\t', prime0.gens()) sol00 = { c[1]: 0, c[2]: 0, c[5]: 0, c[6]: 0, c[0]: 1, c[4]: 1 } # notice that wlog c0=c4=1 sol01 = { c[0]: 0, c[3]: 0, c[4]: 0, c[7]: 0, c[1]: 1, c[5]: 1 } # notice that wlog c1=c5=1 assert len(prime0_lst) == 2 assert set([gen.subs(sol00) for gen in prime0_lst[0].gens()]) == set([0]) assert set([gen.subs(sol01) for gen in prime0_lst[1].gens()]) == set([0]) # sol00: notice that c3!=0 and c7!=0 gcd00 = sage_gcd([comp.subs(sol00) for comp in gr0]) assert gcd00 == x[0] * x[0] gr00 = [comp.subs(sol00) / gcd00 for comp in gr0] SETools.p('gr00 =', len(gr00), gcd00, gr00) assert SERing.get_degree(gr00) == 8 Mgr00 = SERing.get_matrix_P2(gr00) assert Mgr00.dimensions() == (4, 45) # find conditions for c so that Mgr00 has the same kernel as the matrix of f p00_lst = sage_ideal((Mgr00 * Kf).list() + [ring('c3*c7*t-1')]).elimination_ideal( ring('t')).primary_decomposition() assert [p00.gens() for p00 in p00_lst] == [[2 * c[3] - c[7]]] Mgr00 = Mgr00.subs({c[7]: 2 * c[3]}) SETools.p('Mgr00 =', Mgr00.dimensions(), list(Mgr00)) # found a solution: Mgr00 # sol01: notice that c2!=0 and c6!=0 gcd01 = sage_gcd([comp.subs(sol01) for comp in gr0]) assert gcd01 == x[0] * x[0] gr01 = [comp.subs(sol01) / gcd01 for comp in gr0] SETools.p('gr01 =', len(gr01), gcd01, gr01) assert SERing.get_degree(gr01) == 8 assert [] == sage_ideal((SERing.get_matrix_P2(gr01) * Kf).list() + [ring('c2*c6*t-1')]).elimination_ideal( ring('t')).primary_decomposition() # --> no solution ################################################### # reparametrization r1 # ################################################### # compose g with reparametrization r1 gcd1 = sage_gcd([comp.subs(r1) for comp in g]) assert gcd1 == 1 gr1 = [comp.subs(r1) / gcd1 for comp in g] SETools.p('gr1 =', gcd1, gr1) assert SERing.get_degree(gr1) == 10 assert SERing.get_degree(f) == 8 # find conditions on c so that gr1 has the same basepoints as f eqn1_lst = usecase_B2_helper_bp(gr1) eqn1_lst += [ring('(c0*c3-c1*c2)*(c4*c7-c5*c6)*t-1')] SETools.p('eqn1_lst =', len(eqn1_lst), eqn1_lst) prime1_lst = sage_ideal(eqn1_lst).elimination_ideal( ring('t')).primary_decomposition() for prime1 in prime1_lst: SETools.p('\t', prime1.gens()) sol10 = { c[0]: 0, c[3]: 0, c[5]: 0, c[6]: 0, c[1]: 1, c[4]: 1 } # notice that wlog c1=c4=1 sol11 = { c[1]: 0, c[2]: 0, c[4]: 0, c[7]: 0, c[0]: 1, c[5]: 1 } # notice that wlog c0=c5=1 assert len(prime1_lst) == 2 assert set([gen.subs(sol10) for gen in prime1_lst[0].gens()]) == set([0]) assert set([gen.subs(sol11) for gen in prime1_lst[1].gens()]) == set([0]) # sol10: notice that c2!=0 and c7!=0 gcd10 = sage_gcd([comp.subs(sol10) for comp in gr1]) assert gcd10 == x[0] * x[0] gr10 = [comp.subs(sol10) / gcd10 for comp in gr1] SETools.p('gr10 =', len(gr10), gcd10, gr10) assert SERing.get_degree(gr10) == 8 assert [] == sage_ideal((SERing.get_matrix_P2(gr10) * Kf).list() + [ring('c2*c7*t-1')]).elimination_ideal( ring('t')).primary_decomposition() # --> no solution # sol11: notice that c3!=0 and c6!=0 gcd11 = sage_gcd([comp.subs(sol11) for comp in gr1]) assert gcd11 == x[0] * x[0] gr11 = [comp.subs(sol11) / gcd11 for comp in gr1] SETools.p('gr11 =', len(gr11), gcd11, gr11) assert SERing.get_degree(gr11) == 8 assert [] == sage_ideal((SERing.get_matrix_P2(gr11) * Kf).list() + [ring('c3*c6*t-1')]).elimination_ideal( ring('t')).primary_decomposition() # --> no solution ################################################### # compute extended matrices # ################################################### # Mgr00 is the only case we have to consider as other cases had no solution Mgr = Mgr00 # compute the projective isomorphism between the images of f and g # in terms of parametrized matrix U Ef = sage_matrix(sage_QQ, list(Mf) + list(Kf.T)) Egr = sage_matrix(list(Mgr) + list(Kf.T)) UpI = Egr * ~Ef assert (UpI.submatrix(4, 4) - sage_identity_matrix(41)).is_zero() U = UpI.submatrix(0, 0, 4, 4) U = U / sage_gcd(U.list()) 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)) eqg_sub = [eq.subs({z[i]: Uf[i] for i in range(4)}) for eq in eqg] if eqg_sub != [0]: SETools.p('Uf =', len(Uf), Uf) SETools.p('eqg_sub=', len(eqg_sub), eqg_sub) assert eqg_sub == [0]