def test_power_except(self):
     """Test power method raises exceptions."""
     chan = Chi(self.depol_chi(1))
     # Negative power raises error
     self.assertRaises(QiskitError, chan.power, -1)
     # 0 power raises error
     self.assertRaises(QiskitError, chan.power, 0)
     # Non-integer power raises error
     self.assertRaises(QiskitError, chan.power, 0.5)
    def test_init(self):
        """Test initialization"""
        mat4 = np.eye(4) / 2.0
        chan = Chi(mat4)
        self.assertAllClose(chan.data, mat4)
        self.assertEqual(chan.dims, (2, 2))

        mat16 = np.eye(16) / 4
        chan = Chi(mat16)
        self.assertAllClose(chan.data, mat16)
        self.assertEqual(chan.dims, (4, 4))

        # Wrong input or output dims should raise exception
        self.assertRaises(QiskitError, Chi, mat16, input_dim=2, output_dim=4)

        # Non multi-qubit dimensions should raise exception
        self.assertRaises(
            QiskitError, Chi, np.eye(6) / 2, input_dim=3, output_dim=2)
    def test_subtract_inplace(self):
        """Test inplace subtract method."""
        mat1 = 0.5 * self.chiI
        mat2 = 0.5 * self.depol_chi(1)
        targ = Chi(mat1 - mat2)

        chan1 = Chi(mat1)
        chan2 = Chi(mat2)
        chan1.subtract(chan2, inplace=True)
        self.assertEqual(chan1, targ)

        chan1 = Chi(mat1)
        chan2 = Chi(mat2)
        chan1 -= chan2
        self.assertEqual(chan1, targ)
    def test_add_inplace(self):
        """Test inplace add method."""
        mat1 = 0.5 * self.chiI
        mat2 = 0.5 * self.depol_chi(1)
        targ = Chi(mat1 + mat2)

        chan1 = Chi(mat1)
        chan2 = Chi(mat2)
        chan1.add(chan2, inplace=True)
        self.assertEqual(chan1, targ)

        chan1 = Chi(mat1)
        chan2 = Chi(mat2)
        chan1 += chan2
        self.assertEqual(chan1, targ)
 def test_from_qiskit(self):
     """
     Test quantum channels created from qiskit are equals to quantum channels
     created by qiskit -> to myqlm -> to qiskit
     """
     circuit = QuantumCircuit(3)
     circuit.h(0)
     circuit.cx(0, 1)
     circuit.x(2)
     self.assertEqual(
         Kraus(circuit),
         qchannel_to_qiskit(qiskit_to_qchannel(Kraus(circuit))))
     self.assertEqual(Chi(circuit),
                      qchannel_to_qiskit(qiskit_to_qchannel(Chi(circuit))))
     self.assertEqual(Choi(circuit),
                      qchannel_to_qiskit(qiskit_to_qchannel(Choi(circuit))))
     self.assertEqual(
         SuperOp(circuit),
         qchannel_to_qiskit(qiskit_to_qchannel(SuperOp(circuit))))
     self.assertEqual(PTM(circuit),
                      qchannel_to_qiskit(qiskit_to_qchannel(PTM(circuit))))
    def test_multiply_inplace(self):
        """Test inplace multiply method."""
        chan = Chi(self.chiI)
        val = 0.5
        targ = Chi(val * self.chiI)
        chan.multiply(val, inplace=True)
        self.assertEqual(chan, targ)

        chan = Chi(self.chiI)
        chan *= val
        self.assertEqual(chan, targ)
 def test_from_myqlm_chi(self):
     """
     Test all combinations of chi quantum channel between myqlm and qiskit
     """
     arr = np.arange(64 * 64, dtype=complex).reshape((64, 64))
     basis = [array_to_matrix(arr)]
     qchannel = QuantumChannel(representation=RepresentationType.CHI,
                               arity=3,
                               basis=basis)
     qiskit_qchannel = Chi(arr)
     self.assertEqual(qchannel,
                      qiskit_to_qchannel(qchannel_to_qiskit(qchannel)))
     self.assertEqual(qiskit_qchannel, qchannel_to_qiskit(qchannel))
     self.assertEqual(qchannel, qiskit_to_qchannel(qiskit_qchannel))
