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_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_errors(self): qutrit_basis = (bases.general(3),) cz_kraus_mat = np.diag([1, 1, 1, -1]) kraus_op = Operation.from_kraus(cz_kraus_mat, 2) wrong_dim_kraus = np.random.random((4, 4, 2, 2)) with pytest.raises(ValueError): _ = Operation.from_kraus(wrong_dim_kraus, 2) not_sqr_kraus = np.random.random((4, 2, 3)) with pytest.raises(ValueError): _ = Operation.from_kraus(not_sqr_kraus, 2) with pytest.raises(ValueError): _ = Operation.from_kraus(cz_kraus_mat, 3) with pytest.raises(ValueError): _ = kraus_op.set_bases(qutrit_basis + qutrit_basis)
def test_kraus_to_ptm_errors(self): qutrit_basis = (bases.general(3), ) cz_kraus_mat = np.diag([1, 1, 1, -1]) kraus_op = Operation.from_kraus(cz_kraus_mat, 2) wrong_dim_kraus = np.random.random((4, 4, 2, 2)) with pytest.raises(ValueError): _ = Operation.from_kraus(wrong_dim_kraus, 2) not_sqr_kraus = np.random.random((4, 2, 3)) with pytest.raises(ValueError): _ = Operation.from_kraus(not_sqr_kraus, 2) with pytest.raises(ValueError): _ = Operation.from_kraus(cz_kraus_mat, 3) with pytest.raises(ValueError): _ = kraus_op.set_bases(qutrit_basis + qutrit_basis)
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, 0], [-1j * exp_phi * sin_theta, exp_phi * exp_lambda * cos_theta, 0], [0, 0, 1]]) return Operation.from_kraus(matrix, 3)
def phase_flipping(flip_rate): # This is actually equivalent to the phase damping matrix = np.array([ np.sqrt(flip_rate) * _PAULI["I"], np.sqrt(1 - flip_rate) * _PAULI["Z"] ]) return Operation.from_kraus(matrix, 2)
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], [-1j * exp_phi * sin_theta, exp_phi * exp_lambda * cos_theta]]) return Operation.from_kraus(matrix, 2)
def depolarization(rate): rate = rate / 2 sqrt = np.sqrt(rate) matrix = np.array([ np.sqrt(2 - (3 * rate)) * _PAULI["I"], sqrt * _PAULI["X"], sqrt * _PAULI["Y"], sqrt * _PAULI["Z"] ]) return Operation.from_kraus(matrix, 2)
def cnot(): dcnot = np.zeros((9, 9)) dcnot[3, 3] = 0.5 dcnot[4, 4] = 0.5 dcnot[3, 4] = -0.5 dcnot[4, 3] = -0.5 unitary = expm(-1j*np.pi*dcnot) return Operation.from_kraus(unitary, 3)
def depolarization(rate): rate = rate / 2 sqrt = np.sqrt(rate) matrix = np.array([np.sqrt(2 - (3 * rate)) * _PAULI["I"], sqrt * _PAULI["X"], sqrt * _PAULI["Y"], sqrt * _PAULI["Z"]]) return Operation.from_kraus(matrix, 2)
def controlled_unitary(unitary): dim_hilbert = unitary.shape[0] if unitary.shape != (dim_hilbert, dim_hilbert): raise ValueError("Unitary matrix must be square") control_block = np.eye(2) off_diag_block_0 = np.zeros((2, dim_hilbert)) off_diag_block_1 = np.zeros((dim_hilbert, 2)) matrix = np.array([[control_block, off_diag_block_0], [off_diag_block_1, unitary]]) return Operation.from_kraus(matrix, 2)
def hadamard(): """A perfect Hadamard operation. Returns ------- Operation.from_kraus An operation, that corresponds to the rotation. """ matrix = np.sqrt(0.5) * np.array([[1, 1], [1, -1]]) return Operation.from_kraus(matrix, 2)
def hadamard(): """A perfect Hadamard operation. Returns ------- Operation.from_kraus An operation, that corresponds to the rotation. """ matrix = np.sqrt(0.5)*np.array([[1, 1], [1, -1]]) return Operation.from_kraus(matrix, 2)
def hadamard(): """A perfect Hadamard operation. Returns ------- Operation An operation, that corresponds to the rotation. """ s = np.sqrt(0.5) matrix = np.array([[s, s, 0], [s, -s, 0], [0, 0, 1]]) return Operation.from_kraus(matrix, 3)
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 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 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 cphase(angle=np.pi): """A perfect controlled phase rotation. Parameters ---------- angle: float, optional Rotation angle in radians. Default is :math:`\\pi`. Returns ------- Operation.from_kraus An operation, that corresponds to the rotation. """ matrix = np.diag([1, 1, 1, np.exp(1j * angle)]) return Operation.from_kraus(matrix, 2)
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 rotate_y(angle=np.pi): """A perfect single qubit rotation around :math:`Oy` axis. Parameters ---------- angle: float, optional Rotation angle in radians. Default is :math:`\\pi`. Returns ------- Operation.from_kraus An operation, that corresponds to the rotation. """ sin, cos = np.sin(angle / 2), np.cos(angle / 2) matrix = np.array([[cos, -sin], [sin, cos]]) return Operation.from_kraus(matrix, 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 rotate_z(angle=np.pi): """A perfect single qubit rotation around :math:`Oz` axis. Parameters ---------- angle: float, optional Rotation angle in radians. Default is :math:`\\pi`. Returns ------- Operation.from_kraus An operation, that corresponds to the rotation. """ exp = np.exp(-1j * angle / 2) matrix = np.diag([exp, exp.conj()]) return Operation.from_kraus(matrix, 2)
def rotate_z(angle=np.pi): """A perfect single qubit rotation around :math:`Oz` axis. Parameters ---------- angle: float, optional Rotation angle in radians. Default is :math:`\\pi`. Returns ------- Operation An operation, that corresponds to the rotation. """ exp = np.exp(-1j * angle / 2) matrix = np.diag([exp, exp.conj(), 1]) return Operation.from_kraus(matrix, 3)
def rotate_y(angle=np.pi): """A perfect single qubit rotation around :math:`Oy` axis. Parameters ---------- angle: float, optional Rotation angle in radians. Default is :math:`\\pi`. Returns ------- Operation An operation, that corresponds to the rotation. """ sin, cos = np.sin(angle / 2), np.cos(angle / 2) matrix = np.array([[cos, -sin, 0], [sin, cos, 0], [0, 0, 1]]) return Operation.from_kraus(matrix, 3)
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 iswap(angle=np.pi / 2): """A perfect controlled phase rotation. Parameters ---------- angle: float, optional Rotation angle in radians. Default is :math:`\\pi`. Returns ------- Operation.from_kraus An operation, that corresponds to the rotation. """ sin, cos = np.sin(angle), np.cos(angle) matrix = np.array([[1, 0, 0, 0], [0, cos, 1j * sin, 0], [0, 1j * sin, cos, 0], [0, 0, 0, 1]]) return Operation.from_kraus(matrix, 2)
def iswap(angle=np.pi/2): """A perfect controlled phase rotation. Parameters ---------- angle: float, optional Rotation angle in radians. Default is :math:`\\pi`. Returns ------- Operation.from_kraus An operation, that corresponds to the rotation. """ sin, cos = np.sin(angle), np.cos(angle) matrix = np.array([[1, 0, 0, 0], [0, cos, 1j*sin, 0], [0, 1j*sin, cos, 0], [0, 0, 0, 1]]) return Operation.from_kraus(matrix, 2)
def cphase(angle=np.pi, leakage=0.): """A perfect controlled phase rotation. First qubit is low-frequency, second qubit is high-frequency (it leaks). Parameters ---------- angle: float, optional Rotation angle in radians. Default is :math:`\\pi`. leakage: float, optional Leakage rate of a CPhase gate Returns ------- Operation An operation, that corresponds to the rotation. """ dcphase = np.zeros((9, 9)) dcphase[2, 4] = 1 dcphase[4, 2] = 1 angle_frac = 1 - np.arcsin(np.sqrt(leakage)) / np.pi unitary = expm(-1j*angle*angle_frac*dcphase) return Operation.from_kraus(unitary, 3)
def bit_flipping(flip_rate): matrix = np.array([ np.sqrt(flip_rate) * _PAULI["I"], np.sqrt(1 - flip_rate) * _PAULI["X"] ]) return Operation.from_kraus(matrix, bases1_default)
def phase_shift(angle=np.pi): matrix = np.diag([1, np.exp(1j * angle)]) return Operation.from_kraus(matrix, 2)
def cphase(angle=np.pi, *, integrate_idling=False, model='legacy', **kwargs): """ Parameters ---------- angle : float Conditional phase of a CPhase gate, default is :math:`\\pi`. integrate_idling : bool Whether to return model : str Error model (currently only 'legacy' and 'NetZero' is implemented). **kwargs Parameters for the error model. Returns ------- Operation Resulting CPhase operation. First qubit is static (low-frequency) qubit, """ def p(name): return kwargs.get(name, default_cphase_params[name]) for param in kwargs.keys(): if param not in default_cphase_params.keys(): raise ValueError('Unknown model parameter: {}'.format(param)) int_point_time = p('int_time') - (4 * p('rise_time')) if np.isfinite(p('q1_t2')) and np.isfinite(p('q1_t2_int')): rise_t2 = (p('q1_t2') + p('q1_t2_int')) / 2 else: rise_t2 = np.inf int_time = p('int_time') leakage_rate = p('leakage_rate') qstatic_deviation = int_time * np.pi * \ p('sensitivity') * (p('quasistatic_flux') ** 2) qstatic_interf_leakage = (0.5 - (2 * leakage_rate)) * \ (1 - np.cos(1.5 * qstatic_deviation)) phase_corr_error = p('phase_corr_error') rot_angle = angle + (1.5 * qstatic_deviation) + (2 * phase_corr_error) if model.lower() == 'legacy': cz_op = _cphase_legacy(angle, leakage_rate) elif model.lower() == 'netzero': ideal_unitary = expm( 1j * _ideal_generator(phase_10=phase_corr_error, phase_01=phase_corr_error + qstatic_deviation, phase_11=rot_angle, phase_02=rot_angle, phase_12=p('phase_diff_02_12') - rot_angle, phase_20=0, phase_21=p('phase_diff_20_21'), phase_22=p('phase_22'))) noisy_unitary = expm(1j * _exchange_generator( leakage=4 * leakage_rate + qstatic_interf_leakage, leakage_phase=p('leakage_phase'), leakage_mobility_rate=p('leakage_mobility_rate'), leakage_mobility_phase=p('leakage_mobility_phase'), )) cz_unitary = ideal_unitary @ noisy_unitary if not verify_kraus_unitarity(cz_unitary): raise RuntimeError("CPhase gate is not unitary, " "verify provided parameters.") cz_op = Operation.from_kraus(cz_unitary, bases2_default) else: raise ValueError('Unknown CZ model: {}'.format(model)) if integrate_idling: q0_t1 = p('q0_t1') q0_t2 = p('q0_t2') q0_anharmonicity = p('q0_anharmonicity') q1_t1 = p('q1_t1') q1_t2 = p('q1_t2') q1_t2_int = p('q1_t2_int') q1_anharmonicity = p('q1_anharmonicity') rise_time = p('rise_time') phase_corr_time = p('phase_corr_time') return Operation.from_sequence( idle(int_time / 2, q0_t1, q0_t2, q0_anharmonicity).at(0), idle(rise_time, q1_t1, rise_t2, q1_anharmonicity).at(1), idle(int_point_time / 2, q1_t1, q1_t2_int, q1_anharmonicity).at(1), idle(rise_time, q1_t1, rise_t2, q1_anharmonicity).at(1), cz_op.at(0, 1), idle(rise_time, q1_t1, rise_t2, q1_anharmonicity).at(1), idle(int_point_time / 2, q1_t1, q1_t2_int, q1_anharmonicity).at(1), idle(rise_time, q1_t1, rise_t2, q1_anharmonicity).at(1), idle(int_time / 2, q0_t1, q0_t2, q0_anharmonicity).at(0), idle(phase_corr_time, q0_t1, q0_t2, q0_anharmonicity).at(0), idle(phase_corr_time, q1_t1, q1_t2, q1_anharmonicity).at(1)) else: return cz_op
def phase_shift(angle=np.pi): matrix = np.diag([1, np.exp(1j * angle), 1]) return Operation.from_kraus(matrix, 3)
def cnot(): matrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) return Operation.from_kraus(matrix, 2)
def bit_phase_flipping(flip_rate): matrix = np.array([np.sqrt(flip_rate) * _PAULI["I"], np.sqrt(1 - flip_rate) * _PAULI["Y"]]) return Operation.from_kraus(matrix, 2)
def phase_flipping(flip_rate): # This is actually equivalent to the phase damping matrix = np.array([np.sqrt(flip_rate) * _PAULI["I"], np.sqrt(1 - flip_rate) * _PAULI["Z"]]) return Operation.from_kraus(matrix, 2)
def bit_phase_flipping(flip_rate): matrix = np.array([ np.sqrt(flip_rate) * _PAULI["I"], np.sqrt(1 - flip_rate) * _PAULI["Y"] ]) return Operation.from_kraus(matrix, 2)