代数几何

曲线上的点数

在Sage中,如何计算有限域上椭圆曲线上的点?

在素数有限域上,包括小步巨步方法和SEA(Schoof-Elkies-Atkin)算法(由Christophe Doche和Sylvain Duqune在Pari中实现)。参考手册中的一个例子:

sage: E = EllipticCurve(GF(10007),[1,2,3,4,5])
sage: E.cardinality()
10076

该命令 E.points() 将返回有理点的实际列表。

如何计算有限域上的平面曲线上的点?这个 rational_points 命令通过简单的枚举算法生成点。以下是该语法的一个示例:

sage: x,y,z = PolynomialRing(GF(5), 3, 'xyz').gens()
sage: C = Curve(y^2*z^7 - x^9 - x*z^8); C
Projective Plane Curve over Finite Field of size 5 defined by -x^9 + y^2*z^7 - x*z^8
sage: C.rational_points()
[(0 : 0 : 1), (0 : 1 : 0), (2 : 2 : 1), (2 : 3 : 1), (3 : 1 : 1), (3 : 4 : 1)]
sage: C.rational_points(algorithm="bn")
[(0 : 0 : 1), (0 : 1 : 0), (2 : 2 : 1), (2 : 3 : 1), (3 : 1 : 1), (3 : 4 : 1)]

该选项 algorithm="bn 使用Sage的单一接口并调用 brnoeth 包裹。

下面是使用Sage的另一个示例 rational_points 适用于克莱恩的四次方 \(GF(8)\)

sage: x, y, z = PolynomialRing(GF(8,'a'), 3, 'xyz').gens()
sage: f = x^3*y+y^3*z+x*z^3
sage: C = Curve(f); C
Projective Plane Curve over Finite Field in a of size 2^3 defined by x^3*y + y^3*z + x*z^3
sage: C.rational_points()
[(0 : 0 : 1),
 (0 : 1 : 0),
 (1 : 0 : 0),
 (1 : a : 1),
 (1 : a^2 : 1),
 (1 : a^2 + a : 1),
 (a : 1 : 1),
 (a : a^2 : 1),
 (a : a^2 + 1 : 1),
 (a + 1 : a + 1 : 1),
 (a + 1 : a^2 : 1),
 (a + 1 : a^2 + a + 1 : 1),
 (a^2 : 1 : 1),
 (a^2 : a^2 + a : 1),
 (a^2 : a^2 + a + 1 : 1),
 (a^2 + 1 : a + 1 : 1),
 (a^2 + 1 : a^2 + 1 : 1),
 (a^2 + 1 : a^2 + a : 1),
 (a^2 + a : 1 : 1),
 (a^2 + a : a : 1),
 (a^2 + a : a + 1 : 1),
 (a^2 + a + 1 : a : 1),
 (a^2 + a + 1 : a^2 + 1 : 1),
 (a^2 + a + 1 : a^2 + a + 1 : 1)]

