示例#1
0
    def set_up_ops(self, N):
        """
        Generate the Hamiltonians for the spinchain model and save them in the
        attribute `ctrls`.

        Parameters
        ----------
        N: int
            The number of qubits in the system.
        """
        self.pulse_dict = {}
        index = 0
        # sx_ops
        for m in range(N):
            self.pulses.append(
                Pulse(sigmax(), m, spline_kind=self.spline_kind))
            self.pulse_dict["sx" + str(m)] = index
            index += 1
        # sz_ops
        for m in range(N):
            self.pulses.append(
                Pulse(sigmaz(), m, spline_kind=self.spline_kind))
            self.pulse_dict["sz" + str(m)] = index
            index += 1
        # sxsy_ops
        operator = tensor([sigmax(), sigmax()]) + tensor([sigmay(), sigmay()])
        for n in range(N - 1):
            self.pulses.append(
                Pulse(operator, [n, n+1], spline_kind=self.spline_kind))
            self.pulse_dict["g" + str(n)] = index
            index += 1
示例#2
0
    def add_states(self, state, kind='vector'):
        """Add a state vector Qobj to Bloch sphere.

        Parameters
        ----------
        state : qobj
            Input state vector.

        kind : str {'vector','point'}
            Type of object to plot.

        """
        if isinstance(state, Qobj):
            state = [state]
        for st in state:
            if kind == 'vector':
                vec = [
                    expect(sigmax(), st),
                    expect(sigmay(), st),
                    expect(sigmaz(), st)
                ]
                self.add_vectors(vec)
            elif kind == 'point':
                pnt = [
                    expect(sigmax(), st),
                    expect(sigmay(), st),
                    expect(sigmaz(), st)
                ]
                self.add_points(pnt)
示例#3
0
def TestBasicPulse():
    """
    Test for basic pulse generation and attributes.
    """
    coeff = np.array([0.1, 0.2, 0.3, 0.4])
    tlist = np.array([0., 1., 2., 3.])
    ham = sigmaz()

    # Basic tests
    pulse1 = Pulse(ham, 1, tlist, coeff)
    assert_allclose(
        pulse1.get_ideal_qobjevo(2).ops[0].qobj, tensor(identity(2), sigmaz()))
    pulse1.tlist = 2 * tlist
    assert_allclose(pulse1.tlist, 2 * tlist)
    pulse1.tlist = tlist
    pulse1.coeff = 2 * coeff
    assert_allclose(pulse1.coeff, 2 * coeff)
    pulse1.coeff = coeff
    pulse1.qobj = 2 * sigmay()
    assert_allclose(pulse1.qobj, 2 * sigmay())
    pulse1.qobj = ham
    pulse1.targets = 3
    assert_allclose(pulse1.targets, 3)
    pulse1.targets = 1
    assert_allclose(pulse1.get_ideal_qobj(2), tensor(identity(2), sigmaz()))
示例#4
0
    def test_simple_hadamard(self):
        """
        Test for optimizing a simple hadamard gate
        """
        N = 1
        H_d = sigmaz()
        H_c = sigmax()
        qc = QubitCircuit(N)
        qc.add_gate("SNOT", 0)

        # test load_circuit, with verbose info
        num_tslots = 10
        evo_time = 10
        test = OptPulseProcessor(N, drift=H_d)
        test.add_control(H_c, targets=0)
        tlist, coeffs = test.load_circuit(qc,
                                          num_tslots=num_tslots,
                                          evo_time=evo_time,
                                          verbose=True)

        # test run_state
        rho0 = qubit_states(1, [0])
        plus = (qubit_states(1, [0]) + qubit_states(1, [1])).unit()
        result = test.run_state(rho0)
        assert_allclose(fidelity(result.states[-1], plus), 1, rtol=1.0e-6)

        # test add/remove ctrl
        test.add_control(sigmay())
        test.remove_pulse(0)
        assert_(len(test.pulses) == 1,
                msg="Method of remove_pulse could be wrong.")
        assert_allclose(test.drift.drift_hamiltonians[0].qobj, H_d)
        assert_(sigmay() in test.ctrls,
                msg="Method of remove_pulse could be wrong.")
示例#5
0
    def test_simple_hadamard(self):
        N = 1
        H_d = sigmaz()
        H_c = [sigmax()]
        qc = QubitCircuit(N)
        qc.add_gate("SNOT", 0)

        # test load_circuit, with verbose info
        num_tslots = 10
        evo_time = 10
        test = OptPulseProcessor(N, H_d, H_c)
        tlist, coeffs = test.load_circuit(
            qc, num_tslots=num_tslots, evo_time=evo_time, verbose=True)

        # test run_state
        rho0 = qubit_states(1, [0])
        plus = (qubit_states(1, [0]) + qubit_states(1, [1])).unit()
        result = test.run_state(rho0)
        assert_allclose(fidelity(result.states[-1], plus), 1, rtol=1.0e-6)

        # test add/remove ctrl
        test.add_ctrl(sigmay())
        test.remove_ctrl(0)
        assert_(
            len(test.ctrls) == 1,
            msg="Method of remove_ctrl could be wrong.")
        assert_allclose(test.drift, H_d)
        assert_(
            sigmay() in test.ctrls,
            msg="Method of remove_ctrl could be wrong.")
示例#6
0
def concurrence(rho):
    """
    Calculate the concurrence entanglement measure for
    a two-qubit state.

    Parameters
    ----------
    rho : qobj
        Density matrix for two-qubits.

    Returns
    -------
    concur : float
        Concurrence

    """
    if rho.dims != [[2, 2], [2, 2]]:
        raise Exception("Density matrix must be tensor product of two qubits.")

    sysy = tensor(sigmay(), sigmay())

    rho_tilde = (rho * sysy) * (rho.conj() * sysy)

    evals = rho_tilde.eigenenergies()

    # abs to avoid problems with sqrt for very small negative numbers
    evals = abs(sort(real(evals)))

    lsum = sqrt(evals[3]) - sqrt(evals[2]) - sqrt(evals[1]) - sqrt(evals[0])

    return max(0, lsum)
