Я пытаюсь оптимизировать сложную симметричную унитарную матрицу 𝐴 с размерами N*N с использованием Python.
Прежде всего, как сгенерировать матрицу 𝐴, которая должна удовлетворять двум условиям:
𝐴=𝐴^{T} (симметричное ограничение), где 𝐴^{T} — транспонирование 𝐴
𝐴 . 𝐴^{H}= I (унитарное ограничение), где 𝐴^{H} — эрмитово транспонирование 𝐴, а I — единичная матрица.
Во-вторых, я буду использовать его, чтобы максимизировать матричное умножение матрицы B с размерностями N*N, чтобы узнать, как выполнить это матричное умножение, пока 𝐴 остается одновременно симметричным и унитарным.
import random
import numpy as np
import cmath
import math
N = 4 # Matrices dimensions
B=np.array([[0.09+0.76j, 0.67+0.08j, 0.28+0.58j],
[0.47+0.82j, 0.85+0.07j, 0.13+0.49j],
[0.12+0.8j , 0.35+0.31j, 0.76+0.85j]])
result = A @ B
Если ваша исходная матрица не имеет определителя 0, используйте процесс Грама-Шмидта для создания ортогональных столбцов (серия операций по удалению проекций предыдущих столбцов), а затем сделайте их ортонормированными в конце. например math.stackexchange.com/questions/2162190/…
Можете ли вы привести пример кода того, как это выполняется?
Сначала найдите унитарную матрицу U (основная часть материала ниже). Затем V=UTU будет симметричным и унитарным.
Сложнее всего получить унитарную матрицу U. Матрица унитарна тогда и только тогда, когда ее столбцы ортонормированы. (Скалярное произведение разных столбцов равно 0; норма каждого столбца равна 1.) Таким образом, вы можете построить такую матрицу с помощью процесса Грама-Шмидта.
Представьте, что каждый столбец вашей матрицы является вектором. Работая с каждым столбцом по очереди, вы (а) вычитаете проекции предыдущих векторов-столбцов; затем (б) нормализовать этот столбец. Пока у вас есть независимые столбцы (т.е. ваша исходная матрица была обратимой), это приведет к созданию ортонормированных столбцов и, следовательно, к унитарной матрице.
Следующее действие создаст унитарную матрицу из заданной матрицы A. Унитарная матрица — это матрица, для которой сопряженное к ней транспонирование является ее инверсией (см. https://en.wikipedia.org/wiki/Unitary_matrix). В конце он проверяет это путем умножения, чтобы получить единичную матрицу (с точностью до обычной точности с плавающей запятой).
Вы можете улучшить это, (а) сначала проверив, что матрица A обратима (например, вычислив ее определитель) и (б) отформатировав выходные данные немного более аккуратно.
import numpy as np
def makeUnitary( A ):
N = A.shape[0] # number of columns
U = A.copy()
# Gram-Schmidt process
U[:,0] /= np.linalg.norm( U[:,0] ) # normalise first column
for i in range( 1, N ): # make successive columns orthogonal
for j in range( i ): # by subtracting projections of previous columns
U[:,i] -= U[:,i].dot( U[:,j].conj() ) * U[:,j]
U[:,i] /= np.linalg.norm( U[:,i] ) # normalise column
return U
A=np.array([[0.09+0.76j, 0.67+0.08j, 0.28+0.58j],
[0.47+0.82j, 0.85+0.07j, 0.13+0.49j],
[0.12+0.8j , 0.35+0.31j, 0.76+0.85j]])
U = makeUnitary( A ) # a unitary matrix
V = U.T @ U # symmetrised unitary matrix
print( "Original matrix:\n", A )
print( "\nSymmetric unitary matrix constructed from it:\n", V )
print( "\nCheck V.V(conj)T (should be identity matrix):\n", V @ V.conj().T )
Выход:
Original matrix:
[[0.09+0.76j 0.67+0.08j 0.28+0.58j]
[0.47+0.82j 0.85+0.07j 0.13+0.49j]
[0.12+0.8j 0.35+0.31j 0.76+0.85j]]
Symmetric unitary matrix constructed from it:
[[-0.77181963+0.51542139j 0.15837321+0.05726809j -0.30709606+0.12635484j]
[ 0.15837321+0.05726809j 0.40398494-0.53221372j -0.43217941-0.581725j ]
[-0.30709606+0.12635484j -0.43217941-0.581725j 0.55047024-0.24804427j]]
Check V.V(conj)T (should be identity matrix):
[[1.00000000e+00-2.05296819e-18j 3.93579786e-16-6.38754713e-16j
6.37756498e-17-6.66363810e-16j]
[3.93579786e-16+6.24994617e-16j 1.00000000e+00-1.58327863e-18j
1.09796762e-16-1.28773584e-16j]
[6.37756498e-17+6.55406471e-16j 1.09796762e-16+1.49124945e-16j
1.00000000e+00-8.89174271e-19j]]
Унитарную матрицу можно диагонализировать (т. е. записать как Q-1.diag.Q). Затем степени U можно быстро вычислить, просто взяв степени элементов диагональной матрицы.
Большое спасибо за это подробное объяснение, и последнее, когда я показываю U и UT (чтобы проверить, симметричен ли U), они не равны, как сделать его одновременно унитарным и симметричным?
Ах да, мне следовало более внимательно прочитать ваши требования. В любом случае исходный код просто создавал унитарную матрицу (из обратимой матрицы A). Затем просто создайте новую матрицу V=UT.U. Быстрая проверка покажет, что он также унитарен и симметричен.
Большое спасибо за эту полезную информацию, мне просто любопытно, почему новая матрица V становится унитарной и симметричной в результате простого умножения UT.U, а также я только что прочитал о том, что разложение qr берет матрицу Q из команды Q , R = np.linalg.qr(A) аналогично тому, что вы сделали ранее, чтобы сделать его унитарным? еще раз спасибо за ваши усилия.
Любая матрица вида MT.M симметрична, поскольку произведение (A.B)T = BT.AT транспонировано. Для унитарной матрицы вам просто нужно будет сформировать произведение (UT.U)T*(UT.U), и после большого количества умножений внутренних битов вы получите I — итак, унитарную матрицу. Грамм-Шмидт — это один из способов выполнения QR-разложения (на самом деле, это первый способ, который я когда-либо изучал), однако он подвержен некоторой числовой нестабильности из-за неточности операций с плавающей запятой.
Сначала сгенерируйте случайную унитарную матрицу , затем используйте формулу из этого ответа, чтобы сделать ее симметричной. Хотя может быть есть какой-то лучший способ сделать это (я не эксперт в этом)