Код гольфу випадковою ортогональною матрицею


9

Ортогональна матриця являє собою квадратну матрицю з речовими елементами , чиї стовпці і рядки є ортогональні орти (тобто ортонормального вектори).

Це означає, що M ^ TM = I, де I - матриця тотожності, а ^ T означає матричне переміщення.

Зауважимо, що це ортогональне, а не "особливе ортогональне", тому визначник M може бути 1 або -1.

Мета цього завдання не є машинною точністю, тому якщо M ^ TM = I в межах 4 знаків після коми, це буде добре.

Завдання полягає в тому, щоб записати код, який приймає додатне ціле число n > 1і виводить випадкову ортогональну n по матриці n . Матриця повинна бути обрана випадковим чином і рівномірно з усіх n n ортогональних матриць. У цьому контексті "рівномірний" визначається з точки зору міри Хаар, яка по суті вимагає, щоб розподіл не змінювався, якщо помножити на будь-яку вільно обрану ортогональну матрицю. Це означає, що значення матриці будуть значеннями з плаваючою комою в діапазоні від -1 до 1.

Введення та вихід можуть бути в будь-якій формі, яку вам зручно.

Покажіть явний приклад запущеного коду.

Ви не можете використовувати будь-яку функцію бібліотеки, яка створює ортогональні матриці. Це правило трохи тонке, тому я поясню докладніше. Це правило забороняє використовувати будь-яку існуючу функцію, яка займає деякий (або ні) вхід і виводить матрицю розміром принаймні n на n, яка гарантовано є ортогональною. Як крайній приклад, якщо ви хочете матрицю тотожності n за n, вам доведеться створити її самостійно.

Ви можете використовувати будь-яку стандартну бібліотеку генераторів випадкових чисел для вибору випадкових чисел на ваш вибір.

Ваш код має заповнитись не пізніше ніж за кілька секунд n < 50.


Тож використання вбудованої матриці ідентичності заборонено?
JungHwan Min

@JHM Ви не можете використовувати його для створення принаймні матриці ідентичності n за n.

Про що diag? Він створює діагональну матрицю, яка справді є ортогональною, але не завжди ортонормальною.
Карл Напф

Це, мабуть, є прикладом "зробити X без Y", якого - таким чином консенсусу - слід уникати.
flawr

1
Діагональні матриці не є ортогональними матрицями, тому diagповинно бути нормально.
Ангс

Відповіді:


7

Haskell, 169 150 148 141 132 131 байт

import Numeric.LinearAlgebra
z=(unitary.flatten<$>).randn 1
r 1=asRow<$>z 1
r n=do;m<-r$n-1;(<>diagBlock[m,1]).haussholder 2<$>z n

Рекурсивно розширюйте ортогональну матрицю розміру n-1, додаючи 1 до правого нижнього кута та застосуйте випадкове відображення домочадців. randnдає матрицю з випадковими значеннями з гауссового розподілу і z dдає рівномірно розподілений одиничний вектор у dрозмірах.

haussholder tau vповертає матрицю, I - tau*v*vᵀяка не є ортогональною, коли vне є одиничним вектором.

Використання:

*Main> m <- r 5
*Main> disp 5 m
5x5
-0.24045  -0.17761   0.01603  -0.83299  -0.46531
-0.94274   0.12031   0.00566   0.29741  -0.09098
-0.02069   0.30417  -0.93612  -0.13759   0.10865
 0.02155  -0.83065  -0.35109   0.32365  -0.28556
-0.22919  -0.41411   0.01141  -0.30659   0.82575
*Main> (<1e-14) . maxElement . abs $ tr m <> m - ident 5
True

Створення 1×1матриці займає занадто багато місця на мій смак, особливий випадок лише для отримання нуля від гауссової випадкової величини: / (Без цього існує нескінченний малий шанс отримати нульовий стовпчик)
Angs

