Processing math: 100%

First time here? Check out the FAQ!

Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

answered 7 years ago

dan_fulea gravatar image

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 Y2=X3+A4X+A6, with A4,A6 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 Y2=X31213X+169027() 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 36 and group the new variables 33Y and 32X, 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...