Example #8
0
    def test_dot(self):
        """Test dot method."""
        # Random input test state
        rho = DensityMatrix(self.rand_rho(2))

        # UnitaryChannel evolution
        chan1 = Chi(self.chiX)
        chan2 = Chi(self.chiY)
        target = rho.evolve(Chi(self.chiZ))
        output = rho.evolve(chan2.dot(chan1))
        self.assertEqual(output, target)

        # Compose random
        chi1 = self.rand_matrix(4, 4, real=True)
        chi2 = self.rand_matrix(4, 4, real=True)
        chan1 = Chi(chi1, input_dims=2, output_dims=2)
        chan2 = Chi(chi2, input_dims=2, output_dims=2)
        target = rho.evolve(chan1).evolve(chan2)
        output = rho.evolve(chan2.dot(chan1))
        self.assertEqual(output, target)
Example #9
0
    def test_add(self):
        """Test add method."""
        mat1 = 0.5 * self.chiI
        mat2 = 0.5 * self.depol_chi(1)
        chan1 = Chi(mat1)
        chan2 = Chi(mat2)

        targ = Chi(mat1 + mat2)
        self.assertEqual(chan1._add(chan2), targ)
        self.assertEqual(chan1 + chan2, targ)

        targ = Chi(mat1 - mat2)
        self.assertEqual(chan1 - chan2, targ)
Example #10
0
    def test_expand(self):
        """Test expand method."""
        # Pauli channels
        paulis = [self.chiI, self.chiX, self.chiY, self.chiZ]
        targs = 4 * np.eye(16)  # diagonals of Pauli channel Chi mats
        for i, chi1 in enumerate(paulis):
            for j, chi2 in enumerate(paulis):
                chan1 = Chi(chi1)
                chan2 = Chi(chi2)
                chan = chan1.expand(chan2)
                # Target for diagonal Pauli channel
                targ = Chi(np.diag(targs[i + 4 * j]))
                self.assertEqual(chan.dim, (4, 4))
                self.assertEqual(chan, targ)

        # Completely depolarizing
        rho = np.diag([1, 0, 0, 0])
        chan_dep = Chi(self.depol_chi(1))
        chan = chan_dep.expand(chan_dep)
        targ = np.diag([1, 1, 1, 1]) / 4
        self.assertEqual(chan.dim, (4, 4))
        self.assertAllClose(chan._evolve(rho), targ)
Example #11
0
 def test_negate(self):
     """Test negate method"""
     chan = Chi(self.chiI)
     targ = Chi(-self.chiI)
     self.assertEqual(-chan, targ)
Example #12
0
 def test_multiply_except(self):
     """Test multiply method raises exceptions."""
     chan = Chi(self.chiI)
     self.assertRaises(QiskitError, chan.multiply, 's')
     self.assertRaises(QiskitError, chan.multiply, chan)
Example #13
0
 def test_subtract_except(self):
     """Test subtract method raises exceptions."""
     chan1 = Chi(self.chiI)
     chan2 = Chi(np.eye(16))
     self.assertRaises(QiskitError, chan1.subtract, chan2)
     self.assertRaises(QiskitError, chan1.subtract, 5)
Example #14
0
 def test_add_except(self):
     """Test add method raises exceptions."""
     chan1 = Chi(self.chiI)
     chan2 = Chi(np.eye(16))
     self.assertRaises(QiskitError, chan1.add, chan2)
     self.assertRaises(QiskitError, chan1.add, 5)
Example #15
0
    def test_compose_front(self):
        """Test front compose method."""
        # Random input test state
        rho = self.rand_rho(2)

        # UnitaryChannel evolution
        chan1 = Chi(self.chiX)
        chan2 = Chi(self.chiY)
        chan = chan2.compose(chan1, front=True)
        targ = Chi(self.chiZ)._evolve(rho)
        self.assertAllClose(chan._evolve(rho), targ)

        # Compose random
        chi1 = self.rand_matrix(4, 4, real=True)
        chi2 = self.rand_matrix(4, 4, real=True)
        chan1 = Chi(chi1, input_dims=2, output_dims=2)
        chan2 = Chi(chi2, input_dims=2, output_dims=2)
        targ = chan2._evolve(chan1._evolve(rho))
        chan = chan2.compose(chan1, front=True)
        self.assertEqual(chan.dim, (2, 2))
        self.assertAllClose(chan._evolve(rho), targ)
Example #16
0
 def test_compose_except(self):
     """Test compose different dimension exception"""
     self.assertRaises(QiskitError, Chi(np.eye(4)).compose, Chi(np.eye(16)))
     self.assertRaises(QiskitError, Chi(np.eye(4)).compose, 2)