示例#7
0
    def test_multi_gates(self):
        N = 2
        H_d = tensor([sigmaz()]*2)
        H_c = []

        test = OptPulseProcessor(N, H_d, H_c)
        test.add_ctrl(sigmax(), cyclic_permutation=True)
        test.add_ctrl(sigmay(), cyclic_permutation=True)
        test.add_ctrl(tensor([sigmay(), sigmay()]))

        # qubits circuit with 3 gates
        setting_args = {"SNOT": {"num_tslots": 10, "evo_time": 1},
                        "SWAP": {"num_tslots": 30, "evo_time": 3},
                        "CNOT": {"num_tslots": 30, "evo_time": 3}}
        qc = QubitCircuit(N)
        qc.add_gate("SNOT", 0)
        qc.add_gate("SWAP", targets=[0, 1])
        qc.add_gate('CNOT', controls=1, targets=[0])
        test.load_circuit(qc, setting_args=setting_args,
                          merge_gates=False)

        rho0 = rand_ket(4)  # use random generated ket state
        rho0.dims = [[2, 2], [1, 1]]
        U = gate_sequence_product(qc.propagators())
        rho1 = U * rho0
        result = test.run_state(rho0)
        assert_(fidelity(result.states[-1], rho1) > 1-1.0e-6)
示例#8
0
def TestPulseConstructor():
    """
    Test for creating empty Pulse, Pulse with constant coefficients etc.
    """
    coeff = np.array([0.1, 0.2, 0.3, 0.4])
    tlist = np.array([0., 1., 2., 3.])
    ham = sigmaz()
    # Special ways of initializing pulse
    pulse2 = Pulse(sigmax(), 0, tlist, True)
    assert_allclose(pulse2.get_ideal_qobjevo(2).ops[0].qobj,
                    tensor(sigmax(), identity(2)))

    pulse3 = Pulse(sigmay(), 0)
    assert_allclose(pulse3.get_ideal_qobjevo(2).cte.norm(), 0.)

    pulse4 = Pulse(None, None)  # Dummy empty ham
    assert_allclose(pulse4.get_ideal_qobjevo(2).cte.norm(), 0.)

    tlist_noise = np.array([1., 2.5, 3.])
    coeff_noise = np.array([0.5, 0.1, 0.5])
    tlist_noise2 = np.array([0.5, 2, 3.])
    coeff_noise2 = np.array([0.1, 0.2, 0.3])
    # Pulse with different dims
    random_qobj = Qobj(np.random.random((3, 3)))
    pulse5 = Pulse(sigmaz(), 1, tlist, True)
    pulse5.add_coherent_noise(sigmay(), 1, tlist_noise, coeff_noise)
    pulse5.add_lindblad_noise(
        random_qobj, 0, tlist=tlist_noise2, coeff=coeff_noise2)
    qu, c_ops = pulse5.get_noisy_qobjevo(dims=[3, 2])
    assert_allclose(qu.ops[0].qobj, tensor([identity(3), sigmaz()]))
    assert_allclose(qu.ops[1].qobj, tensor([identity(3), sigmay()]))
    assert_allclose(c_ops[0].ops[0].qobj, tensor([random_qobj, identity(2)]))
示例#9
0
    def add_states(self, state, kind='vector', alpha=1.0):
        """Add a state vector Qobj to Bloch sphere.

        Parameters
        ----------
        state : qobj
            Input state vector.

        kind : str {'vector','point'}
            Type of object to plot.

        alpha : float, default=1.
            Transparency value for the vectors. Values between 0 and 1.
        """
        if isinstance(state, Qobj):
            state = [state]
        for st in state:
            if kind == 'vector':
                vec = [
                    expect(sigmax(), st),
                    expect(sigmay(), st),
                    expect(sigmaz(), st)
                ]
                self.add_vectors(vec, alpha=alpha)
            elif kind == 'point':
                pnt = [
                    expect(sigmax(), st),
                    expect(sigmay(), st),
                    expect(sigmaz(), st)
                ]
                self.add_points(pnt, alpha=alpha)
示例#10
0
def concurrence(rho):
    """
    Calculate the concurrence entanglement measure for 
    a two-qubit state.
    
    Parameters
    ----------
    rho : qobj 
        Density matrix for two-qubits.
    
    Returns
    -------
    concur : float
        Concurrence
    
    """
    if rho.dims != [[2, 2], [2, 2]]:
        raise Exception("Density matrix must be tensor product of two qubits.")

    sysy = tensor(sigmay(), sigmay())

    rho_tilde = (rho * sysy) * (rho.conj() * sysy)

    evals = rho_tilde.eigenenergies()

    evals = abs(
        sort(real(evals))
    )  # abs to avoid problems with sqrt for very small negative numbers

    lsum = sqrt(evals[3]) - sqrt(evals[2]) - sqrt(evals[1]) - sqrt(evals[0])

    return max(0, lsum)
示例#11
0
 def test_multiplication(self):
     # Test multiplication of two Hermitian operators.  This results in a
     # skew-Hermitian operator, so we're checking here that __mul__ doesn't
     # set wrong metadata.
     q = sigmax() * sigmay()
     assert_hermicity(q, False)
     # Similarly, we need to check that -Z = X * iY is correctly identified
     # as Hermitian.
     q = sigmax() * (1j * sigmay())
     assert_hermicity(q, True)
示例#12
0
    def testOperatorListState(self):
        """
        expect: operator list and state
        """
        res = expect([sigmax(), sigmay(), sigmaz()], fock(2, 0))
        assert_(len(res) == 3)
        assert_(all(abs(res - [0, 0, 1]) < 1e-12))

        res = expect([sigmax(), sigmay(), sigmaz()], fock_dm(2, 1))
        assert_(len(res) == 3)
        assert_(all(abs(res - [0, 0, -1]) < 1e-12))
示例#13
0
    def testOperatorListState(self):
        """
        expect: operator list and state
        """
        res = expect([sigmax(), sigmay(), sigmaz()], fock(2, 0))
        assert_(len(res) == 3)
        assert_(all(abs(res - [0, 0, 1]) < 1e-12))

        res = expect([sigmax(), sigmay(), sigmaz()], fock_dm(2, 1))
        assert_(len(res) == 3)
        assert_(all(abs(res - [0, 0, -1]) < 1e-12))
