Пример #1
0
    def test_chain_merge_prev(self, d, lib):
        b = bases.general(d)

        rng = np.random.RandomState(4242)
        dm = rng.randn(d * d, d * d) + 1j * rng.randn(d * d, d * d)
        dm += dm.conjugate().transpose()
        dm /= dm.trace()

        chain = Operation.from_sequence(
            (lib.cphase(angle=np.pi / 7, leakage_rate=0.25)
             if d == 3 else lib.cphase(3 * np.pi / 7)).at(0, 1),
            lib.rotate_x(4 * np.pi / 7).at(0),
        )

        bases_full = (b, b)
        chain_c = chain.compile(bases_full, bases_full)
        assert len(chain._units) == 2
        assert isinstance(chain_c, PTMOperation)

        pv1 = PauliVector.from_dm(dm, bases_full)
        pv2 = PauliVector.from_dm(dm, bases_full)
        chain(pv1, 0, 1)
        chain_c(pv2, 0, 1)

        assert np.allclose(pv1.meas_prob(0), pv2.meas_prob(0))
        assert np.allclose(pv1.meas_prob(1), pv2.meas_prob(1))
Пример #2
0
    def test_lindblad_singlequbit(self):
        ham = random_hermitian_matrix(2, seed=56)
        lindblad_ops = np.array([
            [[0, 0.1], [0, 0]],
            [[0, 0], [0, 0.33]],
        ])
        t1 = 10
        t2 = 25
        b1 = (bases.general(2), )
        b2 = (bases.gell_mann(2), )
        op1 = Operation.from_lindblad_form(t1,
                                           b1,
                                           b2,
                                           hamiltonian=ham,
                                           lindblad_ops=lindblad_ops)
        op2 = Operation.from_lindblad_form(t2,
                                           b2,
                                           b1,
                                           hamiltonian=ham,
                                           lindblad_ops=lindblad_ops)
        op = Operation.from_lindblad_form(t1 + t2,
                                          b1,
                                          hamiltonian=ham,
                                          lindblad_ops=lindblad_ops)
        dm = random_hermitian_matrix(2, seed=3)
        state1 = PauliVector.from_dm(dm, b1)
        state2 = PauliVector.from_dm(dm, b1)

        op1(state1, 0)
        op2(state1, 0)
        op(state2, 0)
        assert np.allclose(state1.to_pv(), state2.to_pv())
Пример #3
0
    def test_zz_parity_compilation(self):
        b_full = bases.general(3)
        b0 = b_full.subbasis([0])
        b01 = b_full.subbasis([0, 1])
        b012 = b_full.subbasis([0, 1, 2])

        bases_in = (b01, b01, b0)
        bases_out = (b_full, b_full, b012)
        zz = Operation.from_sequence(
            lib3.rotate_x(-np.pi / 2).at(2),
            lib3.cphase(leakage_rate=0.1).at(0, 2),
            lib3.cphase(leakage_rate=0.25).at(2, 1),
            lib3.rotate_x(np.pi / 2).at(2),
            lib3.rotate_x(np.pi).at(0),
            lib3.rotate_x(np.pi).at(1))
        zz_ptm = zz.ptm(bases_in, bases_out)
        zzc = zz.compile(bases_in=bases_in, bases_out=bases_out)
        zzc_ptm = zzc.ptm(bases_in, bases_out)
        assert zz_ptm == approx(zzc_ptm)

        units = list(zzc.units())
        assert len(units) == 2
        op1, ix1 = units[0]
        op2, ix2 = units[1]
        assert ix1 == (0, 2)
        assert ix2 == (1, 2)
        assert op1.bases_in[0] == bases_in[0]
        assert op2.bases_in[0] == bases_in[1]
        assert op1.bases_in[1] == bases_in[2]
        # Qubit 0 did not leak
        assert op1.bases_out[0] == bases_out[0].subbasis([0, 1])
        # Qubit 1 leaked
        assert op2.bases_out[0] == bases_out[1].subbasis([0, 1, 2, 6])
        # Qubit 2 is measured
        assert op2.bases_out[1] == bases_out[2]

        dm = random_hermitian_matrix(3**3, seed=85)
        pv1 = PauliVector.from_dm(dm, (b01, b01, b0))
        pv2 = PauliVector.from_dm(dm, (b01, b01, b0))

        zz(pv1, 0, 1, 2)
        zzc(pv2, 0, 1, 2)

        # Compiled version still needs to be projected, so we can't compare
        # Pauli vectors, so we can to check only DM diagonals.
        assert np.allclose(pv1.diagonal(), pv2.diagonal())
