def test_general_channel(backend, tfmatrices, oncircuit): """Test `gates.KrausChannel`.""" original_backend = qibo.get_backend() qibo.set_backend(backend) initial_rho = utils.random_density_matrix(2) a1 = np.sqrt(0.4) * np.array([[0, 1], [1, 0]]) a2 = np.sqrt(0.6) * np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) if tfmatrices: from qibo import K a1, a2 = K.cast(a1), K.cast(a2) gate = gates.KrausChannel([((1, ), a1), ((0, 1), a2)]) assert gate.target_qubits == (0, 1) if oncircuit: c = models.Circuit(2, density_matrix=True) c.add(gate) final_rho = c(np.copy(initial_rho)) else: final_rho = gate(np.copy(initial_rho)) m1 = np.kron(np.eye(2), np.array(a1)) m2 = np.array(a2) target_rho = (m1.dot(initial_rho).dot(m1.conj().T) + m2.dot(initial_rho).dot(m2.conj().T)) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
def test_general_channel(backend, tfmatrices, oncircuit): """Test `gates.KrausChannel`.""" original_backend = qibo.get_backend() qibo.set_backend(backend) initial_rho = utils.random_density_matrix(2) a1 = np.sqrt(0.4) * np.array([[0, 1], [1, 0]]) a2 = np.sqrt(0.6) * np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) if tfmatrices: import tensorflow as tf from qibo.config import DTYPES a1 = tf.cast(a1, dtype=DTYPES.get('DTYPECPX')) a2 = tf.cast(a2, dtype=DTYPES.get('DTYPECPX')) gate = gates.KrausChannel([((1, ), a1), ((0, 1), a2)]) assert gate.target_qubits == (0, 1) if oncircuit: c = models.Circuit(2, density_matrix=True) c.add(gate) final_rho = c(np.copy(initial_rho)).numpy() else: if backend == "custom": final_rho = gate(np.copy(initial_rho)) else: final_rho = gate(np.copy(initial_rho).reshape(4 * (2, ))) final_rho = final_rho.numpy().reshape((4, 4)) m1 = np.kron(np.eye(2), np.array(a1)) m2 = np.array(a2) target_rho = (m1.dot(initial_rho).dot(m1.conj().T) + m2.dot(initial_rho).dot(m2.conj().T)) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
def test_reset_error(backend, density_matrix): reset = ResetError(0.8, 0.2) noise = NoiseModel() noise.add(reset, gates.X, 1) noise.add(reset, gates.CNOT) noise.add(reset, gates.Z, (0,1)) circuit = Circuit(3, density_matrix=density_matrix) circuit.add(gates.CNOT(0,1)) circuit.add(gates.Z(1)) target_circuit = Circuit(3, density_matrix=density_matrix) target_circuit.add(gates.CNOT(0,1)) target_circuit.add(gates.ResetChannel(0, 0.8, 0.2)) target_circuit.add(gates.ResetChannel(1, 0.8, 0.2)) target_circuit.add(gates.Z(1)) target_circuit.add(gates.ResetChannel(1, 0.8, 0.2)) initial_psi = random_density_matrix(3) if density_matrix else random_state(3) np.random.seed(123) K.set_seed(123) final_state = noise.apply(circuit)(initial_state=np.copy(initial_psi)) np.random.seed(123) K.set_seed(123) target_final_state = target_circuit(initial_state=np.copy(initial_psi)) K.assert_allclose(final_state, target_final_state)
def test_circuit_dm(backend): """Check passing density matrix as initial state to a circuit.""" original_backend = qibo.get_backend() qibo.set_backend(backend) theta = 0.1234 initial_rho = utils.random_density_matrix(3) c = models.Circuit(3, density_matrix=True) c.add(gates.H(0)) c.add(gates.H(1)) c.add(gates.CNOT(0, 1)) c.add(gates.H(2)) final_rho = c(np.copy(initial_rho)) h = np.array([[1, 1], [1, -1]]) / np.sqrt(2) cnot = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) m1 = np.kron(np.kron(h, h), np.eye(2)) m2 = np.kron(cnot, np.eye(2)) m3 = np.kron(np.eye(4), h) target_rho = m1.dot(initial_rho).dot(m1.T.conj()) target_rho = m2.dot(target_rho).dot(m2.T.conj()) target_rho = m3.dot(target_rho).dot(m3.T.conj()) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
def test_thermal_error(backend, density_matrix): thermal = ThermalRelaxationError(2, 1, 0.3) noise = NoiseModel() noise.add(thermal, gates.X, 1) noise.add(thermal, gates.CNOT) noise.add(thermal, gates.Z, (0,1)) circuit = Circuit(3, density_matrix=density_matrix) circuit.add(gates.CNOT(0,1)) circuit.add(gates.Z(1)) circuit.add(gates.X(1)) circuit.add(gates.X(2)) circuit.add(gates.Z(2)) target_circuit = Circuit(3, density_matrix=density_matrix) target_circuit.add(gates.CNOT(0,1)) target_circuit.add(gates.ThermalRelaxationChannel(0, 2, 1, 0.3)) target_circuit.add(gates.ThermalRelaxationChannel(1, 2, 1, 0.3)) target_circuit.add(gates.Z(1)) target_circuit.add(gates.ThermalRelaxationChannel(1, 2, 1, 0.3)) target_circuit.add(gates.X(1)) target_circuit.add(gates.ThermalRelaxationChannel(1, 2, 1, 0.3)) target_circuit.add(gates.X(2)) target_circuit.add(gates.Z(2)) initial_psi = random_density_matrix(3) if density_matrix else random_state(3) np.random.seed(123) K.set_seed(123) final_state = noise.apply(circuit)(initial_state=np.copy(initial_psi)) np.random.seed(123) K.set_seed(123) target_final_state = target_circuit(initial_state=np.copy(initial_psi)) K.assert_allclose(final_state, target_final_state)
def test_flatten_density_matrix(backend): """Check ``Flatten`` gate works with density matrices.""" original_backend = qibo.get_backend() qibo.set_backend(backend) target_rho = utils.random_density_matrix(3) initial_rho = np.zeros(6 * (2, )) gate = gates.Flatten(target_rho) gate.density_matrix = True final_rho = gate(initial_rho).numpy().reshape((8, 8)) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
def test_pauli_noise_channel(backend): initial_rho = random_density_matrix(2) gate = gates.PauliNoiseChannel(1, px=0.3) gate.density_matrix = True final_rho = gate(K.cast(np.copy(initial_rho))) gate = gates.X(1) gate.density_matrix = True initial_rho = K.cast(initial_rho) target_rho = 0.3 * gate(K.copy(initial_rho)) target_rho += 0.7 * initial_rho K.assert_allclose(final_rho, target_rho)
def test_general_channel(backend): a1 = np.sqrt(0.4) * np.array([[0, 1], [1, 0]]) a2 = np.sqrt(0.6) * np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) a1, a2 = K.cast(a1), K.cast(a2) initial_rho = random_density_matrix(2) gate = gates.KrausChannel([((1, ), a1), ((0, 1), a2)]) assert gate.target_qubits == (0, 1) final_rho = gate(np.copy(initial_rho)) m1 = np.kron(np.eye(2), K.to_numpy(a1)) m2 = K.to_numpy(a2) target_rho = (m1.dot(initial_rho).dot(m1.conj().T) + m2.dot(initial_rho).dot(m2.conj().T)) K.assert_allclose(final_rho, target_rho)
def test_bitflip_noise(backend): """Test `gates.PauliNoiseChannel` on random initial density matrix.""" original_backend = qibo.get_backend() qibo.set_backend(backend) initial_rho = utils.random_density_matrix(2) c = models.Circuit(2, density_matrix=True) c.add(gates.PauliNoiseChannel(1, px=0.3)) final_rho = c(np.copy(initial_rho)).numpy() c = models.Circuit(2, density_matrix=True) c.add(gates.X(1)) target_rho = 0.3 * c(np.copy(initial_rho)).numpy() target_rho += 0.7 * initial_rho.reshape(target_rho.shape) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
def test_reset_channel(backend): initial_rho = random_density_matrix(3) gate = gates.ResetChannel(0, p0=0.2, p1=0.2) gate.density_matrix = True final_rho = gate(K.cast(np.copy(initial_rho))) dtype = initial_rho.dtype collapsed_rho = np.copy(initial_rho).reshape(6 * (2, )) collapsed_rho[0, :, :, 1, :, :] = np.zeros(4 * (2, ), dtype=dtype) collapsed_rho[1, :, :, 0, :, :] = np.zeros(4 * (2, ), dtype=dtype) collapsed_rho[1, :, :, 1, :, :] = np.zeros(4 * (2, ), dtype=dtype) collapsed_rho = collapsed_rho.reshape((8, 8)) collapsed_rho /= np.trace(collapsed_rho) mx = np.kron(np.array([[0, 1], [1, 0]]), np.eye(4)) flipped_rho = mx.dot(collapsed_rho.dot(mx)) target_rho = 0.6 * initial_rho + 0.2 * (collapsed_rho + flipped_rho) K.assert_allclose(final_rho, target_rho)
def test_unitary_channel(backend): a1 = np.array([[0, 1], [1, 0]]) a2 = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) probs = [0.4, 0.3] matrices = [((0, ), a1), ((2, 3), a2)] initial_state = random_density_matrix(4) gate = gates.UnitaryChannel(probs, matrices) gate.density_matrix = True final_state = gate(K.cast(np.copy(initial_state))) eye = np.eye(2) ma1 = np.kron(np.kron(a1, eye), np.kron(eye, eye)) ma2 = np.kron(np.kron(eye, eye), a2) target_state = (0.3 * initial_state + 0.4 * ma1.dot(initial_state.dot(ma1)) + 0.3 * ma2.dot(initial_state.dot(ma2))) K.assert_allclose(final_state, target_state)
def test_thermal_relaxation_channel(backend, t1, t2, time, excpop): """Check ``gates.ThermalRelaxationChannel`` on a 3-qubit random density matrix.""" original_backend = qibo.get_backend() qibo.set_backend(backend) initial_rho = utils.random_density_matrix(3) c = models.Circuit(3, density_matrix=True) gate = gates.ThermalRelaxationChannel(0, t1, t2, time=time, excited_population=excpop) c.add(gate) final_rho = c(np.copy(initial_rho)) exp, p0, p1 = gates.ThermalRelaxationChannel._calculate_probs( t1, t2, time, excpop) if t2 > t1: matrix = np.diag([1 - p1, p0, p1, 1 - p0]) matrix[0, -1], matrix[-1, 0] = exp, exp matrix = matrix.reshape(4 * (2, )) # Apply matrix using Eq. (3.28) from arXiv:1111.6950 target_rho = np.copy(initial_rho).reshape(6 * (2, )) target_rho = np.einsum("abcd,aJKcjk->bJKdjk", matrix, target_rho) target_rho = target_rho.reshape(initial_rho.shape) else: pz = exp pi = 1 - pz - p0 - p1 dtype = initial_rho.dtype collapsed_rho = np.copy(initial_rho).reshape(6 * (2, )) collapsed_rho[0, :, :, 1, :, :] = np.zeros(4 * (2, ), dtype=dtype) collapsed_rho[1, :, :, 0, :, :] = np.zeros(4 * (2, ), dtype=dtype) collapsed_rho[1, :, :, 1, :, :] = np.zeros(4 * (2, ), dtype=dtype) collapsed_rho = collapsed_rho.reshape((8, 8)) collapsed_rho /= np.trace(collapsed_rho) mx = np.kron(np.array([[0, 1], [1, 0]]), np.eye(4)) mz = np.kron(np.array([[1, 0], [0, -1]]), np.eye(4)) z_rho = mz.dot(initial_rho.dot(mz)) flipped_rho = mx.dot(collapsed_rho.dot(mx)) target_rho = (pi * initial_rho + pz * z_rho + p0 * collapsed_rho + p1 * flipped_rho) np.testing.assert_allclose(final_rho, target_rho) # Try to apply to state vector if t1 < t2 if t1 < t2: with pytest.raises(ValueError): gate.state_vector_call(initial_rho) # pylint: disable=no-member qibo.set_backend(original_backend)
def test_symbolic_term_call(backend, density_matrix): """Test applying ``SymbolicTerm`` to state.""" from qibo.symbols import X, Y, Z expression = Z(0) * X(1) * Y(2) term = terms.SymbolicTerm(2, expression) matrixlist = [ np.kron(matrices.Z, np.eye(4)), np.kron(np.kron(np.eye(2), matrices.X), np.eye(2)), np.kron(np.eye(4), matrices.Y) ] initial_state = random_density_matrix( 3) if density_matrix else random_state(3) final_state = term(np.copy(initial_state), density_matrix=density_matrix) target_state = 2 * np.copy(initial_state) for matrix in matrixlist: target_state = matrix @ target_state K.assert_allclose(final_state, target_state)
def test_rygate_application_twoqubit(backend): """Check applying non-hermitian one qubit gate to one qubit density matrix.""" original_backend = qibo.get_backend() qibo.set_backend(backend) theta = 0.1234 initial_rho = utils.random_density_matrix(1) gate = gates.RY(0, theta=theta) gate.density_matrix = True final_rho = gate(np.copy(initial_rho)).numpy() phase = np.exp(1j * theta / 2.0) matrix = phase * np.array([[phase.real, -phase.imag], [phase.imag, phase.real]]) target_rho = matrix.dot(initial_rho).dot(matrix.T.conj()) np.testing.assert_allclose(final_rho, target_rho, atol=_atol) qibo.set_backend(original_backend)
def test_hgate_application_twoqubit(backend): """Check applying H gate to two qubit density matrix.""" original_backend = qibo.get_backend() qibo.set_backend(backend) initial_rho = utils.random_density_matrix(2) gate = gates.H(1) gate.density_matrix = True if backend == "custom": final_rho = np.copy(initial_rho) else: final_rho = np.copy(initial_rho).reshape(4 * (2, )) final_rho = gate(final_rho).numpy().reshape((4, 4)) matrix = np.array([[1, 1], [1, -1]]) / np.sqrt(2) matrix = np.kron(np.eye(2), matrix) initial_rho = initial_rho.reshape((4, 4)) target_rho = matrix.dot(initial_rho).dot(matrix) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
def test_measurement_collapse_density_matrix(backend, nqubits, targets): initial_rho = random_density_matrix(nqubits) gate = gates.M(*targets, collapse=True) gate.density_matrix = True final_rho = gate(K.cast(np.copy(initial_rho)), nshots=1) results = gate.result.binary[0] target_rho = np.reshape(initial_rho, 2 * nqubits * (2, )) for q, r in zip(targets, results): r = int(r) slicer = 2 * nqubits * [slice(None)] slicer[q], slicer[q + nqubits] = 1 - r, 1 - r target_rho[tuple(slicer)] = 0 slicer[q], slicer[q + nqubits] = r, 1 - r target_rho[tuple(slicer)] = 0 slicer[q], slicer[q + nqubits] = 1 - r, r target_rho[tuple(slicer)] = 0 target_rho = np.reshape(target_rho, initial_rho.shape) target_rho = target_rho / np.trace(target_rho) K.assert_allclose(final_rho, target_rho)
def test_pauli_error(backend, density_matrix, nshots): pauli = PauliError(0, 0.2, 0.3) noise = NoiseModel() noise.add(pauli, gates.X, 1) noise.add(pauli, gates.CNOT) noise.add(pauli, gates.Z, (0,1)) circuit = Circuit(3, density_matrix=density_matrix) circuit.add(gates.CNOT(0,1)) circuit.add(gates.Z(1)) circuit.add(gates.X(1)) circuit.add(gates.X(2)) circuit.add(gates.Z(2)) circuit.add(gates.M(0, 1, 2)) target_circuit = Circuit(3, density_matrix=density_matrix) target_circuit.add(gates.CNOT(0,1)) target_circuit.add(gates.PauliNoiseChannel(0, 0, 0.2, 0.3)) target_circuit.add(gates.PauliNoiseChannel(1, 0, 0.2, 0.3)) target_circuit.add(gates.Z(1)) target_circuit.add(gates.PauliNoiseChannel(1, 0, 0.2, 0.3)) target_circuit.add(gates.X(1)) target_circuit.add(gates.PauliNoiseChannel(1, 0, 0.2, 0.3)) target_circuit.add(gates.X(2)) target_circuit.add(gates.Z(2)) target_circuit.add(gates.M(0, 1, 2)) initial_psi = random_density_matrix(3) if density_matrix else random_state(3) np.random.seed(123) K.set_seed(123) final_state = noise.apply(circuit)(initial_state=np.copy(initial_psi), nshots=nshots) final_state_samples = final_state.samples() if nshots else None np.random.seed(123) K.set_seed(123) target_final_state = target_circuit(initial_state=np.copy(initial_psi), nshots=nshots) target_final_state_samples = target_final_state.samples() if nshots else None if nshots is None: K.assert_allclose(final_state, target_final_state) else: K.assert_allclose(final_state_samples, target_final_state_samples)
def test_entropy_density_matrix(backend): from qibo.tests.utils import random_density_matrix rho = random_density_matrix(4) # this rho is not always positive. Make rho positive for this application _, u = np.linalg.eigh(rho) rho = u.dot(np.diag(5 * np.random.random(u.shape[0]))).dot(u.conj().T) # this is a positive rho entropy = callbacks.EntanglementEntropy([1, 3]) entropy.density_matrix = True final_ent = entropy(rho) rho = rho.reshape(8 * (2,)) reduced_rho = np.einsum("abcdafch->bdfh", rho).reshape((4, 4)) eigvals = np.linalg.eigvalsh(reduced_rho).real # assert that all eigenvalues are non-negative assert (eigvals >= 0).prod() mask = eigvals > 0 target_ent = - (eigvals[mask] * np.log2(eigvals[mask])).sum() K.assert_allclose(final_ent, target_ent)
def test_reset_channel(backend): """Check ``gates.ResetChannel`` on a 3-qubit random density matrix.""" original_backend = qibo.get_backend() qibo.set_backend(backend) initial_rho = utils.random_density_matrix(3) c = models.Circuit(3, density_matrix=True) c.add(gates.ResetChannel(0, p0=0.2, p1=0.2)) final_rho = c(np.copy(initial_rho)) dtype = initial_rho.dtype collapsed_rho = np.copy(initial_rho).reshape(6 * (2, )) collapsed_rho[0, :, :, 1, :, :] = np.zeros(4 * (2, ), dtype=dtype) collapsed_rho[1, :, :, 0, :, :] = np.zeros(4 * (2, ), dtype=dtype) collapsed_rho[1, :, :, 1, :, :] = np.zeros(4 * (2, ), dtype=dtype) collapsed_rho = collapsed_rho.reshape((8, 8)) collapsed_rho /= np.trace(collapsed_rho) mx = np.kron(np.array([[0, 1], [1, 0]]), np.eye(4)) flipped_rho = mx.dot(collapsed_rho.dot(mx)) target_rho = 0.6 * initial_rho + 0.2 * (collapsed_rho + flipped_rho) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
def test_density_matrix_circuit(backend): from qibo.tests.utils import random_density_matrix theta = 0.1234 initial_rho = random_density_matrix(3) c = Circuit(3, density_matrix=True) c.add(gates.H(0)) c.add(gates.H(1)) c.add(gates.CNOT(0, 1)) c.add(gates.H(2)) final_rho = c(np.copy(initial_rho)) h = np.array([[1, 1], [1, -1]]) / np.sqrt(2) cnot = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) m1 = np.kron(np.kron(h, h), np.eye(2)) m2 = np.kron(cnot, np.eye(2)) m3 = np.kron(np.eye(4), h) target_rho = m1.dot(initial_rho).dot(m1.T.conj()) target_rho = m2.dot(target_rho).dot(m2.T.conj()) target_rho = m3.dot(target_rho).dot(m3.T.conj()) K.assert_allclose(final_rho, target_rho)
def test_unitary_channel(backend, density_matrix): """Test creating `gates.UnitaryChannel` from matrices and errors.""" original_backend = qibo.get_backend() qibo.set_backend(backend) a1 = np.array([[0, 1], [1, 0]]) a2 = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) probs = [0.4, 0.3] matrices = [((0, ), a1), ((2, 3), a2)] if density_matrix: initial_state = utils.random_density_matrix(4) else: initial_state = utils.random_numpy_state(4) c = models.Circuit(4, density_matrix=density_matrix) c.add(gates.UnitaryChannel(probs, matrices, seed=123)) final_state = c(initial_state, nshots=20).numpy() eye = np.eye(2, dtype=final_state.dtype) ma1 = np.kron(np.kron(a1, eye), np.kron(eye, eye)) ma2 = np.kron(np.kron(eye, eye), a2) if density_matrix: # use density matrices target_state = (0.3 * initial_state + 0.4 * ma1.dot(initial_state.dot(ma1)) + 0.3 * ma2.dot(initial_state.dot(ma2))) else: # sample unitary channel target_state = [] np.random.seed(123) for _ in range(20): temp_state = np.copy(initial_state) if np.random.random() < 0.4: temp_state = ma1.dot(temp_state) if np.random.random() < 0.3: temp_state = ma2.dot(temp_state) target_state.append(np.copy(temp_state)) np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_cu1gate_application_twoqubit(backend): """Check applying two qubit gate to three qubit density matrix.""" original_backend = qibo.get_backend() qibo.set_backend(backend) theta = 0.1234 nqubits = 3 initial_rho = utils.random_density_matrix(nqubits) gate = gates.CU1(0, 1, theta=theta) gate.density_matrix = True if backend == "custom": final_rho = np.copy(initial_rho) else: final_rho = np.copy(initial_rho).reshape(2 * nqubits * (2, )) final_rho = gate(final_rho).numpy().reshape(initial_rho.shape) matrix = np.eye(4, dtype=np.complex128) matrix[3, 3] = np.exp(1j * theta) matrix = np.kron(matrix, np.eye(2)) target_rho = matrix.dot(initial_rho).dot(matrix.T.conj()) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
def test_entanglement_entropy(backend): """Check that entanglement entropy calculation works for density matrices.""" original_backend = qibo.get_backend() qibo.set_backend(backend) rho = utils.random_density_matrix(4) # this rho is not always positive. Make rho positive for this application _, u = np.linalg.eigh(rho) rho = u.dot(np.diag(5 * np.random.random(u.shape[0]))).dot(u.conj().T) # this is a positive rho entropy = callbacks.EntanglementEntropy([1, 3]) entropy.density_matrix = True final_ent = entropy(rho) rho = rho.reshape(8 * (2, )) reduced_rho = np.einsum("abcdafch->bdfh", rho).reshape((4, 4)) eigvals = np.linalg.eigvalsh(reduced_rho).real # assert that all eigenvalues are non-negative assert (eigvals >= 0).prod() mask = eigvals > 0 target_ent = -(eigvals[mask] * np.log2(eigvals[mask])).sum() np.testing.assert_allclose(final_ent, target_ent) qibo.set_backend(original_backend)