有限域F_p上的橢圓曲線E:y^2=x^3+ax+b(mod p)的Mordell-Weil羣的計算

D:\MathTool\gaptool>ECGroup 2 1 13
y^2=x^3+2x+1(mod13)=>GAP[8,1]:
0->(0,0),ord=1=>0->(0,0),ord=1
1->(0,1),ord=8=>2->(0,12),ord=8
2->(0,12),ord=8=>1->(0,1),ord=8
3->(1,2),ord=4=>4->(1,11),ord=4
4->(1,11),ord=4=>3->(1,2),ord=4
5->(2,0),ord=2=>5->(2,0),ord=2
6->(8,3),ord=8=>7->(8,10),ord=8
7->(8,10),ord=8=>6->(8,3),ord=8
1 2 3 4 5 6 7 8
2 5 1 3 8 7 4 6
3 1 4 7 2 8 6 5
4 3 7 6 1 5 8 2
5 8 2 1 6 4 3 7
6 7 8 5 4 1 2 3
7 4 6 8 3 2 5 1
8 6 5 2 7 3 1 4

D:\MathTool\gaptool>ECGroup 4 20 29
y^2=x^3+4x+20(mod29)=>GAP[37,1]:
0->(0,0),ord=1=>0->(0,0),ord=1
1->(0,7),ord=37=>2->(0,22),ord=37
2->(0,22),ord=37=>1->(0,7),ord=37
3->(1,5),ord=37=>4->(1,24),ord=37
4->(1,24),ord=37=>3->(1,5),ord=37
5->(2,6),ord=37=>6->(2,23),ord=37
6->(2,23),ord=37=>5->(2,6),ord=37
7->(3,1),ord=37=>8->(3,28),ord=37
8->(3,28),ord=37=>7->(3,1),ord=37
9->(4,10),ord=37=>10->(4,19),ord=37
10->(4,19),ord=37=>9->(4,10),ord=37
11->(5,7),ord=37=>12->(5,22),ord=37
12->(5,22),ord=37=>11->(5,7),ord=37
13->(6,12),ord=37=>14->(6,17),ord=37
14->(6,17),ord=37=>13->(6,12),ord=37
15->(8,10),ord=37=>16->(8,19),ord=37
16->(8,19),ord=37=>15->(8,10),ord=37
17->(10,4),ord=37=>18->(10,25),ord=37
18->(10,25),ord=37=>17->(10,4),ord=37
19->(13,6),ord=37=>20->(13,23),ord=37
20->(13,23),ord=37=>19->(13,6),ord=37
21->(14,6),ord=37=>22->(14,23),ord=37
22->(14,23),ord=37=>21->(14,6),ord=37
23->(15,2),ord=37=>24->(15,27),ord=37
24->(15,27),ord=37=>23->(15,2),ord=37
25->(16,2),ord=37=>26->(16,27),ord=37
26->(16,27),ord=37=>25->(16,2),ord=37
27->(17,10),ord=37=>28->(17,19),ord=37
28->(17,19),ord=37=>27->(17,10),ord=37
29->(19,13),ord=37=>30->(19,16),ord=37
30->(19,16),ord=37=>29->(19,13),ord=37
31->(20,3),ord=37=>32->(20,26),ord=37
32->(20,26),ord=37=>31->(20,3),ord=37
33->(24,7),ord=37=>34->(24,22),ord=37
34->(24,22),ord=37=>33->(24,7),ord=37
35->(27,2),ord=37=>36->(27,27),ord=37
36->(27,27),ord=37=>35->(27,2),ord=37
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
2 14 1 9 37 32 11 5 29 6 12 35 10 18 3 17 27 21 15 19 28 30 34 36 31 16 33 8 20 24 23 26 7 13 22 4 25
3 1 15 36 8 10 33 28 4 13 7 11 34 2 19 26 16 14 20 29 18 35 31 30 37 32 17 21 9 22 25 6 27 23 12 24 5
4 9 36 11 1 37 6 3 12 5 32 26 8 29 24 23 34 20 30 22 19 17 21 33 14 31 13 15 35 27 18 25 10 28 16 7 2
5 37 8 1 10 7 36 13 2 33 4 9 27 25 28 35 22 31 21 18 23 20 16 15 32 12 30 34 14 19 26 11 24 17 29 3 6
6 32 10 37 7 4 1 33 25 36 2 14 24 26 13 20 19 16 34 23 17 21 22 8 12 29 15 27 31 28 35 9 3 30 18 5 11
7 11 33 6 36 1 5 24 32 3 37 25 15 12 27 18 21 35 17 16 22 23 20 13 9 14 28 30 26 34 29 2 8 19 31 10 4
8 5 28 3 13 33 24 34 1 27 36 4 17 37 21 12 35 25 18 14 31 29 26 19 6 11 22 23 2 20 32 7 30 16 9 15 10
9 29 4 12 2 25 32 1 35 37 26 16 5 20 36 34 13 19 24 30 15 27 28 7 18 23 10 3 22 33 21 31 6 8 17 11 14
10 6 13 5 33 36 3 27 37 24 1 2 30 32 34 29 20 26 23 31 16 18 35 28 11 9 19 17 25 21 12 4 15 22 14 8 7
11 12 7 32 4 2 37 36 26 1 25 31 3 35 33 21 28 22 27 17 30 34 19 10 29 18 8 24 16 13 20 14 5 15 23 6 9
12 35 11 26 9 14 25 4 16 2 31 23 1 22 7 28 8 30 33 27 24 13 15 6 20 21 5 36 17 10 19 18 37 3 34 32 29
13 10 34 8 27 24 15 17 5 30 3 1 22 6 23 9 29 32 31 25 26 14 12 21 7 4 20 16 37 18 11 36 19 35 2 28 33
14 18 2 29 25 26 12 37 20 32 35 22 6 21 1 27 33 28 3 15 8 24 13 4 23 17 7 5 19 36 34 16 11 10 30 9 31
15 3 19 24 28 13 27 21 36 34 33 7 23 1 20 32 26 2 29 9 14 12 25 22 5 6 16 18 4 35 37 10 17 31 11 30 8
16 17 26 23 35 20 18 12 34 29 21 28 9 27 32 3 1 33 6 10 7 5 36 25 30 15 2 11 13 37 24 19 14 4 8 31 22
17 27 16 34 22 19 21 35 13 20 28 8 29 33 26 1 2 7 32 6 11 37 4 31 24 3 14 12 10 25 36 15 18 9 5 23 30
18 21 14 20 31 16 35 25 19 26 22 30 32 28 2 33 7 8 1 3 5 36 10 9 34 27 11 37 15 4 13 17 12 6 24 29 23
19 15 20 30 21 34 17 18 24 23 27 33 31 3 29 6 32 1 9 4 2 11 37 35 8 10 26 14 36 12 5 13 16 25 7 22 28
20 19 29 22 18 23 16 14 30 31 17 27 25 15 9 10 6 3 4 36 1 7 5 12 28 13 32 2 24 11 8 34 26 37 33 35 21
21 28 18 19 23 17 22 31 15 16 30 24 26 8 14 7 11 5 2 1 37 4 6 29 13 33 12 25 3 9 10 27 35 32 36 20 34
22 30 35 17 20 21 23 29 27 18 34 13 14 24 12 5 37 36 11 7 4 6 1 26 15 8 25 9 33 32 3 28 31 2 10 16 19
23 34 31 21 16 22 20 26 28 35 19 15 12 13 25 36 4 10 37 5 6 1 7 14 27 24 9 32 8 2 33 30 29 11 3 18 17
24 36 30 33 15 8 13 19 7 28 10 6 21 4 22 25 31 9 35 12 29 26 14 17 1 37 23 20 11 16 2 5 34 18 32 27 3
25 31 37 14 32 12 9 6 18 11 29 20 7 23 5 30 24 34 8 28 13 15 27 1 16 22 36 10 21 3 17 35 4 33 19 2 26
26 16 32 31 12 29 14 11 23 9 18 21 4 17 6 15 3 27 10 13 33 8 24 37 22 19 1 7 34 5 30 20 2 36 28 25 35
27 33 17 13 30 15 28 22 10 19 8 5 20 7 16 2 14 11 26 32 12 25 9 23 36 1 18 35 6 31 4 3 21 29 37 34 24
28 8 21 15 34 27 30 23 3 17 24 36 16 5 18 11 12 37 14 2 25 9 32 20 10 7 35 31 1 29 6 33 22 26 4 19 13
29 20 9 35 14 31 26 2 22 25 16 17 37 19 4 13 10 15 36 24 3 33 8 11 21 34 6 1 30 7 28 23 32 5 27 12 18
30 24 22 27 19 28 34 20 33 21 13 10 18 36 35 37 25 4 12 11 9 32 2 16 3 5 31 29 7 26 1 8 23 14 6 17 15
31 23 25 18 26 35 29 32 21 12 20 19 11 34 37 24 36 13 5 8 10 3 33 2 17 30 4 6 28 1 27 22 9 7 15 14 16
32 26 6 25 11 9 2 7 31 4 14 18 36 16 10 19 15 17 13 34 27 28 30 5 35 20 3 33 23 8 22 29 1 24 21 37 12
33 7 27 10 24 3 8 30 6 15 5 37 19 11 17 14 18 12 16 26 35 31 29 34 4 2 21 22 32 23 9 1 28 20 25 13 36
34 13 23 28 17 30 19 16 8 22 15 3 35 10 31 4 9 6 25 37 32 2 11 18 33 36 29 26 5 14 7 24 20 12 1 21 27
35 22 12 16 29 18 31 9 17 14 23 34 2 30 11 8 5 24 7 33 36 10 3 32 19 28 37 4 27 6 15 21 25 1 13 26 20
36 4 24 7 3 5 10 15 11 8 6 32 28 9 30 31 23 29 22 35 20 16 18 27 2 25 34 19 12 17 14 37 13 21 26 33 1
37 25 5 2 6 11 4 10 14 7 9 29 33 31 8 22 30 23 28 21 34 19 17 3 26 35 24 13 18 15 16 12 36 27 20 1 32