Пример #4
0
 def test_lindblad_time_inverse(self):
     ham = random_hermitian_matrix(2, seed=4)
     b = (bases.general(2), )
     op_plus = Operation.from_lindblad_form(20, b, hamiltonian=ham)
     op_minus = Operation.from_lindblad_form(20, b, hamiltonian=-ham)
     dm = random_hermitian_matrix(2, seed=5)
     state = PauliVector.from_dm(dm, b)
     op_plus(state, 0)
     op_minus(state, 0)
     assert np.allclose(state.to_dm(), dm)
Пример #5
0
    def test_chain_apply(self):
        b = (bases.general(2), ) * 3
        dm = random_hermitian_matrix(8, seed=93)
        pv1 = PauliVector.from_dm(dm, b)
        pv2 = PauliVector.from_dm(dm, b)

        # Some random gate sequence
        op_indices = [(lib2.rotate_x(np.pi / 2), (0, )),
                      (lib2.rotate_y(0.3333), (1, )), (lib2.cphase(), (0, 2)),
                      (lib2.cphase(), (1, 2)),
                      (lib2.rotate_x(-np.pi / 2), (0, ))]

        for op, indices in op_indices:
            op(pv1, *indices),

        circuit = Operation.from_sequence(*(op.at(*ix)
                                            for op, ix in op_indices))
        circuit(pv2, 0, 1, 2)
        assert np.all(pv1.to_pv() == pv2.to_pv())
Пример #6
0
    def test_chain_compile_single_qubit(self, d, lib):
        b = bases.general(d)
        dm = random_hermitian_matrix(d, seed=487)

        bases_full = (b, )
        subbases = (b.subbasis([0, 1]), )
        angle = np.pi / 5
        rx_angle = lib.rotate_x(angle)
        rx_2angle = lib.rotate_x(2 * angle)
        chain0 = Operation.from_sequence(rx_angle.at(0), rx_angle.at(0))
        pv0 = PauliVector.from_dm(dm, bases_full)
        chain0(pv0, 0)
        assert chain0.num_qubits == 1
        assert len(chain0._units) == 2

        chain0_c = chain0.compile(bases_full, bases_full)
        assert isinstance(chain0_c, PTMOperation)
        pv1 = PauliVector.from_dm(dm, bases_full)
        chain0_c(pv1, 0)
        assert chain0_c.num_qubits == 1
        assert isinstance(chain0_c, PTMOperation)
        op_angle = chain0_c
        op_2angle = rx_2angle.compile(bases_full, bases_full)
        assert isinstance(op_2angle, PTMOperation)
        assert op_angle.shape == op_2angle.shape
        assert op_angle.bases_in == op_2angle.bases_in
        assert op_angle.bases_out == op_2angle.bases_out
        assert op_angle.ptm(op_angle.bases_in, op_angle.bases_out) == \
            approx(op_2angle.ptm(op_2angle.bases_in, op_2angle.bases_out))
        assert pv1.to_pv() == approx(pv0.to_pv())

        rx_pi = lib.rotate_x(np.pi)
        chain_2pi = Operation.from_sequence(rx_pi.at(0), rx_pi.at(0))
        chain_2pi_c1 = chain_2pi.compile(subbases, bases_full)
        assert isinstance(chain_2pi_c1, PTMOperation)
        assert chain_2pi_c1.bases_in == subbases
        assert chain_2pi_c1.bases_out == subbases

        chain_2pi_c2 = chain_2pi.compile(bases_full, subbases)
        assert isinstance(chain_2pi_c2, PTMOperation)
        assert chain_2pi_c2.bases_in == subbases
        assert chain_2pi_c2.bases_out == subbases