其他方法

  • 对于平面曲线,您可以使用单数 closed_points 指挥部。投入是正在消失的理想 \(I\) 曲线的长度 \(X\) 在一圈 \(2\) 变数 \(F[x,y]\) 。这个 closed_points 命令返回一个素数理想列表(每个Gröbner基),对应于(不同的仿射闭点) \(V(I)\) 。下面是一个例子:

    sage: singular_console()
                         SINGULAR                             /  Development
     A Computer Algebra System for Polynomial Computations   /   version 3-0-1
                                                           0<
         by: G.-M. Greuel, G. Pfister, H. Schoenemann        \   October 2005
    FB Mathematik der Universitaet, D-67653 Kaiserslautern    \
    // ** executing /home/wdj/sagefiles/sage-0.9.4/local/LIB/.singularrc
    > LIB "brnoeth.lib";
    > ring s = 2,(x,y),lp;
    > ideal I = x4+x,y4+y;
    > list L = closed_points(I);
    > L;
    [1]:
       _[1] = y
       _[2] = x
    [2]:
       _[1] = y
       _[2] = x+1
    [3]:
       _[1] = y
       _[2] = x2+x+1
    [4]:
       _[1] = y+1
       _[2] = x
    [5]:
       _[1] = y+1
       _[2] = x+1
    [6]:
       _[1] = y+1
       _[2] = x2+x+1
    [7]:
       _[1] = y2+y+1
       _[2] = x+1
    [8]:
       _[1] = y2+y+1
       _[2] = x
    [9]:
       _[1] = y2+y+1
       _[2] = x+y
    [10]:
       _[1] = y2+y+1
       _[2] = x+y+1
    > Auf Wiedersehen.
    
    sage: singular.lib("brnoeth.lib")
    sage: s = singular.ring(2,'(x,y)','lp')
    sage: I = singular.ideal('x^4+x', 'y^4+y')
    sage: L = singular.closed_points(I)
    sage: # Here you have all the points :
    sage: L       # random
    [1]:
       _[1]=y+1
       _[2]=x+1
    ...
    sage: l=[L[k].sage() for k in [1..10]]; len(l) # there are 10 points
    10
    sage: r=sorted(l[0].ring().gens()); r
    [y, x]
    sage: r in [t.gens() for t in l] #  one of them is given by [y,x]
    True
    
  • 计算有理点的另一种方法是使用奇异点 NSplaces 指挥部。这是克莱因的四重奏 \(GF(8)\) 这样做:

    sage: singular.LIB("brnoeth.lib")
    sage: s = singular.ring(2,'(x,y)','lp')
    ...
    sage: f = singular.poly('x3y+y3+x')
    ...
    sage: klein1 = f.Adj_div(); print(klein1)
    [1]:
       [1]:
          //   coefficients: ZZ/2
    //   number of vars : 2
    //        block   1 : ordering lp
    //                  : names    x y
    //        block   2 : ordering C
    ...
    sage: # define a curve X = {f = 0} over GF(2)
    sage: klein2 = singular.NSplaces(3,klein1)
    sage: print(singular.eval('extcurve(3,%s)'%klein2.name()))
    Total number of rational places : NrRatPl = 23
    ...
    sage: klein3 = singular.extcurve(3, klein2)
    

    上面我们定义了一条曲线 \(X = \{f = 0\}\) 完毕 \(GF(8)\) 单数。

    sage: print(klein1)
    [1]:
       [1]:
          //   coefficients: ZZ/2
    //   number of vars : 2
    //        block   1 : ordering lp
    //                  : names    x y
    //        block   2 : ordering C
       [2]:
          //   coefficients: ZZ/2
    //   number of vars : 3
    //        block   1 : ordering lp
    //                  : names    x y z
    //        block   2 : ordering C
    [2]:
       4,3
    [3]:
       [1]:
          1,1
       [2]:
          1,2
    [4]:
       0
    [5]:
       [1]:
          [1]:
             //   coefficients: ZZ/2
    //   number of vars : 3
    //        block   1 : ordering ls
    //                  : names    x y t
    //        block   2 : ordering C
          [2]:
             1,1
    sage: print(klein1[3])
    [1]:
       1,1
    [2]:
       1,2
    

    对于学位的位置 \(3\)

    sage: print(klein2[3])
    [1]:
       1,1
    [2]:
       1,2
    [3]:
       3,1
    [4]:
       3,2
    [5]:
       3,3
    [6]:
       3,4
    [7]:
       3,5
    [8]:
       3,6
    [9]:
       3,7
    

    下面的每个点都是一对:(度,点指数)。

    sage: print(klein3[3])
    [1]:
       1,1
    [2]:
       1,2
    [3]:
       3,1
    [4]:
       3,2
    [5]:
       3,3
    [6]:
       3,4
    [7]:
       3,5
    [8]:
       3,6
    [9]:
       3,7
    

    要真正得到……的分数 \(X(GF(8))\)

    sage: R = klein3[1][5]
    sage: R.set_ring()
    sage: singular("POINTS;")
    [1]:
       [1]:
          0
       [2]:
          1
       [3]:
          0
    [2]:
       [1]:
          1
       [2]:
          0
       [3]:
          0
    ...
    

    加上其他21个(省略)。总共有几个 \(23\) 理性的观点。

利用奇异的Riemann-Roch空间

求除数的Riemann-Roch空间的基 \(D\) 在田野上的曲线上 \(F\) ,可以使用Sage的包装纸 riemann_roch_basis 斯兰奇对布里尔·诺太算法的实现。请注意,此包装当前仅在以下情况下起作用 \(F\) 是素数和除数 \(D\) 在有理点上得到支持。以下是如何使用的示例 riemann_roch_basis 以及如何使用单数本身来帮助理解包装器的工作原理。

  • vbl.使用 riemann_roch_basis

    sage: x, y, z = PolynomialRing(GF(5), 3, 'xyz').gens()
    sage: f = x^7 + y^7 + z^7
    sage: X = Curve(f); pts = X.rational_points()
    sage: D = X.divisor([ (3, pts[0]), (-1,pts[1]), (10, pts[5]) ])
    sage: X.riemann_roch_basis(D)
    [(-2*x + y)/(x + y), (-x + z)/(x + y)]
    
  • Using Singular's BrillNoether command (for details see the section Brill-Noether in the Singular online documentation (http://www.singular.uni-kl.de/Manual/html/sing_960.htm and the paper {CF}):

    sage: singular.LIB('brnoeth.lib')
    sage: _ = singular.ring(5,'(x,y)','lp')
    sage: print(singular.eval("list X = Adj_div(-x5+y2+x);"))
    Computing affine singular points ...
    Computing all points at infinity ...
    Computing affine singular places ...
    Computing singular places at infinity ...
    Computing non-singular places at infinity ...
    Adjunction divisor computed successfully
    <BLANKLINE>
    The genus of the curve is 2
    sage: print(singular.eval("X = NSplaces(1,X);"))
    Computing non-singular affine places of degree 1 ...
    sage: print(singular("X[3];"))
    [1]:
       1,1
    [2]:
       1,2
    [3]:
       1,3
    [4]:
       1,4
    [5]:
       1,5
    [6]:
       1,6
    

    上述列表中每对的第一个整数是度数 d 一点也不假。第二个整数是该点在环X的列表点中的索引 [5] [d] [1] 。请注意,后一列表的顺序在每次运行算法时都不同,例如 11 在上面的列表中,每次指的是不同的理性点。除数是通过定义一个列表来给出的 G 与X长度相同的整数 [3] 这样,如果 k -第X个条目 [3] 是 di ,然后是 k -第3个条目 G 除数的重数是 i -环X的列表点中的第一点 [5] [d] [1] 。让我们继续定义一个12次的“随机”因子,并计算它的Riemann-Roch空间的基:

    sage: singular.eval("intvec G = 4,4,4,0,0,0;")
    ''
    sage: singular.eval("def R = X[1][2];")
    ''
    sage: singular.eval("setring R;")
    ''
    sage: print(singular.eval("list LG = BrillNoether(G,X);"))
    Forms of degree 6 :
    28
    <BLANKLINE>
    Vector basis successfully computed
    <BLANKLINE>
    