示例#14
0
    def TestPlot(self):
        try:
            import matplotlib.pyplot as plt
        except:
            return True
        # step_func
        tlist = np.linspace(0., 2 * np.pi, 20)
        processor = Processor(N=1, spline_kind="step_func")
        processor.add_ctrl(sigmaz())
        processor.tlist = tlist
        processor.coeffs = np.array([[np.sin(t) for t in tlist]])
        processor.plot_pulses(noisy=False)
        plt.clf()

        # cubic spline
        tlist = np.linspace(0., 2 * np.pi, 20)
        processor = Processor(N=1, spline_kind="cubic")
        processor.add_ctrl(sigmaz())
        processor.tlist = tlist
        processor.coeffs = np.array([[np.sin(t) for t in tlist]])
        processor.plot_pulses(noisy=False)
        plt.clf()

        # noisy
        processor = Processor(N=1)
        processor.add_ctrl(sigmaz(), targets=0)
        processor.add_ctrl(sigmay(), targets=0)
        processor.coeffs = np.array([[0.5, 0., 0.5], [0., 0.5, 0.]])
        processor.tlist = np.array(
            [0., np.pi / 2., 2 * np.pi / 2, 3 * np.pi / 2])

        processor.plot_pulses(noisy=False)
        plt.clf()
        processor.plot_pulses(noisy=True)
        plt.clf()
示例#15
0
    def TestRandomNoise(self):
        """
        Test for the white noise
        """
        tlist = np.array([1, 2, 3, 4, 5, 6])
        coeff = np.array([1, 1, 1, 1, 1, 1])
        dummy_qobjevo = QobjEvo(sigmaz(), tlist=tlist)
        mean = 0.
        std = 0.5
        ops = [sigmaz(), sigmax()]
        proc_qobjevo = QobjEvo(
            [[sigmaz(), coeff], [sigmax(), coeff], [sigmay(), coeff]],
            tlist=tlist)

        # random noise with external operators
        gaussnoise = RandomNoise(ops=ops, loc=mean, scale=std)
        noise = gaussnoise.get_noise(N=1, proc_qobjevo=dummy_qobjevo)
        assert_allclose(noise.ops[1].qobj, sigmax())
        assert_allclose(len(noise.ops[1].coeff), len(tlist))
        assert_allclose(len(noise.ops), len(ops))

        # random noise with operators from proc_qobjevo
        gaussnoise = RandomNoise(loc=mean, scale=std)
        noise = gaussnoise.get_noise(N=1, proc_qobjevo=proc_qobjevo)
        assert_allclose(noise.ops[1].qobj, sigmax())
        assert_(len(noise.ops[0].coeff) == len(tlist))
        assert_(len(noise.ops) == len(proc_qobjevo.ops))

        # random noise with dt and other random number generator
        gaussnoise = RandomNoise(lam=0.1, dt=0.2, rand_gen=np.random.poisson)
        assert_(gaussnoise.rand_gen is np.random.poisson)
        noise = gaussnoise.get_noise(N=1, proc_qobjevo=proc_qobjevo)
        assert_allclose(noise.tlist, np.linspace(1, 6, int(5 / 0.2) + 1))
示例#16
0
    def add_annotation(self, state_or_vector, text, **kwargs):
        """Add a text or LaTeX annotation to Bloch sphere,
        parametrized by a qubit state or a vector.

        Parameters
        ----------
        state_or_vector : Qobj/array/list/tuple
            Position for the annotaion.
            Qobj of a qubit or a vector of 3 elements.

        text : str/unicode
            Annotation text.
            You can use LaTeX, but remember to use raw string
            e.g. r"$\\langle x \\rangle$"
            or escape backslashes
            e.g. "$\\\\langle x \\\\rangle$".

        **kwargs :
            Options as for mplot3d.axes3d.text, including:
            fontsize, color, horizontalalignment, verticalalignment.
        """
        if isinstance(state_or_vector, Qobj):
            vec = [expect(sigmax(), state_or_vector),
                   expect(sigmay(), state_or_vector),
                   expect(sigmaz(), state_or_vector)]
        elif isinstance(state_or_vector, (list, ndarray, tuple)) \
                and len(state_or_vector) == 3:
            vec = state_or_vector
        else:
            raise Exception("Position needs to be specified by a qubit " +
                            "state or a 3D vector.")
        self.annotations.append({'position': vec,
                                 'text': text,
                                 'opts': kwargs})
示例#17
0
文件: bloch.py 项目: mdruger/qutip
    def add_annotation(self, state_or_vector, text, **kwargs):
        """Add a text or LaTeX annotation to Bloch sphere,
        parametrized by a qubit state or a vector.

        Parameters
        ----------
        state_or_vector : Qobj/array/list/tuple
            Position for the annotaion.
            Qobj of a qubit or a vector of 3 elements.

        text : str/unicode
            Annotation text.
            You can use LaTeX, but remember to use raw string
            e.g. r"$\\langle x \\rangle$"
            or escape backslashes
            e.g. "$\\\\langle x \\\\rangle$".

        **kwargs :
            Options as for mplot3d.axes3d.text, including:
            fontsize, color, horizontalalignment, verticalalignment.
        """
        if isinstance(state_or_vector, Qobj):
            vec = [expect(sigmax(), state_or_vector),
                   expect(sigmay(), state_or_vector),
                   expect(sigmaz(), state_or_vector)]
        elif isinstance(state_or_vector, (list, ndarray, tuple)) \
                and len(state_or_vector) == 3:
            vec = state_or_vector
        else:
            raise Exception("Position needs to be specified by a qubit " +
                            "state or a 3D vector.")
        self.annotations.append({'position': vec,
                                 'text': text,
                                 'opts': kwargs})
示例#18
0
 def set_up_ops(self, N):
     super(CircularSpinChain, self).set_up_ops(N)
     x = [identity(2)] * N
     x[0] = x[N - 1] = sigmax()
     y = [identity(2)] * N
     y[0] = y[N - 1] = sigmay()
     self.ctrls.append(tensor(x) + tensor(y))
示例#19
0
    def set_up_ops(self, N):
        """
        Generate the Hamiltonians for the spinchain model and save them in the
        attribute `ctrls`.

        Parameters
        ----------
        N: int
            The number of qubits in the system.
        """
        # sx_ops
        self.ctrls += [
            tensor([sigmax() if m == n else identity(2) for n in range(N)])
            for m in range(N)
        ]
        # sz_ops
        self.ctrls += [
            tensor([sigmaz() if m == n else identity(2) for n in range(N)])
            for m in range(N)
        ]
        # sxsy_ops
        for n in range(N - 1):
            x = [identity(2)] * N
            x[n] = x[n + 1] = sigmax()
            y = [identity(2)] * N
            y[n] = y[n + 1] = sigmay()
            self.ctrls.append(tensor(x) + tensor(y))
