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))
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())
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())
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)
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())
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
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())
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))
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())