def test_partial_transpose_bipartite():
    """partial transpose of bipartite systems"""

    rho = Qobj(np.arange(16).reshape(4, 4), dims=[[2, 2], [2, 2]])

    # no transpose
    rho_pt = partial_transpose(rho, [0, 0])
    assert_(np.abs(np.max(rho_pt.full() - rho.full())) < 1e-12)

    # partial transpose subsystem 1
    rho_pt = partial_transpose(rho, [1, 0])
    rho_pt_expected = np.array([[0, 1,  8,  9],
                                [4, 5, 12, 13],
                                [2, 3, 10, 11],
                                [6, 7, 14, 15]])
    assert_(np.abs(np.max(rho_pt.full() - rho_pt_expected)) < 1e-12)

    # partial transpose subsystem 2
    rho_pt = partial_transpose(rho, [0, 1])
    rho_pt_expected = np.array([[0, 4, 2, 6],
                                [1, 5, 3, 7],
                                [8, 12, 10, 14],
                                [9, 13, 11, 15]])
    assert_(np.abs(np.max(rho_pt.full() - rho_pt_expected)) < 1e-12)

    # full transpose
    rho_pt = partial_transpose(rho, [1, 1])
    assert_(np.abs(np.max(rho_pt.full() - rho.trans().full())) < 1e-12)
def test_partial_transpose_comparison():
    """partial transpose: comparing sparse and dense implementations"""

    N = 10
    rho = tensor(rand_dm(N, density=0.5), rand_dm(N, density=0.5))

    # partial transpose of system 1
    rho_pt1 = partial_transpose(rho, [1, 0], method="dense")
    rho_pt2 = partial_transpose(rho, [1, 0], method="sparse")
    np.abs(np.max(rho_pt1.full() - rho_pt1.full())) < 1e-12

    # partial transpose of system 2
    rho_pt1 = partial_transpose(rho, [0, 1], method="dense")
    rho_pt2 = partial_transpose(rho, [0, 1], method="sparse")
    np.abs(np.max(rho_pt1.full() - rho_pt2.full())) < 1e-12
def test_partial_transpose_randomized():
    """partial transpose: randomized tests on tripartite system"""

    rho = tensor(rand_dm(2, density=1),
                 rand_dm(2, density=1),
                 rand_dm(2, density=1))

    mask = np.random.randint(2, size=3)

    rho_pt_ref = _partial_transpose_reference(rho, mask)

    rho_pt1 = partial_transpose(rho, mask, method="dense")
    np.abs(np.max(rho_pt1.full() - rho_pt_ref.full())) < 1e-12

    rho_pt2 = partial_transpose(rho, mask, method="sparse")
    np.abs(np.max(rho_pt2.full() - rho_pt_ref.full())) < 1e-12
示例#4
1
def peres_horodecki_bipartite(rho, mask=[0,1]):
    """ Tests the given bipartite state for Peres-Horodecki criterion
    
    Parameters
    ----------
    rho: qobj/array-like
        Density operator for the state
    mask: list of int, length 2
        mask used for partial transpose
    
    Returns
    -------
    isentangled: bool
        True for entangled, False for disentangled
    
    """
    if rho.type != 'oper':
        raise TypeError("Input must be a density matrix")
    rhopt = partial_transpose(rho,mask)
    rhopt_eigs = rhopt.eigenenergies()
    if min(rhopt_eigs) < 0:
        isentangled = True
    else:
        isentangled = False
    return isentangled
示例#5
1
def log_neg(rho,mask=[1,0]):
    """ Calculate the logarithmic negativity for a density matrix
    
    Parameters:
    -----------
    rho : qobj/array-like
        Input density matrix
    
    Returns:
    --------
    logneg: Logarithmic Negativity
    
    """
    if rho.type != 'oper':
        raise TypeError("Input must be a density matrix")
    rhopt = partial_transpose(rho,mask)
    logneg = log2( rhopt.norm() )
    return logneg
示例#6
1
def negativity(rho,mask=[1,0]):
    """ Calculate the negativity for a density matrix
    
    Parameters:
    -----------
    rho : qobj/array-like
        Input density matrix
    
    Returns:
    --------
    neg : Negativity
    
    """
    if rho.type != 'oper':
        raise TypeError("Input must be a density matrix")
    rhopt = partial_transpose(rho,mask)
    neg = ( rhopt.norm() - 1 ) / 2
    return neg
示例#7
0
def test_partial_transpose_randomized():
    """partial transpose: randomized tests on tripartite system"""

    rho = tensor(rand_dm(2, density=1), rand_dm(2, density=1),
                 rand_dm(2, density=1))

    mask = np.random.randint(2, size=3)

    rho_pt_ref = _partial_transpose_reference(rho, mask)

    rho_pt1 = partial_transpose(rho, mask, method="dense")
    np.abs(np.max(rho_pt1.full() - rho_pt_ref.full())) < 1e-12

    rho_pt2 = partial_transpose(rho, mask, method="sparse")
    np.abs(np.max(rho_pt2.full() - rho_pt_ref.full())) < 1e-12