#include"IGroup.h"
#include<functional>
#include<iostream>
#include<vector>
#include<cassert>
using namespace std;

/*
本程序計算有限域F_p上的橢圓曲線E:y^2=x^3+ax+b(mod p)的#E階交換羣結構。
橢圓曲線上有理點全體構成一個Abel羣。也就是說羣的元素現在不是數而是點。因此我們必須規定,兩個點的和(我們用(+)表示)應該是哪一點?每個點的逆元素是什麼?然後再驗證它們是否滿足Abel羣的幾條公理。
1.首先我們規定每一點P的反點~P。即如果P(x,y)是橢圓曲線上一點,則(x,-y)也是橢圓曲線上一點,我們稱它爲P(x,y)的反點,記作~P(x,-y)。
2.現在我們定義兩點P_1(x_1,y_1)和P_2(x_2,y_2)的加法運算(+)。如果連接P_1與P_2的直線與橢圓曲線相交於一點P_3,則定義其和爲P_3的反點:P_1(+)P_2=~P_3。
3.每一點的逆元素爲其反點。
4.零元素爲無窮原點。
已知有限域F_p上的橢圓曲線羣E(F_p):{(x,y)|y^2=x^3+ax+b,a,b∈F_p}∪{O},以及點P=(x,y)的階爲一個大素數,
那麼給定整數a,計算點aP=(x_a,y_a)=Q很容易;給定點Q,計算整數x,使得xP=Q非常困難。
假定有橢圓曲線上的點P和B並且我們知道有某個整數k滿足B=kP=P+P+…+P。找到這個k就被稱爲橢圓曲線上的離散對數問題。
數論和算術中常用的形式EC3:y^2=x^3+ax+b(mod p)
Mordell-Weil定理:橢圓曲線上有理點構成的羣是有限生成的。
Siegel定理:橢圓曲線上的整點只有有限多個。
y^2=x^3+4x+20(mod29)=>GAP[37,1]:
y^2=x^3+1x+1(mod5)=>GAP[9,1]:
y^2=x^3+1x+1(mod7)=>GAP[5,1]:
y^2=x^3+1x+1(mod11)=>GAP[14,2]:
y^2=x^3+1x+1(mod13)=>GAP[18,2]:
y^2=x^3+1x+7(mod17)=>GAP[12,5]:
y^2=x^3+1x+11(mod17)=>GAP[20,2]:
y^2=x^3+2x+1(mod5)=>GAP[7,1]:
y^2=x^3+2x+1(mod7)=>GAP[5,1]:
y^2=x^3+2x+1(mod11)=>GAP[16,1]:
y^2=x^3+2x+1(mod13)=>GAP[8,1]:
y^2=x^3+2x+1(mod17)=>GAP[24,9]:
*/
// y^2=x^3+ax+b
typedef int(*pFuncInt2)(int x,int a,int b);
typedef pair<int,int> IntPoint;
IntPoint g_Zero=make_pair(0,0);// 無窮遠點,與有限整點區分開來即可,加法羣的單位元
//struct IntPoint
//{
//    int x;
//    int y;
//};
struct EC3:public IGroup
{
public:
    //  靜態函數  
    static int Mod(int ret,unsigned int n);
    static int minv(int a,int b,int c);
    static int calk(int a,int p,int xp,int yp,int xq,int yq);
    static IntPoint Add(int a,int p,const IntPoint &P,const IntPoint &Q);// R=P+Q
public:
    // 實現抽象基類的方法
    virtual void printSet();
    virtual void printTable();     
    virtual int mul(int a,int b);
    virtual int size();
    virtual int inv(int a);
    // 構造函數
    EC3(int a,int b,int p);
    // 析構函數
    ~EC3(){};
    // 成員函數 
    // 成員變量 
    vector<IntPoint> m_Set;
    function<int(int,int,int)> m_PolygonEC;
    int m_a;
    int m_b;
    int m_p;
};

