def test_kraus_to_ptm_qubit(self): p_damp = 0.5 damp_kraus_mat = np.array( [[[1, 0], [0, np.sqrt(1 - p_damp)]], [[0, np.sqrt(p_damp)], [0, 0]]]) gm_qubit_basis = (bases.gell_mann(2),) gm_two_qubit_basis = gm_qubit_basis + gm_qubit_basis damp_op = Operation.from_kraus(damp_kraus_mat, 2) damp_ptm = damp_op.set_bases(bases_in=gm_qubit_basis, bases_out=gm_qubit_basis).ptm expected_mat = np.array([[1, 0, 0, 0], [0, np.sqrt(1-p_damp), 0, 0], [0, 0, np.sqrt(1-p_damp), 0], [p_damp, 0, 0, 1-p_damp]]) assert np.allclose(damp_ptm, expected_mat) with pytest.raises(ValueError, match=r'.* should be a list, .*'): damp_op.set_bases(bases.gell_mann(2), bases.gell_mann(2)) cz_kraus_mat = np.diag([1, 1, 1, -1]) cz = Operation.from_kraus(cz_kraus_mat, 2).set_bases(gm_two_qubit_basis, gm_two_qubit_basis) assert cz.ptm.shape == (4, 4, 4, 4) cz_ptm = cz.ptm.reshape((16, 16)) assert np.all(cz_ptm.round(3) <= 1) assert np.all(cz_ptm.round(3) >= -1) assert np.isclose(np.sum(cz_ptm[0, :]), 1) assert np.isclose(np.sum(cz_ptm[:, 0]), 1)
def test_kraus_to_ptm_qubit(self): p_damp = 0.5 damp_kraus_mat = np.array([[[1, 0], [0, np.sqrt(1 - p_damp)]], [[0, np.sqrt(p_damp)], [0, 0]]]) gm_qubit_basis = (bases.gell_mann(2), ) gm_two_qubit_basis = gm_qubit_basis * 2 damp_op = Operation.from_kraus(damp_kraus_mat, gm_qubit_basis) damp_ptm = damp_op.ptm(gm_qubit_basis) expected_mat = np.array([[1, 0, 0, 0], [0, np.sqrt(1 - p_damp), 0, 0], [0, 0, np.sqrt(1 - p_damp), 0], [p_damp, 0, 0, 1 - p_damp]]) assert np.allclose(damp_ptm, expected_mat) with pytest.raises(ValueError, match=r'.* must be list-like, .*'): damp_op.set_bases(bases.gell_mann(2), bases.gell_mann(2)) cz_kraus_mat = np.diag([1, 1, 1, -1]) cz = Operation.from_kraus(cz_kraus_mat, gm_two_qubit_basis) cz_ptm = cz.ptm(gm_two_qubit_basis) assert cz_ptm.shape == (4, 4, 4, 4) cz_ptm = cz_ptm.reshape((16, 16)) assert np.all(cz_ptm.round(3) <= 1) assert np.all(cz_ptm.round(3) >= -1) assert np.isclose(np.sum(cz_ptm[0, :]), 1) assert np.isclose(np.sum(cz_ptm[:, 0]), 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_convert_ptm_basis(self): p_damp = 0.5 damp_kraus_mat = np.array([[[1, 0], [0, np.sqrt(1 - p_damp)]], [[0, np.sqrt(p_damp)], [0, 0]]]) gell_mann_basis = (bases.gell_mann(2), ) general_basis = (bases.general(2), ) op1 = Operation.from_kraus(damp_kraus_mat, gell_mann_basis) op2 = op1.set_bases(general_basis, general_basis) \ .set_bases(gell_mann_basis, gell_mann_basis) assert np.allclose(op1.ptm(gell_mann_basis), op2.ptm(gell_mann_basis)) assert op1.bases_in == op2.bases_in assert op1.bases_out == op2.bases_out
def phase_damping(total_rate=None, *, x_deph_rate=None, y_deph_rate=None, z_deph_rate=None): if total_rate is not None: kraus = np.array([[[1, 0], [0, np.sqrt(1 - total_rate)]], [[0, 0], [0, np.sqrt(total_rate)]]]) return Operation.from_kraus(kraus, 2) else: if None in (x_deph_rate, y_deph_rate, z_deph_rate): raise ValueError( "Either the total_rate or the dephasing rates along each of " "the three axis must be provided") ptm = np.diag( [1, 1 - x_deph_rate, 1 - y_deph_rate, 1 - z_deph_rate]) return Operation.from_ptm(ptm, (bases.gell_mann(2),))
def test_kraus_to_ptm_qutrits(self): cz_kraus_mat = np.diag([1, 1, 1, 1, -1, 1, -1, 1, 1]) qutrit_basis = (bases.gell_mann(3),) system_bases = qutrit_basis * 2 cz = Operation.from_kraus(cz_kraus_mat, 3).set_bases(system_bases, system_bases) assert cz.ptm.shape == (9, 9, 9, 9) cz_ptm_flat = cz.ptm.reshape((81, 81)) assert np.all(cz_ptm_flat.round(3) <= 1) and np.all( cz.ptm.round(3) >= -1) assert np.isclose(np.sum(cz_ptm_flat[0, :]), 1) assert np.isclose(np.sum(cz_ptm_flat[:, 0]), 1)
def test_kraus_to_ptm_qutrits(self): cz_kraus_mat = np.diag([1, 1, 1, 1, -1, 1, -1, 1, 1]) qutrit_basis = (bases.gell_mann(3), ) system_bases = qutrit_basis * 2 cz = Operation.from_kraus(cz_kraus_mat, system_bases) cz_ptm = cz.ptm(system_bases) assert cz_ptm.shape == (9, 9, 9, 9) cz_ptm_flat = cz_ptm.reshape((81, 81)) assert np.all(cz_ptm_flat.round(3) <= 1) and np.all( cz_ptm.round(3) >= -1) assert np.isclose(np.sum(cz_ptm_flat[0, :]), 1) assert np.isclose(np.sum(cz_ptm_flat[:, 0]), 1)
def test_convert_ptm_basis(self): p_damp = 0.5 damp_kraus_mat = np.array( [[[1, 0], [0, np.sqrt(1-p_damp)]], [[0, np.sqrt(p_damp)], [0, 0]]]) gell_mann_basis = (bases.gell_mann(2),) general_basis = (bases.general(2),) damp_op_kraus = Operation.from_kraus(damp_kraus_mat, 2) op1 = damp_op_kraus.set_bases(gell_mann_basis, gell_mann_basis) op2 = damp_op_kraus.set_bases(general_basis, general_basis) \ .set_bases(gell_mann_basis, gell_mann_basis) assert np.allclose(op1.ptm, op2.ptm) assert op1.bases_in == op2.bases_in assert op1.bases_out == op2.bases_out
def amp_damping(total_rate=None, *, exc_rate=None, damp_rate=None): if total_rate is not None: kraus = np.array([[[1, 0], [0, np.sqrt(1 - total_rate)]], [[0, np.sqrt(total_rate)], [0, 0]]]) return Operation.from_kraus(kraus, 2) else: if None in (exc_rate, damp_rate): raise ValueError( "Either the total_rate or both the exc_rate and damp_rate " "must be provided") comb_rate = exc_rate + damp_rate ptm = np.array([[1, 0, 0, 0], [0, np.sqrt((1 - comb_rate)), 0, 0], [0, 0, np.sqrt((1 - comb_rate)), 0], [2 * damp_rate - comb_rate, 0, 0, 1 - comb_rate]]) return Operation.from_ptm(ptm, (bases.gell_mann(2), ))
def phase_damping(total_rate=None, *, x_deph_rate=None, y_deph_rate=None, z_deph_rate=None): if total_rate is not None: kraus = np.array([[[1, 0], [0, np.sqrt(1 - total_rate)]], [[0, 0], [0, np.sqrt(total_rate)]]]) return Operation.from_kraus(kraus, 2) else: if None in (x_deph_rate, y_deph_rate, z_deph_rate): raise ValueError( "Either the total_rate or the dephasing rates along each of " "the three axis must be provided") ptm = np.diag([1, 1 - x_deph_rate, 1 - y_deph_rate, 1 - z_deph_rate]) return Operation.from_ptm(ptm, (bases.gell_mann(2), ))
def amp_damping(total_rate=None, *, exc_rate=None, damp_rate=None): if total_rate is not None: kraus = np.array([[[1, 0], [0, np.sqrt(1 - total_rate)]], [[0, np.sqrt(total_rate)], [0, 0]]]) return Operation.from_kraus(kraus, 2) else: if None in (exc_rate, damp_rate): raise ValueError( "Either the total_rate or both the exc_rate and damp_rate " "must be provided") comb_rate = exc_rate + damp_rate ptm = np.array([ [1, 0, 0, 0], [0, np.sqrt((1 - comb_rate)), 0, 0], [0, 0, np.sqrt((1 - comb_rate)), 0], [2*damp_rate - comb_rate, 0, 0, 1 - comb_rate]]) return Operation.from_ptm(ptm, (bases.gell_mann(2),))
import numpy as np from functools import lru_cache from quantumsim import bases, Operation _PAULI = dict(zip(['I', 'X', 'Y', 'Z'], bases.gell_mann(2).vectors)) @lru_cache(maxsize=64) def rotate_euler(phi, theta, lamda): """A perfect single qubit rotation described by three Euler angles. Unitary operation, that corresponds to this rotation, is: .. math:: U = R_Z(\\phi) \\cdot R_X(\\theta) \\cdot R_Z(\\lambda) Parameters ---------- phi, theta, lamda: float Euler rotation angles in radians. Returns ------- Operation An operation, that corresponds to the rotation. """ exp_phi, exp_lambda = np.exp(1j * phi), np.exp(1j * lamda) sin_theta, cos_theta = np.sin(theta / 2), np.cos(theta / 2) matrix = np.array([ [cos_theta, -1j * exp_lambda * sin_theta],
import numpy as np from functools import lru_cache from scipy.linalg import expm from quantumsim import bases, Operation _PAULI = dict(zip(['I', 'X', 'Y', 'Z'], bases.gell_mann(2).vectors)) @lru_cache(maxsize=64) def rotate_euler(phi, theta, lamda): """A perfect single qubit rotation described by three Euler angles. Unitary operation, that corresponds to this rotation, is: .. math:: U = R_Z(\\phi) \\cdot R_X(\\theta) \\cdot R_Z(\\lambda) Parameters ---------- phi, theta, lamda: float Euler rotation angles in radians. Returns ------- Operation An operation, that corresponds to the rotation. """ exp_phi, exp_lambda = np.exp(1j * phi), np.exp(1j * lamda) sin_theta, cos_theta = np.sin(theta / 2), np.cos(theta / 2) matrix = np.array([