PartialTranspose
From QETLAB
PartialTranspose | |
Computes the partial transpose of a matrix | |
Other toolboxes required | none |
---|---|
Related functions | PartialMap PartialTrace |
Function category | Superoperators |
PartialTranspose is a function that computes the partial transpose of a matrix. The transposition may be taken on any subset of the subsystems on which the matrix acts.
Syntax
- XPT = PartialTranspose(X)
- XPT = PartialTranspose(X,SYS)
- XPT = PartialTranspose(X,SYS,DIM)
Argument descriptions
- X: A matrix to have its partial transpose returned.
- SYS (optional, default 2): A scalar or vector containing the indices of the subsystems on which the transpose is to be applied.
- DIM (optional, by default has all subsystems of equal dimension): A specification of the dimensions of the subsystems that X lives on. DIM can be provided in one of three ways:
- If DIM is a scalar, it is assumed that X lives on the tensor product of two spaces, the first of which has dimension DIM and the second of which has dimension length(X)/DIM.
- If $X \in M_{n_1} \otimes \cdots \otimes M_{n_p}$ then DIM should be a row vector containing the dimensions (i.e., DIM = [n_1, ..., n_p]).
- If the subsystems aren't square (i.e., $X \in M_{m_1, n_1} \otimes \cdots \otimes M_{m_p, n_p}$) then DIM should be a matrix with two rows. The first row of DIM should contain the row dimensions of the subsystems (i.e., the m_{i}'s) and its second row should contain the column dimensions (i.e., the n_{i}'s). In other words, you should set DIM = [m_1, ..., m_p; n_1, ..., n_p].
Examples
A bipartite square matrix
By default, the PartialTranspose function performs the transposition on the second subsystem:
>> X = reshape(1:16,4,4)' X = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 >> PartialTranspose(X) ans = 1 5 3 7 2 6 4 8 9 13 11 15 10 14 12 16
By specifying the SYS argument, you can perform the transposition on the first subsystem instead:
>> PartialTranspose(X,1) ans = 1 2 9 10 5 6 13 14 3 4 11 12 7 8 15 16
Applying the transpose to both the first and second subsystems results in the standard transpose of X:
>> norm(PartialTranspose(X,[1,2]) - X.') ans = 0
Source code
Click on "expand" to the right to view the MATLAB source code for this function.
%% PARTIALTRANSPOSE Computes the partial transpose of a matrix
% This function has one required argument:
% X: a matrix
%
% XPT = PartialTranspose(X) is the partial transpose of the matrix X,
% where it is assumed that the number of rows and columns of X are both
% perfect squares and both subsystems have equal dimension. The transpose
% is applied to the second subsystem.
%
% This function has two optional arguments:
% SYS (default 2)
% DIM (default has all subsystems of equal dimension)
%
% XPT = PartialTranspose(X,SYS,DIM) gives the partial transpose of the
% matrix X, where the dimensions of the (possibly more than 2)
% subsystems are given by the vector DIM and the subsystems to take the
% partial transpose on are given by the scalar or vector SYS. 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.
%
% URL: http://www.qetlab.com/PartialTranspose
% requires: opt_args.m, PermuteSystems.m
% author: Nathaniel Johnston (nathaniel@njohnston.ca)
% package: QETLAB
% last updated: December 28, 2012
function Xpt = PartialTranspose(X,varargin)
dX = size(X);
sdX = round(sqrt(dX));
% set optional argument defaults: sys=2, dim=round(sqrt(length(X)))
[sys,dim] = opt_args({ 2, [sdX(1) sdX(1);sdX(2) sdX(2)] },varargin{:});
num_sys = length(dim);
% allow the user to enter a single number for dim
if(num_sys == 1)
dim = [dim,dX(1)/dim];
if abs(dim(2) - round(dim(2))) >= 2*dX(1)*eps
error('PartialTranspose: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));
num_sys = 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
% prepare the partial transposition
prod_dimR = prod(dim(1,:));
prod_dimC = prod(dim(2,:));
sub_prodR = prod(dim(1,sys));
sub_prodC = prod(dim(2,sys));
sub_sys_vecR = prod_dimR*ones(1,sub_prodR)/sub_prodR;
sub_sys_vecC = prod_dimC*ones(1,sub_prodC)/sub_prodC;
perm = [sys,setdiff(1:num_sys,sys)];
Xpt = PermuteSystems(X,perm,dim); % permute the subsystems so that we just have to do the partial transpose on the first (potentially larger) subsystem
if(isnumeric(Xpt)) % if the input is a numeric matrix, perform the partial transpose operation the fastest way we know how
Xpt = cell2mat(mat2cell(Xpt, sub_sys_vecR, sub_sys_vecC).'); % partial transpose on first subsystem
else % if the input is not numeric (such as a variable in a semidefinite program), do a slower method that avoids mat2cell (mat2cell doesn't like non-numeric arrays)
Xpt = reshape(permute(reshape(Xpt,[sub_sys_vecR(1),sub_prodR,sub_sys_vecC(1),sub_prodC]),[1,4,3,2]),[sub_sys_vecR(1)*sub_prodC,sub_sys_vecC(1)*sub_prodR]);
end
% return the subsystems back to their original positions
dim(:,sys) = dim([2,1],sys);
dim = dim(:,perm);
Xpt = PermuteSystems(Xpt,perm,dim,0,1);