Генерация Случайных Не Сингулярных Целочисленных Матриц
в рамках алгоритма синтетического шума, я должен построить на лету много больших невырожденных квадратных матриц
a i, j (i, j: 1..n) / ∀ (i,j) a i, j ∈ ℤ и 0 ≤ a i, j ≤ k и Det[a] ≠ 0
но a i, j также должно быть случайным после равномерного распределения в [0, k].
в своем нынешнем воплощении проблема имеет n ≅ 300, k≅ 100.
In Mathematica, я могу генерировать матрицы случайных элементов очень быстро, но проблема в том, что я также должен проверить сингулярность. В настоящее время я использую для этого значение Determinant.
проблема в том, что эта проверка для матриц 300x300 занимает около 2 секунд, и я не могу себе этого позволить.
конечно, я могу построить строки, выбрав случайную первую строку, а затем построив последовательные ортогональные строки, но я не уверен, как гарантировать, что эти строки будут имеют свои элементы, следующие равномерному распределению в [0, k].
Я ищу решение в Mathematica, но также приветствуется более быстрый алгоритм генерации матриц.
NB> условие U[0,k] означает, что принято множество матриц, каждая позиция (i , j) по множеству должно следовать равномерное распределение.
4 ответов
если вы используете числовые приближенные матрицы в тестах сингулярности, вы получите гораздо лучшую скорость.
k = 100; n = 500;
mat = RandomInteger[100, {n, n}];
AbsoluteTiming[Det[mat] == 0]
Out[57]= {6.8640000, False}
AbsoluteTiming[Det[N@mat] == 0.] (*warning light!!*)
Out[58]= {0.0230000, False}
AbsoluteTiming[MatrixRank[N@mat] != n]
Out[59]= {0.1710000, False}
к сожалению, этот самый быстрый тест не является надежным. Но тест на звание должен работать хорошо. Вот краткий пример, в котором мы заменяем последнюю строку суммой предыдущих строк.
mat2 = mat;
mat2[[-1]] = Total[Most[mat]];
AbsoluteTiming[Det[mat2] == 0]
Out[70]= {9.4750000, True}
AbsoluteTiming[Det[N@mat2] == 0.]
Out[69]= {0.0470000, False}
AbsoluteTiming[MatrixRank[N@mat2] != n]
Out[71]= {0.1440000, True}
в принципе, я полагаю, что есть небольшой шанс, что тест ранга может дать ложное отрицание. скажем из-за плохого кондиционирования. Поскольку ваше использование будет лучше переносить ложные срабатывания (то есть неправильные утверждения о сингулярности), вы можете вместо этого проверить сингулярность по простому модулю. Я думаю, что это была одна из рекомендаций других сделанный.
продолжение приведенных выше примеров:
AbsoluteTiming[Det[mat, Modulus -> Prime[1000]]]
выход[77]= {0.6320000, 4054}
AbsoluteTiming[Det[mat2, Modulus -> Prime[1000]]]
выход[78]= {0.6470000, 0}
это медленно, но быстрее, чем более рациональных. Для чего это стоит, для большинства использования я был бы довольно уверен в результатах более быстрого тестирования через MatrixRank[N[matrix]].
Даниил Лихтблау Wolfram Research
как в Matlab, так и в Octave детерминант и Lu-факторизация матрицы 500x500 в основном мгновенны. У Mathematica есть режим, в котором он может вызвать LAPACK или какую-то подобную библиотеку? Возможно, вам придется отметить, что ваши массивы следует рассматривать как числа с плавающей запятой, а не символически; это может сделать это намного быстрее. Для сравнения, LU на матрице 5000x5000 занимает 8,66 секунды в моей системе с использованием Октавы; 500x500 должен быть примерно в 1000 раз быстрее чем.
можно использовать . На моей машине это примерно в n / 10 раз быстрее для больших целочисленных матриц nxn.
вот расширение комментария, который я сделал немного. Я согласен с Дэном, что очень маловероятно, что числовая версия вернет ложноположительный результат. Тем не менее, вы можете избежать этого сценария, изучив сингулярные значения и надежно вернув False, если наименьшее сингулярное значение больше некоторого допуска к ошибке. (По общему признанию, было бы немного сложно найти доказуемую терпимость.) Если наименьшее сингулярное значение неудобно мало, вы можете применить Det к целому числу матрица.
вот функция, которая должна быстро возвращать False для большинства неособых матриц. Если матрица близка к сингулярной, выполняется более дорогостоящее целочисленное вычисление.
singularQ[M_?MatrixQ] := If[
Last[SingularValueList[N[M], Tolerance -> 0]] > 1/10.0^8,
False, Det[M] == 0];
вот 200 матриц, которые соответствуют вашему описанию. Один в середине был сфальсифицирован как единственный.
SeedRandom[1];
matrices = RandomInteger[{0, 100}, {200, 300, 300}];
matrices[[100, -1]] = Sum[RandomInteger[{0, 10}]*matrices[[100, k]],
{k, 1, Length[matrices[[100]]] - 1}];
Теперь давайте найдем индексы всех сингулярных матриц, наблюдая, как мы идем.
Flatten@Monitor[Table[
If[singularQ[matrices[[k]]], k, {}],
{k, 1, Length[matrices]}], k]