示例#8
0
def test_partial_transpose_comparison():
    """partial transpose: comparing sparse and dense implementations"""

    N = 10
    rho = tensor(rand_dm(N, density=0.5), rand_dm(N, density=0.5))

    # partial transpose of system 1
    rho_pt1 = partial_transpose(rho, [1, 0], method="dense")
    rho_pt2 = partial_transpose(rho, [1, 0], method="sparse")
    np.abs(np.max(rho_pt1.full() - rho_pt1.full())) < 1e-12

    # partial transpose of system 2
    rho_pt1 = partial_transpose(rho, [0, 1], method="dense")
    rho_pt2 = partial_transpose(rho, [0, 1], method="sparse")
    np.abs(np.max(rho_pt1.full() - rho_pt2.full())) < 1e-12
示例#9
0
def peres_horodecki_bipartite(rho, mask=[0, 1]):
    """ Tests the given bipartite state for Peres-Horodecki criterion
    
    Parameters
    ----------
    rho: qobj/array-like
        Density operator for the state
    mask: list of int, length 2
        mask used for partial transpose
    
    Returns
    -------
    isentangled: bool
        True for entangled, False for disentangled
    
    """
    if rho.type != 'oper':
        raise TypeError("Input must be a density matrix")
    rhopt = partial_transpose(rho, mask)
    rhopt_eigs = rhopt.eigenenergies()
    if min(rhopt_eigs) < 0:
        isentangled = True
    else:
        isentangled = False
    return isentangled
def least_ent_eig(r, theta, a_z):
    rho=(1/4)*(qt.tensor(qt.qeye(2), qt.qeye(2)) + qt.tensor(a_z*qt.sigmaz(), qt.qeye(2))\
               - r*np.sin(theta)/np.sqrt(2)*qt.tensor(qt.sigmax(),qt.sigmax())\
                   - r*np.sin(theta)/np.sqrt(2)*qt.tensor(qt.sigmay(),qt.sigmay())\
                       - r*np.cos(theta)*qt.tensor(qt.sigmaz(),qt.sigmaz()))
    rho_pt = qt.partial_transpose(rho, [0, 1])
    eigs = np.linalg.eigvalsh(rho_pt.full())
    return min(eigs)
示例#11
0
def test_partial_transpose_bipartite():
    """partial transpose of bipartite systems"""

    rho = Qobj(np.arange(16).reshape(4, 4), dims=[[2, 2], [2, 2]])

    # no transpose
    rho_pt = partial_transpose(rho, [0, 0])
    assert_(np.abs(np.max(rho_pt.full() - rho.full())) < 1e-12)

    # partial transpose subsystem 1
    rho_pt = partial_transpose(rho, [1, 0])
    rho_pt_expected = np.array([[0, 1, 8, 9], [4, 5, 12, 13], [2, 3, 10, 11],
                                [6, 7, 14, 15]])
    assert_(np.abs(np.max(rho_pt.full() - rho_pt_expected)) < 1e-12)

    # partial transpose subsystem 2
    rho_pt = partial_transpose(rho, [0, 1])
    rho_pt_expected = np.array([[0, 4, 2, 6], [1, 5, 3, 7], [8, 12, 10, 14],
                                [9, 13, 11, 15]])
    assert_(np.abs(np.max(rho_pt.full() - rho_pt_expected)) < 1e-12)

    # full transpose
    rho_pt = partial_transpose(rho, [1, 1])
    assert_(np.abs(np.max(rho_pt.full() - rho.trans().full())) < 1e-12)
示例#12
0
def negativity(rho, mask=[1, 0]):
    """ Calculate the negativity for a density matrix
    
    Parameters:
    -----------
    rho : qobj/array-like
        Input density matrix
    
    Returns:
    --------
    neg : Negativity
    
    """
    if rho.type != 'oper':
        raise TypeError("Input must be a density matrix")
    rhopt = partial_transpose(rho, mask)
    neg = (rhopt.norm() - 1) / 2
    return neg
示例#13
0
def create_dataset(n_samples):
  """Create dataset.
  
  Parameters:
  n_samples(int): Number of samples
  
  Output:
  _states(list): States associated with each set of measurements.
  _measurements(list): Measurements.
  _labels(list): Label associated with each set of measurements.
  """

  _states = []
  _labels = []
  _measurements = []

  #Basis Measured
  name_basis = ['I', 'X', 'Y', 'Z']
  basis = [qutip.identity(2), qutip.sigmax(),qutip.sigmay(),qutip.sigmaz()]



  for _ in range(n_samples):    
    density = qutip.rand_dm(4, density=0.75, dims=[[2,2],[2,2]])
    
    #Partial Transpose
    density_partial_T = qutip.partial_transpose(density, [0,1])    
  
    #Labels: 1 if entangled 0 if separable (PPT Criterion)
    if (density_partial_T.eigenenergies() < 0).any():
      _labels.append(1)
  
    else:      
      _labels.append(-1)  

    _states.append(density)  
  
    val_measurements = measurement(density_matrix=density, 
                                   base=basis, 
                                   name_base=name_basis)
  
    _measurements.append(val_measurements)
    
  return _states, _measurements, _labels