AG代码

Sage可以计算AG代码 \(C=C_X(D,E)\) 通过调用Single的BrillNoether来计算Riemann Roch空间的一个基 \(L(D)=L_X(D)\) 。除了曲线之外 \(X\) 和除数 \(D\) ,则还必须指定求值因子 \(E\)

请注意,此部分自包装器以来未更新 riemann_roch_basis 已经修好了。有关如何正确定义单数的除数的信息,请参阅上文 BrillNoether 指挥部。

这里有一个例子,它计算相关AG代码的生成矩阵。这一次我们使用单数 AGCode_L 指挥部。

sage: singular.LIB('brnoeth.lib')
sage: singular.eval("ring s = 2,(x,y),lp;")
''
sage: print(singular.eval("list HC = Adj_div(x3+y2+y);"))
Computing affine singular points ...
Computing all points at infinity ...
Computing affine singular places ...
Computing singular places at infinity ...
Computing non-singular places at infinity ...
Adjunction divisor computed successfully
<BLANKLINE>
The genus of the curve is 1
sage: print(singular.eval("list HC1 = NSplaces(1..2,HC);"))
Computing non-singular affine places of degree 1 ...
Computing non-singular affine places of degree 2 ...
sage: print(singular.eval("HC = extcurve(2,HC1);"))
Total number of rational places : NrRatPl = 9

我们将以下内容设置为 junk 要丢弃输出::

sage: junk = singular.eval("intvec G = 5;")      # the rational divisor G = 5*HC[3][1]
sage: junk = singular.eval("def R = HC[1][2];")
sage: singular.eval("setring R;")
''

向量 \(G\) 表示除数“是无穷远点的5倍”。

接下来,我们计算Riemann-Roch空间。

sage: print(singular.eval("BrillNoether(G,HC);"))
Forms of degree 3 :
10
<BLANKLINE>
Vector basis successfully computed
<BLANKLINE>
[1]:
   _[1]=x
   _[2]=z
[2]:
   _[1]=y
   _[2]=z
[3]:
   _[1]=1
   _[2]=1
[4]:
   _[1]=y2+yz
   _[2]=xz
[5]:
   _[1]=y3+y2z
   _[2]=x2z

这是Riemann-Roch空间的基础,其中每一对函数表示商(第一个函数除以第二个函数)。在某些点上对这些基本元素中的每一个进行评估,以构造代码的生成矩阵。接下来,我们构建这些点。

sage: singular.eval("def R = HC[1][5];")
'// ** redefining R **'
sage: singular.eval("setring R;")
''
sage: print(singular.eval("POINTS;"))
[1]:
   [1]:
      0
   [2]:
      1
   [3]:
      0
[2]:
   [1]:
      0
   [2]:
      1
   [3]:
      1
[3]:
   [1]:
      0
   [2]:
      0
   [3]:
      1
[4]:
   [1]:
      (a+1)
   [2]:
      (a)
   [3]:
      1
...

\(5\) 更多,总共 \(9\) 曲线上的有理点。我们定义了我们的“评估因子” \(D\) 使用这些点的子集(除第一个点之外的所有点):

sage: singular.eval("def ER = HC[1][4];")
''
sage: singular.eval("setring ER;")
''
sage: # D = sum of the rational places no. 2..9 over F_4
sage: singular.eval("intvec D = 2..9;")
''
sage: # let us construct the corresponding evaluation AG code :
sage: print(singular.eval("matrix C = AGcode_L(G,D,HC);"))
Forms of degree 3 :
10
<BLANKLINE>
Vector basis successfully computed
<BLANKLINE>
sage: # here is a linear code of type [8,5,> = 3] over F_4
sage: print(singular.eval("print(C);"))
0,0,(a+1),(a),  1,  1,    (a),  (a+1),
1,0,(a),  (a+1),(a),(a+1),(a),  (a+1),
1,1,1,    1,    1,  1,    1,    1,
0,0,(a),  (a+1),1,  1,    (a+1),(a),
0,0,1,    1,    (a),(a+1),(a+1),(a)

最后,这是我们想要的生成矩阵,其中 a 表示域的度扩张的生成器 \(2\) 在基场上 \(GF(2)\)

这个能“包起来”吗?