示例#20
0
    def test_multi_qubits(self):
        """
        Test for multi-qubits system.
        """
        N = 3
        H_d = tensor([sigmaz()] * 3)
        H_c = []

        # test empty ctrls
        num_tslots = 30
        evo_time = 10
        test = OptPulseProcessor(N)
        test.add_drift(H_d, [0, 1, 2])
        test.add_control(tensor([sigmax(), sigmax()]), cyclic_permutation=True)
        # test periodically adding ctrls
        sx = sigmax()
        iden = identity(2)
        # print(test.ctrls)
        # print(Qobj(tensor([sx, iden, sx])))
        assert_(Qobj(tensor([sx, iden, sx])) in test.ctrls)
        assert_(Qobj(tensor([iden, sx, sx])) in test.ctrls)
        assert_(Qobj(tensor([sx, sx, iden])) in test.ctrls)
        test.add_control(sigmax(), cyclic_permutation=True)
        test.add_control(sigmay(), cyclic_permutation=True)

        # test pulse genration for cnot gate, with kwargs
        qc = [tensor([identity(2), cnot()])]
        test.load_circuit(qc,
                          num_tslots=num_tslots,
                          evo_time=evo_time,
                          min_fid_err=1.0e-6)
        rho0 = qubit_states(3, [1, 1, 1])
        rho1 = qubit_states(3, [1, 1, 0])
        result = test.run_state(rho0, options=Options(store_states=True))
        assert_(fidelity(result.states[-1], rho1) > 1 - 1.0e-6)
示例#21
0
    def add_line(self, start, end, fmt="k", **kwargs):
        """Adds a line segment connecting two points on the bloch sphere.

        The line segment is set to be a black solid line by default.

        Parameters
        ----------
        start : Qobj or array-like
            Array with cartesian coordinates of the first point, or a state
            vector or density matrix that can be mapped to a point on or
            within the Bloch sphere.
        end : Qobj or array-like
            Array with cartesian coordinates of the second point, or a state
            vector or density matrix that can be mapped to a point on or
            within the Bloch sphere.
        fmt : str, default: "k"
            A matplotlib format string for rendering the line.
        **kwargs : dict
            Additional parameters to pass to the matplotlib .plot function
            when rendering this line.
        """
        if isinstance(start, Qobj):
            pt1 = [
                expect(sigmax(), start),
                expect(sigmay(), start),
                expect(sigmaz(), start),
            ]
        else:
            pt1 = start

        if isinstance(end, Qobj):
            pt2 = [
                expect(sigmax(), end),
                expect(sigmay(), end),
                expect(sigmaz(), end),
            ]
        else:
            pt2 = end

        pt1 = np.asarray(pt1)
        pt2 = np.asarray(pt2)

        x = [pt1[1], pt2[1]]
        y = [-pt1[0], -pt2[0]]
        z = [pt1[2], pt2[2]]
        v = [x, y, z]
        self._lines.append([v, fmt, kwargs])
示例#22
0
    def test_random_noise(self):
        """
        Test for the white noise
        """
        tlist = np.array([1, 2, 3, 4, 5, 6])
        coeff = np.array([1, 1, 1, 1, 1, 1])
        dummy_qobjevo = QobjEvo(sigmaz(), tlist=tlist)
        mean = 0.
        std = 0.5
        pulses = [
            Pulse(sigmaz(), 0, tlist, coeff),
            Pulse(sigmax(), 0, tlist, coeff * 2),
            Pulse(sigmay(), 0, tlist, coeff * 3)
        ]

        # random noise with operators from proc_qobjevo
        gaussnoise = RandomNoise(dt=0.1,
                                 rand_gen=np.random.normal,
                                 loc=mean,
                                 scale=std)
        noisy_pulses, systematic_noise = \
            gaussnoise.get_noisy_dynamics(pulses=pulses)
        assert_allclose(noisy_pulses[2].qobj, sigmay())
        assert_allclose(noisy_pulses[1].coherent_noise[0].qobj, sigmax())
        assert_allclose(len(noisy_pulses[0].coherent_noise[0].tlist),
                        len(noisy_pulses[0].coherent_noise[0].coeff))

        # random noise with dt and other random number generator
        pulses = [
            Pulse(sigmaz(), 0, tlist, coeff),
            Pulse(sigmax(), 0, tlist, coeff * 2),
            Pulse(sigmay(), 0, tlist, coeff * 3)
        ]
        gaussnoise = RandomNoise(lam=0.1, dt=0.2, rand_gen=np.random.poisson)
        assert_(gaussnoise.rand_gen is np.random.poisson)
        noisy_pulses, systematic_noise = \
            gaussnoise.get_noisy_dynamics(pulses=pulses)
        assert_allclose(noisy_pulses[0].coherent_noise[0].tlist,
                        np.linspace(1, 6,
                                    int(5 / 0.2) + 1))
        assert_allclose(noisy_pulses[1].coherent_noise[0].tlist,
                        np.linspace(1, 6,
                                    int(5 / 0.2) + 1))
        assert_allclose(noisy_pulses[2].coherent_noise[0].tlist,
                        np.linspace(1, 6,
                                    int(5 / 0.2) + 1))
示例#23
0
    def __init__(self,
                 N,
                 correct_global_phase=True,
                 sx=None,
                 sz=None,
                 sxsy=None):
        """
        Parameters
        ----------
        sx: Integer/List
            The delta for each of the qubits in the system.

        sz: Integer/List
            The epsilon for each of the qubits in the system.

        sxsy: Integer/List
            The interaction strength for each of the qubit pair in the system.
        """

        super(SpinChain, self).__init__(N, correct_global_phase)

        self.sx_ops = [
            tensor([sigmax() if m == n else identity(2) for n in range(N)])
            for m in range(N)
        ]
        self.sz_ops = [
            tensor([sigmaz() if m == n else identity(2) for n in range(N)])
            for m in range(N)
        ]

        self.sxsy_ops = []
        for n in range(N - 1):
            x = [identity(2)] * N
            x[n] = x[n + 1] = sigmax()
            y = [identity(2)] * N
            y[n] = y[n + 1] = sigmay()
            self.sxsy_ops.append(tensor(x) + tensor(y))

        if sx is None:
            self.sx_coeff = [0.25 * 2 * np.pi] * N
        elif not isinstance(sx, list):
            self.sx_coeff = [sx * 2 * np.pi] * N
        else:
            self.sx_coeff = sx

        if sz is None:
            self.sz_coeff = [1.0 * 2 * np.pi] * N
        elif not isinstance(sz, list):
            self.sz_coeff = [sz * 2 * np.pi] * N
        else:
            self.sz_coeff = sz

        if sxsy is None:
            self.sxsy_coeff = [0.1 * 2 * np.pi] * (N - 1)
        elif not isinstance(sxsy, list):
            self.sxsy_coeff = [sxsy * 2 * np.pi] * (N - 1)
        else:
            self.sxsy_coeff = sxsy
