У меня большая матрица, n! x n!, для которого мне нужно взять определитель. Для каждой перестановки n я связываю
- вектор длины 2n (это легко вычислить)
- многочлен от 2n переменных (произведение линейных множителей, вычисляемых рекурсивно по n)
Матрица представляет собой оценочную матрицу полиномов на векторах (рассматриваемых как точки). Таким образом, элемент сигма, тау матрицы (индексированный перестановками) представляет собой полином для сигмы, оцененный в векторе для тау.
Пример. Для n=3
, если i
-й полином равен (x1 - 4)(x3 - 5)(x4 - 4)(x6 - 1)
, а j
-я точка равна (2,2,1,3,5,2)
, то (i,j)
-й элемент матрицы будет (2 - 4)(1 - 5)(3 - 4)(2 - 1) = -8
. Здесь n=3
, поэтому точки находятся в R^(3!) = R^6
, а полиномы имеют 3!=6
переменных.
Моя цель - определить, является ли матрица неособой.
Мой подход сейчас таков:
- функция
point
выполняет перестановку и выводит вектор - функция
poly
выполняет перестановку и выводит полином - функция
nextPerm
дает следующую перестановку в лексикографическом порядке
Сокращенная версия псевдокода моего кода такова:
B := [];
P := [];
w := [1,2,...,n];
while w <> NULL do
B := B append poly(w);
P := P append point(w);
w := nextPerm(w);
od;
// BUILD A MATRIX IN MAPLE
M := Matrix(n!, (i,j) -> eval(B[i],P[j]));
// COMPUTE DETERMINANT IN MAPLE
det := LinearAlgebra[Determinant]( M );
// TELL ME IF IT'S NONSINGULAR
if det = 0 then return false;
else return true; fi;
Я работаю в Maple, используя встроенную функцию LinearAlgebra[Determinant]
, но все остальное — это пользовательская функция, которая использует низкоуровневые функции Maple (например, seq
, convert
и cat
).
Моя проблема в том, что это занимает слишком много времени, то есть я могу набраться терпения до n=7
, но чтобы получить n=8
, нужны дни. В идеале я хочу иметь возможность добраться до n=10
.
У кого-нибудь есть идея, как я могу улучшить время? Я открыт для работы на другом языке, например. Matlab или C, но предпочел бы найти способ ускорить это в Maple.
Я понимаю, что на это может быть трудно ответить без всех кровавых подробностей, но код для каждой функции, например. point
и poly
уже оптимизированы, поэтому реальный вопрос здесь заключается в том, есть ли более быстрый способ получить определитель путем построения матрицы на лету или что-то в этом роде.
ОБНОВЛЕНИЕ: вот две идеи, с которыми я играл, которые не работают:
Я могу сохранить полиномы (поскольку их вычисление занимает некоторое время, я не хочу переделывать это, если смогу) в вектор длины
n!
, вычислить точки на лету и подставить эти значения в перестановку. формула определителя:Проблема здесь в том, что это
O(N!)
по размеру матрицы, поэтому для моего случая это будетO((n!)!)
. Когдаn=10
,(n!)! = 3,628,800!
слишком много, чтобы даже думать об этом.Вычислите определитель, используя разложение LU. К счастью, главная диагональ моей матрицы отлична от нуля, так что это возможно. Поскольку это
O(N^3)
в размере матрицы, это становитсяO((n!)^3)
, что намного ближе к выполнимому. Проблема, однако, в том, что мне нужно хранить всю матрицу, что создает серьезную нагрузку на память, не говоря уже о времени выполнения. Так что это тоже не работает, по крайней мере, без ума. Есть идеи?