Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

This post seems to be related to

https://ask.sagemath.org/question/36637/change-of-variable-from-hyperellictic-curve-to-weierstrass-form/

Please always mention the source, when there is almost a copy+pasted version of existing code.

The following code tries to catch all needed ad-hoc passages in a homogenous structure.

For this, i have introduced the class W, where we can bind all needed coefficients.

First of all the code, than the comments:

class W( object ):
    def __init__( self, a,b,c,d,q, Q, a1,a2,a3,a4,a6, A4,A6 ):
        self.a, self.b, self.c, self.d, self.q = a, b, c, d, q
        self.Q = Q
        self.a1, self.a2, self.a3, self.a4, self.a6 = a1, a2, a3, a4, a6
        self.A4, self.A6 = A4,A6
        self.f = lambda x, y : y^2 - ( a*x^4 + b*x^3 + c*x^2 + d*x + q^2 )
        self.g = lambda x, y : y^2 + a1*x*y + a3*y - ( x^3 + a2*x^2 + a4*x + a6 )
        self.h = lambda x, y : y^2 - ( x^3 + A4*x + A6 )

# var( 'a,b,c,d,q' )
def getData( a,b,c,d,q ):
    Q = 2*q

    a1, a2, a3, a4 = d/q, c - ((d/(2*q)))^2, b*(2*q), -a*(2*q)^2
    a6 = a2 * a4

    A4 = a4 + a1*a3/2 - a1^4/48 - a1^2*a2/6 - a2^2/3
    A6 = a1^6/864 + a1^4*a2/72 + a1^2*a2^2/18 - a1^3*a3/24 + 2/27*a2^3 - a1*a2*a3/6 - a1^2*a4/12 + a3^2/4 - a2*a4/3 + a6

    w = W( a,b,c,d,q, Q, a1,a2,a3,a4,a6, A4,A6 )
    return w

def Passage_uv_to_xy( uv, data ):
    u, v = uv
    c,d, q,Q = data.c, data.d, data.q, data.Q

    x = ( Q*(v+q) + d*u ) / u^2
    y = ( Q^2*(v+q) + Q*( d*u + c*u^2 ) - d^2*u^2/Q ) / u^3
    return x,y

def Passage_xy_to_uv( xy, data ):
    x, y = xy
    c,d, q,Q = data.c, data.d, data.q, data.Q

    U = ( Q*(x+c) - d^2/Q ) / y
    V = -q + U*(U*x-d) / Q
    return U,V

# var( 'a1,a2,a3,a4,a6' )
# use the above to test Y^2 - (X^3+A4*X+A6) == y^2+a1*x*y+a3*y - (x^3+a2*x^2+a4*x+a6) ...
# where var( 'x,y' ); X,Y = Passage_xy_to_XY( (x,y) )
# A4 = a4 + a1*a3/2 - a1^4/48 - a1^2*a2/6 - a2^2/3
# A6 = a1^6/864 + a1^4*a2/72 + a1^2*a2^2/18 - a1^3*a3/24 + 2/27*a2^3 - a1*a2*a3/6 - a1^2*a4/12 + a3^2/4 - a2*a4/3 + a6
# and associate a corresponding data...

def Passage_xy_to_XY( xy, data ):
    x,y = xy
    a1, a2, a3 = data.a1, data.a2, data.a3

    X = x + (a2+a1^2/4)/3
    Y = y + a1*x/2 + a3/2
    return X,Y

def Passage_XY_to_xy( XY, data ):
    X, Y = XY
    a1, a2, a3 = data.a1, data.a2, data.a3

    x = X - (a2+a1^2/4)/3
    y = Y - a1*x/2 - a3/2
    return x,y

# # # =================================================
# # # TESTS AND APPLICATION TO THE GIVEN CASE
var( 'u,v' )
var( 'a,b,c,d,q' )
data = getData( a,b,c,d,q )

u1, v1 = Passage_xy_to_uv( Passage_uv_to_xy( (u,v), data ), data )
print "Is u1=u ? %s" % bool( u1==u )
print "Is v1=v ? %s" % bool( v1==v )
print

var( 'x,y' )
x1, y1 = Passage_XY_to_xy( Passage_xy_to_XY( (x,y), data ), data )
print "Is x1=x ? %s" % bool( x1==x )
print "Is y1=y ? %s" % bool( y1==y )
print