示例#24
0
    def case_is_clifford(self, U):
        paulis = (identity(2), sigmax(), sigmay(), sigmaz())

        for P in paulis:
            U_P = U * P * U.dag()

            out = (np.any(
                np.array([self._prop_identity(U_P * Q) for Q in paulis])))
        return out
示例#25
0
文件: entropy.py 项目: roshanzr/qutip
def concurrence(rho):
    """
    Calculate the concurrence entanglement measure for a two-qubit state.

    Parameters
    ----------
    state : qobj
        Ket, bra, or density matrix for a two-qubit state.

    Returns
    -------
    concur : float
        Concurrence

    References
    ----------

    .. [1] http://en.wikipedia.org/wiki/Concurrence_(quantum_computing)

    """
    if rho.isket and rho.dims != [[2, 2], [1, 1]]:
        raise Exception("Ket must be tensor product of two qubits.")

    elif rho.isbra and rho.dims != [[1, 1], [2, 2]]:
        raise Exception("Bra must be tensor product of two qubits.")

    elif rho.isoper and rho.dims != [[2, 2], [2, 2]]:
        raise Exception("Density matrix must be tensor product of two qubits.")

    if rho.isket or rho.isbra:
        rho = ket2dm(rho)

    sysy = tensor(sigmay(), sigmay())

    rho_tilde = (rho * sysy) * (rho.conj() * sysy)

    evals = rho_tilde.eigenenergies()

    # abs to avoid problems with sqrt for very small negative numbers
    evals = abs(sort(real(evals)))

    lsum = sqrt(evals[3]) - sqrt(evals[2]) - sqrt(evals[1]) - sqrt(evals[0])

    return max(0, lsum)
示例#26
0
文件: entropy.py 项目: tmng/qutip
def concurrence(rho):
    """
    Calculate the concurrence entanglement measure for a two-qubit state.

    Parameters
    ----------
    state : qobj
        Ket, bra, or density matrix for a two-qubit state.

    Returns
    -------
    concur : float
        Concurrence

    References
    ----------

    .. [1] http://en.wikipedia.org/wiki/Concurrence_(quantum_computing)

    """
    if rho.isket and rho.dims != [[2, 2], [1, 1]]:
        raise Exception("Ket must be tensor product of two qubits.")

    elif rho.isbra and rho.dims != [[1, 1], [2, 2]]:
        raise Exception("Bra must be tensor product of two qubits.")

    elif rho.isoper and rho.dims != [[2, 2], [2, 2]]:
        raise Exception("Density matrix must be tensor product of two qubits.")

    if rho.isket or rho.isbra:
        rho = ket2dm(rho)

    sysy = tensor(sigmay(), sigmay())

    rho_tilde = (rho * sysy) * (rho.conj() * sysy)

    evals = rho_tilde.eigenenergies()

    # abs to avoid problems with sqrt for very small negative numbers
    evals = abs(sort(real(evals)))

    lsum = sqrt(evals[3]) - sqrt(evals[2]) - sqrt(evals[1]) - sqrt(evals[0])

    return max(0, lsum)
示例#27
0
    def testNoisyPulse(self):
        """
        Test for lindblad noise and different tlist
        """
        coeff = np.array([0.1, 0.2, 0.3, 0.4])
        tlist = np.array([0., 1., 2., 3.])
        ham = sigmaz()
        pulse1 = Pulse(ham, 1, tlist, coeff)
        # Add coherent noise and lindblad noise with different tlist
        pulse1.spline_kind = "step_func"
        tlist_noise = np.array([1., 2.5, 3.])
        coeff_noise = np.array([0.5, 0.1, 0.5])
        pulse1.add_coherent_noise(sigmay(), 0, tlist_noise, coeff_noise)
        tlist_noise2 = np.array([0.5, 2, 3.])
        coeff_noise2 = np.array([0.1, 0.2, 0.3])
        pulse1.add_lindblad_noise(sigmax(), 1, coeff=True)
        pulse1.add_lindblad_noise(sigmax(),
                                  0,
                                  tlist=tlist_noise2,
                                  coeff=coeff_noise2)

        assert_allclose(
            pulse1.get_ideal_qobjevo(2).ops[0].qobj,
            tensor(identity(2), sigmaz()))
        noise_qu, c_ops = pulse1.get_noisy_qobjevo(2)
        assert_allclose(noise_qu.tlist, np.array([0., 0.5, 1., 2., 2.5, 3.]))
        for ele in noise_qu.ops:
            if ele.qobj == tensor(identity(2), sigmaz()):
                assert_allclose(ele.coeff,
                                np.array([0.1, 0.1, 0.2, 0.3, 0.3, 0.4]))
            elif ele.qobj == tensor(sigmay(), identity(2)):
                assert_allclose(ele.coeff,
                                np.array([0., 0., 0.5, 0.5, 0.1, 0.5]))
        for c_op in c_ops:
            if len(c_op.ops) == 0:
                assert_allclose(c_ops[0].cte, tensor(identity(2), sigmax()))
            else:
                assert_allclose(c_ops[1].ops[0].qobj,
                                tensor(sigmax(), identity(2)))
                assert_allclose(c_ops[1].tlist,
                                np.array([0., 0.5, 1., 2., 2.5, 3.]))
                assert_allclose(c_ops[1].ops[0].coeff,
                                np.array([0., 0.1, 0.1, 0.2, 0.2, 0.3]))
示例#28
0
    def case_is_clifford(self, U):
        paulis = (identity(2), sigmax(), sigmay(), sigmaz())

        for P in paulis:
            U_P = U * P * U.dag()
            
            out = (np.any(
                np.array([self._prop_identity(U_P * Q) for Q in paulis])
            ))
        return out
示例#29
0
    def case_is_clifford(self, U):
        paulis = (identity(2), sigmax(), sigmay(), sigmaz())

        for P in paulis:
            U_P = U * P * U.dag()
            
            assert_(any(
                self._prop_identity(U_P * Q)
                for Q in paulis
            ))