int EC3::Mod(int ret,unsigned int n){
    assert(n>0);
    if(ret<0){
        int ret1=ret+(-ret+1)*n;
        return ret1%n;
    }
    return ret%n;
}

int EC3::minv(int a,int b,int c){
    int ret=1;
    a=a%c;
    while(b){
        if(b&1){
            ret=(ret*a)%c;
        }
        a=(a*a)%c;
        b=b>>1;
    }
    return ret;
}

int EC3::calk(int a,int p,int xp,int yp,int xq,int yq){
    if(xp==xq&&yp==yq)
        return (((3*xp*xp+a)*minv(2*yp,p-2,p))%p+p)%p;
    return (((yq-yp)*minv(xq-xp,p-2,p))%p+p)%p;
}

IntPoint EC3::Add(int a,int p,const IntPoint &P,const IntPoint &Q){
    int x1=P.first;
    int y1=P.second;
    int x2=Q.first;
    int y2=Q.second;
    int t=calk(a,p,x1,y1,x2,y2);
    int x3=((t*t-x1-x2)%p+p)%p;
    int y3=((t*(x1-x3)-y1)%p+p)%p;
    return make_pair(x3,y3);
}

EC3::EC3(int a,int b,int p):m_a(a),m_b(b),m_p(p){
    m_PolygonEC=[=](int x,int a,int b){return x*x*x+a*x+b;};
    m_Set.push_back(g_Zero);
    for(int i=0;i<p;i++){
        for(int j=0;j<p;j++){
            if(Mod(m_PolygonEC(i,a,b),p)==Mod(j*j,p)){
                m_Set.push_back(make_pair(i,j));
            }
        }
    }
}