var( 'u,v' )
X,Y = Passage_xy_to_XY( Passage_uv_to_xy( (u,v), data ), data )
print "YY - (XXX +A4*X + A6)  is %s" % ( (Y^2 - (X^3+A4*X+A6) ).factor() )
print

var( 'X,Y' )
U,V = Passage_xy_to_uv( Passage_XY_to_xy( (X,Y), data ), data )
print "U = %s" % U
print "V = %s" % V
print

# in the concrete case given:
data = getData( 1,-2,5,8,2 )
var( 'X,Y' )
U,V = Passage_xy_to_uv( Passage_XY_to_xy( (X,Y), data ), data )
print "U = %s" % U
print "V = %s" % V
print "f(U,V) = %s" % ( data.f(U,V).factor() )

This gives:

(u, v)
(a, b, c, d, q)
Is u1=u ? True
Is v1=v ? True

(x, y)
Is x1=x ? True
Is y1=y ? True

(u, v)
YY - (XXX +A4*X + A6)  is (4*c*q^2*u^2 + 8*q^4 + 4*d*q^2*u - d^2*u^2 + 8*q^3*v)*(a*u^4 + b*u^3 + c*u^2 + q^2 + d*u - v^2)/u^6

(X, Y)
U = -(4*(3*X + 2*c)*q - 3*d^2/q)/(6*b*q - 6*Y + (3*X - c)*d/q)
V = -q + 1/6*(4*(3*X + 2*c)*q - 3*d^2/q)*((4*(3*X + 2*c)*q - 3*d^2/q)*(3*X - c)/(6*b*q - 6*Y + (3*X - c)*d/q) + 3*d)/((6*b*q - 6*Y + (3*X - c)*d/q)*q)

(X, Y)
U = -4*(3*X - 2)/(6*X - 3*Y - 22)
V = 4/3*((3*X - 2)*(3*X - 5)/(6*X - 3*Y - 22) + 6)*(3*X - 2)/(6*X - 3*Y - 22) - 2
f(U,V) = 16/9*(27*X^3 - 27*Y^2 - 1089*X + 1690)*(3*X - 2)^3/(6*X - 3*Y - 22)^4

Comments to the above:

  • The equalities u1==u and v1==v shows that the passages Passage_xy_to_uv and Passage_uv_to_xy are inverse to each other.
  • The equalities x1==x and y1==y shows that the passages Passage_xy_to_XY and Passage_XY_to_xy are inverse to each other.
  • The factor (a*u^4 + b*u^3 + c*u^2 + q^2 + d*u - v^2) in YY - (XXX +A4*X + A6) shows that if the pair $(u,v)$ satisfies "the quartic", than $(X,Y)$ satisfies $$Y^2 =X^3 +A_4X+A_6$$, with $A_4,A_6$ also captured in the instance data.
  • Let now data be the "special data", obtained as data = getData( 1,-2,5,8,2 ). Then if we start with $(X,Y)$ on the curve with the equation

    sage: data.h(X,Y)
    -X^3 + Y^2 + 121/3*X - 1690/27
    sage: data.h(X,Y)*27
    -27*X^3 + 27*Y^2 + 1089*X - 1690
    
  • then building $(U,V)$ from $(X,Y)$ satisfying $h=0$, we get the point $(U,V)$ satisfying $f(U,V)=0$, because of the factor (27*X^3 - 27*Y^2 - 1089*X + 1690).

  • So for $(U,V)$ satisfying the equation of the elliptic curve $$Y^2 = X^3 - \frac{121}3X + \frac{1690}{27}\qquad(*)$$ the corresponding $(U,V)$ point has:

    sage: U.factor()
    -4*(3*X - 2)/(6*X - 3*Y - 22)
    sage: V.factor()
    2/3*(54*X^3 - 54*X^2 - 27*Y^2 - 324*Y - 964)/(6*X - 3*Y - 22)^2
    

I hope this helps to finally dissolve the puzzle. (In the given situation we have only to rescale $X,Y$ using corresponding powers of $3$, i.e. formally multiply $(*)$ with $3^6$ and group the new variables $3^3Y$ and $3^2X$, for the new equation.)

A final note: As in mathematics, it is always simpler to catch the idea when the shape of the text / of the code comes in a pleasant way. Please try to use (for the own sake) a better spacing and a more structural approach. In the posted code it was quite hard to find a Leitfaden, a red line...