示例#30
0
 def test_modify_ctrls(self):
     """
     Test for modifying Hamiltonian, add_control, remove_pulse
     """
     N = 2
     proc = Processor(N=N)
     proc.ctrls
     proc.add_control(sigmaz())
     assert_(tensor([sigmaz(), identity(2)]), proc.ctrls[0])
     proc.add_control(sigmax(), cyclic_permutation=True)
     assert_allclose(len(proc.ctrls), 3)
     assert_allclose(tensor([sigmax(), identity(2)]), proc.ctrls[1])
     assert_allclose(tensor([identity(2), sigmax()]), proc.ctrls[2])
     proc.add_control(sigmay(), targets=1)
     assert_allclose(tensor([identity(2), sigmay()]), proc.ctrls[3])
     proc.remove_pulse([0, 1, 2])
     assert_allclose(tensor([identity(2), sigmay()]), proc.ctrls[0])
     proc.remove_pulse(0)
     assert_allclose(len(proc.ctrls), 0)
示例#31
0
 def add_states(self, state, kind="vector"):
     """Add a state vector Qobj to Bloch sphere.
     
     Parameters
     ----------
     state : qobj
         Input state vector.
         
     kind : str {'vector','point'}
         Type of object to plot.
     
     """
     if isinstance(state, Qobj):
         state = [state]
     for st in state:
         if kind == "vector":
             vec = [expect(sigmax(), st), expect(sigmay(), st), expect(sigmaz(), st)]
             self.add_vectors(vec)
         elif kind == "point":
             pnt = [expect(sigmax(), st), expect(sigmay(), st), expect(sigmaz(), st)]
             self.add_points(pnt)
示例#32
0
def TestCoherentNoise():
    """
    Test for pulse genration with coherent noise.
    """
    coeff = np.array([0.1, 0.2, 0.3, 0.4])
    tlist = np.array([0., 1., 2., 3.])
    ham = sigmaz()
    pulse1 = Pulse(ham, 1, tlist, coeff)
    # Add coherent noise with the same tlist
    pulse1.add_coherent_noise(sigmay(), 0, tlist, coeff)
    assert_allclose(
        pulse1.get_ideal_qobjevo(2).ops[0].qobj, tensor(identity(2), sigmaz()))
    assert_(len(pulse1.coherent_noise) == 1)
    noise_qu, c_ops = pulse1.get_noisy_qobjevo(2)
    assert_allclose(c_ops, [])
    assert_allclose(noise_qu.tlist, np.array([0., 1., 2., 3.]))
    qobj_list = [ele.qobj for ele in noise_qu.ops]
    assert_(tensor(identity(2), sigmaz()) in qobj_list)
    assert_(tensor(sigmay(), identity(2)) in qobj_list)
    for ele in noise_qu.ops:
        assert_allclose(ele.coeff, coeff)
示例#33
0
def test_unitarity_known():
    """
    Metrics: Unitarity for known cases.
    """
    def case(q_oper, known_unitarity):
        assert_almost_equal(unitarity(q_oper), known_unitarity)

    yield case, to_super(sigmax()), 1.0
    yield case, sum(map(
        to_super,
        [qeye(2), sigmax(), sigmay(), sigmaz()])) / 4, 0.0
    yield case, sum(map(to_super, [qeye(2), sigmax()])) / 2, 1 / 3.0
示例#34
0
def test_QobjHerm():
    "Qobj Hermicity"
    N = 10
    data = np.random.random(
        (N, N)) + 1j * np.random.random((N, N)) - (0.5 + 0.5j)
    q = Qobj(data)
    assert_equal(q.isherm, False)

    data = data + data.conj().T
    q = Qobj(data)
    assert_(q.isherm)

    q_a = destroy(5)
    assert_(not q_a.isherm)

    q_ad = create(5)
    assert_(not q_ad.isherm)

    # test addition of two nonhermitian operators adding up to a hermitian one
    q_x = q_a + q_ad
    assert_hermicity(q_x, True)

    # test addition of one hermitan and one nonhermitian operator
    q = q_x + q_a
    assert_hermicity(q, False)

    # test addition of two hermitan operators
    q = q_x + q_x
    assert_hermicity(q, True)

    # Test multiplication of two Hermitian operators.
    # This results in a skew-Hermitian operator, so
    # we're checking here that __mul__ doesn't set wrong
    # metadata.
    q = sigmax() * sigmay()
    assert_hermicity(q, False, "Expected iZ = X * Y to be skew-Hermitian.")
    # Similarly, we need to check that -Z = X * iY is correctly
    # identified as Hermitian.
    q = sigmax() * (1j * sigmay())
    assert_hermicity(q, True, "Expected -Z = X * iY to be Hermitian.")
示例#35
0
文件: test_qobj.py 项目: arnelg/qutip
def test_QobjHerm():
    "Qobj Hermicity"
    N = 10
    data = np.random.random(
        (N, N)) + 1j * np.random.random((N, N)) - (0.5 + 0.5j)
    q = Qobj(data)
    assert_equal(q.isherm, False)

    data = data + data.conj().T
    q = Qobj(data)
    assert_(q.isherm)

    q_a = destroy(5)
    assert_(not q_a.isherm)

    q_ad = create(5)
    assert_(not q_ad.isherm)

    # test addition of two nonhermitian operators adding up to a hermitian one
    q_x = q_a + q_ad
    assert_hermicity(q_x, True)

    # test addition of one hermitan and one nonhermitian operator
    q = q_x + q_a
    assert_hermicity(q, False)

    # test addition of two hermitan operators
    q = q_x + q_x
    assert_hermicity(q, True)

    # Test multiplication of two Hermitian operators.
    # This results in a skew-Hermitian operator, so
    # we're checking here that __mul__ doesn't set wrong
    # metadata.
    q = sigmax() * sigmay()
    assert_hermicity(q, False, "Expected iZ = X * Y to be skew-Hermitian.")
    # Similarly, we need to check that -Z = X * iY is correctly
    # identified as Hermitian.
    q = sigmax() * (1j * sigmay())
    assert_hermicity(q, True, "Expected -Z = X * iY to be Hermitian.")