Example #17
0
    def test_compose(self):
        """Test compose method."""
        # Random input test state
        rho = self.rand_rho(2)

        # UnitaryChannel evolution
        chan1 = Chi(self.chiX)
        chan2 = Chi(self.chiY)
        chan = chan1.compose(chan2)
        targ = Chi(self.chiZ)._evolve(rho)
        self.assertAllClose(chan._evolve(rho), targ)

        # 50% depolarizing channel
        chan1 = Chi(self.depol_chi(0.5))
        chan = chan1.compose(chan1)
        targ = Chi(self.depol_chi(0.75))._evolve(rho)
        self.assertAllClose(chan._evolve(rho), targ)

        # Compose random
        chi1 = self.rand_matrix(4, 4, real=True)
        chi2 = self.rand_matrix(4, 4, real=True)
        chan1 = Chi(chi1, input_dims=2, output_dims=2)
        chan2 = Chi(chi2, input_dims=2, output_dims=2)
        targ = chan2._evolve(chan1._evolve(rho))
        chan = chan1.compose(chan2)
        self.assertEqual(chan.dim, (2, 2))
        self.assertAllClose(chan._evolve(rho), targ)
        chan = chan1 @ chan2
        self.assertEqual(chan.dim, (2, 2))
        self.assertAllClose(chan._evolve(rho), targ)
Example #18
0
    def test_tensor_inplace(self):
        """Test inplace tensor method."""
        # Pauli channels
        paulis = [self.chiI, self.chiX, self.chiY, self.chiZ]
        targs = 4 * np.eye(16)  # diagonals of Pauli channel Chi mats
        for i, chi1 in enumerate(paulis):
            for j, chi2 in enumerate(paulis):
                chan1 = Chi(chi1)
                chan2 = Chi(chi2)
                chan2.tensor(chan1, inplace=True)
                # Target for diagonal Pauli channel
                targ = Chi(np.diag(targs[i + 4 * j]))
                self.assertEqual(chan2.dims, (4, 4))
                self.assertEqual(chan2, targ)
                # Test operator overload
                chan1 = Chi(chi1)
                chan2 = Chi(chi2)
                chan2 ^= chan1
                self.assertEqual(chan2.dims, (4, 4))
                self.assertEqual(chan2, targ)

        # Completely depolarizing
        rho = np.diag([1, 0, 0, 0])
        chan_dep = Chi(self.depol_chi(1))
        chan_dep.tensor(chan_dep, inplace=True)
        targ = np.diag([1, 1, 1, 1]) / 4
        self.assertEqual(chan_dep.dims, (4, 4))
        self.assertAllClose(chan_dep._evolve(rho), targ)
        # Test operator overload
        chan_dep = Chi(self.depol_chi(1))
        chan_dep ^= chan_dep
        self.assertEqual(chan_dep.dims, (4, 4))
        self.assertAllClose(chan_dep._evolve(rho), targ)
Example #19
0
    def test_evolve(self):
        """Test evolve method."""
        input_psi = [0, 1]
        input_rho = [[0, 0], [0, 1]]

        # Identity channel
        chan = Chi(self.chiI)
        target_rho = np.array([[0, 0], [0, 1]])
        self.assertAllClose(chan._evolve(input_psi), target_rho)
        self.assertAllClose(chan._evolve(np.array(input_psi)), target_rho)
        self.assertAllClose(chan._evolve(input_rho), target_rho)
        self.assertAllClose(chan._evolve(np.array(input_rho)), target_rho)

        # Hadamard channel
        chan = Chi(self.chiH)
        target_rho = np.array([[1, -1], [-1, 1]]) / 2
        self.assertAllClose(chan._evolve(input_psi), target_rho)
        self.assertAllClose(chan._evolve(np.array(input_psi)), target_rho)
        self.assertAllClose(chan._evolve(input_rho), target_rho)
        self.assertAllClose(chan._evolve(np.array(input_rho)), target_rho)

        # Completely depolarizing channel
        chan = Chi(self.depol_chi(1))
        target_rho = np.eye(2) / 2
        self.assertAllClose(chan._evolve(input_psi), target_rho)
        self.assertAllClose(chan._evolve(np.array(input_psi)), target_rho)
        self.assertAllClose(chan._evolve(input_rho), target_rho)
        self.assertAllClose(chan._evolve(np.array(input_rho)), target_rho)
Example #20
0
 def test_circuit_init(self):
     """Test initialization from a circuit."""
     circuit, target = self.simple_circuit_no_measure()
     op = Chi(circuit)
     target = Chi(target)
     self.assertEqual(op, target)
