Surface-Equivalence is a library for computing projective isomorphisms between rational surfaces that are given in terms of their parametrizations. The main idea is to reduce the computation of such projective isomorphisms to five base cases by modifying the parametric maps such that the components of the resulting maps have lower degree. Our method can be used to compute affine, Euclidean and Moebius isomorphisms between surfaces.
The underlying theory for these for these algorithm was developed by Bert Jüttler, Niels Lubbes and Josef Schicho. We refer to the accompanying article arxiv:2010.08393 for more information.
This library depends on SageMath libraries. For the Gröbner basis computation we use Maple as for our examples it was faster than the one called by Sage by default. In Examples 5 and 6 we access Mathematica. However, our methods can in principle be implemented in any computer algebra system that can compute the Gröbner basis and primary decomposition of ideals in a polynomial ring.
-
Install Sage from SageMath. We assume that
sage
is accessible from your commandline interface. -
Install Maple. We assume for some examples that
maple
is accessible from your commandline interface. -
Install Mathematica. We assume for some examples that
mathematica
is accessible from your commandline interface. -
Install the
surface_equivalence
package:
sage -pip install surface_equivalence
If you do not have root access use the following command instead:
sage -pip install --user surface_equivalence
- We advice to upgrade the
surface_equivalence
package regularly:
sage -pip install --upgrade surface_equivalence
- To execute some usecases type:
sage -python -m surface_equivalence
- For showing which files were installed
or for uninstalling the
surface_equivalence
package, use one of the following commands:
sage -pip show --files surface_equivalence
sage -pip uninstall surface_equivalence
For running the examples below, either copy paste the code into the Sage interface or run them as a Python module:
sage -python -m my_module_name.py
For pasting code into a Sage terminal type %paste
.
See this file
for more example usecases.
See the source code
the io-specification of each function.
The test functions
might be informative for how to call each function.
For an explanation of the underlying theory behind the code we refer to (Example 5, arxiv:2010.08393).
We start by importing the required libraries and initialize parameters.
from surface_equivalence.class_se_ring import ring
from surface_equivalence.class_se_ring import SERing
from surface_equivalence.sage_interface import sage_gcd
from surface_equivalence.sage_interface import sage_matrix
from surface_equivalence.sage_interface import sage_vector
from surface_equivalence.sage_interface import sage_SR
from surface_equivalence.sage_interface import sage_solve
from surface_equivalence.sage_interface import sage_ideal
from surface_equivalence.sage_interface import sage_QQ
from surface_equivalence.sage_interface import sage_identity_matrix
y = ring( 'y0,y1,y2,y3' )
x = ring( 'x0,x1,x2' )
c = ring( 'c0,c1,c2,c3,c4,c5,c6,c7,c8' )
We denote the parametrizations of the two Roman surfaces by f and g.
f = ring( '[x0^2+x1^2+x2^2,x0*x1,x0*x2,x1*x2]' )
g = f
Our goal is to recover matrices U that define the projective automorphisms of the Roman surface. For this purpose we first compute coefficient matrices.
# compatible reparametrizations are linear and indexed by c
r = {x[0]:c[0] * y[0] + c[1] * y[1] + c[2] * y[2], x[1]:c[3] * y[0] + c[4] * y[1] + c[5] * y[2], x[2]:c[6] * y[0] + c[7] * y[1] + c[8] * y[2]}
# compute kernel and coefficient matrix of f
Mf = SERing.get_matrix_P2( f )
Kf = Mf.right_kernel_matrix().T
assert ( Mf * Kf ).is_zero()
# compute the coefficient matrix of g composed with r
gr = [ comp.subs( r ) for comp in g ]
assert sage_gcd( gr ) == 1
assert SERing.get_degree( gr, 'y0,y1,y2' ) == SERing.get_degree( f )
Mgr = SERing.get_matrix_P2( gr, 'y0,y1,y2' )
# output
print( 'f =', f )
print( 'g =', g )
print( 'r =', r )
print( 'Mf =', Mf.dimensions(), list( Mf ), SERing.get_mon_P2( 2 ) )
print( 'Kf.T =', Kf.T.dimensions(), list( Kf.T ) )
print( 'Mgr =', Mgr.dimensions(), list( Mgr ), '\n' + str( Mgr ) )
Output:
f = [x0^2 + x1^2 + x2^2, x0*x1, x0*x2, x1*x2]
g = [x0^2 + x1^2 + x2^2, x0*x1, x0*x2, x1*x2]
r = {x2: c6*y0 + c7*y1 + c8*y2, x1: c3*y0 + c4*y1 + c5*y2, x0: c0*y0 + c1*y1 + c2*y2}
Mf = (4, 6) [(1, 0, 0, 1, 0, 1), (0, 1, 0, 0, 0, 0), (0, 0, 1, 0, 0, 0), (0, 0, 0, 0, 1, 0)] [x0^2, x0*x1, x0*x2, x1^2, x1*x2, x2^2]
Kf.T = (2, 6) [(1, 0, 0, 0, 0, -1), (0, 0, 0, 1, 0, -1)]
Mgr = (4, 6) [(c0^2 + c3^2 + c6^2, 2*c0*c1 + 2*c3*c4 + 2*c6*c7, 2*c0*c2 + 2*c3*c5 + 2*c6*c8, c1^2 + c4^2 + c7^2, 2*c1*c2 + 2*c4*c5 + 2*c7*c8, c2^2 + c5^2 + c8^2), (c0*c3, c1*c3 + c0*c4, c2*c3 + c0*c5, c1*c4, c2*c4 + c1*c5, c2*c5), (c0*c6, c1*c6 + c0*c7, c2*c6 + c0*c8, c1*c7, c2*c7 + c1*c8, c2*c8), (c3*c6, c4*c6 + c3*c7, c5*c6 + c3*c8, c4*c7, c5*c7 + c4*c8, c5*c8)]
[ c0^2 + c3^2 + c6^2 2*c0*c1 + 2*c3*c4 + 2*c6*c7 2*c0*c2 + 2*c3*c5 + 2*c6*c8 c1^2 + c4^2 + c7^2 2*c1*c2 + 2*c4*c5 + 2*c7*c8 c2^2 + c5^2 + c8^2]
[ c0*c3 c1*c3 + c0*c4 c2*c3 + c0*c5 c1*c4 c2*c4 + c1*c5 c2*c5]
[ c0*c6 c1*c6 + c0*c7 c2*c6 + c0*c8 c1*c7 c2*c7 + c1*c8 c2*c8]
[ c3*c6 c4*c6 + c3*c7 c5*c6 + c3*c8 c4*c7 c5*c7 + c4*c8 c5*c8]
We compute all solutions for c such that Mgr*Kf==0
. This takes a few seconds.
ec_lst = ( Mgr * Kf ).list() + [ sage_matrix( SERing.R, 3, 3, c ).det() * ring( 't' ) - 1 ]
pc_lst = sage_ideal( ec_lst ).elimination_ideal( ring( 't' ) ).primary_decomposition()
sol_lst = []
for pc in pc_lst:
s_lst = list( reversed( sorted( pc.gens() ) ) )
s_dct = ring( sage_solve( [sage_SR( comp ) for comp in s_lst], [sage_SR( comp ) for comp in c], solution_dict = True )[0] )
sol_lst += [s_dct]
print( s_lst, '-->', s_dct )
Output:
[c0, c1 - c6, c2, c3, c4, c5 - c6, c7, c8] --> {c3: 0, c8: 0, c4: 0, c5: r1, c0: 0, c1: r1, c6: r1, c7: 0, c2: 0}
[c0, c1 + c6, c2, c3, c4, c5 - c6, c7, c8] --> {c3: 0, c8: 0, c4: 0, c5: r2, c0: 0, c1: -r2, c6: r2, c7: 0, c2: 0}
[c0, c1 - c6, c2, c3, c4, c5 + c6, c7, c8] --> {c3: 0, c8: 0, c4: 0, c5: r3, c0: 0, c1: -r3, c6: -r3, c7: 0, c2: 0}
[c0, c1 + c6, c2, c3, c4, c5 + c6, c7, c8] --> {c3: 0, c8: 0, c4: 0, c5: r4, c0: 0, c1: r4, c6: -r4, c7: 0, c2: 0}
[c0 - c7, c1, c2, c3, c4, c5 - c7, c6, c8] --> {c3: 0, c8: 0, c4: 0, c5: r5, c0: r5, c1: 0, c6: 0, c7: r5, c2: 0}
[c0 + c7, c1, c2, c3, c4, c5 - c7, c6, c8] --> {c3: 0, c8: 0, c4: 0, c5: r6, c0: -r6, c1: 0, c6: 0, c7: r6, c2: 0}
[c0 + c7, c1, c2, c3, c4, c5 + c7, c6, c8] --> {c3: 0, c8: 0, c4: 0, c5: r7, c0: r7, c1: 0, c6: 0, c7: -r7, c2: 0}
[c0 - c7, c1, c2, c3, c4, c5 + c7, c6, c8] --> {c3: 0, c8: 0, c4: 0, c5: r8, c0: -r8, c1: 0, c6: 0, c7: -r8, c2: 0}
[c0 - c8, c1, c2, c3, c4 - c8, c5, c6, c7] --> {c3: 0, c8: r9, c4: r9, c5: 0, c0: r9, c1: 0, c6: 0, c7: 0, c2: 0}
[c0 + c8, c1, c2, c3, c4 - c8, c5, c6, c7] --> {c3: 0, c8: r10, c4: r10, c5: 0, c0: -r10, c1: 0, c6: 0, c7: 0, c2: 0}
[c0 + c8, c1, c2, c3, c4 + c8, c5, c6, c7] --> {c3: 0, c8: r11, c4: -r11, c5: 0, c0: -r11, c1: 0, c6: 0, c7: 0, c2: 0}
[c0 - c8, c1, c2, c3, c4 + c8, c5, c6, c7] --> {c3: 0, c8: r12, c4: -r12, c5: 0, c0: r12, c1: 0, c6: 0, c7: 0, c2: 0}
[c0, c1, c2 - c6, c3, c4 - c6, c5, c7, c8] --> {c3: 0, c8: 0, c4: r13, c5: 0, c0: 0, c1: 0, c6: r13, c7: 0, c2: r13}
[c0, c1, c2 + c6, c3, c4 - c6, c5, c7, c8] --> {c3: 0, c8: 0, c4: -r14, c5: 0, c0: 0, c1: 0, c6: -r14, c7: 0, c2: r14}
[c0, c1 - c8, c2, c3 - c8, c4, c5, c6, c7] --> {c3: r15, c8: r15, c4: 0, c5: 0, c0: 0, c1: r15, c6: 0, c7: 0, c2: 0}
[c0, c1 - c8, c2, c3 + c8, c4, c5, c6, c7] --> {c3: -r16, c8: r16, c4: 0, c5: 0, c0: 0, c1: r16, c6: 0, c7: 0, c2: 0}
[c0, c1 + c8, c2, c3 - c8, c4, c5, c6, c7] --> {c3: r17, c8: r17, c4: 0, c5: 0, c0: 0, c1: -r17, c6: 0, c7: 0, c2: 0}
[c0, c1 + c8, c2, c3 + c8, c4, c5, c6, c7] --> {c3: -r18, c8: r18, c4: 0, c5: 0, c0: 0, c1: -r18, c6: 0, c7: 0, c2: 0}
[c0, c1, c2 - c7, c3 - c7, c4, c5, c6, c8] --> {c3: r19, c8: 0, c4: 0, c5: 0, c0: 0, c1: 0, c6: 0, c7: r19, c2: r19}
[c0, c1, c2 - c7, c3 + c7, c4, c5, c6, c8] --> {c3: r20, c8: 0, c4: 0, c5: 0, c0: 0, c1: 0, c6: 0, c7: -r20, c2: -r20}
[c0, c1, c2 + c7, c3 - c7, c4, c5, c6, c8] --> {c3: r21, c8: 0, c4: 0, c5: 0, c0: 0, c1: 0, c6: 0, c7: r21, c2: -r21}
[c0, c1, c2 + c7, c3 + c7, c4, c5, c6, c8] --> {c3: r22, c8: 0, c4: 0, c5: 0, c0: 0, c1: 0, c6: 0, c7: -r22, c2: r22}
[c0, c1, c2 - c6, c3, c4 + c6, c5, c7, c8] --> {c3: 0, c8: 0, c4: -r23, c5: 0, c0: 0, c1: 0, c6: r23, c7: 0, c2: r23}
[c0, c1, c2 + c6, c3, c4 + c6, c5, c7, c8] --> {c3: 0, c8: 0, c4: r24, c5: 0, c0: 0, c1: 0, c6: -r24, c7: 0, c2: r24}
We testing the outcome below we first compute the ideal of the Roman surface parametrized by g.
eqg = sage_ideal( [y[i] - g[i] for i in range( 4 )] ).elimination_ideal( x ).gens()
print( eqg )
print( str( eqg.subs( {y[0]:1} ) ).replace( 'y1', 'x' ).replace( 'y2', 'y' ).replace( 'y3', 'z' ) )
Output:
[y1^2*y2^2 - y0*y1*y2*y3 + y1^2*y3^2 + y2^2*y3^2]
[x^2*y^2 + x^2*z^2 + y^2*z^2 - x*y*z]
For each of the 24 solutions in sol_lst
obtained, we recover the corresponding projective automorphism U.
Each of the 24 symmetries of the Roman surface corresponds to the symmetries of a tetrahedron.
# type "%paste" for pasting indented code into a Python or Sage terminal
for sol in sol_lst:
# compute the projective isomorphism in terms of parametrized matrix U
Ef = sage_matrix( sage_QQ, list( Mf ) + list( Kf.T ) )
Egr = sage_matrix( list( Mgr.subs( sol ) ) + list( Kf.T ) )
UpI = Egr * ~Ef
assert ( UpI.submatrix( 4, 4 ) - sage_identity_matrix( 2 ) ).is_zero()
U = UpI.submatrix( 0, 0, 4, 4 )
U = U / sage_gcd( U.list() )
assert U.dimensions() == ( 4, 4 )
# verify whether U*f is a parametrization for Y for all (c0,...,c7)
Uf = list( U * sage_vector( f ) )
eqg_sub = [ eq.subs( {y[i]:Uf[i] for i in range( 4 )} ) for eq in eqg ]
assert eqg_sub == [0]
# output U with corresponding solution
print( 'U =', list( U ), ', sol =', sol )
Output:
U = [(1, 0, 0, 0), (0, 0, 0, 1), (0, 1, 0, 0), (0, 0, 1, 0)] , sol = {c3: 0, c8: 0, c4: 0, c5: r1, c0: 0, c1: r1, c6: r1, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, 0, 0, -1), (0, -1, 0, 0), (0, 0, 1, 0)] , sol = {c3: 0, c8: 0, c4: 0, c5: r2, c0: 0, c1: -r2, c6: r2, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, 0, 0, -1), (0, 1, 0, 0), (0, 0, -1, 0)] , sol = {c3: 0, c8: 0, c4: 0, c5: r3, c0: 0, c1: -r3, c6: -r3, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, 0, 0, 1), (0, -1, 0, 0), (0, 0, -1, 0)] , sol = {c3: 0, c8: 0, c4: 0, c5: r4, c0: 0, c1: r4, c6: -r4, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, 0, 1, 0), (0, 1, 0, 0), (0, 0, 0, 1)] , sol = {c3: 0, c8: 0, c4: 0, c5: r5, c0: r5, c1: 0, c6: 0, c7: r5, c2: 0}
U = [(1, 0, 0, 0), (0, 0, -1, 0), (0, -1, 0, 0), (0, 0, 0, 1)] , sol = {c3: 0, c8: 0, c4: 0, c5: r6, c0: -r6, c1: 0, c6: 0, c7: r6, c2: 0}
U = [(1, 0, 0, 0), (0, 0, 1, 0), (0, -1, 0, 0), (0, 0, 0, -1)] , sol = {c3: 0, c8: 0, c4: 0, c5: r7, c0: r7, c1: 0, c6: 0, c7: -r7, c2: 0}
U = [(1, 0, 0, 0), (0, 0, -1, 0), (0, 1, 0, 0), (0, 0, 0, -1)] , sol = {c3: 0, c8: 0, c4: 0, c5: r8, c0: -r8, c1: 0, c6: 0, c7: -r8, c2: 0}
U = [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)] , sol = {c3: 0, c8: r9, c4: r9, c5: 0, c0: r9, c1: 0, c6: 0, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, -1, 0, 0), (0, 0, -1, 0), (0, 0, 0, 1)] , sol = {c3: 0, c8: r10, c4: r10, c5: 0, c0: -r10, c1: 0, c6: 0, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, -1, 0), (0, 0, 0, -1)] , sol = {c3: 0, c8: r11, c4: -r11, c5: 0, c0: -r11, c1: 0, c6: 0, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, -1, 0, 0), (0, 0, 1, 0), (0, 0, 0, -1)] , sol = {c3: 0, c8: r12, c4: -r12, c5: 0, c0: r12, c1: 0, c6: 0, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, 0)] , sol = {c3: 0, c8: 0, c4: r13, c5: 0, c0: 0, c1: 0, c6: r13, c7: 0, c2: r13}
U = [(1, 0, 0, 0), (0, 0, 0, -1), (0, 0, -1, 0), (0, 1, 0, 0)] , sol = {c3: 0, c8: 0, c4: -r14, c5: 0, c0: 0, c1: 0, c6: -r14, c7: 0, c2: r14}
U = [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0)] , sol = {c3: r15, c8: r15, c4: 0, c5: 0, c0: 0, c1: r15, c6: 0, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, -1, 0, 0), (0, 0, 0, 1), (0, 0, -1, 0)] , sol = {c3: -r16, c8: r16, c4: 0, c5: 0, c0: 0, c1: r16, c6: 0, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, -1, 0, 0), (0, 0, 0, -1), (0, 0, 1, 0)] , sol = {c3: r17, c8: r17, c4: 0, c5: 0, c0: 0, c1: -r17, c6: 0, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 0, -1), (0, 0, -1, 0)] , sol = {c3: -r18, c8: r18, c4: 0, c5: 0, c0: 0, c1: -r18, c6: 0, c7: 0, c2: 0}
U = [(1, 0, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1), (0, 1, 0, 0)] , sol = {c3: r19, c8: 0, c4: 0, c5: 0, c0: 0, c1: 0, c6: 0, c7: r19, c2: r19}
U = [(1, 0, 0, 0), (0, 0, -1, 0), (0, 0, 0, 1), (0, -1, 0, 0)] , sol = {c3: r20, c8: 0, c4: 0, c5: 0, c0: 0, c1: 0, c6: 0, c7: -r20, c2: -r20}
U = [(1, 0, 0, 0), (0, 0, -1, 0), (0, 0, 0, -1), (0, 1, 0, 0)] , sol = {c3: r21, c8: 0, c4: 0, c5: 0, c0: 0, c1: 0, c6: 0, c7: r21, c2: -r21}
U = [(1, 0, 0, 0), (0, 0, 1, 0), (0, 0, 0, -1), (0, -1, 0, 0)] , sol = {c3: r22, c8: 0, c4: 0, c5: 0, c0: 0, c1: 0, c6: 0, c7: -r22, c2: r22}
U = [(1, 0, 0, 0), (0, 0, 0, -1), (0, 0, 1, 0), (0, -1, 0, 0)] , sol = {c3: 0, c8: 0, c4: -r23, c5: 0, c0: 0, c1: 0, c6: r23, c7: 0, c2: r23}
U = [(1, 0, 0, 0), (0, 0, 0, 1), (0, 0, -1, 0), (0, -1, 0, 0)] , sol = {c3: 0, c8: 0, c4: r24, c5: 0, c0: 0, c1: 0, c6: -r24, c7: 0, c2: r24}
We compute the projective isomorphisms between two Veronese-Segre surfaces. A Veronese-Segre surface is a projective surface that can be parametrized by a map whose components consists of bihomogeneous polynomials. Thus the domain of this map is the fiber product of the projective line with itself.
We start by importing the required libraries.
from surface_equivalence.class_se_ring import ring
from surface_equivalence.class_se_ring import SERing
from surface_equivalence.sage_interface import sage_gcd
from surface_equivalence.sage_interface import sage_matrix
from surface_equivalence.sage_interface import sage_identity_matrix
from surface_equivalence.sage_interface import sage_vector
from surface_equivalence.sage_interface import sage_ideal
from surface_equivalence.sage_interface import sage_maple
from surface_equivalence.sage_interface import sage_QQ
from surface_equivalence.sage_interface import sage_SR
from surface_equivalence.sage_interface import sage_solve
os.environ['PATH'] += os.pathsep + '/home/niels/Desktop/n/app/maple/link/bin' # edit PATH
Initialize the parameters for the parametrizations f and g. See this file for code for obtaining random parameters.
# bidegree of f
d1, d2 = 2, 2
# coefficient matrix of f
matf = sage_matrix( sage_QQ, ring( '[(3/5, 87, -1/2, 1/4, 0, 1/8, 16/5, 0, 0), (0, 11, -1/9, 44, 0, 0, -1, 0, 1/3), (1/12, -4, 0, 2, -1, 1/4, 0, -3, -1/9), (1/3, 1/4, 1, -4, 1/2, -1, -6, 2, 22)]' ) )
# projective automorphism P^4--->P^4
matU = sage_matrix( sage_QQ, ring( '[( 1, 0, -1, -3 ), ( -1 / 18, -3, 0, 15 / 2 ), ( -1, 0, 13, 1 ), ( -3, -1 / 11, -2, 3 / 23 )]' ) )
# projective automorphism s: P^1xP^1--> P^1xP^1.
L, R = ring( '[-1, 0, -1/87, -1/2] ' ), ring( '[2, 1, 0, 2]' )
y = [ring( 'y' + str( i ) ) for i in range( 4 )]
s = {y[0]:L[0] * y[0] + L[1] * y[1], y[1]:L[2] * y[0] + L[3] * y[1], y[2]:R[0] * y[2] + R[1] * y[3], y[3]:R[2] * y[2] + R[3] * y[3]}
Construct f and g from the parameters.
f = list( matf * sage_vector( SERing.get_mon_P1xP1( d1, d2 ) ) )
g = list( matU * sage_vector( [ comp.subs( s ) for comp in f ] ) )
assert set( SERing.get_bidegree( f ) ) == set( SERing.get_bidegree( g ) )
print( 'f =', f )
print( 'g =', g )
Output:
f = [3/5*y0^2*y2^2 + 1/4*y0*y1*y2^2 + 16/5*y1^2*y2^2 + 87*y0^2*y2*y3 - 1/2*y0^2*y3^2 + 1/8*y0*y1*y3^2, 44*y0*y1*y2^2 - y1^2*y2^2 + 11*y0^2*y2*y3 - 1/9*y0^2*y3^2 + 1/3*y1^2*y3^2, 1/12*y0^2*y2^2 + 2*y0*y1*y2^2 - 4*y0^2*y2*y3 - y0*y1*y2*y3 - 3*y1^2*y2*y3 + 1/4*y0*y1*y3^2 - 1/9*y1^2*y3^2, 1/3*y0^2*y2^2 - 4*y0*y1*y2^2 - 6*y1^2*y2^2 + 1/4*y0^2*y2*y3 + 1/2*y0*y1*y2*y3 + 2*y1^2*y2*y3 + y0^2*y3^2 - y0*y1*y3^2 + 22*y1^2*y3^2]
g = [-54908/37845*y0^2*y2^2 + 18683/870*y0*y1*y2^2 + 106/5*y1^2*y2^2 + 13606207/37845*y0^2*y2*y3 + 17693/870*y0*y1*y2*y3 + 91/5*y1^2*y2*y3 + 56616167/340605*y0^2*y3^2 + 235537/31320*y0*y1*y3^2 - 2794/45*y1^2*y3^2, 1631813/681210*y0^2*y2^2 - 5104643/15660*y0*y1*y2^2 - 1898/45*y1^2*y2^2 - 48113021/340605*y0^2*y2*y3 - 4976393/15660*y0*y1*y2*y3 - 1223/45*y1^2*y2*y3 - 109107127/2724840*y0^2*y3^2 - 5316293/62640*y0*y1*y3^2 + 7243/45*y1^2*y3^2, 161288/37845*y0^2*y2^2 + 37477/870*y0*y1*y2^2 - 46/5*y1^2*y2^2 - 2318353/4205*y0^2*y2*y3 + 4749/290*y0*y1*y2*y3 - 231/5*y1^2*y2*y3 - 92175587/340605*y0^2*y3^2 + 81863/31320*y0*y1*y3^2 - 11/45*y1^2*y3^2, -77790143/9574785*y0^2*y2^2 - 4185757/220110*y0*y1*y2^2 - 13019/1265*y1^2*y2^2 - 9803581988/9574785*y0^2*y2*y3 - 3213247/220110*y0*y1*y2*y3 - 5099/1265*y1^2*y2*y3 - 173517820907/344692260*y0^2*y3^2 - 1521101/344520*y0*y1*y3^2 + 164809/45540*y1^2*y3^2]
We will now recover the projective automorphism defined by the matrix matU
from only f and g.
# Superset of compatible reparametrizations P^1xP^1--->P^1xP^1 consists of
# two families r0 and r1 parametrized by c.
# Notice that r1 flips the factors of P^1xP^1.
y = [ring( 'y' + str( i ) ) for i in range( 4 )]
c = [ring( 'c' + str( i ) ) for i in range( 8 )]
r0 = {y[0]:c[0] * y[0] + c[1] * y[1], y[1]:c[2] * y[0] + c[3] * y[1], y[2]:c[4] * y[2] + c[5] * y[3], y[3]:c[6] * y[2] + c[7] * y[3]}
r1 = {y[2]:c[0] * y[0] + c[1] * y[1], y[3]:c[2] * y[0] + c[3] * y[1], y[0]:c[4] * y[2] + c[5] * y[3], y[1]:c[6] * y[2] + c[7] * y[3]}
We check whether we can find a solution for c with compatible reparametrization r0.
r=r0
# compute kernel and coefficient matrix of f
Mf = SERing.get_matrix_P1xP1( f )
Kf = Mf.right_kernel_matrix().T
assert ( Mf * Kf ).is_zero()
# compute the coefficient matrix of g composed with r
gr = [ comp.subs( r ) for comp in g ]
Mgr = SERing.get_matrix_P1xP1( gr )
assert sage_gcd( gr ) == 1
# compute c such that Mgr*Kf==0
ec_lst = ( Mgr * Kf ).list() + ring( '[(c0*c3-c1*c2)*t-1, (c4*c7-c5*c6)*t-1]' )
sage_maple.eval( 'with(Groebner);' )
sage_maple.eval( 'gb := Basis( ' + str( ec_lst ) + ', plex(' + str( c )[1:-1] + ', t) );' )
gb_lst = ring( sage_maple.eval( 'lprint(gb);' ) )
assert gb_lst != [1]
pc_lst = sage_ideal( gb_lst ).elimination_ideal( ring( 't' ) ).primary_decomposition()
assert len(pc_lst)==1
sol_lst = ring( sage_solve( [sage_SR( comp ) for comp in pc_lst[0].gens()], [sage_SR( comp ) for comp in c], solution_dict = True ) )
sol_lst = [ sol for sol in sol_lst if sol.values() != 8 * [0] ]
assert len(sol_lst)==2
sol = sol_lst[0] # both solutions are equivalent
print( 'sol_lst =', sol_lst )
print( 'sol =', sol )
Output:
sol_lst = [{c3: 2*r3, c4: sqrt(2)*r3, c5: -1/2*sqrt(2)*r3, c0: r3, c1: 0, c6: 0, c7: sqrt(2)*r3, c2: -2/87*r3}, {c3: 2*r4, c4: -sqrt(2)*r4, c5: 1/2*sqrt(2)*r4, c0: r4, c1: 0, c6: 0, c7: -sqrt(2)*r4, c2: -2/87*r4}]
sol = {c3: 2*r3, c4: sqrt(2)*r3, c5: -1/2*sqrt(2)*r3, c0: r3, c1: 0, c6: 0, c7: sqrt(2)*r3, c2: -2/87*r3}
We now compute from the solution sol for c the matrix U, which defines a projective isomorphisms.
Ef = sage_matrix( sage_QQ, list( Mf ) + list( Kf.T ) )
Egr = sage_matrix( list( Mgr.subs( sol ) ) + list( Kf.T ) )
UpI = Egr * ~Ef
U = UpI.submatrix( 0, 0, 4, 4 )
assert ( UpI.submatrix( 4, 4 ) - sage_identity_matrix( len( SERing.get_mon_P1xP1( d1, d2 ) ) - 4 ) ).is_zero()
assert U.dimensions() == ( 4, 4 )
print( 'U =', list( U ), ', sol =', sol )
# we verify that we indeed recovered the projective isomorphism
assert ( matU[0, 0] / U[0, 0] ) * U == matU
We repeat the same procedure for the case r=r1
, but find that there are no solutions in this case.
r = r1
Mf = SERing.get_matrix_P1xP1( f )
Kf = Mf.right_kernel_matrix().T
gr = [ comp.subs( r ) for comp in g ]
Mgr = SERing.get_matrix_P1xP1( gr )
ec_lst = ( Mgr * Kf ).list() + ring( '[(c0*c3-c1*c2)*t-1, (c4*c7-c5*c6)*t-1]' )
sage_maple.eval( 'with(Groebner);' )
sage_maple.eval( 'gb := Basis( ' + str( ec_lst ) + ', plex(' + str( c )[1:-1] + ', t) );' )
gb_lst = ring( sage_maple.eval( 'lprint(gb);' ) )
assert gb_lst == [1]
We compute the projective isomorphisms between two projective surfaces that are adjoint to double ruled quadrics. For an explanation of the code we refer to (Example 10, arxiv:2010.08393).
We start by importing the required libraries and declaring parameters.
from surface_equivalence.class_se_ring import ring
from surface_equivalence.class_se_ring import SERing
from surface_equivalence.sage_interface import sage_gcd
from surface_equivalence.sage_interface import sage_matrix
from surface_equivalence.sage_interface import sage_identity_matrix
from surface_equivalence.sage_interface import sage_vector
from surface_equivalence.sage_interface import sage_ideal
from surface_equivalence.sage_interface import sage_QQ
from surface_equivalence.sage_interface import sage_SR
from surface_equivalence.sage_interface import sage_solve
from surface_equivalence.sage_interface import sage_diff
from linear_series.class_poly_ring import PolyRing
from linear_series.class_base_points import BasePointTree
from linear_series.class_linear_series import LinearSeries
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 )]
We initialize the parametric maps f and g.
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]]
assert sage_gcd( f ) == 1
assert sage_gcd( g ) == 1
We do a a basepoint analysis for f and g.
bf = LinearSeries( SERing.conv( f ), PolyRing( 'x,y,z', True ) ).get_bp_tree()
bg = LinearSeries( SERing.conv( g ), PolyRing( 'x,y,v,w', True ) ).get_bp_tree()
print( 'bf =' + str(bf) )
print( 'bg =' + str(bg) )
Output:
bf =
{ 4, <<x^2*z^6, x^5*y^2*z, x^3*y^5, x*y^2*z^5 + 2*y^3*z^5>>, QQ[x, y, z] }
chart=z, depth=0, mult=2, sol=(0, 0), { 4, <<x^2, x^5*y^2, x^3*y^5, x*y^2 + 2*y^3>>, QQ[x, y] }
chart=t, depth=1, mult=1, sol=(0, 0), { 4, <<x^2, x^5*y^5, x^3*y^6, x*y + 2*y>>, QQ[x, y] }
chart=s, depth=2, mult=1, sol=(0, 0), { 4, <<x, x^9*y^5, x^8*y^6, x*y + 2*y>>, QQ[x, y] }
chart=x, depth=0, mult=3, sol=(0, 0), { 4, <<z^6, y^2*z, y^5, 2*y^3*z^5 + y^2*z^5>>, QQ[y, z] }
chart=t, depth=1, mult=2, sol=(0, 0), { 4, <<z^3, y^2, y^5*z^2, 2*y^3*z^5 + y^2*z^4>>, QQ[y, z] }
chart=t, depth=2, mult=1, sol=(0, 0), { 4, <<z, y^2, y^5*z^5, 2*y^3*z^6 + y^2*z^4>>, QQ[y, z] }
chart=s, depth=3, mult=1, sol=(0, 0), { 4, <<z, y, y^9*z^5, 2*y^8*z^6 + y^5*z^4>>, QQ[y, z] }
chart=s, depth=1, mult=1, sol=(0, 0), { 4, <<y^3*z^6, z, y^2, 2*y^5*z^5 + y^4*z^5>>, QQ[y, z] }
chart=s, depth=2, mult=1, sol=(0, 0), { 4, <<y^8*z^6, z, y, 2*y^9*z^5 + y^8*z^5>>, QQ[y, z] }
chart=y, depth=0, mult=3, sol=(0, 0), { 4, <<x^2*z^6, x^5*z, x^3, x*z^5 + 2*z^5>>, QQ[x, z] }
chart=t, depth=1, mult=2, sol=(0, 0), { 4, <<x^2*z^5, x^5*z^3, x^3, x*z^3 + 2*z^2>>, QQ[x, z] }
chart=s, depth=2, mult=1, sol=(0, 0), { 4, <<x^5*z^5, x^6*z^3, x, x^2*z^3 + 2*z^2>>, QQ[x, z] }
chart=t, depth=3, mult=1, sol=(0, 0), { 4, <<x^5*z^9, x^6*z^8, x, x^2*z^4 + 2*z>>, QQ[x, z] }
bg =
{ 4, <<x^3*y^2*v^5, x^3*y^2*v^5 + y^5*v^3*w^2, x^2*y^3*w^5, x^4*y*v^3*w^2 + x^5*v^2*w^3 + x^2*y^3*w^5>>, QQ[x, y, v, w] }
chart=xv, depth=0, mult=2, sol=(0, 0), { 4, <<y^2, y^5*w^2 + y^2, y^3*w^5, y^3*w^5 + y*w^2 + w^3>>, QQ[y, w] }
chart=t, depth=1, mult=1, sol=(0, 0), { 4, <<y^2, y^5*w^5 + y^2, y^3*w^6, y^3*w^6 + y*w + w>>, QQ[y, w] }
chart=s, depth=2, mult=1, sol=(0, 0), { 4, <<y, y^9*w^5 + y, y^8*w^6, y^8*w^6 + y*w + w>>, QQ[y, w] }
chart=xw, depth=0, mult=2, sol=(0, 0), { 4, <<y^2*v^5, y^5*v^3 + y^2*v^5, y^3, y*v^3 + y^3 + v^2>>, QQ[y, v] }
chart=s, depth=1, mult=1, sol=(0, 0), { 4, <<y^5*v^5, y^5*v^5 + y^6*v^3, y, y^2*v^3 + v^2 + y>>, QQ[y, v] }
chart=t, depth=2, mult=1, sol=(0, 0), { 4, <<y^5*v^9, y^6*v^8 + y^5*v^9, y, y^2*v^4 + y + v>>, QQ[y, v] }
chart=yv, depth=0, mult=2, sol=(0, 0), { 4, <<x^3, x^3 + w^2, x^2*w^5, x^5*w^3 + x^2*w^5 + x^4*w^2>>, QQ[x, w] }
chart=s, depth=1, mult=1, sol=(0, 0), { 4, <<x, w^2 + x, x^5*w^5, x^5*w^5 + x^6*w^3 + x^4*w^2>>, QQ[x, w] }
chart=t, depth=2, mult=1, sol=(0, 0), { 4, <<x, x + w, x^5*w^9, x^6*w^8 + x^5*w^9 + x^4*w^5>>, QQ[x, w] }
chart=yw, depth=0, mult=2, sol=(0, 0), { 4, <<x^3*v^5, x^3*v^5 + v^3, x^2, x^5*v^2 + x^4*v^3 + x^2>>, QQ[x, v] }
chart=t, depth=1, mult=1, sol=(0, 0), { 4, <<x^3*v^6, x^3*v^6 + v, x^2, x^5*v^5 + x^4*v^5 + x^2>>, QQ[x, v] }
chart=s, depth=2, mult=1, sol=(0, 0), { 4, <<x^8*v^6, x^8*v^6 + v, x, x^9*v^5 + x^8*v^5 + x>>, QQ[x, v] }
We compute the implicit equations of the images of the maps f and g for testing purposes. This is not required for the algorithm.
eqf = sage_ideal( [z[i] - f[i] for i in range( 4 )] ).elimination_ideal( x ).gens()
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()
assert len( eqg ) == 1
assert eqg[0].degree() == 26
print( 'eqf =', eqf )
print( 'eqg =', eqg )
Output:
eqf = [z0^12*z1^6*z2^8 + 8192*z0^13*z2^13 - 53248*z0^12*z1*z2^12*z3 + 159744*z0^11*z1^2*z2^11*z3^2 - 292864*z0^10*z1^3*z2^10*z3^3 + 366080*z0^9*z1^4*z2^9*z3^4 - 329472*z0^8*z1^5*z2^8*z3^5 + 219648*z0^7*z1^6*z2^7*z3^6 - 109824*z0^6*z1^7*z2^6*z3^7 + 41184*z0^5*z1^8*z2^5*z3^8 - 11440*z0^4*z1^9*z2^4*z3^9 + 2288*z0^3*z1^10*z2^3*z3^10 - 312*z0^2*z1^11*z2^2*z3^11 + 26*z0*z1^12*z2*z3^12 - z1^13*z3^13]
eqg = [z0^18*z2^8 - 6*z0^17*z1*z2^8 + 15*z0^16*z1^2*z2^8 - 20*z0^15*z1^3*z2^8 + 15*z0^14*z1^4*z2^8 - 6*z0^13*z1^5*z2^8 + z0^12*z1^6*z2^8 + z1^13*z2^13 + 13*z0*z1^12*z2^12*z3 - 13*z1^13*z2^12*z3 + 78*z0^2*z1^11*z2^11*z3^2 - 156*z0*z1^12*z2^11*z3^2 + 78*z1^13*z2^11*z3^2 + 286*z0^3*z1^10*z2^10*z3^3 - 858*z0^2*z1^11*z2^10*z3^3 + 858*z0*z1^12*z2^10*z3^3 - 286*z1^13*z2^10*z3^3 + 715*z0^4*z1^9*z2^9*z3^4 - 2860*z0^3*z1^10*z2^9*z3^4 + 4290*z0^2*z1^11*z2^9*z3^4 - 2860*z0*z1^12*z2^9*z3^4 + 715*z1^13*z2^9*z3^4 + 1287*z0^5*z1^8*z2^8*z3^5 - 6435*z0^4*z1^9*z2^8*z3^5 + 12870*z0^3*z1^10*z2^8*z3^5 - 12870*z0^2*z1^11*z2^8*z3^5 + 6435*z0*z1^12*z2^8*z3^5 - 1287*z1^13*z2^8*z3^5 + 1716*z0^6*z1^7*z2^7*z3^6 - 10296*z0^5*z1^8*z2^7*z3^6 + 25740*z0^4*z1^9*z2^7*z3^6 - 34320*z0^3*z1^10*z2^7*z3^6 + 25740*z0^2*z1^11*z2^7*z3^6 - 10296*z0*z1^12*z2^7*z3^6 + 1716*z1^13*z2^7*z3^6 + 1716*z0^7*z1^6*z2^6*z3^7 - 12012*z0^6*z1^7*z2^6*z3^7 + 36036*z0^5*z1^8*z2^6*z3^7 - 60060*z0^4*z1^9*z2^6*z3^7 + 60060*z0^3*z1^10*z2^6*z3^7 - 36036*z0^2*z1^11*z2^6*z3^7 + 12012*z0*z1^12*z2^6*z3^7 - 1716*z1^13*z2^6*z3^7 + 1287*z0^8*z1^5*z2^5*z3^8 - 10296*z0^7*z1^6*z2^5*z3^8 + 36036*z0^6*z1^7*z2^5*z3^8 - 72072*z0^5*z1^8*z2^5*z3^8 + 90090*z0^4*z1^9*z2^5*z3^8 - 72072*z0^3*z1^10*z2^5*z3^8 + 36036*z0^2*z1^11*z2^5*z3^8 - 10296*z0*z1^12*z2^5*z3^8 + 1287*z1^13*z2^5*z3^8 + 715*z0^9*z1^4*z2^4*z3^9 - 6435*z0^8*z1^5*z2^4*z3^9 + 25740*z0^7*z1^6*z2^4*z3^9 - 60060*z0^6*z1^7*z2^4*z3^9 + 90090*z0^5*z1^8*z2^4*z3^9 - 90090*z0^4*z1^9*z2^4*z3^9 + 60060*z0^3*z1^10*z2^4*z3^9 - 25740*z0^2*z1^11*z2^4*z3^9 + 6435*z0*z1^12*z2^4*z3^9 - 715*z1^13*z2^4*z3^9 + 286*z0^10*z1^3*z2^3*z3^10 - 2860*z0^9*z1^4*z2^3*z3^10 + 12870*z0^8*z1^5*z2^3*z3^10 - 34320*z0^7*z1^6*z2^3*z3^10 + 60060*z0^6*z1^7*z2^3*z3^10 - 72072*z0^5*z1^8*z2^3*z3^10 + 60060*z0^4*z1^9*z2^3*z3^10 - 34320*z0^3*z1^10*z2^3*z3^10 + 12870*z0^2*z1^11*z2^3*z3^10 - 2860*z0*z1^12*z2^3*z3^10 + 286*z1^13*z2^3*z3^10 + 78*z0^11*z1^2*z2^2*z3^11 - 858*z0^10*z1^3*z2^2*z3^11 + 4290*z0^9*z1^4*z2^2*z3^11 - 12870*z0^8*z1^5*z2^2*z3^11 + 25740*z0^7*z1^6*z2^2*z3^11 - 36036*z0^6*z1^7*z2^2*z3^11 + 36036*z0^5*z1^8*z2^2*z3^11 - 25740*z0^4*z1^9*z2^2*z3^11 + 12870*z0^3*z1^10*z2^2*z3^11 - 4290*z0^2*z1^11*z2^2*z3^11 + 858*z0*z1^12*z2^2*z3^11 - 78*z1^13*z2^2*z3^11 + 13*z0^12*z1*z2*z3^12 - 156*z0^11*z1^2*z2*z3^12 + 858*z0^10*z1^3*z2*z3^12 - 2860*z0^9*z1^4*z2*z3^12 + 6435*z0^8*z1^5*z2*z3^12 - 10296*z0^7*z1^6*z2*z3^12 + 12012*z0^6*z1^7*z2*z3^12 - 10296*z0^5*z1^8*z2*z3^12 + 6435*z0^4*z1^9*z2*z3^12 - 2860*z0^3*z1^10*z2*z3^12 + 858*z0^2*z1^11*z2*z3^12 - 156*z0*z1^12*z2*z3^12 + 13*z1^13*z2*z3^12 + z0^13*z3^13 - 13*z0^12*z1*z3^13 + 78*z0^11*z1^2*z3^13 - 286*z0^10*z1^3*z3^13 + 715*z0^9*z1^4*z3^13 - 1287*z0^8*z1^5*z3^13 + 1716*z0^7*z1^6*z3^13 - 1716*z0^6*z1^7*z3^13 + 1287*z0^5*z1^8*z3^13 - 715*z0^4*z1^9*z3^13 + 286*z0^3*z1^10*z3^13 - 78*z0^2*z1^11*z3^13 + 13*z0*z1^12*z3^13 - z1^13*z3^13]
We first compute the r0 reductions of the rational maps f and g.
hf = LinearSeries.get( [8], bf )
hg = LinearSeries.get( [5, 5], bg )
assert len( hf.pol_lst ) == len( hg.pol_lst ) == 16
print( len( hf.pol_lst ), SERing.conv( hf.pol_lst ) )
print( len( hg.pol_lst ), SERing.conv( hg.pol_lst ) )
Output:
usecase_B2(422): 16 [x0*x1^5*x2^2, x0*x1^4*x2^3, x0^2*x1^4*x2^2, x1^3*x2^5, x0*x1^3*x2^4, x0^2*x1^3*x2^3, x0^3*x1^3*x2^2, x0^4*x1^3*x2, x0^2*x1^2*x2^4, x0^3*x1^2*x2^3, x0^4*x1^2*x2^2, x0^5*x1^2*x2, x0^6*x1^2, x0^4*x1*x2^3, x0^5*x1*x2^2, x0^5*x2^3]
usecase_B2(423): 16 [y0^5*y2^2*y3^3, y0^4*y1*y2^3*y3^2, y0^4*y1*y2^2*y3^3, y0^3*y1^2*y2^5, y0^3*y1^2*y2^4*y3, y0^3*y1^2*y2^3*y3^2, y0^3*y1^2*y2^2*y3^3, y0^3*y1^2*y2*y3^4, y0^2*y1^3*y2^4*y3, y0^2*y1^3*y2^3*y3^2, y0^2*y1^3*y2^2*y3^3, y0^2*y1^3*y2*y3^4, y0^2*y1^3*y3^5, y0*y1^4*y2^3*y3^2, y0*y1^4*y2^2*y3^3, y1^5*y2^3*y3^2]
Next we compute the r1 reductions of the above output maps.
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
Output:
12 [x1^3*x2^2, x0*x1^3*x2, x1^2*x2^3, x0*x1^2*x2^2, x0^2*x1^2*x2, x0^3*x1^2, x0*x1*x2^3, x0^2*x1*x2^2, x0^3*x1*x2, x0^4*x1, x0^3*x2^2, x0^4*x2]
12 [y0^3*y2^2*y3, y0^3*y2*y3^2, y0^2*y1*y2^3, y0^2*y1*y2^2*y3, y0^2*y1*y2*y3^2, y0^2*y1*y3^3, y0*y1^2*y2^3, y0*y1^2*y2^2*y3, y0*y1^2*y2*y3^2, y0*y1^2*y3^3, y1^3*y2^2*y3, y1^3*y2*y3^2]
We again compute the r1 reductions of the newly obtained rational maps.
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
Output:
4 [x1*x2, x0*x1, x0*x2, x0^2]
4 [y0, y1, y2, y3]
The above output maps are the (r0,r1,r2)-reductions of the rational maps f and g.
We declare a method which takes as input a map gr with parameters c
and outputs conditions on c such that gr has the same basepoints as f (see bf
):
# use "%paste" to paste this code in a Sage or Python terminal.
def usecase_B2_helper_bp( gr ):
eqn_lst = []
#
# chart=z, depth=0, mult=2, sol=(0, 0), { 4, <<x^2, x^5*y^2, x^3*y^5, x*y^2 + 2*y^3>>, QQ[x, y] }
# chart=t, depth=1, mult=1, sol=(0, 0), { 4, <<x^2, x^5*y^5, x^3*y^6, x*y + 2*y>>, QQ[x, y] }
# chart=s, depth=2, mult=1, sol=(0, 0), { 4, <<x, x^9*y^5, x^8*y^6, x*y + 2*y>>, QQ[x, y] }
#
gr0 = [ comp.subs( {x[0]:1} ) for comp in gr ]
gr0t = [ comp.subs( {x[1]:x[1] * x[2]} ).quo_rem( x[2] ** 2 )[0] for comp in gr0 ]
gr0ts = [ comp.subs( {x[2]:x[1] * x[2]} ).quo_rem( x[1] )[0] for comp in gr0t ]
for a, b in [( 0, 0 ), ( 0, 1 ), ( 1, 0 )]:
eqn_lst += [ sage_diff( comp, x[1], a, x[2], b ).subs( {x[1]:0, x[2]:0} ) for comp in gr0 ]
eqn_lst += [ comp.subs( {x[1]:0, x[2]:0} ) for comp in gr0t ]
eqn_lst += [ comp.subs( {x[1]:0, x[2]:0} ) for comp in gr0ts ]
#
# chart=x, depth=0, mult=3, sol=(0, 0), { 4, <<z^6, y^2*z, y^5, 2*y^3*z^5 + y^2*z^5>>, QQ[y, z] }
# chart=t, depth=1, mult=2, sol=(0, 0), { 4, <<z^3, y^2, y^5*z^2, 2*y^3*z^5 + y^2*z^4>>, QQ[y, z] }
# chart=t, depth=2, mult=1, sol=(0, 0), { 4, <<z, y^2, y^5*z^5, 2*y^3*z^6 + y^2*z^4>>, QQ[y, z] }
# chart=s, depth=3, mult=1, sol=(0, 0), { 4, <<z, y, y^9*z^5, 2*y^8*z^6 + y^5*z^4>>, QQ[y, z] }
# chart=s, depth=1, mult=1, sol=(0, 0), { 4, <<y^3*z^6, z, y^2, 2*y^5*z^5 + y^4*z^5>>, QQ[y, z] }
# chart=s, depth=2, mult=1, sol=(0, 0), { 4, <<y^8*z^6, z, y, 2*y^9*z^5 + y^8*z^5>>, QQ[y, z] }
#
gr1 = [ comp.subs( {x[1]:1} ) for comp in gr ]
gr1t = [ comp.subs( {x[0]:x[0] * x[2]} ).quo_rem( x[2] ** 3 )[0] for comp in gr1 ]
gr1tt = [ comp.subs( {x[0]:x[0] * x[2]} ).quo_rem( x[2] ** 2 )[0] for comp in gr1t ]
gr1tts = [ comp.subs( {x[2]:x[0] * x[2]} ).quo_rem( x[0] ** 1 )[0] for comp in gr1tt ]
gr1s = [ comp.subs( {x[2]:x[0] * x[2]} ).quo_rem( x[0] ** 3 )[0] for comp in gr1 ]
gr1ss = [ comp.subs( {x[2]:x[0] * x[2]} ).quo_rem( x[0] ** 1 )[0] for comp in gr1s ]
for a, b in [( 0, 0 ), ( 0, 1 ), ( 1, 0 ), ( 2, 0 ), ( 1, 1 ), ( 0, 2 )]:
eqn_lst += [ sage_diff( comp, x[0], a, x[2], b ).subs( {x[0]:0, x[2]:0} ) for comp in gr1 ]
for a, b in [( 0, 0 ), ( 0, 1 ), ( 1, 0 )]:
eqn_lst += [ sage_diff( comp, x[0], a, x[2], b ).subs( {x[0]:0, x[2]:0} ) for comp in gr1t ]
eqn_lst += [ comp.subs( {x[0]:0, x[2]:0} ) for comp in gr1tt ]
eqn_lst += [ comp.subs( {x[0]:0, x[2]:0} ) for comp in gr1tts ]
eqn_lst += [ comp.subs( {x[0]:0, x[2]:0} ) for comp in gr1s ]
eqn_lst += [ comp.subs( {x[0]:0, x[2]:0} ) for comp in gr1ss ]
#
# chart=y, depth=0, mult=3, sol=(0, 0), { 4, <<x^2*z^6, x^5*z, x^3, x*z^5 + 2*z^5>>, QQ[x, z] }
# chart=t, depth=1, mult=2, sol=(0, 0), { 4, <<x^2*z^5, x^5*z^3, x^3, x*z^3 + 2*z^2>>, QQ[x, z] }
# chart=s, depth=2, mult=1, sol=(0, 0), { 4, <<x^5*z^5, x^6*z^3, x, x^2*z^3 + 2*z^2>>, QQ[x, z] }
# chart=t, depth=3, mult=1, sol=(0, 0), { 4, <<x^5*z^9, x^6*z^8, x, x^2*z^4 + 2*z>>, QQ[x, z] }
#
gr2 = [ comp.subs( {x[2]:1} ) for comp in gr ]
gr2t = [ comp.subs( {x[0]:x[0] * x[1]} ).quo_rem( x[1] ** 3 )[0] for comp in gr2 ]
gr2ts = [ comp.subs( {x[1]:x[0] * x[1]} ).quo_rem( x[0] ** 2 )[0] for comp in gr2t ]
gr2tst = [ comp.subs( {x[0]:x[0] * x[1]} ).quo_rem( x[1] ** 1 )[0] for comp in gr2ts ]
for a, b in [( 0, 0 ), ( 0, 1 ), ( 1, 0 ), ( 2, 0 ), ( 1, 1 ), ( 0, 2 )]:
eqn_lst += [ sage_diff( comp, x[0], a, x[1], b ).subs( {x[0]:0, x[1]:0} ) for comp in gr2 ]
for a, b in [( 0, 0 ), ( 0, 1 ), ( 1, 0 )]:
eqn_lst += [ sage_diff( comp, x[0], a, x[1], b ).subs( {x[0]:0, x[1]:0} ) for comp in gr2t ]
eqn_lst += [ comp.subs( {x[0]:0, x[1]:0} ) for comp in gr2ts ]
eqn_lst += [ comp.subs( {x[0]:0, x[1]:0} ) for comp in gr2tst ]
eqn_lst = sorted( list( set( eqn_lst ) ) )
assert 'x0' not in str( eqn_lst )
assert 'x1' not in str( eqn_lst )
assert 'x2' not in str( eqn_lst )
return eqn_lst
The superset of the compatible reparametrizations consist of two components r0 and r1.
# 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 )
assert set(pen1) == set(ring('[x1, x0]'))
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 )
assert set(pen2) == set(ring('[x2, x0]'))
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 obtain 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]}
We compute the coefficient matrix Mf for f and its kernel Kf.
Mf = SERing.get_matrix_P2( f )
Kf = Mf.right_kernel_matrix().T
assert ( Mf * Kf ).is_zero()
assert Mf.dimensions() == (4, 45)
assert Kf.dimensions() == (45, 41)
We first consider the reparametrization r0 and we find the coefficient matrix Mgr00.
# 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 ]
print( '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()
print( 'eqn0_lst =', len( eqn0_lst ), eqn0_lst )
for prime0 in prime0_lst: print( '\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]
print( '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]} )
print( '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]
print( '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
Output:
gr0 = 4 1 [c0^3*c2^2*c4^5*x0^10 + 3*c0^2*c1*c2^2*c4^5*x0^9*x1 + 2*c0^3*c2*c3*c4^5*x0^9*x1 + 3*c0*c1^2*c2^2*c4^5*x0^8*x1^2 + 6*c0^2*c1*c2*c3*c4^5*x0^8*x1^2 + c0^3*c3^2*c4^5*x0^8*x1^2 + c1^3*c2^2*c4^5*x0^7*x1^3 + 6*c0*c1^2*c2*c3*c4^5*x0^7*x1^3 + 3*c0^2*c1*c3^2*c4^5*x0^7*x1^3 + 2*c1^3*c2*c3*c4^5*x0^6*x1^4 + 3*c0*c1^2*c3^2*c4^5*x0^6*x1^4 + c1^3*c3^2*c4^5*x0^5*x1^5 + 5*c0^3*c2^2*c4^4*c5*x0^9*x2 + 15*c0^2*c1*c2^2*c4^4*c5*x0^8*x1*x2 + 10*c0^3*c2*c3*c4^4*c5*x0^8*x1*x2 + 15*c0*c1^2*c2^2*c4^4*c5*x0^7*x1^2*x2 + 30*c0^2*c1*c2*c3*c4^4*c5*x0^7*x1^2*x2 + 5*c0^3*c3^2*c4^4*c5*x0^7*x1^2*x2 + 5*c1^3*c2^2*c4^4*c5*x0^6*x1^3*x2 + 30*c0*c1^2*c2*c3*c4^4*c5*x0^6*x1^3*x2 + 15*c0^2*c1*c3^2*c4^4*c5*x0^6*x1^3*x2 + 10*c1^3*c2*c3*c4^4*c5*x0^5*x1^4*x2 + 15*c0*c1^2*c3^2*c4^4*c5*x0^5*x1^4*x2 + 5*c1^3*c3^2*c4^4*c5*x0^4*x1^5*x2 + 10*c0^3*c2^2*c4^3*c5^2*x0^8*x2^2 + 30*c0^2*c1*c2^2*c4^3*c5^2*x0^7*x1*x2^2 + 20*c0^3*c2*c3*c4^3*c5^2*x0^7*x1*x2^2 + 30*c0*c1^2*c2^2*c4^3*c5^2*x0^6*x1^2*x2^2 + 60*c0^2*c1*c2*c3*c4^3*c5^2*x0^6*x1^2*x2^2 + 10*c0^3*c3^2*c4^3*c5^2*x0^6*x1^2*x2^2 + 10*c1^3*c2^2*c4^3*c5^2*x0^5*x1^3*x2^2 + 60*c0*c1^2*c2*c3*c4^3*c5^2*x0^5*x1^3*x2^2 + 30*c0^2*c1*c3^2*c4^3*c5^2*x0^5*x1^3*x2^2 + 20*c1^3*c2*c3*c4^3*c5^2*x0^4*x1^4*x2^2 + 30*c0*c1^2*c3^2*c4^3*c5^2*x0^4*x1^4*x2^2 + 10*c1^3*c3^2*c4^3*c5^2*x0^3*x1^5*x2^2 + 10*c0^3*c2^2*c4^2*c5^3*x0^7*x2^3 + 30*c0^2*c1*c2^2*c4^2*c5^3*x0^6*x1*x2^3 + 20*c0^3*c2*c3*c4^2*c5^3*x0^6*x1*x2^3 + 30*c0*c1^2*c2^2*c4^2*c5^3*x0^5*x1^2*x2^3 + 60*c0^2*c1*c2*c3*c4^2*c5^3*x0^5*x1^2*x2^3 + 10*c0^3*c3^2*c4^2*c5^3*x0^5*x1^2*x2^3 + 10*c1^3*c2^2*c4^2*c5^3*x0^4*x1^3*x2^3 + 60*c0*c1^2*c2*c3*c4^2*c5^3*x0^4*x1^3*x2^3 + 30*c0^2*c1*c3^2*c4^2*c5^3*x0^4*x1^3*x2^3 + 20*c1^3*c2*c3*c4^2*c5^3*x0^3*x1^4*x2^3 + 30*c0*c1^2*c3^2*c4^2*c5^3*x0^3*x1^4*x2^3 + 10*c1^3*c3^2*c4^2*c5^3*x0^2*x1^5*x2^3 + 5*c0^3*c2^2*c4*c5^4*x0^6*x2^4 + 15*c0^2*c1*c2^2*c4*c5^4*x0^5*x1*x2^4 + 10*c0^3*c2*c3*c4*c5^4*x0^5*x1*x2^4 + 15*c0*c1^2*c2^2*c4*c5^4*x0^4*x1^2*x2^4 + 30*c0^2*c1*c2*c3*c4*c5^4*x0^4*x1^2*x2^4 + 5*c0^3*c3^2*c4*c5^4*x0^4*x1^2*x2^4 + 5*c1^3*c2^2*c4*c5^4*x0^3*x1^3*x2^4 + 30*c0*c1^2*c2*c3*c4*c5^4*x0^3*x1^3*x2^4 + 15*c0^2*c1*c3^2*c4*c5^4*x0^3*x1^3*x2^4 + 10*c1^3*c2*c3*c4*c5^4*x0^2*x1^4*x2^4 + 15*c0*c1^2*c3^2*c4*c5^4*x0^2*x1^4*x2^4 + 5*c1^3*c3^2*c4*c5^4*x0*x1^5*x2^4 + c0^3*c2^2*c5^5*x0^5*x2^5 + 3*c0^2*c1*c2^2*c5^5*x0^4*x1*x2^5 + 2*c0^3*c2*c3*c5^5*x0^4*x1*x2^5 + 3*c0*c1^2*c2^2*c5^5*x0^3*x1^2*x2^5 + 6*c0^2*c1*c2*c3*c5^5*x0^3*x1^2*x2^5 + c0^3*c3^2*c5^5*x0^3*x1^2*x2^5 + c1^3*c2^2*c5^5*x0^2*x1^3*x2^5 + 6*c0*c1^2*c2*c3*c5^5*x0^2*x1^3*x2^5 + 3*c0^2*c1*c3^2*c5^5*x0^2*x1^3*x2^5 + 2*c1^3*c2*c3*c5^5*x0*x1^4*x2^5 + 3*c0*c1^2*c3^2*c5^5*x0*x1^4*x2^5 + c1^3*c3^2*c5^5*x1^5*x2^5, c0^3*c2^2*c4^5*x0^10 + c2^5*c4^3*c6^2*x0^10 + 3*c0^2*c1*c2^2*c4^5*x0^9*x1 + 2*c0^3*c2*c3*c4^5*x0^9*x1 + 5*c2^4*c3*c4^3*c6^2*x0^9*x1 + 3*c0*c1^2*c2^2*c4^5*x0^8*x1^2 + 6*c0^2*c1*c2*c3*c4^5*x0^8*x1^2 + c0^3*c3^2*c4^5*x0^8*x1^2 + 10*c2^3*c3^2*c4^3*c6^2*x0^8*x1^2 + c1^3*c2^2*c4^5*x0^7*x1^3 + 6*c0*c1^2*c2*c3*c4^5*x0^7*x1^3 + 3*c0^2*c1*c3^2*c4^5*x0^7*x1^3 + 10*c2^2*c3^3*c4^3*c6^2*x0^7*x1^3 + 2*c1^3*c2*c3*c4^5*x0^6*x1^4 + 3*c0*c1^2*c3^2*c4^5*x0^6*x1^4 + 5*c2*c3^4*c4^3*c6^2*x0^6*x1^4 + c1^3*c3^2*c4^5*x0^5*x1^5 + c3^5*c4^3*c6^2*x0^5*x1^5 + 5*c0^3*c2^2*c4^4*c5*x0^9*x2 + 3*c2^5*c4^2*c5*c6^2*x0^9*x2 + 2*c2^5*c4^3*c6*c7*x0^9*x2 + 15*c0^2*c1*c2^2*c4^4*c5*x0^8*x1*x2 + 10*c0^3*c2*c3*c4^4*c5*x0^8*x1*x2 + 15*c2^4*c3*c4^2*c5*c6^2*x0^8*x1*x2 + 10*c2^4*c3*c4^3*c6*c7*x0^8*x1*x2 + 15*c0*c1^2*c2^2*c4^4*c5*x0^7*x1^2*x2 + 30*c0^2*c1*c2*c3*c4^4*c5*x0^7*x1^2*x2 + 5*c0^3*c3^2*c4^4*c5*x0^7*x1^2*x2 + 30*c2^3*c3^2*c4^2*c5*c6^2*x0^7*x1^2*x2 + 20*c2^3*c3^2*c4^3*c6*c7*x0^7*x1^2*x2 + 5*c1^3*c2^2*c4^4*c5*x0^6*x1^3*x2 + 30*c0*c1^2*c2*c3*c4^4*c5*x0^6*x1^3*x2 + 15*c0^2*c1*c3^2*c4^4*c5*x0^6*x1^3*x2 + 30*c2^2*c3^3*c4^2*c5*c6^2*x0^6*x1^3*x2 + 20*c2^2*c3^3*c4^3*c6*c7*x0^6*x1^3*x2 + 10*c1^3*c2*c3*c4^4*c5*x0^5*x1^4*x2 + 15*c0*c1^2*c3^2*c4^4*c5*x0^5*x1^4*x2 + 15*c2*c3^4*c4^2*c5*c6^2*x0^5*x1^4*x2 + 10*c2*c3^4*c4^3*c6*c7*x0^5*x1^4*x2 + 5*c1^3*c3^2*c4^4*c5*x0^4*x1^5*x2 + 3*c3^5*c4^2*c5*c6^2*x0^4*x1^5*x2 + 2*c3^5*c4^3*c6*c7*x0^4*x1^5*x2 + 10*c0^3*c2^2*c4^3*c5^2*x0^8*x2^2 + 3*c2^5*c4*c5^2*c6^2*x0^8*x2^2 + 6*c2^5*c4^2*c5*c6*c7*x0^8*x2^2 + c2^5*c4^3*c7^2*x0^8*x2^2 + 30*c0^2*c1*c2^2*c4^3*c5^2*x0^7*x1*x2^2 + 20*c0^3*c2*c3*c4^3*c5^2*x0^7*x1*x2^2 + 15*c2^4*c3*c4*c5^2*c6^2*x0^7*x1*x2^2 + 30*c2^4*c3*c4^2*c5*c6*c7*x0^7*x1*x2^2 + 5*c2^4*c3*c4^3*c7^2*x0^7*x1*x2^2 + 30*c0*c1^2*c2^2*c4^3*c5^2*x0^6*x1^2*x2^2 + 60*c0^2*c1*c2*c3*c4^3*c5^2*x0^6*x1^2*x2^2 + 10*c0^3*c3^2*c4^3*c5^2*x0^6*x1^2*x2^2 + 30*c2^3*c3^2*c4*c5^2*c6^2*x0^6*x1^2*x2^2 + 60*c2^3*c3^2*c4^2*c5*c6*c7*x0^6*x1^2*x2^2 + 10*c2^3*c3^2*c4^3*c7^2*x0^6*x1^2*x2^2 + 10*c1^3*c2^2*c4^3*c5^2*x0^5*x1^3*x2^2 + 60*c0*c1^2*c2*c3*c4^3*c5^2*x0^5*x1^3*x2^2 + 30*c0^2*c1*c3^2*c4^3*c5^2*x0^5*x1^3*x2^2 + 30*c2^2*c3^3*c4*c5^2*c6^2*x0^5*x1^3*x2^2 + 60*c2^2*c3^3*c4^2*c5*c6*c7*x0^5*x1^3*x2^2 + 10*c2^2*c3^3*c4^3*c7^2*x0^5*x1^3*x2^2 + 20*c1^3*c2*c3*c4^3*c5^2*x0^4*x1^4*x2^2 + 30*c0*c1^2*c3^2*c4^3*c5^2*x0^4*x1^4*x2^2 + 15*c2*c3^4*c4*c5^2*c6^2*x0^4*x1^4*x2^2 + 30*c2*c3^4*c4^2*c5*c6*c7*x0^4*x1^4*x2^2 + 5*c2*c3^4*c4^3*c7^2*x0^4*x1^4*x2^2 + 10*c1^3*c3^2*c4^3*c5^2*x0^3*x1^5*x2^2 + 3*c3^5*c4*c5^2*c6^2*x0^3*x1^5*x2^2 + 6*c3^5*c4^2*c5*c6*c7*x0^3*x1^5*x2^2 + c3^5*c4^3*c7^2*x0^3*x1^5*x2^2 + 10*c0^3*c2^2*c4^2*c5^3*x0^7*x2^3 + c2^5*c5^3*c6^2*x0^7*x2^3 + 6*c2^5*c4*c5^2*c6*c7*x0^7*x2^3 + 3*c2^5*c4^2*c5*c7^2*x0^7*x2^3 + 30*c0^2*c1*c2^2*c4^2*c5^3*x0^6*x1*x2^3 + 20*c0^3*c2*c3*c4^2*c5^3*x0^6*x1*x2^3 + 5*c2^4*c3*c5^3*c6^2*x0^6*x1*x2^3 + 30*c2^4*c3*c4*c5^2*c6*c7*x0^6*x1*x2^3 + 15*c2^4*c3*c4^2*c5*c7^2*x0^6*x1*x2^3 + 30*c0*c1^2*c2^2*c4^2*c5^3*x0^5*x1^2*x2^3 + 60*c0^2*c1*c2*c3*c4^2*c5^3*x0^5*x1^2*x2^3 + 10*c0^3*c3^2*c4^2*c5^3*x0^5*x1^2*x2^3 + 10*c2^3*c3^2*c5^3*c6^2*x0^5*x1^2*x2^3 + 60*c2^3*c3^2*c4*c5^2*c6*c7*x0^5*x1^2*x2^3 + 30*c2^3*c3^2*c4^2*c5*c7^2*x0^5*x1^2*x2^3 + 10*c1^3*c2^2*c4^2*c5^3*x0^4*x1^3*x2^3 + 60*c0*c1^2*c2*c3*c4^2*c5^3*x0^4*x1^3*x2^3 + 30*c0^2*c1*c3^2*c4^2*c5^3*x0^4*x1^3*x2^3 + 10*c2^2*c3^3*c5^3*c6^2*x0^4*x1^3*x2^3 + 60*c2^2*c3^3*c4*c5^2*c6*c7*x0^4*x1^3*x2^3 + 30*c2^2*c3^3*c4^2*c5*c7^2*x0^4*x1^3*x2^3 + 20*c1^3*c2*c3*c4^2*c5^3*x0^3*x1^4*x2^3 + 30*c0*c1^2*c3^2*c4^2*c5^3*x0^3*x1^4*x2^3 + 5*c2*c3^4*c5^3*c6^2*x0^3*x1^4*x2^3 + 30*c2*c3^4*c4*c5^2*c6*c7*x0^3*x1^4*x2^3 + 15*c2*c3^4*c4^2*c5*c7^2*x0^3*x1^4*x2^3 + 10*c1^3*c3^2*c4^2*c5^3*x0^2*x1^5*x2^3 + c3^5*c5^3*c6^2*x0^2*x1^5*x2^3 + 6*c3^5*c4*c5^2*c6*c7*x0^2*x1^5*x2^3 + 3*c3^5*c4^2*c5*c7^2*x0^2*x1^5*x2^3 + 5*c0^3*c2^2*c4*c5^4*x0^6*x2^4 + 2*c2^5*c5^3*c6*c7*x0^6*x2^4 + 3*c2^5*c4*c5^2*c7^2*x0^6*x2^4 + 15*c0^2*c1*c2^2*c4*c5^4*x0^5*x1*x2^4 + 10*c0^3*c2*c3*c4*c5^4*x0^5*x1*x2^4 + 10*c2^4*c3*c5^3*c6*c7*x0^5*x1*x2^4 + 15*c2^4*c3*c4*c5^2*c7^2*x0^5*x1*x2^4 + 15*c0*c1^2*c2^2*c4*c5^4*x0^4*x1^2*x2^4 + 30*c0^2*c1*c2*c3*c4*c5^4*x0^4*x1^2*x2^4 + 5*c0^3*c3^2*c4*c5^4*x0^4*x1^2*x2^4 + 20*c2^3*c3^2*c5^3*c6*c7*x0^4*x1^2*x2^4 + 30*c2^3*c3^2*c4*c5^2*c7^2*x0^4*x1^2*x2^4 + 5*c1^3*c2^2*c4*c5^4*x0^3*x1^3*x2^4 + 30*c0*c1^2*c2*c3*c4*c5^4*x0^3*x1^3*x2^4 + 15*c0^2*c1*c3^2*c4*c5^4*x0^3*x1^3*x2^4 + 20*c2^2*c3^3*c5^3*c6*c7*x0^3*x1^3*x2^4 + 30*c2^2*c3^3*c4*c5^2*c7^2*x0^3*x1^3*x2^4 + 10*c1^3*c2*c3*c4*c5^4*x0^2*x1^4*x2^4 + 15*c0*c1^2*c3^2*c4*c5^4*x0^2*x1^4*x2^4 + 10*c2*c3^4*c5^3*c6*c7*x0^2*x1^4*x2^4 + 15*c2*c3^4*c4*c5^2*c7^2*x0^2*x1^4*x2^4 + 5*c1^3*c3^2*c4*c5^4*x0*x1^5*x2^4 + 2*c3^5*c5^3*c6*c7*x0*x1^5*x2^4 + 3*c3^5*c4*c5^2*c7^2*x0*x1^5*x2^4 + c0^3*c2^2*c5^5*x0^5*x2^5 + c2^5*c5^3*c7^2*x0^5*x2^5 + 3*c0^2*c1*c2^2*c5^5*x0^4*x1*x2^5 + 2*c0^3*c2*c3*c5^5*x0^4*x1*x2^5 + 5*c2^4*c3*c5^3*c7^2*x0^4*x1*x2^5 + 3*c0*c1^2*c2^2*c5^5*x0^3*x1^2*x2^5 + 6*c0^2*c1*c2*c3*c5^5*x0^3*x1^2*x2^5 + c0^3*c3^2*c5^5*x0^3*x1^2*x2^5 + 10*c2^3*c3^2*c5^3*c7^2*x0^3*x1^2*x2^5 + c1^3*c2^2*c5^5*x0^2*x1^3*x2^5 + 6*c0*c1^2*c2*c3*c5^5*x0^2*x1^3*x2^5 + 3*c0^2*c1*c3^2*c5^5*x0^2*x1^3*x2^5 + 10*c2^2*c3^3*c5^3*c7^2*x0^2*x1^3*x2^5 + 2*c1^3*c2*c3*c5^5*x0*x1^4*x2^5 + 3*c0*c1^2*c3^2*c5^5*x0*x1^4*x2^5 + 5*c2*c3^4*c5^3*c7^2*x0*x1^4*x2^5 + c1^3*c3^2*c5^5*x1^5*x2^5 + c3^5*c5^3*c7^2*x1^5*x2^5, c0^2*c2^3*c6^5*x0^10 + 2*c0*c1*c2^3*c6^5*x0^9*x1 + 3*c0^2*c2^2*c3*c6^5*x0^9*x1 + c1^2*c2^3*c6^5*x0^8*x1^2 + 6*c0*c1*c2^2*c3*c6^5*x0^8*x1^2 + 3*c0^2*c2*c3^2*c6^5*x0^8*x1^2 + 3*c1^2*c2^2*c3*c6^5*x0^7*x1^3 + 6*c0*c1*c2*c3^2*c6^5*x0^7*x1^3 + c0^2*c3^3*c6^5*x0^7*x1^3 + 3*c1^2*c2*c3^2*c6^5*x0^6*x1^4 + 2*c0*c1*c3^3*c6^5*x0^6*x1^4 + c1^2*c3^3*c6^5*x0^5*x1^5 + 5*c0^2*c2^3*c6^4*c7*x0^9*x2 + 10*c0*c1*c2^3*c6^4*c7*x0^8*x1*x2 + 15*c0^2*c2^2*c3*c6^4*c7*x0^8*x1*x2 + 5*c1^2*c2^3*c6^4*c7*x0^7*x1^2*x2 + 30*c0*c1*c2^2*c3*c6^4*c7*x0^7*x1^2*x2 + 15*c0^2*c2*c3^2*c6^4*c7*x0^7*x1^2*x2 + 15*c1^2*c2^2*c3*c6^4*c7*x0^6*x1^3*x2 + 30*c0*c1*c2*c3^2*c6^4*c7*x0^6*x1^3*x2 + 5*c0^2*c3^3*c6^4*c7*x0^6*x1^3*x2 + 15*c1^2*c2*c3^2*c6^4*c7*x0^5*x1^4*x2 + 10*c0*c1*c3^3*c6^4*c7*x0^5*x1^4*x2 + 5*c1^2*c3^3*c6^4*c7*x0^4*x1^5*x2 + 10*c0^2*c2^3*c6^3*c7^2*x0^8*x2^2 + 20*c0*c1*c2^3*c6^3*c7^2*x0^7*x1*x2^2 + 30*c0^2*c2^2*c3*c6^3*c7^2*x0^7*x1*x2^2 + 10*c1^2*c2^3*c6^3*c7^2*x0^6*x1^2*x2^2 + 60*c0*c1*c2^2*c3*c6^3*c7^2*x0^6*x1^2*x2^2 + 30*c0^2*c2*c3^2*c6^3*c7^2*x0^6*x1^2*x2^2 + 30*c1^2*c2^2*c3*c6^3*c7^2*x0^5*x1^3*x2^2 + 60*c0*c1*c2*c3^2*c6^3*c7^2*x0^5*x1^3*x2^2 + 10*c0^2*c3^3*c6^3*c7^2*x0^5*x1^3*x2^2 + 30*c1^2*c2*c3^2*c6^3*c7^2*x0^4*x1^4*x2^2 + 20*c0*c1*c3^3*c6^3*c7^2*x0^4*x1^4*x2^2 + 10*c1^2*c3^3*c6^3*c7^2*x0^3*x1^5*x2^2 + 10*c0^2*c2^3*c6^2*c7^3*x0^7*x2^3 + 20*c0*c1*c2^3*c6^2*c7^3*x0^6*x1*x2^3 + 30*c0^2*c2^2*c3*c6^2*c7^3*x0^6*x1*x2^3 + 10*c1^2*c2^3*c6^2*c7^3*x0^5*x1^2*x2^3 + 60*c0*c1*c2^2*c3*c6^2*c7^3*x0^5*x1^2*x2^3 + 30*c0^2*c2*c3^2*c6^2*c7^3*x0^5*x1^2*x2^3 + 30*c1^2*c2^2*c3*c6^2*c7^3*x0^4*x1^3*x2^3 + 60*c0*c1*c2*c3^2*c6^2*c7^3*x0^4*x1^3*x2^3 + 10*c0^2*c3^3*c6^2*c7^3*x0^4*x1^3*x2^3 + 30*c1^2*c2*c3^2*c6^2*c7^3*x0^3*x1^4*x2^3 + 20*c0*c1*c3^3*c6^2*c7^3*x0^3*x1^4*x2^3 + 10*c1^2*c3^3*c6^2*c7^3*x0^2*x1^5*x2^3 + 5*c0^2*c2^3*c6*c7^4*x0^6*x2^4 + 10*c0*c1*c2^3*c6*c7^4*x0^5*x1*x2^4 + 15*c0^2*c2^2*c3*c6*c7^4*x0^5*x1*x2^4 + 5*c1^2*c2^3*c6*c7^4*x0^4*x1^2*x2^4 + 30*c0*c1*c2^2*c3*c6*c7^4*x0^4*x1^2*x2^4 + 15*c0^2*c2*c3^2*c6*c7^4*x0^4*x1^2*x2^4 + 15*c1^2*c2^2*c3*c6*c7^4*x0^3*x1^3*x2^4 + 30*c0*c1*c2*c3^2*c6*c7^4*x0^3*x1^3*x2^4 + 5*c0^2*c3^3*c6*c7^4*x0^3*x1^3*x2^4 + 15*c1^2*c2*c3^2*c6*c7^4*x0^2*x1^4*x2^4 + 10*c0*c1*c3^3*c6*c7^4*x0^2*x1^4*x2^4 + 5*c1^2*c3^3*c6*c7^4*x0*x1^5*x2^4 + c0^2*c2^3*c7^5*x0^5*x2^5 + 2*c0*c1*c2^3*c7^5*x0^4*x1*x2^5 + 3*c0^2*c2^2*c3*c7^5*x0^4*x1*x2^5 + c1^2*c2^3*c7^5*x0^3*x1^2*x2^5 + 6*c0*c1*c2^2*c3*c7^5*x0^3*x1^2*x2^5 + 3*c0^2*c2*c3^2*c7^5*x0^3*x1^2*x2^5 + 3*c1^2*c2^2*c3*c7^5*x0^2*x1^3*x2^5 + 6*c0*c1*c2*c3^2*c7^5*x0^2*x1^3*x2^5 + c0^2*c3^3*c7^5*x0^2*x1^3*x2^5 + 3*c1^2*c2*c3^2*c7^5*x0*x1^4*x2^5 + 2*c0*c1*c3^3*c7^5*x0*x1^4*x2^5 + c1^2*c3^3*c7^5*x1^5*x2^5, c0^4*c2*c4^3*c6^2*x0^10 + c0^5*c4^2*c6^3*x0^10 + c0^2*c2^3*c6^5*x0^10 + 4*c0^3*c1*c2*c4^3*c6^2*x0^9*x1 + c0^4*c3*c4^3*c6^2*x0^9*x1 + 5*c0^4*c1*c4^2*c6^3*x0^9*x1 + 2*c0*c1*c2^3*c6^5*x0^9*x1 + 3*c0^2*c2^2*c3*c6^5*x0^9*x1 + 6*c0^2*c1^2*c2*c4^3*c6^2*x0^8*x1^2 + 4*c0^3*c1*c3*c4^3*c6^2*x0^8*x1^2 + 10*c0^3*c1^2*c4^2*c6^3*x0^8*x1^2 + c1^2*c2^3*c6^5*x0^8*x1^2 + 6*c0*c1*c2^2*c3*c6^5*x0^8*x1^2 + 3*c0^2*c2*c3^2*c6^5*x0^8*x1^2 + 4*c0*c1^3*c2*c4^3*c6^2*x0^7*x1^3 + 6*c0^2*c1^2*c3*c4^3*c6^2*x0^7*x1^3 + 10*c0^2*c1^3*c4^2*c6^3*x0^7*x1^3 + 3*c1^2*c2^2*c3*c6^5*x0^7*x1^3 + 6*c0*c1*c2*c3^2*c6^5*x0^7*x1^3 + c0^2*c3^3*c6^5*x0^7*x1^3 + c1^4*c2*c4^3*c6^2*x0^6*x1^4 + 4*c0*c1^3*c3*c4^3*c6^2*x0^6*x1^4 + 5*c0*c1^4*c4^2*c6^3*x0^6*x1^4 + 3*c1^2*c2*c3^2*c6^5*x0^6*x1^4 + 2*c0*c1*c3^3*c6^5*x0^6*x1^4 + c1^4*c3*c4^3*c6^2*x0^5*x1^5 + c1^5*c4^2*c6^3*x0^5*x1^5 + c1^2*c3^3*c6^5*x0^5*x1^5 + 3*c0^4*c2*c4^2*c5*c6^2*x0^9*x2 + 2*c0^5*c4*c5*c6^3*x0^9*x2 + 2*c0^4*c2*c4^3*c6*c7*x0^9*x2 + 3*c0^5*c4^2*c6^2*c7*x0^9*x2 + 5*c0^2*c2^3*c6^4*c7*x0^9*x2 + 12*c0^3*c1*c2*c4^2*c5*c6^2*x0^8*x1*x2 + 3*c0^4*c3*c4^2*c5*c6^2*x0^8*x1*x2 + 10*c0^4*c1*c4*c5*c6^3*x0^8*x1*x2 + 8*c0^3*c1*c2*c4^3*c6*c7*x0^8*x1*x2 + 2*c0^4*c3*c4^3*c6*c7*x0^8*x1*x2 + 15*c0^4*c1*c4^2*c6^2*c7*x0^8*x1*x2 + 10*c0*c1*c2^3*c6^4*c7*x0^8*x1*x2 + 15*c0^2*c2^2*c3*c6^4*c7*x0^8*x1*x2 + 18*c0^2*c1^2*c2*c4^2*c5*c6^2*x0^7*x1^2*x2 + 12*c0^3*c1*c3*c4^2*c5*c6^2*x0^7*x1^2*x2 + 20*c0^3*c1^2*c4*c5*c6^3*x0^7*x1^2*x2 + 12*c0^2*c1^2*c2*c4^3*c6*c7*x0^7*x1^2*x2 + 8*c0^3*c1*c3*c4^3*c6*c7*x0^7*x1^2*x2 + 30*c0^3*c1^2*c4^2*c6^2*c7*x0^7*x1^2*x2 + 5*c1^2*c2^3*c6^4*c7*x0^7*x1^2*x2 + 30*c0*c1*c2^2*c3*c6^4*c7*x0^7*x1^2*x2 + 15*c0^2*c2*c3^2*c6^4*c7*x0^7*x1^2*x2 + 12*c0*c1^3*c2*c4^2*c5*c6^2*x0^6*x1^3*x2 + 18*c0^2*c1^2*c3*c4^2*c5*c6^2*x0^6*x1^3*x2 + 20*c0^2*c1^3*c4*c5*c6^3*x0^6*x1^3*x2 + 8*c0*c1^3*c2*c4^3*c6*c7*x0^6*x1^3*x2 + 12*c0^2*c1^2*c3*c4^3*c6*c7*x0^6*x1^3*x2 + 30*c0^2*c1^3*c4^2*c6^2*c7*x0^6*x1^3*x2 + 15*c1^2*c2^2*c3*c6^4*c7*x0^6*x1^3*x2 + 30*c0*c1*c2*c3^2*c6^4*c7*x0^6*x1^3*x2 + 5*c0^2*c3^3*c6^4*c7*x0^6*x1^3*x2 + 3*c1^4*c2*c4^2*c5*c6^2*x0^5*x1^4*x2 + 12*c0*c1^3*c3*c4^2*c5*c6^2*x0^5*x1^4*x2 + 10*c0*c1^4*c4*c5*c6^3*x0^5*x1^4*x2 + 2*c1^4*c2*c4^3*c6*c7*x0^5*x1^4*x2 + 8*c0*c1^3*c3*c4^3*c6*c7*x0^5*x1^4*x2 + 15*c0*c1^4*c4^2*c6^2*c7*x0^5*x1^4*x2 + 15*c1^2*c2*c3^2*c6^4*c7*x0^5*x1^4*x2 + 10*c0*c1*c3^3*c6^4*c7*x0^5*x1^4*x2 + 3*c1^4*c3*c4^2*c5*c6^2*x0^4*x1^5*x2 + 2*c1^5*c4*c5*c6^3*x0^4*x1^5*x2 + 2*c1^4*c3*c4^3*c6*c7*x0^4*x1^5*x2 + 3*c1^5*c4^2*c6^2*c7*x0^4*x1^5*x2 + 5*c1^2*c3^3*c6^4*c7*x0^4*x1^5*x2 + 3*c0^4*c2*c4*c5^2*c6^2*x0^8*x2^2 + c0^5*c5^2*c6^3*x0^8*x2^2 + 6*c0^4*c2*c4^2*c5*c6*c7*x0^8*x2^2 + 6*c0^5*c4*c5*c6^2*c7*x0^8*x2^2 + c0^4*c2*c4^3*c7^2*x0^8*x2^2 + 3*c0^5*c4^2*c6*c7^2*x0^8*x2^2 + 10*c0^2*c2^3*c6^3*c7^2*x0^8*x2^2 + 12*c0^3*c1*c2*c4*c5^2*c6^2*x0^7*x1*x2^2 + 3*c0^4*c3*c4*c5^2*c6^2*x0^7*x1*x2^2 + 5*c0^4*c1*c5^2*c6^3*x0^7*x1*x2^2 + 24*c0^3*c1*c2*c4^2*c5*c6*c7*x0^7*x1*x2^2 + 6*c0^4*c3*c4^2*c5*c6*c7*x0^7*x1*x2^2 + 30*c0^4*c1*c4*c5*c6^2*c7*x0^7*x1*x2^2 + 4*c0^3*c1*c2*c4^3*c7^2*x0^7*x1*x2^2 + c0^4*c3*c4^3*c7^2*x0^7*x1*x2^2 + 15*c0^4*c1*c4^2*c6*c7^2*x0^7*x1*x2^2 + 20*c0*c1*c2^3*c6^3*c7^2*x0^7*x1*x2^2 + 30*c0^2*c2^2*c3*c6^3*c7^2*x0^7*x1*x2^2 + 18*c0^2*c1^2*c2*c4*c5^2*c6^2*x0^6*x1^2*x2^2 + 12*c0^3*c1*c3*c4*c5^2*c6^2*x0^6*x1^2*x2^2 + 10*c0^3*c1^2*c5^2*c6^3*x0^6*x1^2*x2^2 + 36*c0^2*c1^2*c2*c4^2*c5*c6*c7*x0^6*x1^2*x2^2 + 24*c0^3*c1*c3*c4^2*c5*c6*c7*x0^6*x1^2*x2^2 + 60*c0^3*c1^2*c4*c5*c6^2*c7*x0^6*x1^2*x2^2 + 6*c0^2*c1^2*c2*c4^3*c7^2*x0^6*x1^2*x2^2 + 4*c0^3*c1*c3*c4^3*c7^2*x0^6*x1^2*x2^2 + 30*c0^3*c1^2*c4^2*c6*c7^2*x0^6*x1^2*x2^2 + 10*c1^2*c2^3*c6^3*c7^2*x0^6*x1^2*x2^2 + 60*c0*c1*c2^2*c3*c6^3*c7^2*x0^6*x1^2*x2^2 + 30*c0^2*c2*c3^2*c6^3*c7^2*x0^6*x1^2*x2^2 + 12*c0*c1^3*c2*c4*c5^2*c6^2*x0^5*x1^3*x2^2 + 18*c0^2*c1^2*c3*c4*c5^2*c6^2*x0^5*x1^3*x2^2 + 10*c0^2*c1^3*c5^2*c6^3*x0^5*x1^3*x2^2 + 24*c0*c1^3*c2*c4^2*c5*c6*c7*x0^5*x1^3*x2^2 + 36*c0^2*c1^2*c3*c4^2*c5*c6*c7*x0^5*x1^3*x2^2 + 60*c0^2*c1^3*c4*c5*c6^2*c7*x0^5*x1^3*x2^2 + 4*c0*c1^3*c2*c4^3*c7^2*x0^5*x1^3*x2^2 + 6*c0^2*c1^2*c3*c4^3*c7^2*x0^5*x1^3*x2^2 + 30*c0^2*c1^3*c4^2*c6*c7^2*x0^5*x1^3*x2^2 + 30*c1^2*c2^2*c3*c6^3*c7^2*x0^5*x1^3*x2^2 + 60*c0*c1*c2*c3^2*c6^3*c7^2*x0^5*x1^3*x2^2 + 10*c0^2*c3^3*c6^3*c7^2*x0^5*x1^3*x2^2 + 3*c1^4*c2*c4*c5^2*c6^2*x0^4*x1^4*x2^2 + 12*c0*c1^3*c3*c4*c5^2*c6^2*x0^4*x1^4*x2^2 + 5*c0*c1^4*c5^2*c6^3*x0^4*x1^4*x2^2 + 6*c1^4*c2*c4^2*c5*c6*c7*x0^4*x1^4*x2^2 + 24*c0*c1^3*c3*c4^2*c5*c6*c7*x0^4*x1^4*x2^2 + 30*c0*c1^4*c4*c5*c6^2*c7*x0^4*x1^4*x2^2 + c1^4*c2*c4^3*c7^2*x0^4*x1^4*x2^2 + 4*c0*c1^3*c3*c4^3*c7^2*x0^4*x1^4*x2^2 + 15*c0*c1^4*c4^2*c6*c7^2*x0^4*x1^4*x2^2 + 30*c1^2*c2*c3^2*c6^3*c7^2*x0^4*x1^4*x2^2 + 20*c0*c1*c3^3*c6^3*c7^2*x0^4*x1^4*x2^2 + 3*c1^4*c3*c4*c5^2*c6^2*x0^3*x1^5*x2^2 + c1^5*c5^2*c6^3*x0^3*x1^5*x2^2 + 6*c1^4*c3*c4^2*c5*c6*c7*x0^3*x1^5*x2^2 + 6*c1^5*c4*c5*c6^2*c7*x0^3*x1^5*x2^2 + c1^4*c3*c4^3*c7^2*x0^3*x1^5*x2^2 + 3*c1^5*c4^2*c6*c7^2*x0^3*x1^5*x2^2 + 10*c1^2*c3^3*c6^3*c7^2*x0^3*x1^5*x2^2 + c0^4*c2*c5^3*c6^2*x0^7*x2^3 + 6*c0^4*c2*c4*c5^2*c6*c7*x0^7*x2^3 + 3*c0^5*c5^2*c6^2*c7*x0^7*x2^3 + 3*c0^4*c2*c4^2*c5*c7^2*x0^7*x2^3 + 6*c0^5*c4*c5*c6*c7^2*x0^7*x2^3 + c0^5*c4^2*c7^3*x0^7*x2^3 + 10*c0^2*c2^3*c6^2*c7^3*x0^7*x2^3 + 4*c0^3*c1*c2*c5^3*c6^2*x0^6*x1*x2^3 + c0^4*c3*c5^3*c6^2*x0^6*x1*x2^3 + 24*c0^3*c1*c2*c4*c5^2*c6*c7*x0^6*x1*x2^3 + 6*c0^4*c3*c4*c5^2*c6*c7*x0^6*x1*x2^3 + 15*c0^4*c1*c5^2*c6^2*c7*x0^6*x1*x2^3 + 12*c0^3*c1*c2*c4^2*c5*c7^2*x0^6*x1*x2^3 + 3*c0^4*c3*c4^2*c5*c7^2*x0^6*x1*x2^3 + 30*c0^4*c1*c4*c5*c6*c7^2*x0^6*x1*x2^3 + 5*c0^4*c1*c4^2*c7^3*x0^6*x1*x2^3 + 20*c0*c1*c2^3*c6^2*c7^3*x0^6*x1*x2^3 + 30*c0^2*c2^2*c3*c6^2*c7^3*x0^6*x1*x2^3 + 6*c0^2*c1^2*c2*c5^3*c6^2*x0^5*x1^2*x2^3 + 4*c0^3*c1*c3*c5^3*c6^2*x0^5*x1^2*x2^3 + 36*c0^2*c1^2*c2*c4*c5^2*c6*c7*x0^5*x1^2*x2^3 + 24*c0^3*c1*c3*c4*c5^2*c6*c7*x0^5*x1^2*x2^3 + 30*c0^3*c1^2*c5^2*c6^2*c7*x0^5*x1^2*x2^3 + 18*c0^2*c1^2*c2*c4^2*c5*c7^2*x0^5*x1^2*x2^3 + 12*c0^3*c1*c3*c4^2*c5*c7^2*x0^5*x1^2*x2^3 + 60*c0^3*c1^2*c4*c5*c6*c7^2*x0^5*x1^2*x2^3 + 10*c0^3*c1^2*c4^2*c7^3*x0^5*x1^2*x2^3 + 10*c1^2*c2^3*c6^2*c7^3*x0^5*x1^2*x2^3 + 60*c0*c1*c2^2*c3*c6^2*c7^3*x0^5*x1^2*x2^3 + 30*c0^2*c2*c3^2*c6^2*c7^3*x0^5*x1^2*x2^3 + 4*c0*c1^3*c2*c5^3*c6^2*x0^4*x1^3*x2^3 + 6*c0^2*c1^2*c3*c5^3*c6^2*x0^4*x1^3*x2^3 + 24*c0*c1^3*c2*c4*c5^2*c6*c7*x0^4*x1^3*x2^3 + 36*c0^2*c1^2*c3*c4*c5^2*c6*c7*x0^4*x1^3*x2^3 + 30*c0^2*c1^3*c5^2*c6^2*c7*x0^4*x1^3*x2^3 + 12*c0*c1^3*c2*c4^2*c5*c7^2*x0^4*x1^3*x2^3 + 18*c0^2*c1^2*c3*c4^2*c5*c7^2*x0^4*x1^3*x2^3 + 60*c0^2*c1^3*c4*c5*c6*c7^2*x0^4*x1^3*x2^3 + 10*c0^2*c1^3*c4^2*c7^3*x0^4*x1^3*x2^3 + 30*c1^2*c2^2*c3*c6^2*c7^3*x0^4*x1^3*x2^3 + 60*c0*c1*c2*c3^2*c6^2*c7^3*x0^4*x1^3*x2^3 + 10*c0^2*c3^3*c6^2*c7^3*x0^4*x1^3*x2^3 + c1^4*c2*c5^3*c6^2*x0^3*x1^4*x2^3 + 4*c0*c1^3*c3*c5^3*c6^2*x0^3*x1^4*x2^3 + 6*c1^4*c2*c4*c5^2*c6*c7*x0^3*x1^4*x2^3 + 24*c0*c1^3*c3*c4*c5^2*c6*c7*x0^3*x1^4*x2^3 + 15*c0*c1^4*c5^2*c6^2*c7*x0^3*x1^4*x2^3 + 3*c1^4*c2*c4^2*c5*c7^2*x0^3*x1^4*x2^3 + 12*c0*c1^3*c3*c4^2*c5*c7^2*x0^3*x1^4*x2^3 + 30*c0*c1^4*c4*c5*c6*c7^2*x0^3*x1^4*x2^3 + 5*c0*c1^4*c4^2*c7^3*x0^3*x1^4*x2^3 + 30*c1^2*c2*c3^2*c6^2*c7^3*x0^3*x1^4*x2^3 + 20*c0*c1*c3^3*c6^2*c7^3*x0^3*x1^4*x2^3 + c1^4*c3*c5^3*c6^2*x0^2*x1^5*x2^3 + 6*c1^4*c3*c4*c5^2*c6*c7*x0^2*x1^5*x2^3 + 3*c1^5*c5^2*c6^2*c7*x0^2*x1^5*x2^3 + 3*c1^4*c3*c4^2*c5*c7^2*x0^2*x1^5*x2^3 + 6*c1^5*c4*c5*c6*c7^2*x0^2*x1^5*x2^3 + c1^5*c4^2*c7^3*x0^2*x1^5*x2^3 + 10*c1^2*c3^3*c6^2*c7^3*x0^2*x1^5*x2^3 + 2*c0^4*c2*c5^3*c6*c7*x0^6*x2^4 + 3*c0^4*c2*c4*c5^2*c7^2*x0^6*x2^4 + 3*c0^5*c5^2*c6*c7^2*x0^6*x2^4 + 2*c0^5*c4*c5*c7^3*x0^6*x2^4 + 5*c0^2*c2^3*c6*c7^4*x0^6*x2^4 + 8*c0^3*c1*c2*c5^3*c6*c7*x0^5*x1*x2^4 + 2*c0^4*c3*c5^3*c6*c7*x0^5*x1*x2^4 + 12*c0^3*c1*c2*c4*c5^2*c7^2*x0^5*x1*x2^4 + 3*c0^4*c3*c4*c5^2*c7^2*x0^5*x1*x2^4 + 15*c0^4*c1*c5^2*c6*c7^2*x0^5*x1*x2^4 + 10*c0^4*c1*c4*c5*c7^3*x0^5*x1*x2^4 + 10*c0*c1*c2^3*c6*c7^4*x0^5*x1*x2^4 + 15*c0^2*c2^2*c3*c6*c7^4*x0^5*x1*x2^4 + 12*c0^2*c1^2*c2*c5^3*c6*c7*x0^4*x1^2*x2^4 + 8*c0^3*c1*c3*c5^3*c6*c7*x0^4*x1^2*x2^4 + 18*c0^2*c1^2*c2*c4*c5^2*c7^2*x0^4*x1^2*x2^4 + 12*c0^3*c1*c3*c4*c5^2*c7^2*x0^4*x1^2*x2^4 + 30*c0^3*c1^2*c5^2*c6*c7^2*x0^4*x1^2*x2^4 + 20*c0^3*c1^2*c4*c5*c7^3*x0^4*x1^2*x2^4 + 5*c1^2*c2^3*c6*c7^4*x0^4*x1^2*x2^4 + 30*c0*c1*c2^2*c3*c6*c7^4*x0^4*x1^2*x2^4 + 15*c0^2*c2*c3^2*c6*c7^4*x0^4*x1^2*x2^4 + 8*c0*c1^3*c2*c5^3*c6*c7*x0^3*x1^3*x2^4 + 12*c0^2*c1^2*c3*c5^3*c6*c7*x0^3*x1^3*x2^4 + 12*c0*c1^3*c2*c4*c5^2*c7^2*x0^3*x1^3*x2^4 + 18*c0^2*c1^2*c3*c4*c5^2*c7^2*x0^3*x1^3*x2^4 + 30*c0^2*c1^3*c5^2*c6*c7^2*x0^3*x1^3*x2^4 + 20*c0^2*c1^3*c4*c5*c7^3*x0^3*x1^3*x2^4 + 15*c1^2*c2^2*c3*c6*c7^4*x0^3*x1^3*x2^4 + 30*c0*c1*c2*c3^2*c6*c7^4*x0^3*x1^3*x2^4 + 5*c0^2*c3^3*c6*c7^4*x0^3*x1^3*x2^4 + 2*c1^4*c2*c5^3*c6*c7*x0^2*x1^4*x2^4 + 8*c0*c1^3*c3*c5^3*c6*c7*x0^2*x1^4*x2^4 + 3*c1^4*c2*c4*c5^2*c7^2*x0^2*x1^4*x2^4 + 12*c0*c1^3*c3*c4*c5^2*c7^2*x0^2*x1^4*x2^4 + 15*c0*c1^4*c5^2*c6*c7^2*x0^2*x1^4*x2^4 + 10*c0*c1^4*c4*c5*c7^3*x0^2*x1^4*x2^4 + 15*c1^2*c2*c3^2*c6*c7^4*x0^2*x1^4*x2^4 + 10*c0*c1*c3^3*c6*c7^4*x0^2*x1^4*x2^4 + 2*c1^4*c3*c5^3*c6*c7*x0*x1^5*x2^4 + 3*c1^4*c3*c4*c5^2*c7^2*x0*x1^5*x2^4 + 3*c1^5*c5^2*c6*c7^2*x0*x1^5*x2^4 + 2*c1^5*c4*c5*c7^3*x0*x1^5*x2^4 + 5*c1^2*c3^3*c6*c7^4*x0*x1^5*x2^4 + c0^4*c2*c5^3*c7^2*x0^5*x2^5 + c0^5*c5^2*c7^3*x0^5*x2^5 + c0^2*c2^3*c7^5*x0^5*x2^5 + 4*c0^3*c1*c2*c5^3*c7^2*x0^4*x1*x2^5 + c0^4*c3*c5^3*c7^2*x0^4*x1*x2^5 + 5*c0^4*c1*c5^2*c7^3*x0^4*x1*x2^5 + 2*c0*c1*c2^3*c7^5*x0^4*x1*x2^5 + 3*c0^2*c2^2*c3*c7^5*x0^4*x1*x2^5 + 6*c0^2*c1^2*c2*c5^3*c7^2*x0^3*x1^2*x2^5 + 4*c0^3*c1*c3*c5^3*c7^2*x0^3*x1^2*x2^5 + 10*c0^3*c1^2*c5^2*c7^3*x0^3*x1^2*x2^5 + c1^2*c2^3*c7^5*x0^3*x1^2*x2^5 + 6*c0*c1*c2^2*c3*c7^5*x0^3*x1^2*x2^5 + 3*c0^2*c2*c3^2*c7^5*x0^3*x1^2*x2^5 + 4*c0*c1^3*c2*c5^3*c7^2*x0^2*x1^3*x2^5 + 6*c0^2*c1^2*c3*c5^3*c7^2*x0^2*x1^3*x2^5 + 10*c0^2*c1^3*c5^2*c7^3*x0^2*x1^3*x2^5 + 3*c1^2*c2^2*c3*c7^5*x0^2*x1^3*x2^5 + 6*c0*c1*c2*c3^2*c7^5*x0^2*x1^3*x2^5 + c0^2*c3^3*c7^5*x0^2*x1^3*x2^5 + c1^4*c2*c5^3*c7^2*x0*x1^4*x2^5 + 4*c0*c1^3*c3*c5^3*c7^2*x0*x1^4*x2^5 + 5*c0*c1^4*c5^2*c7^3*x0*x1^4*x2^5 + 3*c1^2*c2*c3^2*c7^5*x0*x1^4*x2^5 + 2*c0*c1*c3^3*c7^5*x0*x1^4*x2^5 + c1^4*c3*c5^3*c7^2*x1^5*x2^5 + c1^5*c5^2*c7^3*x1^5*x2^5 + c1^2*c3^3*c7^5*x1^5*x2^5]
eqn0_lst = 26 [0, c1^2*c3^3*c7^5, 10*c0^2*c2^3*c6^3*c7^2, c1^4*c3*c5^3*c7^2 + c1^5*c5^2*c7^3 + c1^2*c3^3*c7^5, 10*c0*c1*c2^3*c6^4*c7 + 15*c0^2*c2^2*c3*c6^4*c7, 5*c0^2*c2^3*c6^4*c7, 2*c0*c1*c2^3*c6^5 + 3*c0^2*c2^2*c3*c6^5, c0^2*c2^3*c6^5, 3*c0^4*c2*c4*c5^2*c6^2 + c0^5*c5^2*c6^3 + 6*c0^4*c2*c4^2*c5*c6*c7 + 6*c0^5*c4*c5*c6^2*c7 + c0^4*c2*c4^3*c7^2 + 3*c0^5*c4^2*c6*c7^2 + 10*c0^2*c2^3*c6^3*c7^2, 12*c0^3*c1*c2*c4^2*c5*c6^2 + 3*c0^4*c3*c4^2*c5*c6^2 + 10*c0^4*c1*c4*c5*c6^3 + 8*c0^3*c1*c2*c4^3*c6*c7 + 2*c0^4*c3*c4^3*c6*c7 + 15*c0^4*c1*c4^2*c6^2*c7 + 10*c0*c1*c2^3*c6^4*c7 + 15*c0^2*c2^2*c3*c6^4*c7, 3*c0^4*c2*c4^2*c5*c6^2 + 2*c0^5*c4*c5*c6^3 + 2*c0^4*c2*c4^3*c6*c7 + 3*c0^5*c4^2*c6^2*c7 + 5*c0^2*c2^3*c6^4*c7, 4*c0^3*c1*c2*c4^3*c6^2 + c0^4*c3*c4^3*c6^2 + 5*c0^4*c1*c4^2*c6^3 + 2*c0*c1*c2^3*c6^5 + 3*c0^2*c2^2*c3*c6^5, c0^4*c2*c4^3*c6^2 + c0^5*c4^2*c6^3 + c0^2*c2^3*c6^5, c1^3*c3^2*c5^5, c1^3*c3^2*c5^5 + c3^5*c5^3*c7^2, 10*c0^3*c2^2*c4^3*c5^2, 10*c0^3*c2^2*c4^3*c5^2 + 3*c2^5*c4*c5^2*c6^2 + 6*c2^5*c4^2*c5*c6*c7 + c2^5*c4^3*c7^2, 15*c0^2*c1*c2^2*c4^4*c5 + 10*c0^3*c2*c3*c4^4*c5, 15*c0^2*c1*c2^2*c4^4*c5 + 10*c0^3*c2*c3*c4^4*c5 + 15*c2^4*c3*c4^2*c5*c6^2 + 10*c2^4*c3*c4^3*c6*c7, 5*c0^3*c2^2*c4^4*c5, 5*c0^3*c2^2*c4^4*c5 + 3*c2^5*c4^2*c5*c6^2 + 2*c2^5*c4^3*c6*c7, 3*c0^2*c1*c2^2*c4^5 + 2*c0^3*c2*c3*c4^5, 3*c0^2*c1*c2^2*c4^5 + 2*c0^3*c2*c3*c4^5 + 5*c2^4*c3*c4^3*c6^2, c0^3*c2^2*c4^5, c0^3*c2^2*c4^5 + c2^5*c4^3*c6^2, t*c1*c2*c5*c6 - t*c0*c3*c5*c6 - t*c1*c2*c4*c7 + t*c0*c3*c4*c7 - 1]
[c6, c2, c1^2, c5^3]
[c4, c0, c3^2, c7^4, c3*c7^3, c3*c5*c7^2 + c1*c7^3]
gr00 = 4 x0^2 [c3^2*x0^6*x1^2, c3^5*c7^2*x0*x1^5*x2^2 + c3^2*x0^6*x1^2, c3^3*c7^5*x1^3*x2^5, c3^3*c7^5*x1^3*x2^5 + c3*c7^2*x0^5*x1*x2^2 + c7^3*x0^5*x2^3]
Mgr00 = (4, 45) [(0, 0, 0, c3^2, 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, c3^2, 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, 4*c3^7, 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, 32*c3^8, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 4*c3^3, 8*c3^3, 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, 32*c3^8, 0, 0, 0)]
We do the same for the reparametrization r1, but here we do not find a solution.
# 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 ]
print( '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' ) ]
print( 'eqn1_lst =', len( eqn1_lst ), eqn1_lst )
prime1_lst = sage_ideal( eqn1_lst ).elimination_ideal( ring( 't' ) ).primary_decomposition()
for prime1 in prime1_lst: print( '\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]
print( '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 <