Мені подобається ваш дух зробити це абсолютно правильним, але я думаю, ви можете відмовитися від цієї вимоги. У моєму коді також є ймовірність того, що 2 ряди лінійно залежні і нікого не цікавить.
Карл Напф

@KarlNapf добре, я придумав спосіб втратити два байти з тієї частини, так що проблема частково вирішена :)
Angs

Ну добре, видаляючи мої коментарі ...
Карл Напф

Завжди щасливий, коли відповідь Haskell виграє!

4

Python 2 + NumPy, 163 байти

Завдяки xnor за те, що вказав на використання звичайних розподілених випадкових значень замість однакових.

from numpy import*
n=input()
Q=random.randn(n,n)
for i in range(n):
 for j in range(i):u=Q[:,j];Q[:,i]-=u*dot(u,Q[:,i])/dot(u,u)
Q/=(Q**2).sum(axis=0)**0.5
print Q

Використовує ортогоналізацію Грама Шмідта на матриці з гауссовими випадковими значеннями, щоб мати усі напрямки.

Демонстраційний код дотримується

print dot(Q.transpose(),Q)

n = 3:

[[-0.2555327   0.89398324  0.36809917]
 [-0.55727299  0.17492767 -0.81169398]
 [ 0.79003155  0.41254608 -0.45349298]]
[[  1.00000000e+00   0.00000000e+00   0.00000000e+00]
 [  0.00000000e+00   1.00000000e+00  -5.55111512e-17]
 [  0.00000000e+00  -5.55111512e-17   1.00000000e+00]]

n = 5:

[[-0.63470728  0.41984536  0.41569193  0.25708079  0.42659843]
 [-0.36418389  0.06244462 -0.82734663 -0.24066123  0.3479231 ]
 [ 0.07863783  0.7048799   0.08914089 -0.64230492 -0.27651168]
 [ 0.67691426  0.33798442 -0.05984083  0.17555011  0.62702062]
 [-0.01095148 -0.45688226  0.36217501 -0.65773717  0.47681205]]
[[  1.00000000e+00   1.73472348e-16   5.37764278e-17   4.68375339e-17
   -2.23779328e-16]
 [  1.73472348e-16   1.00000000e+00   1.38777878e-16   3.33066907e-16
   -6.38378239e-16]
 [  5.37764278e-17   1.38777878e-16   1.00000000e+00   1.38777878e-16
    1.11022302e-16]
 [  4.68375339e-17   3.33066907e-16   1.38777878e-16   1.00000000e+00
    5.55111512e-16]
 [ -2.23779328e-16  -6.38378239e-16   1.11022302e-16   5.55111512e-16
    1.00000000e+00]]

Він завершується за мить протягом n = 50 та декількох секунд за n = 500.


Я не думаю, що це однаково. Ваш початковий розподіл за допомогою куба, який має більше речей у напрямку діагоналей. Випадкові гаусианці спрацюють, оскільки вони генерують сферично симетричний розподіл.
xnor

@xnor виправлено. На щастя, це коштувало рівно 1 байт.
Карл Напф

@xnor Ще більше пощастило, що це врятувало байтів для-0.5
Karl Napf

Майже вам потрібно, щоб середнє значення нормального було 0, але це не більше ніж n.
xnor

-1

Математика, 69 байт, ймовірно, не конкуруючий

#&@@QRDecomposition@Array[RandomVariate@NormalDistribution[]&,{#,#}]&

QRDecompositionповертає пару матриць, перша з яких гарантовано є ортогональною (а друга з них не ортогональна, а верхня трикутна). Можна стверджувати, що це технічно підкоряється букві обмеження в дописі: воно виводить не ортогональну матрицю, а пару матриць ....

Математика, 63 байти, безумовно, не конкурує

Orthogonalize@Array[RandomVariate@NormalDistribution[]&,{#,#}]&

Orthogonalizeоднозначно заборонено ОП. Тим не менш, Mathematica досить класний, так?


You may not use any existing library function which creates orthogonal **matrices**.
Карл Напф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.