def lanczos(les: LinearEquationSystem): assert les.n == les.m for row in range(les.n): for col in range(row + 1): if les.a[row][col] != les.a[col][row]: print('Алгоритм Ланцоша : определен только для симмтеричных матриц, ' 'см. индексы ({0},{1}) и ({1},{0})'.format(row + 1, col + 1)) return p = les.p ws = [M.column(les.b, 0)] vs = [None, M.mul_vec(les.a, ws[0], p)] ws.append(V.minus(vs[1], V.mul_scalar(ws[0], ratio(V.mul_sum(vs[1], vs[1], p), V.mul_sum(ws[0], vs[1], p), p), p), p)) for trial in range(max(MAX_TRIALS, les.n)): if V.mul_sum(ws[-1], M.mul_vec(les.a, ws[-1], p), p) == 0: if V.is_zero(ws[-1]): x = V.zero(les.n) for i in range(len(ws) - 1): bi = ratio(V.mul_sum(ws[i], ws[0], p), V.mul_sum(ws[i], vs[i + 1], p), p) x = V.add(x, V.mul_scalar(ws[i], bi, p), p) return x vs.append(M.mul_vec(les.a, ws[-1], p)) w1 = V.mul_scalar(ws[-1], ratio(V.mul_sum(vs[-1], vs[-1], p), V.mul_sum(ws[-1], vs[-1], p), p), p) w2 = V.mul_scalar(ws[-2], ratio(V.mul_sum(vs[-1], vs[-2], p), V.mul_sum(ws[-2], vs[-2], p), p), p) w_end = V.minus(V.minus(vs[-1], w1, p), w2, p) ws.append(w_end)
def wiedemann2(les: LinearEquationSystem): a, b, p, n = les.a, M.t(les.b)[0], les.p, les.n a_powers = [M.unit(n, n)] for i in range(1, 2 * n): a_powers.append(M.mul(a_powers[-1], a, p)) aib = [M.mul_vec(ai, b, p) for ai in a_powers] k = 0 gs = [[1]] uk1 = [0, 1] + ([0] * (n - 2)) while Poly.deg(gs[k]) < n and k < n: seq = [] for i in range(2 * n - Poly.deg(gs[k])): gab = M.mul_vec(fa(gs[k], a, p), aib[i], p) ugab = V.mul_sum(uk1, gab, p) seq.append(ugab) assert len(seq) f = berlekamp(seq, p) gs.append(Poly.mul(f, gs[k], p)) k += 1 uk1 = ([0] * k) + [1] + ([0] * (n - k - 1)) print('k =', k) g = gs[-1] x = V.zero(n) for i in range(Poly.deg(g)): x = V.add(x, V.mul_scalar(aib[i], -g[i], p), p) return x
def wiedemann1(les: LinearEquationSystem): a, b, p, n = les.a, M.t(les.b)[0], les.p, les.n for trial in range(MAX_TRIALS): bs = [b] ys = [[0] * n] ds = [0] k = 0 while bs[k] != V.zero(n): u = [random.randint(0, p - 1) for _idx in range(n)] seq = [] for i in range(2 * (n - ds[k])): ai = M.power(a, i, p) aib = M.mul_vec(ai, b, p) uaib = V.mul_sum(u, aib, p) seq.append(uaib) if not len(seq): break f = berlekamp(seq, p) if f is None: break ys.append(V.add(ys[k], M.mul_vec(f_tilda(f, a, p), b, p), p)) bs.append(V.add(b, M.mul_vec(a, ys[k + 1], p), p)) ds.append(ds[k] + len(f)) k += 1 if bs[k] != V.zero(n): print(trial, end='\r') continue return V.mul_scalar(ys[k], -1, p)
def alpha_ij(wi, wj, a, p): nom = mul_a(M.mul_vec(a, wi, p), wj, a, p) rat = mul_a(wj, wj, a, p) return ratio(nom, rat, p)
def mul_a(x, y, a, p): return V.mul_sum(M.mul_vec(a, x, p), y, p)