Example #1
0
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)
Example #2
0
def gaussian(les: LinearEquationSystem):
    a, b = copy.deepcopy(les.a), copy.deepcopy(les.b)
    n, m, p = les.n, les.m, les.p

    for col in range(m):
        row_replaced = find_nonzero(a, col)
        if row_replaced == -1:
            continue
        if row_replaced != col:
            a[col], a[row_replaced] = a[row_replaced], a[col]
            b[col], b[row_replaced] = b[row_replaced], b[col]
        for row in range(col + 1, n):
            if a[row][col] != 0:
                scalar = get_inverse(a[row][col], p) * a[col][col] % p
                a[row] = V.mul_scalar(a[row], scalar, p)
                a[row] = V.minus(a[row], a[col], p)
                brow = b[row][0]
                b[row] = [(brow * scalar - b[col][0]) % p]
                assert a[row][col] == 0

    func = all_solutions(a[-1][n - 1:], b[-1][0], p)

    def solution(t):
        x = [0] * m
        x[n - 1:] = func(t)
        for row in range(n - 1, -1, -1):
            xcol = b[row][0]
            for col in range(m - 1, row, -1):
                xcol = (xcol - a[row][col] * x[col]) % p
            xcol = xcol * get_inverse(a[row][row], p) % p
            x[row] = xcol
        return x
    return solution, m - n