forked from nathanieljohnston/QETLAB
-
Notifications
You must be signed in to change notification settings - Fork 0
/
OperatorSchmidtDecomposition.m
64 lines (56 loc) · 2.8 KB
/
OperatorSchmidtDecomposition.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
%% OPERATORSCHMIDTDECOMPOSITION Computes the operator Schmidt decomposition of a bipartite operator
% This function has one required argument:
% X: a bipartite operator
%
% S = OperatorSchmidtDecomposition(X) is a vector containing the non-zero
% operator Schmidt coefficients of the bipartite operator X, where the
% two subsystems are each of size sqrt(length(X)) and X is assumed to be
% square.
%
% This function has two optional input arguments:
% DIM (default has both subsystems of equal size)
% K (default 0)
%
% [S,U,V] = OperatorSchmidtDecomposition(X,DIM,K) gives the operator
% Schmidt coefficients S of the operator X and the corresponding left and
% right tensor operators in the cells U and V. DIM is a 1x2 vector containing
% the dimensions of the subsystems that X lives on. If X is non-square,
% different row and column dimensions can be specified by putting the row
% dimensions in the first row of DIM and the column dimensions in the
% second row of DIM. K is a flag that determines how many terms in the
% operator Schmidt decomposition should be computed. If K = 0 then all
% terms with non-zero operator Schmidt coefficients are computed. If
% K = -1 then all terms (including zero terms) are computed. If K > 0
% then the K terms with largest operator Schmidt coefficients are
% computed.
%
% URL: http://www.qetlab.com/OperatorSchmidtDecomposition
% requires: opt_args.m, PermuteSystems.m, SchmidtDecomposition.m, Swap.m
% author: Nathaniel Johnston ([email protected])
% package: QETLAB
% last updated: November 12, 2014
function [s,U,V] = OperatorSchmidtDecomposition(X,varargin)
dX = size(X);
sdX = round(sqrt(dX));
% set optional argument defaults: dim=sqrt(length(X)), k=0
[dim,k] = opt_args({ [sdX(1) sdX(1);sdX(2) sdX(2)], 0 },varargin{:});
% allow the user to enter a single number for dim
if(length(dim) == 1)
dim = [dim,dX(1)/dim];
if abs(dim(2) - round(dim(2))) >= 2*dX(1)*eps
error('OperatorSchmidtDecomposition:InvalidDim','If DIM is a scalar, X must be square and DIM must evenly divide length(X); please provide the DIM array containing the dimensions of the subsystems.');
end
dim(2) = round(dim(2));
end
% allow the user to enter a vector for dim if X is square
if(min(size(dim)) == 1)
dim = dim(:)'; % force dim to be a row vector
dim = [dim;dim];
end
% The operator Schmidt decomposition is just the Schmidt decomposition of a
% related vector obtained by moving matrix elements around.
[s,u,v] = SchmidtDecomposition(Swap(reshape(X,prod(prod(dim)),1),[2,3],[dim(2,:),dim(1,:)]),prod(dim),k);
% Now reshape things into the proper output format.
sr = length(s);
U = mat2cell(reshape(u,dim(1,1),dim(2,1)*sr),dim(1,1),dim(2,1)*ones(1,sr));
V = mat2cell(reshape(v,dim(1,2),dim(2,2)*sr),dim(1,2),dim(2,2)*ones(1,sr));