diff options
author | Eugeniy E. Mikhailov <evgmik@gmail.com> | 2024-11-20 17:38:02 -0500 |
---|---|---|
committer | Eugeniy E. Mikhailov <evgmik@gmail.com> | 2024-11-20 17:39:07 -0500 |
commit | db7ee776d2a10f50752c23f57b11184cb3347a15 (patch) | |
tree | b77da6830cafcaec80cef4568d4d8e87bfa3eb12 /takagi.m | |
parent | 984d56b4d94bf298a197f1567834451acf49cab9 (diff) | |
download | matlab_strawberryfields-db7ee776d2a10f50752c23f57b11184cb3347a15.tar.gz matlab_strawberryfields-db7ee776d2a10f50752c23f57b11184cb3347a15.zip |
draft of bloch_messiah
Diffstat (limited to 'takagi.m')
-rw-r--r-- | takagi.m | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/takagi.m b/takagi.m new file mode 100644 index 0000000..f9375a8 --- /dev/null +++ b/takagi.m @@ -0,0 +1,77 @@ +function [rl, U] = takagi(N, tol, rounding) + % Autonne-Takagi decomposition of a complex symmetric (not Hermitian!) matrix. + % + % Args: + % N (complex matrix): square, symmetric matrix N + % tol (double): tolerance for symmetry check (default: 1e-13) + % rounding (integer): decimal places for rounding singular values (default: 13) + % + % Returns: + % rl (vector): rounded singular values + % U (matrix): Takagi unitary, such that N = U * diag(rl) * U.' + + if nargin < 2 + tol = 1e-13; + end + if nargin < 3 + rounding = 13; + end + + [n, m] = size(N); + + if n ~= m + error('The input matrix must be square'); + end + + if norm(N - N.') >= tol + error('The input matrix is not symmetric'); + end + + if all(abs(imag(N(:))) < eps) + N = real(N); + end + + if all(N(:) == 0) + rl = zeros(n, 1); + U = eye(n); + return; + end + + if isreal(N) + % If the matrix N is real, use its eigendecomposition + [U, L] = eig(N); + l = diag(L); + vals = abs(l); + phases = sqrt(complex(sign(l))); + Uc = U * diag(phases); + + [sorted_l, idx] = sort(vals, 'descend'); + Uc = Uc(:, idx); + + rl = sorted_l; + U = Uc; + return; + end + + [v, l, ws] = svd(N); + w = ws'; + rl = round(diag(l), rounding); + + % Group degenerate singular values + [~, ~, ic] = unique(rl); + result = accumarray(ic, (1:numel(rl))', [], @(x) {x}); + + % Generate the matrices qs of the degenerate subspaces + qs = cell(1, length(result)); + for i = 1:length(result) + idx = result{i}; + vas = v(:, idx); + was = w(:, idx); + qs{i} = sqrtm(vas' * was); + end + + % Construct the Takagi unitary + qb = blkdiag(qs{:}); + U = v * conj(qb); +end + |