val2.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import itertools
  2. import numpy as np
  3. import pickle
  4. # V: y^2 = x^3 + 4x
  5. # P = (2, 4)
  6. # f = y - 2x
  7. # V = span{1, x, x^2, y, xy, x^2 y}
  8. # multiply polynomials
  9. # perform reduction
  10. K = 11
  11. dim_x = 3
  12. dim_y = 2
  13. n = dim_x*dim_y
  14. P = Px, Py = 2, 4
  15. V = [
  16. [0, 7, 0, 10, 0, 0],
  17. [0, 0, 0, 0, 0, 0],
  18. [1, 0, 0, 0, 0, 0],
  19. [0, 0, 0, 0, 0, 0]
  20. ]
  21. coeffs = [list(range(K))]*dim_x
  22. x_vals = list(itertools.product(*coeffs))
  23. y_vals = x_vals[:]
  24. ring = list(itertools.product(x_vals, y_vals))
  25. #for idx in range(0, len(ring), 10):
  26. # print(ring[idx:idx + 10])
  27. def call(poly, point):
  28. x, y = point
  29. result = 0
  30. for j, row in enumerate(poly):
  31. for i, a in enumerate(row):
  32. v = a * x**i * y**j
  33. #print(f'{a} x^{i} y^{j} = {a} {x**i} {y**j} = {v}')
  34. result += v
  35. return result % K
  36. p = [[2, 7, 0], [6, 7, 0]]
  37. assert call(p, (2, 4)) == 8
  38. p = [[1, 2, 0], [0, 0, 3]]
  39. assert call(p, (6, 3)) == 7
  40. def sub(poly_a, poly_b):
  41. c = []
  42. for row_a, row_b in zip(poly_a, poly_b):
  43. c_row = [(a - b) % K for (a, b) in zip(row_a, row_b)]
  44. c.append(c_row)
  45. return c
  46. def add(poly_a, poly_b):
  47. c = []
  48. for row_a, row_b in zip(poly_a, poly_b):
  49. c_row = [(a + b) % K for (a, b) in zip(row_a, row_b)]
  50. c.append(c_row)
  51. return c
  52. a = [[4, 2, 3], [6, 0, 2]]
  53. b = [[2, 1, 2], [9, 3, 4]]
  54. assert sub(a, b) == [[2, 1, 1], [8, 8, 9]]
  55. def _expand_double(poly):
  56. assert len(poly) > 0
  57. x_size = len(poly[0])
  58. return [[0]*2*x_size]*2*len(poly)
  59. def _copy_double(poly):
  60. assert len(poly) > 0
  61. x_size = len(poly[0])
  62. return [row[:] + [0]*x_size for row in poly] + [[0]*2*x_size]*len(poly)
  63. def _mul_x(poly):
  64. p = []
  65. for row in poly:
  66. p.append([0] + row[:-1])
  67. return p
  68. def _mul_y(p):
  69. assert len(p) > 0
  70. x_size = len(p[0])
  71. return [[0]*x_size] + p[:-1]
  72. def _mul_const(p, c):
  73. return [[p*c % K for p in row] for row in p]
  74. def mul(a, b):
  75. result = _expand_double(a)
  76. for j, row in enumerate(b):
  77. for i, c in enumerate(row):
  78. # c x^i y^j
  79. v = _copy_double(a)
  80. v = _mul_const(v, c)
  81. for _ in range(i):
  82. v = _mul_x(v)
  83. for _ in range(j):
  84. v = _mul_y(v)
  85. result = add(result, v)
  86. return result
  87. #print(_expand_double(a))
  88. #print(_mul_x(_expand_double(a)))
  89. #print(_mul_y(_expand_double(a)))
  90. #print(_mul_const(_expand_double(a), 2))
  91. a = [[4, 2, 3], [6, 0, 2]]
  92. b = [[2, 1, 2], [9, 3, 4]]
  93. ab = mul(a, b)
  94. assert ab == [
  95. [8, 8, 5, 7, 6, 0], [4, 3, 10, 8, 5, 0],
  96. [10, 7, 9, 6, 8, 0], [0, 0, 0, 0, 0, 0]
  97. ]
  98. def max_monomial(p):
  99. degree = 0
  100. pos = 0, 0
  101. coeff = 0
  102. for j, row in enumerate(p):
  103. for i, c in enumerate(row):
  104. if c == 0:
  105. continue
  106. current_deg = i + j
  107. if current_deg > degree:
  108. degree = current_deg
  109. pos = i, j
  110. coeff = c
  111. return coeff, pos
  112. def deg(p):
  113. _, pos = max_monomial(p)
  114. return sum(pos)
  115. assert deg([[0, 0, 0], [0, 0, 0]]) == 0
  116. assert deg([[1, 0, 0], [0, 0, 0]]) == 0
  117. assert deg([[0, 1, 0], [0, 0, 0]]) == 1
  118. assert deg([[0, 0, 0], [1, 0, 0]]) == 1
  119. assert deg([[0, 0, 1], [1, 0, 0]]) == 2
  120. assert deg([[0, 0, 0], [0, 0, 1]]) == 3
  121. assert deg([[0, 0, 0], [0, 0, 1], [0, 0, 1]]) == 4
  122. def invert(b):
  123. n = 11
  124. (x0, x1, y0, y1) = (1, 0, 0, 1)
  125. while n != 0:
  126. q = b // n
  127. b = n
  128. n = b % n
  129. (x0, x1) = (x1, x0 - q * x1)
  130. (y0, y1) = (y1, y0 - q * y1)
  131. return b, x0, y0
  132. def _extended_euclid(a, b):
  133. if a == 0 :
  134. return 0, 1
  135. x1, y1 = _extended_euclid(b % a, a)
  136. # Update x and y using results of recursive call
  137. x = y1 - (b//a) * x1
  138. y = x1
  139. return x, y
  140. def invert(x):
  141. return _extended_euclid(x, K)[0] % K
  142. assert 5 * invert(5) % K == 1
  143. assert 3 * invert(3) % K == 1
  144. assert 7 * invert(7) % K == 1
  145. def __reduce(p, q):
  146. q_deg_x, q_deg_y = deg_x(q), deg_y(q)
  147. r = [row[:] for row in p]
  148. for j in range(len(r) - 1, -1, -1):
  149. row = r[j]
  150. for i in range(len(row)):
  151. c = row[i]
  152. if c == 0:
  153. continue
  154. term = [[0]*len(row) for _ in r]
  155. # TODO
  156. return r
  157. #print(reduce(ab, V))
  158. #ring_valid_denoms = list(filter(lambda g: call(g, P) != 0, ring))
  159. #
  160. #local_ring = []
  161. #for f1 in ring:
  162. # for g1 in ring_valid_denoms:
  163. # is_unique = True
  164. # for (f2, g2) in local_ring:
  165. # # Test: f1 g2 - f2 g1 in I
  166. # f1g2 = mul(f1, g2)
  167. # f2g1 = mul(f2, g1)
  168. # fg_fg = sub(f1g2, f2g1)