Example #21
0
def qchannel_to_qiskit(representation):
    """
    Create a qiskit representation of quantum channel from a myqlm representation
    of a quantum channel.

    Args:
        representation: (QuantumChannel) myqlm representation of a quantum channel.

    Returns:
        (Kraus|Choi|Chi|SuperOp|PTM): qiskit representation of a quantum channel.
    """

    rep = representation.representation
    # Find what representation it is.
    # Then create the corresponding matrix and shape it like qiskit is expecting it.
    # Finally, create the qiskit representation from that matrix.
    if rep in (RepresentationType.PTM, RepresentationType.CHOI):
        matri = representation.matrix
        data_re = []
        data_im = []
        for i in range(matri.nRows):
            for j in range(matri.nCols):
                data_re.append(matri.data[i * matri.nRows + j].re + 0.j)
                data_im.append(matri.data[i * matri.nRows + j].im)
        data = np.array(data_re)
        data.imag = np.array(data_im)
        data = data.reshape((matri.nRows, matri.nCols))
        return PTM(data) if (rep == RepresentationType.PTM) else Choi(data)
    if rep in (RepresentationType.CHI, RepresentationType.SUPEROP):
        final_data = []
        for matri in representation.basis:
            data_re = []
            data_im = []
            for i in range(matri.nRows):
                for j in range(matri.nCols):
                    data_re.append(matri.data[i * matri.nRows + j].re + 0.j)
                    data_im.append(matri.data[i * matri.nRows + j].im)
            data = np.array(data_re)
            data.imag = np.array(data_im)
            data = data.reshape((matri.nRows, matri.nCols))
            final_data.append(data)
        if rep == RepresentationType.CHI:
            return Chi(final_data) if len(final_data) > 1 else Chi(
                final_data[0])
        return SuperOp(final_data) if len(final_data) > 1 else SuperOp(
            final_data[0])
    if rep == RepresentationType.KRAUS:
        final_data = []
        for matri in representation.kraus_ops:
            data_re = []
            data_im = []
            for i in range(matri.nRows):
                for j in range(matri.nCols):
                    data_re.append(matri.data[i * matri.nRows + j].re + 0.j)
                    data_im.append(matri.data[i * matri.nRows + j].im)
            data = np.array(data_re)
            data.imag = np.array(data_im)
            data = data.reshape((matri.nRows, matri.nCols))
            final_data.append(data)
        return Kraus(final_data)
    return None
Example #22
0
def _transform_by_operator_list(
        basis_ops: Sequence[Union[QuantumChannel, QuantumError]],
        target: Union[QuantumChannel, QuantumError]) -> List[float]:
    r"""
    Transform (or approximate) the target quantum channel into a mixture of
    basis operators (channels) and return the mixing probabilities.

    The approximate channel is found by minimizing the Hilbert-Schmidt
    distance between the process matrix of the target channel (:math:`T`) and
    the process matrix of the output channel (:math:`S = \sum_i{p_i S_i}`),
    i.e. :math:`Tr[(T-S)^\dagger (T-S)]`,
    where
    :math:`[p_1, p_2, ..., p_n]` denote probabilities and
    :math:`[S_1, S_2, ..., S_n]` denote basis operators (channels).

    Such an optimization can represented as a quadratic program:
    Minimize :math:`p^T A p + b^T p`,
    subject to :math:`p \ge 0`, `\sum_i{p_i} = 1`, `\sum_i{p_i} = 1`.
    The last constraint is for making the approximation conservative by
    forcing the output channel have more error than the target channel
    in the sense that a "fidelity" against identity channel should be worse.

    See `arXiv:1207.0046 <http://arxiv.org/abs/1207.0046>`_ for the details.

    Args:
        target: Quantum channel to be transformed.
        basis_ops: a list of channel objects constructing the output channel.

    Returns:
        list: A list of amplitudes (probabilities) of basis that define the output channel.

    Raises:
        MissingOptionalLibraryError: if cvxpy is not installed.
    """
    # pylint: disable=invalid-name
    N = 2**basis_ops[0].num_qubits
    # add identity channel in front
    basis_ops = [Kraus(np.eye(N))] + basis_ops

    # create objective function coefficients
    basis_ops_mats = [Chi(op).data for op in basis_ops]
    T = Chi(target).data
    n = len(basis_ops_mats)
    A = np.zeros((n, n))
    for i, S_i in enumerate(basis_ops_mats):
        for j, S_j in enumerate(basis_ops_mats):
            # A[i][j] = 1/2 * {Tr(S_i^† S_j) - Tr(S_j^† S_i)} = Re[Tr(S_i^† S_j)]
            if i < j:
                A[i][j] = _hs_inner_prod_real(S_i, S_j)
            elif i > j:
                A[i][j] = A[j][i]
            else:  # i==j
                A[i][i] = _hs_norm(S_i)
    b = -2 * np.array([_hs_inner_prod_real(T, S_i) for S_i in basis_ops_mats])

    # c = _hs_norm(T)

    # create honesty constraint coefficients
    def fidelity(channel):  # fidelity w.r.t. identity omitting the N^-2 factor
        return float(np.abs(np.trace(SuperOp(channel))))

    source_fids = np.array([fidelity(op) for op in basis_ops])
    target_fid = fidelity(target)

    try:
        import cvxpy
    except ImportError as err:
        logger.error("cvxpy module needs to be installed to use this feature.")
        raise MissingOptionalLibraryError(
            libname="cvxpy",
            name="Transformation/Approximation of noise",
            pip_install="pip install cvxpy",
            msg="CVXPY is required to solve an optimization problem of"
            " approximating a noise channel.") from err
    # create quadratic program
    x = cvxpy.Variable(n)
    prob = cvxpy.Problem(cvxpy.Minimize(cvxpy.quad_form(x, A) + b.T @ x),
                         constraints=[
                             cvxpy.sum(x) <= 1, x >= 0,
                             source_fids.T @ x <= target_fid
                         ])
    # solve quadratic program
    prob.solve()
    probabilities = x.value
    return probabilities
