valuate.sage 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. # $ sage -sh
  2. # $ pip install tabulate
  3. from tabulate import tabulate
  4. # P = (2, 4)
  5. # ord_P(y - 2x) = 2
  6. # from Washington example 11.4 page 345
  7. K.<x, y> = GF(11)[]
  8. Px, Py = K(2), K(4)
  9. assert (3*Px^2 + 4) / (2*Py) == 2
  10. basis = [(x - Px), (y - Py), 1]
  11. # Return components for basis
  12. def decomp(f, basis):
  13. comps = []
  14. r = f
  15. for b in basis:
  16. a, r = r.quo_rem(b)
  17. comps.append(a)
  18. assert r == 0
  19. return comps
  20. def comp(comps, basis):
  21. return sum(a*b for a, b in zip(comps, basis))
  22. original_f = y - 2*x
  23. assert comp(decomp(original_f, basis), basis) == original_f
  24. # P = (a, b)
  25. # y² = x³ + Ax + B
  26. # (y - b)(y + b) = (x - a)³ + C(3,2)a(x - a)² + (3a² + A)(x - a)
  27. #
  28. # sage: ((x - a)^3 + binomial(3,2)*a*(x - a)^2 + (3*a^2 + A)*(x - a)).expand()
  29. # -a^3 + x^3 - A*a + A*x
  30. # But since (a, b) ∈ E(K) => b² = a³ + Aa + B
  31. # => B = b² - (a³ + Aa)
  32. #
  33. # So at every step we replace the component for (y - Py)
  34. # with the reduction to the component for (x - Px)
  35. EC_A = 4
  36. EC_B = 0
  37. EC = y^2 - x^3 - A*x - B
  38. # so we can replace (y - Py) with this
  39. Ef = b0^2 + binomial(3,2)*Px*b0^1 + (3*Px^2 + EC_A)
  40. Eg = (y + Py)
  41. assert EC == b1*Eg - b0*Ef
  42. # f / g
  43. # Technically we don't need g but we keep track of it anyway
  44. def apply_reduction(f, g, basis):
  45. #a1 = f[1]
  46. #f[1] = 0
  47. b0, b1, _ = basis
  48. # b1 == b0 * f / g
  49. # so we can replace c b1 with (cf/g) b0
  50. # a2 = 0
  51. assert f[2] == 0
  52. # note that
  53. # b1 = (f/g) b0
  54. # so
  55. # x = a0 b0 + a1 b1 + 0 b2
  56. # = (a0 + a1 f/g) b0
  57. # let a0 = p/q
  58. # x = (pg + a1 f)
  59. # ----------- b0
  60. # qg
  61. f[0] = f[0]*Eg + f[1]*Ef
  62. f[1] = 0
  63. g[0] *= Eg
  64. k = 1
  65. table = []
  66. table.append(("", "f", "g", "k"))
  67. def log(step_name, f, g, k):
  68. table.append((step_name, str(f), str(g), k))
  69. f = decomp(original_f, basis)
  70. g = [1]
  71. log("start", f, g, k)
  72. # Reduce
  73. apply_reduction(f, g, basis)
  74. log("reduce", f, g, k)
  75. f = f[0]
  76. # Decompose
  77. f = decomp(f, basis)
  78. log("decomp", f, g, k)
  79. assert comp(f, basis) == (x - 2)^2 - 5*(x - 2) - 2*(y - 4)
  80. assert f[2] == 0
  81. k += 1
  82. # Reduce
  83. apply_reduction(f, g, basis)
  84. log("reduce", f, g, k)
  85. f = f[0]
  86. # Decompose
  87. f = decomp(f, basis)
  88. log("decomp", f, g, k)
  89. # Program terminates because remainder is nonzero
  90. assert f[2] != 0
  91. print(f"basis = {basis}")
  92. print(tabulate(table))
  93. print(f"k = {k}")
  94. # Test final value is correct
  95. S = K.quotient(y^2 - x^3 - 4*x).fraction_field()
  96. f0, f1, f2 = f
  97. f = f0*b0 + f1*b1 + f2*b2
  98. g = g[0]
  99. fprime = b0^k * f/g
  100. assert fprime == S(original_f)
  101. # to convert fprime back again:
  102. #f, g = fprime.numerator().lift(), fprime.denominator().lift()
  103. assert g(Px, Py) != 0
  104. assert f(Px, Py) != 0
  105. assert b0(Px, Py) == 0