# file name: lines.sage # compute the number of lines on a cubic surface # usage: sage lines.sage 2 3 5 7 import sys K = QQ R. = PolynomialRing(K, order = "lex") S. = PolynomialRing(K) # moduli parameters: p1, p2, p3, p4 = map( lambda x: int(x), sys.argv[1:]) # define a cubic form F: F = x^3 + y^3 + z^3 + w^3 + p1*y*z*w + p2*x*z*w + p3*x*y*w + p4*x*y*z J = ideal(F.jacob()) pd = J.dimension() - 1 print print "F =", F print "Projective dimension of singular locus =", pd # Set up a parametrized line L(t) depending on four # indeterminates. The indeterminates a, b, c, d # are parameters for the Grassmanian of lines in P^3, G(2,4): L = lambda t: (1,t,a+b*t,c+d*t) # compose F with L(t): FL = lambda t: F(L(t)) # The ideal J defines the set of points X in an # affine cell of G(2,4) corresponding to lines # which lie on the surface F = 0. This is because # a line which intersects a cubic surface in four # points lies on the cubic surface. J = ideal( FL(0), FL(1), FL(2), FL(3) ) # Compute a Groebner basis of J B = J.groebner_basis() # Check to see on what variables the elements # of the Groebner basis depend: print "Variables on which g[i] depends:" for i in range(0,len(B)): print i, B[i].variables() # Sure enough, the polyonmial g = B[0] is univariate. # It cuts out the projection of the set X # onto the d-axis. Its degree is the # degree of the projection, which is generically # the degree of X. g = B[0]; dg = g.degree(); nf = len(factor(g)) print "degree(g) =", g.degree() print "number of factors of g =", len(factor(g)) if nf == 1 and dg == 27: print "cubic surface has 27 lines" print