% decompose Creates a string with the Pauli decomposition of a
% Hermitian matrix.
% Form of use: decompose(rho) where rho is the density matrix.
% One can print in LaTeX format with decompose(rho,1).
% For the numbering of qubits we note that mkron(x,y,z) is
% decomposed into "xyz" or "X^{(1)}Y^{(2)}Z^{(3)}".
% For the LaTeX output the numbering is different from
% the one used in other commands (e.g., reorder) in which
% the numbering of qubits were 3 2 1 and not 1 2 3. This is
% to help to produce a LaTeX formula that can directly be
% used in a paper. Form decompose(rho,mode,threshold)
% makes it possible to give a threshold. Below this
% value a correlation is considered zero. Default is 1e-14.
function pstring=decompose(rho,varargin)
% Correlations smaller than that are taken to be zero
mincorr=1e-14;
LaTeXON=0;
if ~isempty(varargin),
if length(varargin)>=1,
LaTeXON=varargin{1};
end %if
if length(varargin)==2,
mincorr=varargin{2};
end %if
if length(varargin)>2,
error('Wrong number of input arguments.')
end %if
end %if
x=[0 1;1 0];
z=[1 0;0 -1];
y=i*x*z;
e=eye(2);
% Use sparse matrices
e=sparse(e);
x=sparse(x);
y=sparse(y);
z=sparse(z);
% rho=ketbra2(rho);
[sy,sx]=size(rho);
N=log2(sx);
pstring='';
OPstr='1xyz';
OPstr2='EXYZ';
opindex=zeros(N);
while 1
switch opindex(1)
case 0, op=e;
case 1, op=x;
case 2, op=y;
case 3, op=z;
end %switch
for m=2:N
switch opindex(m)
case 0, op=kron(op,e);
case 1, op=kron(op,x);
case 2, op=kron(op,y);
case 3, op=kron(op,z);
end %switch
end %for
if trace(rho*op)~=0,
% Correlations: Use "real" to get rid off small imaginary parts
corr=real(trace(rho*op))/2^N;
termstr='';
% Construct string for the term
if LaTeXON,
if opindex==zeros(N),
termstr='E';
else
for m=1:N
if opindex (m) >0,
termstr=[termstr,OPstr2(opindex(m)+1) '^{(' num2str(m) ')}' ];
end %if
end %for
end %if
else
for m=1:N
termstr=[termstr,OPstr(opindex(m)+1)];
end %for
end %if
if isempty(pstring),
if abs(corr-1)<mincorr,
pstring=[termstr];
elseif abs(corr+1)<mincorr,
pstring=['-' termstr];
elseif abs(corr)>mincorr,
pstring=[num2str(corr) '*' termstr];
end %if
else
if corr>mincorr,
if abs(corr-1)<mincorr,
pstring=[pstring '+' termstr];
else
pstring=[pstring '+' num2str(corr) '*' termstr];
end %if
elseif corr<-mincorr,
if abs(corr+1)<mincorr,
pstring=[pstring '-' termstr];
else
pstring=[pstring '-' num2str(abs(corr)) '*' termstr];
end %if
end %if
end %if
end %if
% Increase counter
k=N;
opindex(k)=opindex(k)+1;
while opindex(k)==4
opindex(k)=0;
k=k-1;
if k==0,
if isempty(pstring),
pstring='0';
end %if
return
end %if
opindex(k)=opindex(k)+1;
end %while
end %while