Я пытаюсь получить один элемент вспомогательного A_adj
матрицы A
, оба из которых должны быть символическими выражениями, где символы x_i
двоичные, а матрица A
симметричная и разреженная. Python sympy
отлично подходит для небольших задач:
from sympy import zeros, symbols
size = 4
A = zeros(size,size)
x_i = [x for x in symbols(f'x0:{size}')]
for i in range(size-1):
A[i,i] += 0.5*x_i[i]
A[i+1,i+1] += 0.5*x_i[i]
A[i,i+1] = A[i+1,i] = -0.3*(i+1)*x_i[i]
A_adj_0 = A[1:,1:].det()
A_adj_0
Это вычисляет первый элемент A_adj_0
матрицы кофакторов (который является соответствующим второстепенным) и правильно дает мне 0,125x_0x_1x_2 - 0,28x_2x_2 ^ 2 - 0,055x_1 ^ 2x_2 - 0,28x_1x_2 ^ 2, это выражение, которое мне нужно, но есть две проблемы:
- Это совершенно невозможно для больших матриц (мне это нужно для
size
s из ~100). x_i
являются двоичными переменными (то есть 0 или 1), и, похоже,sympy
не может упростить выражения двоичных переменных, то есть упростить многочлены x_i^n = x_i.
Первую проблему можно частично решить, вместо этого решая систему линейных уравнений Ay = b
, где b
задается первым базисным вектором [1, 0, 0, 0]
, так что y
является первым столбцом обратного A
. Первая запись y
является первым элементом, обратным A
:
b = zeros(size,1)
b[0] = 1
y = A.LUsolve(b)
s = {x_i[i]: 1 for i in range(size)}
print(y[0].subs(s) * A.subs(s).det())
print(A_adj_0.subs(s))
Проблема здесь в том, что выражение для первого элемента y
чрезвычайно сложно, даже после использования simplify()
и так далее. Это будет очень простое выражение с упрощением двоичных выражений, как указано в пункте 2 выше. Это более быстрый метод, но все же неприемлемый для больших матриц.
Это сводится к моему актуальному вопросу:
Существует ли эффективный способ вычисления одного элемента сопряжения разреженной и симметричной символьной матрицы, где символы являются двоичными значениями?
Я также открыт для использования другого программного обеспечения.
Приложение 1:
Кажется, упрощение бинарных выражений в sympy
возможно с помощью простой пользовательской замены, о которой я не знал:
A_subs = A_adj_0
for i in range(size):
A_subs = A_subs.subs(x_i[i]*x_i[i], x_i[i])
A_subs