void EC3::printSet(){
    int ID=IdGroup(this);
    printf("y^2=x^3+%dx+%d(mod%d)=>GAP[%d,%d]:\n",m_a,m_b,m_p,size(),ID);
    function<int(int)> ord=[=](int a){vector<int> S1=Order(this,a);int o=S1.size();return o;};
    for(int i=0;i<size();i++){
        IntPoint I=m_Set[i];
        int i1=inv(i);
        IntPoint I1=m_Set[i1];
        int o=ord(i);
        int o1=ord(i1);
        printf("%d->(%d,%d),ord=%d=>%d->(%d,%d),ord=%d\n",i,I.first,I.second,o,i1,I1.first,I1.second,o1);
    }
}

void EC3::printTable(){ 
    printGroup(this);
}

int EC3::mul(int a,int b){
    if(a<0||b<0)
        return -1;
    if(a==0)
        return b;
    if(b==0)
        return a;
    if(m_Set[a].first==m_Set[b].first && m_Set[a].second+m_Set[b].second==m_p)
        return 0;
    if(a==b && m_Set[a].second==0)
        return 0;
    IntPoint R=Add(m_a,m_p,m_Set[a],m_Set[b]);
    int ret=-1;
    vector<IntPoint>::iterator p=std::find(m_Set.begin(),m_Set.end(),R);
    if(p!=m_Set.end()){
        ret=p-m_Set.begin();
    }else{
        //cout<<"("<<R.first<<","<<R.second<<")";
    }
    return ret;
}

