| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- import itertools
- import numpy as np
- import pickle
- # V: y^2 = x^3 + 4x
- # P = (2, 4)
- # f = y - 2x
- # V = span{1, x, x^2, y, xy, x^2 y}
- # multiply polynomials
- # perform reduction
- K = 11
- dim_x = 3
- dim_y = 2
- n = dim_x*dim_y
- P = Px, Py = 2, 4
- V = [
- [0, 7, 0, 10, 0, 0],
- [0, 0, 0, 0, 0, 0],
- [1, 0, 0, 0, 0, 0],
- [0, 0, 0, 0, 0, 0]
- ]
- coeffs = [list(range(K))]*dim_x
- x_vals = list(itertools.product(*coeffs))
- y_vals = x_vals[:]
- ring = list(itertools.product(x_vals, y_vals))
- #for idx in range(0, len(ring), 10):
- # print(ring[idx:idx + 10])
- def call(poly, point):
- x, y = point
- result = 0
- for j, row in enumerate(poly):
- for i, a in enumerate(row):
- v = a * x**i * y**j
- #print(f'{a} x^{i} y^{j} = {a} {x**i} {y**j} = {v}')
- result += v
- return result % K
- p = [[2, 7, 0], [6, 7, 0]]
- assert call(p, (2, 4)) == 8
- p = [[1, 2, 0], [0, 0, 3]]
- assert call(p, (6, 3)) == 7
- def sub(poly_a, poly_b):
- c = []
- for row_a, row_b in zip(poly_a, poly_b):
- c_row = [(a - b) % K for (a, b) in zip(row_a, row_b)]
- c.append(c_row)
- return c
- def add(poly_a, poly_b):
- c = []
- for row_a, row_b in zip(poly_a, poly_b):
- c_row = [(a + b) % K for (a, b) in zip(row_a, row_b)]
- c.append(c_row)
- return c
- a = [[4, 2, 3], [6, 0, 2]]
- b = [[2, 1, 2], [9, 3, 4]]
- assert sub(a, b) == [[2, 1, 1], [8, 8, 9]]
- def _expand_double(poly):
- assert len(poly) > 0
- x_size = len(poly[0])
- return [[0]*2*x_size]*2*len(poly)
- def _copy_double(poly):
- assert len(poly) > 0
- x_size = len(poly[0])
- return [row[:] + [0]*x_size for row in poly] + [[0]*2*x_size]*len(poly)
- def _mul_x(poly):
- p = []
- for row in poly:
- p.append([0] + row[:-1])
- return p
- def _mul_y(p):
- assert len(p) > 0
- x_size = len(p[0])
- return [[0]*x_size] + p[:-1]
- def _mul_const(p, c):
- return [[p*c % K for p in row] for row in p]
- def mul(a, b):
- result = _expand_double(a)
- for j, row in enumerate(b):
- for i, c in enumerate(row):
- # c x^i y^j
- v = _copy_double(a)
- v = _mul_const(v, c)
- for _ in range(i):
- v = _mul_x(v)
- for _ in range(j):
- v = _mul_y(v)
- result = add(result, v)
- return result
- #print(_expand_double(a))
- #print(_mul_x(_expand_double(a)))
- #print(_mul_y(_expand_double(a)))
- #print(_mul_const(_expand_double(a), 2))
- a = [[4, 2, 3], [6, 0, 2]]
- b = [[2, 1, 2], [9, 3, 4]]
- ab = mul(a, b)
- assert ab == [
- [8, 8, 5, 7, 6, 0], [4, 3, 10, 8, 5, 0],
- [10, 7, 9, 6, 8, 0], [0, 0, 0, 0, 0, 0]
- ]
- def max_monomial(p):
- degree = 0
- pos = 0, 0
- coeff = 0
- for j, row in enumerate(p):
- for i, c in enumerate(row):
- if c == 0:
- continue
- current_deg = i + j
- if current_deg > degree:
- degree = current_deg
- pos = i, j
- coeff = c
- return coeff, pos
- def deg(p):
- _, pos = max_monomial(p)
- return sum(pos)
- assert deg([[0, 0, 0], [0, 0, 0]]) == 0
- assert deg([[1, 0, 0], [0, 0, 0]]) == 0
- assert deg([[0, 1, 0], [0, 0, 0]]) == 1
- assert deg([[0, 0, 0], [1, 0, 0]]) == 1
- assert deg([[0, 0, 1], [1, 0, 0]]) == 2
- assert deg([[0, 0, 0], [0, 0, 1]]) == 3
- assert deg([[0, 0, 0], [0, 0, 1], [0, 0, 1]]) == 4
- def invert(b):
- n = 11
- (x0, x1, y0, y1) = (1, 0, 0, 1)
- while n != 0:
- q = b // n
- b = n
- n = b % n
- (x0, x1) = (x1, x0 - q * x1)
- (y0, y1) = (y1, y0 - q * y1)
- return b, x0, y0
- def _extended_euclid(a, b):
- if a == 0 :
- return 0, 1
-
- x1, y1 = _extended_euclid(b % a, a)
-
- # Update x and y using results of recursive call
- x = y1 - (b//a) * x1
- y = x1
-
- return x, y
- def invert(x):
- return _extended_euclid(x, K)[0] % K
- assert 5 * invert(5) % K == 1
- assert 3 * invert(3) % K == 1
- assert 7 * invert(7) % K == 1
- def __reduce(p, q):
- q_deg_x, q_deg_y = deg_x(q), deg_y(q)
- r = [row[:] for row in p]
- for j in range(len(r) - 1, -1, -1):
- row = r[j]
- for i in range(len(row)):
- c = row[i]
- if c == 0:
- continue
- term = [[0]*len(row) for _ in r]
- # TODO
- return r
- #print(reduce(ab, V))
- #ring_valid_denoms = list(filter(lambda g: call(g, P) != 0, ring))
- #
- #local_ring = []
- #for f1 in ring:
- # for g1 in ring_valid_denoms:
- # is_unique = True
- # for (f2, g2) in local_ring:
- # # Test: f1 g2 - f2 g1 in I
- # f1g2 = mul(f1, g2)
- # f2g1 = mul(f2, g1)
- # fg_fg = sub(f1g2, f2g1)
|