Пример #7
0
    def test_ptm(self):
        # Some random gate sequence
        op_indices = [(lib2.rotate_x(np.pi / 2), (0, )),
                      (lib2.rotate_y(0.3333), (1, )), (lib2.cphase(), (0, 2)),
                      (lib2.cphase(), (1, 2)),
                      (lib2.rotate_x(-np.pi / 2), (0, ))]
        circuit = Operation.from_sequence(*(op.at(*ix)
                                            for op, ix in op_indices))

        b = (bases.general(2), ) * 3
        ptm = circuit.ptm(b, b)
        assert isinstance(ptm, np.ndarray)

        op_3q = Operation.from_ptm(ptm, b)
        dm = random_hermitian_matrix(8, seed=93)
        state1 = PauliVector.from_dm(dm, b)
        state2 = PauliVector.from_dm(dm, b)

        circuit(state1, 0, 1, 2)
        op_3q(state2, 0, 1, 2)
        assert np.allclose(state1.to_pv(), state2.to_pv())
Пример #8
0
    def test_chain_merge_next(self, d, lib):
        b = bases.general(d)

        dm = random_hermitian_matrix(d**2, seed=574)

        chain = Operation.from_sequence(
            lib.rotate_x(np.pi / 5).at(0),
            (lib.cphase(angle=3 * np.pi / 7, leakage_rate=0.1)
             if d == 3 else lib.cphase(3 * np.pi / 7)).at(0, 1),
        )

        bases_full = (b, b)
        chain_c = chain.compile(bases_full, bases_full)
        assert len(chain._units) == 2
        assert isinstance(chain_c, PTMOperation)

        pv1 = PauliVector.from_dm(dm, bases_full)
        pv2 = PauliVector.from_dm(dm, bases_full)
        chain(pv1, 0, 1)
        chain_c(pv2, 0, 1)

        assert pv1.meas_prob(0) == approx(pv2.meas_prob(0))
        assert pv1.meas_prob(1) == approx(pv2.meas_prob(1))
Пример #9
0
    def test_lindblad_two_qubit(self):
        b = (bases.general(2), )
        id = np.array([[1, 0], [0, 1]])
        ham1 = random_hermitian_matrix(2, seed=6)
        ham2 = random_hermitian_matrix(2, seed=7)
        ham = np.kron(ham1, id).reshape(2, 2, 2, 2) + \
              np.kron(id, ham2).reshape(2, 2, 2, 2)
        dm = random_hermitian_matrix(4, seed=3)
        op1 = Operation.from_lindblad_form(25, b, hamiltonian=ham1)
        op2 = Operation.from_lindblad_form(25, b, hamiltonian=ham2)
        op = Operation.from_lindblad_form(25, b * 2, hamiltonian=ham)
        state1 = PauliVector.from_dm(dm, b * 2)
        state2 = PauliVector.from_dm(dm, b * 2)
        op1(state1, 0)
        op2(state1, 1)
        op(state2, 0, 1)
        assert np.allclose(state1.to_pv(), state2.to_pv())

        ops1 = np.array([
            [[0, 0.1], [0, 0]],
            [[0, 0], [0, 0.33]],
        ])
        ops2 = np.array([
            [[0, 0.15], [0, 0]],
            [[0, 0], [0, 0.17]],
        ])
        ops = [np.kron(op, id).reshape(2, 2, 2, 2) for op in ops1] +\
              [np.kron(id, op).reshape(2, 2, 2, 2) for op in ops2]
        op1 = Operation.from_lindblad_form(25, b, lindblad_ops=ops1)
        op2 = Operation.from_lindblad_form(25, b, lindblad_ops=ops2)
        op = Operation.from_lindblad_form(25, b * 2, lindblad_ops=ops)
        state1 = PauliVector.from_dm(dm, b * 2)
        state2 = PauliVector.from_dm(dm, b * 2)
        op1(state1, 0)
        op2(state1, 1)
        op(state2, 0, 1)
        assert np.allclose(state1.to_pv(), state2.to_pv())

        op1 = Operation.from_lindblad_form(25,
                                           b,
                                           hamiltonian=ham1,
                                           lindblad_ops=ops1)
        op2 = Operation.from_lindblad_form(25,
                                           b,
                                           hamiltonian=ham2,
                                           lindblad_ops=ops2)
        op = Operation.from_lindblad_form(25,
                                          b * 2,
                                          hamiltonian=ham,
                                          lindblad_ops=ops)
        state1 = PauliVector.from_dm(dm, b * 2)
        state2 = PauliVector.from_dm(dm, b * 2)
        op1(state1, 0)
        op2(state1, 1)
        op(state2, 0, 1)
        assert np.allclose(state1.to_pv(), state2.to_pv())