示例#36
0
    def __init__(self, N, correct_global_phase=True,
                 sx=None, sz=None, sxsy=None):
        """
        Parameters
        ----------
        sx: Integer/List
            The delta for each of the qubits in the system.

        sz: Integer/List
            The epsilon for each of the qubits in the system.

        sxsy: Integer/List
            The interaction strength for each of the qubit pair in the system.
        """

        super(SpinChain, self).__init__(N, correct_global_phase)

        self.sx_ops = [tensor([sigmax() if m == n else identity(2)
                               for n in range(N)])
                       for m in range(N)]
        self.sz_ops = [tensor([sigmaz() if m == n else identity(2)
                               for n in range(N)])
                       for m in range(N)]

        self.sxsy_ops = []
        for n in range(N - 1):
            x = [identity(2)] * N
            x[n] = x[n + 1] = sigmax()
            y = [identity(2)] * N
            y[n] = y[n + 1] = sigmay()
            self.sxsy_ops.append(tensor(x) + tensor(y))

        if sx is None:
            self.sx_coeff = [0.25 * 2 * np.pi] * N
        elif not isinstance(sx, list):
            self.sx_coeff = [sx * 2 * np.pi] * N
        else:
            self.sx_coeff = sx

        if sz is None:
            self.sz_coeff = [1.0 * 2 * np.pi] * N
        elif not isinstance(sz, list):
            self.sz_coeff = [sz * 2 * np.pi] * N
        else:
            self.sz_coeff = sz

        if sxsy is None:
            self.sxsy_coeff = [0.1 * 2 * np.pi] * (N - 1)
        elif not isinstance(sxsy, list):
            self.sxsy_coeff = [sxsy * 2 * np.pi] * (N - 1)
        else:
            self.sxsy_coeff = sxsy
示例#37
0
    def TestControlAmpNoise(self):
        """
        Test for the control amplitude noise
        """
        tlist = np.array([1, 2, 3, 4, 5, 6])
        coeff = np.array([1, 1, 1, 1, 1, 1])

        # use external operators and no expansion
        dummy_qobjevo = QobjEvo(sigmaz(), tlist=tlist)
        connoise = ControlAmpNoise(ops=sigmax(), coeffs=[coeff], tlist=tlist)
        noise = connoise.get_noise(N=1, proc_qobjevo=dummy_qobjevo)
        assert_allclose(noise.ops[0].qobj, sigmax())
        assert_allclose(noise.tlist, tlist)
        assert_allclose(noise.ops[0].coeff, coeff)

        dummy_qobjevo = QobjEvo(tensor([sigmaz(), sigmaz()]), tlist=tlist)
        connoise = ControlAmpNoise(ops=[sigmay()],
                                   coeffs=[coeff],
                                   tlist=tlist,
                                   targets=1)
        noise = connoise.get_noise(N=2, proc_qobjevo=dummy_qobjevo)
        assert_allclose(noise.ops[0].qobj, tensor([qeye(2), sigmay()]))

        # use external operators with expansion
        dummy_qobjevo = QobjEvo(sigmaz(), tlist=tlist)
        connoise = ControlAmpNoise(ops=sigmaz(),
                                   coeffs=[coeff] * 2,
                                   tlist=tlist,
                                   cyclic_permutation=True)
        noise = connoise.get_noise(N=2, proc_qobjevo=dummy_qobjevo)
        assert_allclose(noise.ops[0].qobj, tensor([sigmaz(), qeye(2)]))
        assert_allclose(noise.ops[1].qobj, tensor([qeye(2), sigmaz()]))

        # use proc_qobjevo
        proc_qobjevo = QobjEvo([[sigmaz(), coeff]], tlist=tlist)
        connoise = ControlAmpNoise(coeffs=[coeff], tlist=tlist)
        noise = connoise.get_noise(N=2, proc_qobjevo=proc_qobjevo)
        assert_allclose(noise.ops[0].qobj, sigmaz())
        assert_allclose(noise.ops[0].coeff, coeff[0])
示例#38
0
def y_gate(N=None, target=0):
    """Pauli-Y gate or sigmay operator.

    Returns
    -------
    result : :class:`qutip.Qobj`
        Quantum object for operator describing
        a single-qubit rotation through pi radians around the y-axis.

    """
    if N is not None:
        return gate_expand_1toN(y_gate(), N, target)
    return sigmay()
示例#39
0
def test_unitarity_known():
    """
    Metrics: Unitarity for known cases.
    """
    def case(q_oper, known_unitarity):
        assert_almost_equal(unitarity(q_oper), known_unitarity)

    yield case, to_super(sigmax()), 1.0
    yield case, sum(map(
        to_super, [qeye(2), sigmax(), sigmay(), sigmaz()]
    )) / 4, 0.0
    yield case, sum(map(
        to_super, [qeye(2), sigmax()]
    )) / 2, 1 / 3.0
示例#40
0
def _spin_hamiltonian(N):
    from qutip.tensor import tensor
    from qutip.operators import qeye, sigmax, sigmay, sigmaz
    # array of spin energy splittings and coupling strengths. here we use
    # uniform parameters, but in general we don't have too
    h  = 1.0 * 2 * np.pi * np.ones(N) 
    Jz = 0.1 * 2 * np.pi * np.ones(N)
    Jx = 0.1 * 2 * np.pi * np.ones(N)
    Jy = 0.1 * 2 * np.pi * np.ones(N)
    # dephasing rate
    gamma = 0.01 * np.ones(N)

    si = qeye(2)
    sx = sigmax()
    sy = sigmay()
    sz = sigmaz()

    sx_list = []
    sy_list = []
    sz_list = []

    for n in range(N):
        op_list = []
        for m in range(N):
            op_list.append(si)

        op_list[n] = sx
        sx_list.append(tensor(op_list))

        op_list[n] = sy
        sy_list.append(tensor(op_list))

        op_list[n] = sz
        sz_list.append(tensor(op_list))

    # construct the hamiltonian
    H = 0

    # energy splitting terms
    for n in range(N):
        H += - 0.5 * h[n] * sz_list[n]

    # interaction terms
    for n in range(N-1):
        H += - 0.5 * Jx[n] * sx_list[n] * sx_list[n+1]
        H += - 0.5 * Jy[n] * sy_list[n] * sy_list[n+1]
        H += - 0.5 * Jz[n] * sz_list[n] * sz_list[n+1]
    return H
示例#41
0
    def __init__(self, N, correct_global_phase=True,
                 sx=None, sz=None, sxsy=None):

        super(CircularSpinChain, self).__init__(N, correct_global_phase,
                                                sx, sz, sxsy)

        x = [identity(2)] * N
        x[0] = x[N - 1] = sigmax()
        y = [identity(2)] * N
        y[0] = y[N - 1] = sigmay()
        self.sxsy_ops.append(tensor(x) + tensor(y))

        if sxsy is None:
            self.sxsy_coeff = [0.1 * 2 * np.pi] * N
        elif not isinstance(sxsy, list):
            self.sxsy_coeff = [sxsy * 2 * np.pi] * N
        else:
            self.sxsy_coeff = sxsy