示例#14
0
def generate_separable(n_samples):
  """Create n_samples separable states.
  
  Parameters:
  n_samples(int): Number of samples
  
  Output:
  states_train(list): States associated with each set of measurements.
  measurements_train(list):  measurements
  """
  _states = []  
  _measurements = []

  #Basis Measured
  name_basis = ['I', 'X', 'Y', 'Z']
  basis = [qutip.identity(2), qutip.sigmax(),qutip.sigmay(),qutip.sigmaz()]


  counter = 0

  while not counter == n_samples:    
    density = qutip.rand_dm(4, density=0.75, dims=[[2,2],[2,2]])
    
    #Partial Transpose
    density_partial_T = qutip.partial_transpose(density, [0,1])    
  
    #Labels: 1 if entangled 0 if separable (PPT Criterion)
    if (density_partial_T.eigenenergies() < 0).any():      
      pass
  
    else:      
      _states.append(density)  
  
      val_measurements = measurement(density_matrix=density, 
                                   base=basis, 
                                   name_base=name_basis)
  
      _measurements.append(val_measurements)
      
      counter += 1

  return _states, _measurements
示例#15
0
def entangled(state):
    if state.shape == (4, 4):
        return (np.any(q.partial_transpose(state, [1, 0]).eigenenergies() < 0))
    else:
        raise TypeError(
            'The Peres-Horodecki criterion only works for pairs of qubits.')
示例#16
0
def simulate_process_prep_measure(E_AB, prep_meas_settings):
    """
    Simulate measurements for process tomography using the prepare-and-measure
    scheme, given a "true" quantum process `E_AB`, a list of input states and
    measurement settings specified by `prep_meas_settings`.

    The process `E_AB` should be a :py:class:`qutip.Qobj` containing the Choi
    matrix of the channel being applied, as a :py:class:`qutip.Qobj` matrix (NOT
    as a superoperator).  It should not be normalized, i.e., we expect
    :math:`\mathrm{tr}_B(E_{AB}) = \mathbb{I}_A`.

    The argument `prep_meas_settings` must be a list of tuples `(sigma_in,
    Mk_out, num_repeats)`, where `sigma_in` is an input state specified as a
    :py:class:`qutip.Qobj` object, where `Mk_out` is a POVM specified as a list
    of POVM effects (each POVM effect is a positive semidefinite matrix of norm
    ≤ 1, and is specified as a :py:class:`qutip.Qobj` matrix), and finally
    `num_repeats` is the number of times to repeat this setting.

    Returns: an object `d` with properties `d.Emn_ch`, `d.Nm`, representing the
    arguments suitable for :py:meth:`QPtomographer.channelspace.run()` and the
    simulated frequency counts.
    """

    Emn_ch = []
    Nm = []

    dimA = E_AB.dims[0][0]
    dimB = E_AB.dims[0][1]
    dimAB = dimA * dimB

    for (sigma_in, Mk_out, num_repeats) in prep_meas_settings:

        # calculate the output state after sending sigma_in through the process
        rho_out = (E_AB * qutip.tensor(qutip.partial_transpose(sigma_in, [1]),
                                       qutip.qeye(dimB))).ptrace(1)

        # output POVM
        num_out_effects = len(Mk_out)

        # get some random numbers for this measurement setting
        x = np.random.rand(num_repeats)
        proboffset = 0

        # We sample the measurement outcomes as follows: we split the interval
        # [0,1] in number sections equal to the number of possible outcomes,
        # each of length = probability of that outcome.  Then, for each possible
        # outcome, we count the number of random numbers in `x` that fall into
        # the corresponding section.

        for Mk in Mk_out:
            p = qutip.expect(Mk, rho_out)  # = trace(Mk * rho_out)
            Emn_ch.append(
                qutip.tensor(qutip.partial_transpose(sigma_in, [1]),
                             Mk).data.toarray().astype(dtype=complex))
            Nm.append(
                np.count_nonzero((proboffset <= x) & (x < proboffset + p)))
            proboffset += p

        # sanity check
        assert np.abs(proboffset - 1.0) < 1e-6

    d = _Store()
    d.Emn_ch = Emn_ch
    d.Nm = np.array(Nm)
    return d
# Set initial state
sys = cv.System(N, 2)
r = np.arcsinh(np.sqrt(mu))
#sys.apply_SMS(r)
sys.apply_TMS(r)

# Make state no Gaussian
k = 0.4
sys.apply_photon_subtraction(k, 1)

psi0 = sys.state
if psi0.isket:
    rho0 = psi0 * psi0.dag()

# State with partial transpose
rho = qt.partial_transpose(rho0, [1, 0])

# Method 1 - Fastest
norm = rho.norm()
log_neg = np.log2(norm)

# Method 2
rho2 = rho * rho.dag()
norm2 = (rho2.sqrtm()).tr()
log_neg2 = np.log2(norm2)

# Method 3 - for Gaussian states - best approx for small N?
sys.set_state(rho)
sys.set_quadratures_basis()
cm = sys.get_full_CM()
print(cm)