"""
Module defines the two basic distance measures *Trace Distance* and
*Quantum Infidelity* for density matrices. Moreover the maximum distance
over two systems can be determined.
"""
import numpy as np
#import numpy.linalg as la
__all__ = ['distance', 'infidelity', 'tracedist',
'single_site_rho_max_distance', 'two_site_rho_max_distance']
[docs]def distance(StateA, StateB, dist='Infidelity'):
"""
Calculate the distance between two quantum states. States can be
either pure states or density matrices. Must be defined on a
Hilbert space of equal size.
**Arguments**
StateA : 1d or 2d numpy array
Represents the first quantum state as pure state or density
matrix.
StateB : 1d or 2d numpy array
Represents the second quantum state as pure state or density
matrix.
dist : str, optional
Define the measure used, e.g. ``Infidelity`` or ``Trace``
distance.
Default to ``Infidelity``.
"""
if(dist == 'Infidelity'):
return infidelity(StateA, StateB)
elif(dist == 'Trace'):
return tracedist(StateA, StateB)
else:
raise Exception("Unknown string identifier for distance.")
[docs]def single_site_rho_max_distance(Out1, Out2, ll, dist='Infidelity'):
"""
Calculate the maximal distance (infidelity) between the single-site
density matrices of two outputs.
**Arguments**
Out1 : dictionary
containing the output of the first simulation.
Out2 : dicitionary
containing the output of the second simulation.
ll : int
system size
dist : str, optional
Choose which distance should be used. Either 'Infidelity' (default)
of 'TraceDistance'.
"""
if(dist == 'Infidelity'):
distancef = infidelity_rho_rho
else:
distancef = tracedist_rho_rho
err = 0.0
for ii in range(1, ll + 1):
infid = distancef(Out1['rho'][str(ii)], Out2['rho'][str(ii)])
err = max(err, np.real(infid))
return err
[docs]def two_site_rho_max_distance(Out1, Out2, ll, dist='Infidelity'):
"""
Calculate the maximal distance (infidelity) between the two-site density
matrices of two outputs.
**Arguments**
Out1 : dictionary
containing the output of the first simulation.
Out2 : dicitionary
containing the output of the second simulation.
ll : int
system size
dist : str, optional
Choose which distance should be used. Either 'Infidelity' (default)
of 'TraceDistance'.
"""
if(dist == 'Infidelity'):
distancef = infidelity_rho_rho
else:
distancef = tracedist_rho_rho
err = 0.0
for ii in range(1, ll):
for jj in range(ii + 1, ll + 1):
key = str(ii) + '_' + str(jj)
infid = distancef(Out1['rho'][key], Out2['rho'][key])
err = max(err, np.real(infid))
return err
# ------------------------------------------------------------------------------
# QUANTUM INFIDELITY
# ------------------------------------------------------------------------------
[docs]def infidelity(StateA, StateB):
"""
Calculate the infidelity :math:`I = 1 - \sqrt{\sqrt{rho} sigma \sqrt{rho}}`
**Arguments**
StateA : 1d or 2d numpy array
Represents the first quantum state as pure state or density
matrix.
StateB : 1d or 2d numpy array
Represents the second quantum state as pure state or density
matrix.
"""
purea = ispure(StateA)
pureb = ispure(StateB)
if(purea and pureb):
return infidelity_psi_psi(StateA, StateB)
elif(purea):
return infidelity_psi_rho(StateA, StateB)
elif(pureb):
return infidelity_psi_rho(StateB, StateA)
else:
return infidelity_rho_rho(StateA, StateB)
[docs]def infidelity_psi_psi(psi, phi):
"""
Calculate the infidelity of two pure states, which simplifies to
:math:`I = 1 - | \\langle \psi | \phi \\rangle`.
**Arguments**
psi : 1d numpy array
Represents the first quantum state for the distance measurement.
phi : 1d numpy array
Represents the second quantum state for the distance measurement.
"""
return 1 - np.abs(psi.conj().dot(phi))
[docs]def infidelity_psi_rho(psi, rho):
"""
Calculate the infidelity of a pure state and a density matrix, which
simplifies to
:math:`I = 1 - \\sqrt{\\langle \psi | \\rho | \psi \\rangle}`.
**Arguments**
psi : 1d numpy array
Represents the first quantum state for the distance measurement,
which is a pure state.
rho : 2d numpy array
Represents the second quantum state for the distance measurement,
which is the density matrix.
"""
return np.real(1 - np.sqrt(psi.conj().dot(rho).dot(psi)))
[docs]def infidelity_rho_rho(rho, sigma):
"""
Calculate the infidelity :math:`I = 1 - \sqrt{\sqrt{rho} sigma \sqrt{rho}}`
**Arguments**
rho : 2d numpy array
First density matrix.
sigma : 2d numpy array
Second density matrix.
"""
tmp = sqrtm(rho)
tmp = np.dot(tmp, np.dot(sigma, tmp))
return np.real(1 - np.trace(sqrtm(tmp)))
# ------------------------------------------------------------------------------
# TRACE DISTANCE
# ------------------------------------------------------------------------------
[docs]def tracedist(StateA, StateB):
"""
Calculate the trace distance :math:`D = 0.5 Tr | rho - sigma |` with
:math:`|A| = \sqrt{A^{\dagger} A}`.
**Arguments**
StateA : 1d or 2d numpy array
Represents the first quantum state as pure state or density
matrix.
StateB : 1d or 2d numpy array
Represents the second quantum state as pure state or density
matrix.
"""
purea = ispure(StateA)
pureb = ispure(StateB)
if(purea and pureb):
return tracedist_psi_psi(StateA, StateB)
elif(purea):
return tracedist_psi_rho(StateA, StateB)
elif(pureb):
return tracedist_psi_rho(StateB, StateA)
else:
return tracedist_rho_rho(StateA, StateB)
[docs]def tracedist_psi_psi(psi, phi):
"""
Calculate the trace distance for two pure states, which simplifies to
:math:`\\sqrt{1 - |\\langle \psi | \phi \\rangle|^2}`
**Arguments**
psi : 1d numpy array
Represents the first quantum state for the distance measurement.
phi : 1d numpy array
Represents the second quantum state for the distance measurement.
"""
return np.sqrt(1 - np.abs(psi.conj().dot(phi))**2)
[docs]def tracedist_psi_rho(psi, rho):
"""
Calculate the trace distance for a pure state and a density matrix, that is
:math:`\\frac{1}{2} \sum_{i} \Lambda_{i}` where :math:`\Lambda_{i}` are the
singular values of :math:`\\rho - | \psi \\rangle \langle \psi |`.
**Arguments**
psi : 1d numpy array
Represents the first quantum state for the distance measurement,
which is a pure state.
rho : 2d numpy array
Represents the second quantum state for the distance measurement,
which is the density matrix.
"""
tmp = rho - np.outer(psi.conj(), psi)
return 0.5 * np.sum(la.svd(tmp, compute_uv=False))
[docs]def tracedist_rho_rho(rho, sigma):
"""
Calculate the trace distance :math:`D = 0.5 Tr | rho - sigma |` with
:math:`|A| = \sqrt{A^{\dagger} A}`.
**Arguments**
rho : 2d numpy array
First density matrix.
sigma : 2d numpy array
Second density matrix.
"""
tmp = rho - sigma
return 0.5 * np.sum(la.svd(tmp, compute_uv=False))
# ------------------------------------------------------------------------------
# AUXILIARY FUNCTIONS
# ------------------------------------------------------------------------------
[docs]def sqrtm(Math):
"""
Calculate the matrix square root of a hermitian matrix
**Arguments**
Math : 2d numpy array (square matrix)
Hermitian matrix for calculating :math:`\sqrt{Math}` of the matrix,
not element-wise.
"""
vals, vecs = la.eigh(Math)
vals[vals < 1e-20] = 0.0
vals = np.sqrt(vals)
return np.dot(vecs, np.dot(np.diag(vals), np.conj(np.transpose(vecs))))
[docs]def ispure(State):
"""
Inquire if state is a pure state. 1d numpy array are pure states, 2d
numpy arrays are density matrices and not pure.
**Arguments**
State : 1d or 2d numpy array
Representing the state.
"""
if(len(State.shape) == 1):
pure = True
elif(len(State.shape) == 2):
pure = False
else:
raise Exception("Passed rank-3 tensor as quantum state.")
return pure