Example #23
0
 def test_equal(self):
     """Test __eq__ method"""
     mat = self.rand_matrix(4, 4, real=True)
     self.assertEqual(Chi(mat), Chi(mat))
Example #24
0
    def test_sub_qargs(self):
        """Test subtract method with qargs."""
        mat = self.rand_matrix(8**2, 8**2)
        mat0 = self.rand_matrix(4, 4)
        mat1 = self.rand_matrix(4, 4)

        op = Chi(mat)
        op0 = Chi(mat0)
        op1 = Chi(mat1)
        op01 = op1.tensor(op0)
        eye = Chi(self.chiI)

        with self.subTest(msg='qargs=[0]'):
            value = op - op0([0])
            target = op - eye.tensor(eye).tensor(op0)
            self.assertEqual(value, target)

        with self.subTest(msg='qargs=[1]'):
            value = op - op0([1])
            target = op - eye.tensor(op0).tensor(eye)
            self.assertEqual(value, target)

        with self.subTest(msg='qargs=[2]'):
            value = op - op0([2])
            target = op - op0.tensor(eye).tensor(eye)
            self.assertEqual(value, target)

        with self.subTest(msg='qargs=[0, 1]'):
            value = op - op01([0, 1])
            target = op - eye.tensor(op1).tensor(op0)
            self.assertEqual(value, target)

        with self.subTest(msg='qargs=[1, 0]'):
            value = op - op01([1, 0])
            target = op - eye.tensor(op0).tensor(op1)
            self.assertEqual(value, target)

        with self.subTest(msg='qargs=[0, 2]'):
            value = op - op01([0, 2])
            target = op - op1.tensor(eye).tensor(op0)
            self.assertEqual(value, target)

        with self.subTest(msg='qargs=[2, 0]'):
            value = op - op01([2, 0])
            target = op - op0.tensor(eye).tensor(op1)
            self.assertEqual(value, target)
Example #25
0
 def test_is_cptp(self):
     """Test is_cptp method."""
     self.assertTrue(Chi(self.depol_chi(0.25)).is_cptp())
     # Non-CPTP should return false
     self.assertFalse(
         Chi(1.25 * self.chiI - 0.25 * self.depol_chi(1)).is_cptp())
Example #26
0
    def test_compose(self):
        """Test compose method."""
        # Random input test state
        rho = DensityMatrix(self.rand_rho(2))

        # UnitaryChannel evolution
        chan1 = Chi(self.chiX)
        chan2 = Chi(self.chiY)
        chan = chan1.compose(chan2)
        target = rho.evolve(Chi(self.chiZ))
        output = rho.evolve(chan)
        self.assertEqual(output, target)

        # 50% depolarizing channel
        chan1 = Chi(self.depol_chi(0.5))
        chan = chan1.compose(chan1)
        target = rho.evolve(Chi(self.depol_chi(0.75)))
        output = rho.evolve(chan)
        self.assertEqual(output, target)

        # Compose random
        chi1 = self.rand_matrix(4, 4, real=True)
        chi2 = self.rand_matrix(4, 4, real=True)
        chan1 = Chi(chi1, input_dims=2, output_dims=2)
        chan2 = Chi(chi2, input_dims=2, output_dims=2)
        target = rho.evolve(chan1).evolve(chan2)
        chan = chan1.compose(chan2)
        output = rho.evolve(chan)
        self.assertEqual(chan.dim, (2, 2))
        self.assertEqual(output, target)
        chan = chan1 @ chan2
        output = rho.evolve(chan)
        self.assertEqual(chan.dim, (2, 2))
        self.assertEqual(output, target)