int EC3::size(){
    return m_Set.size();
}

int EC3::inv(int a){
    vector<int> S1=Order(this,a);
    int ord=S1.size();    
    return S1[ord-1];
}

void test(){
    // E:y^2=x^3+4x+20(mod29)
    EC3 c37(4,20,29);
    //cout<<"有限整點個數:"<<c37.size()-1<<endl;
    //for(int i=1;i<c37.size();i++){
    //    cout<<"("<<c37.m_Set[i].first<<","<<c37.m_Set[i].second<<")";
    //    if(i<c37.size())
    //        cout<<",";
    //}
    //cout<<endl;
    c37.printSet();
    //c37.printTable();

    EC3 c9(1,1,5);
    c9.printSet();

    EC3 c5(1,1,7);
    c5.printSet();

    EC3 c14(1,1,11);
    c14.printSet();

    EC3 c18(1,1,13);
    c18.printSet();

    EC3 c18a(1,1,17);
    c18a.printSet();

    EC3 c2c2c3(1,7,17);
    c2c2c3.printSet();

    EC3 c20(1,11,17);
    c20.printSet();

    EC3 c7(2,1,5);
    c7.printSet();

    EC3 c5a(2,1,7);
    c5a.printSet();

    EC3 c16(2,1,11);
    c16.printSet();

    EC3 c8(2,1,13);
    c8.printSet();

    EC3 c2c12(2,1,17);
    c2c12.printSet();
}

bool IsPrime(unsigned int N){
    if(N==0||N==1)
        return false;
    int up=sqrt((float)N);
    for(int i=2;i<=up;i++){
        if(N%i==0)
            return false;
    }
    return true;
}

int main(int argc, char* argv[]){
#if 0
    test();
    system("pause");
    return 0;
#endif
    char sz[100]={0};
    if(argc<4){
        printf("Usage:  ECGroup a b p\n");
        return 0;
    }
    
    int a=atoi(argv[1]);
    int b=atoi(argv[2]);
    int p=atoi(argv[3]);
    if(a<1||b<1||!IsPrime(p)){
        return 0;
    }

    EC3 E(a,b,p);
    E.printSet();
    E.printTable();

    return 0;
}
 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章