示例#42
0
def test_QobjUnitaryOper():
    "Qobj unitarity"
    # Check some standard operators
    Sx = sigmax()
    Sy = sigmay()
    assert_unitarity(qeye(4), True, "qeye(4) should be unitary.")
    assert_unitarity(Sx, True, "sigmax() should be unitary.")
    assert_unitarity(Sy, True, "sigmax() should be unitary.")
    assert_unitarity(sigmam(), False, "sigmam() should NOT be unitary.")
    assert_unitarity(destroy(10), False, "destroy(10) should NOT be unitary.")
    # Check multiplcation of unitary is unitary
    assert_unitarity(Sx*Sy, True, "sigmax()*sigmay() should be unitary.")
    # Check some other operations clear unitarity
    assert_unitarity(Sx+Sy, False, "sigmax()+sigmay() should NOT be unitary.")
    assert_unitarity(4*Sx, False, "4*sigmax() should NOT be unitary.")
    assert_unitarity(Sx*4, False, "sigmax()*4 should NOT be unitary.")
    assert_unitarity(4+Sx, False, "4+sigmax() should NOT be unitary.")
    assert_unitarity(Sx+4, False, "sigmax()+4 should NOT be unitary.")
示例#43
0
    def testOperatorListStateList(self):
        """
        expect: operator list and state list
        """
        operators = [sigmax(), sigmay(), sigmaz(), sigmam(), sigmap()]
        states = [fock(2, 0), fock(2, 1), fock_dm(2, 0), fock_dm(2, 1)]
        res = expect(operators, states)

        assert_(len(res) == len(operators))

        for r_idx, r in enumerate(res):

            assert_(isinstance(r, np.ndarray))

            if operators[r_idx].isherm:
                assert_(r.dtype == np.float64)
            else:
                assert_(r.dtype == np.complex128)

            for s_idx, s in enumerate(states):
                assert_(r[s_idx] == expect(operators[r_idx], states[s_idx]))
示例#44
0
    def testExpectSolverCompatibility(self):
        """
        expect: operator list and state list
        """
        c_ops = [0.0001 * sigmaz()]
        e_ops = [sigmax(), sigmay(), sigmaz(), sigmam(), sigmap()]
        times = np.linspace(0, 10, 100)

        res1 = mesolve(sigmax(), fock(2, 0), times, c_ops, e_ops)
        res2 = mesolve(sigmax(), fock(2, 0), times, c_ops, [])

        e1 = res1.expect
        e2 = expect(e_ops, res2.states)

        assert_(len(e1) == len(e2))

        for n in range(len(e1)):
            assert_(len(e1[n]) == len(e2[n]))
            assert_(isinstance(e1[n], np.ndarray))
            assert_(isinstance(e2[n], np.ndarray))
            assert_(e1[n].dtype == e2[n].dtype)
            assert_(all(abs(e1[n] - e2[n]) < 1e-12))
示例#45
0
    CPTP, expand to arbitrary dimensional systems, etc.
    """
    return Qobj(dims=[[[2], [2]], [[2], [2]]],
                inpt=array([[1. - pe / 2., 0., 0., 1. - pe],
                            [0., pe / 2., 0., 0.],
                            [0., 0., pe / 2., 0.],
                            [1. - pe, 0., 0., 1. - pe / 2.]]),
                superrep='choi')


# CHANGE OF BASIS FUNCTIONS ---------------------------------------------------
# These functions find change of basis matrices, and are useful in converting
# between (for instance) Choi and chi matrices. At some point, these should
# probably be moved out to another module.

_SINGLE_QUBIT_PAULI_BASIS = (identity(2), sigmax(), sigmay(), sigmaz())


def _pauli_basis(nq=1):
    # NOTE: This is slow as can be.
    # TODO: Make this sparse. CSR format was causing problems for the [idx, :]
    #       slicing below.
    B = zeros((4 ** nq, 4 ** nq), dtype=complex)
    dims = [[[2] * nq] * 2] * 2

    for idx, op in enumerate(starmap(tensor,
                                     product(_SINGLE_QUBIT_PAULI_BASIS,
                                             repeat=nq))):
        B[:, idx] = operator_to_vector(op).dag().data.todense()

    return Qobj(B, dims=dims)
示例#46
0
    def test_known_iscptp(self):
        """
        Superoperator: ishp, iscp, istp and iscptp known cases.
        """
        def case(qobj, shouldhp, shouldcp, shouldtp):
            hp = qobj.ishp
            cp = qobj.iscp
            tp = qobj.istp
            cptp = qobj.iscptp

            shouldcptp = shouldcp and shouldtp

            if (
                hp == shouldhp and
                cp == shouldcp and
                tp == shouldtp and
                cptp == shouldcptp
            ):
                return

            fails = []
            if hp != shouldhp:
                fails.append(("ishp", shouldhp, hp))
            if tp != shouldtp:
                fails.append(("istp", shouldtp, tp))
            if cp != shouldcp:
                fails.append(("iscp", shouldcp, cp))
            if cptp != shouldcptp:
                fails.append(("iscptp", shouldcptp, cptp))

            raise AssertionError("Expected {}.".format(" and ".join([
                "{} == {} (got {})".format(fail, expected, got)
                for fail, expected, got in fails
            ])))

        # Conjugation by a creation operator should
        # have be CP (and hence HP), but not TP.
        a = create(2).dag()
        S = sprepost(a, a.dag())
        case(S, True, True, False)

        # A single off-diagonal element should not be CP,
        # nor even HP.
        S = sprepost(a, a)
        case(S, False, False, False)
        
        # Check that unitaries are CPTP and HP.
        case(identity(2), True, True, True)
        case(sigmax(), True, True, True)

        # Check that unitaries on bipartite systems are CPTP and HP.
        case(tensor(sigmax(), identity(2)), True, True, True)

        # Check that a linear combination of bipartitie unitaries is CPTP and HP.
        S = (
            to_super(tensor(sigmax(), identity(2))) + to_super(tensor(identity(2), sigmay()))
        ) / 2
        case(S, True, True, True)

        # The partial transpose map, whose Choi matrix is SWAP, is TP
        # and HP but not CP (one negative eigenvalue).
        W = Qobj(swap(), type='super', superrep='choi')
        case(W, True, False, True)

        # Subnormalized maps (representing erasure channels, for instance)
        # can be CP but not TP.
        subnorm_map = Qobj(identity(4) * 0.9, type='super', superrep='super')
        case(subnorm_map, True, True, False)

        # Check that things which aren't even operators aren't identified as
        # CPTP.
        case(basis(2), False, False, False)