def test_thermal_relaxation_channel_repeated(backend): initial_state = random_state(5) c = Circuit(5) c.add( gates.ThermalRelaxationChannel(4, t1=1.0, t2=0.6, time=0.8, excited_population=0.8, seed=123)) final_state = c(K.cast(np.copy(initial_state)), nshots=30) pz, p0, p1 = c.queue[0].calculate_probabilities(1.0, 0.6, 0.8, 0.8) np.random.seed(123) target_state = [] collapse = gates.M(4, collapse=True) collapse.nqubits = 5 zgate, xgate = gates.Z(4), gates.X(4) for _ in range(30): state = K.cast(np.copy(initial_state)) if np.random.random() < pz: state = zgate(state) if np.random.random() < p0: state = K.state_vector_collapse(collapse, state, [0]) if np.random.random() < p1: state = K.state_vector_collapse(collapse, state, [0]) state = xgate(state) target_state.append(K.copy(state)) target_state = K.stack(target_state) K.assert_allclose(final_state, target_state)
def test_trotter_hamiltonian_three_qubit_term(backend): """Test creating ``TrotterHamiltonian`` with three qubit term.""" from scipy.linalg import expm from qibo.core.terms import HamiltonianTerm m1 = random_hermitian(3) m2 = random_hermitian(2) m3 = random_hermitian(1) terms = [HamiltonianTerm(m1, 0, 1, 2), HamiltonianTerm(m2, 2, 3), HamiltonianTerm(m3, 1)] ham = hamiltonians.SymbolicHamiltonian() ham.terms = terms # Test that the `TrotterHamiltonian` dense matrix is correct eye = np.eye(2, dtype=m1.dtype) mm1 = np.kron(m1, eye) mm2 = np.kron(np.kron(eye, eye), m2) mm3 = np.kron(np.kron(eye, m3), np.kron(eye, eye)) target_ham = hamiltonians.Hamiltonian(4, mm1 + mm2 + mm3) K.assert_allclose(ham.matrix, target_ham.matrix) dt = 1e-2 initial_state = random_state(4) if K.op is not None: with pytest.raises(NotImplementedError): circuit = ham.circuit(dt=dt) else: circuit = ham.circuit(dt=dt) final_state = circuit(np.copy(initial_state)) u = [expm(-0.5j * dt * (mm1 + mm3)), expm(-0.5j * dt * mm2)] target_state = u[1].dot(u[0].dot(initial_state)) target_state = u[0].dot(u[1].dot(target_state)) K.assert_allclose(final_state, target_state)
def test_qaoa_callbacks(backend, accelerators): from qibo import callbacks # use ``Y`` Hamiltonian so that there are no errors # in the Trotter decomposition if accelerators: with K.on_cpu(): h = hamiltonians.Y(5) else: h = hamiltonians.Y(5) energy = callbacks.Energy(h) params = 0.1 * np.random.random(4) state = random_state(5) ham = hamiltonians.Y(5, dense=False) qaoa = models.QAOA(ham, callbacks=[energy], accelerators=accelerators) qaoa.set_parameters(params) final_state = qaoa(np.copy(state)) h_matrix = K.to_numpy(h.matrix) m_matrix = K.to_numpy(qaoa.mixer.matrix) calc_energy = lambda s: (s.conj() * h_matrix.dot(s)).sum() target_state = np.copy(state) target_energy = [calc_energy(target_state)] for i, p in enumerate(params): if i % 2: u = expm(-1j * p * m_matrix) else: u = expm(-1j * p * h_matrix) target_state = u @ target_state target_energy.append(calc_energy(target_state)) K.assert_allclose(energy[:], target_energy)
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_qaoa_execution(backend, solver, dense, accel=None): h = hamiltonians.TFIM(6, h=1.0, dense=dense) m = hamiltonians.X(6, dense=dense) # Trotter and RK require small p's! params = 0.01 * (1 - 2 * np.random.random(4)) state = random_state(6) # set absolute test tolerance according to solver if "rk" in solver: atol = 1e-2 elif not dense: atol = 1e-5 else: atol = 0 target_state = np.copy(state) h_matrix = K.to_numpy(h.matrix) m_matrix = K.to_numpy(m.matrix) for i, p in enumerate(params): if i % 2: u = expm(-1j * p * m_matrix) else: u = expm(-1j * p * h_matrix) target_state = u @ target_state qaoa = models.QAOA(h, mixer=m, solver=solver, accelerators=accel) qaoa.set_parameters(params) final_state = qaoa(np.copy(state)) K.assert_allclose(final_state, target_state, atol=atol)
def test_measurement_result_parameters_repeated_execution( backend, accelerators, use_loop): test_device = K.cpu_devices[0] if accelerators else K.default_device initial_state = random_state(4) set_device_seed(123, accelerators) c = models.Circuit(4, accelerators) output = c.add(gates.M(1, collapse=True)) c.add(gates.RX(2, theta=np.pi * output / 4)) if use_loop: final_states = [] for _ in range(20): final_states.append(c(np.copy(initial_state)).state()) else: final_states = c(initial_state=np.copy(initial_state), nshots=20) set_device_seed(123, accelerators) target_states = [] with K.device(test_device): for _ in range(20): collapse = gates.M(1, collapse=True) target_state = collapse(K.cast(np.copy(initial_state))) if int(collapse.result.outcome()): target_state = gates.RX(2, theta=np.pi / 4)(target_state) target_states.append(np.copy(target_state)) final_states = K.stack(final_states) target_states = K.stack(target_states) K.assert_allclose(final_states, target_states)
def test_controlled_dagger(backend, gate, args): gate = getattr(gates, gate)(*args).controlled_by(0, 1, 2) c = Circuit(4) c.add((gate, gate.dagger())) initial_state = random_state(4) final_state = c(np.copy(initial_state)) K.assert_allclose(final_state, initial_state)
def test_measurement_result_parameters_repeated_execution_final_measurements( backend): initial_state = random_state(4) K.set_seed(123) c = models.Circuit(4) output = c.add(gates.M(1, collapse=True)) c.add(gates.RY(0, theta=np.pi * output / 3)) c.add(gates.RY(2, theta=np.pi * output / 4)) c.add(gates.M(0, 1, 2, 3)) result = c(initial_state=np.copy(initial_state), nshots=30) final_samples = result.samples(binary=False) K.set_seed(123) target_samples = [] for _ in range(30): collapse = gates.M(1, collapse=True) target_state = collapse(K.cast(np.copy(initial_state))) if int(collapse.result.outcome()): target_state = gates.RY(0, theta=np.pi / 3)(target_state) target_state = gates.RY(2, theta=np.pi / 4)(target_state) with K.device(K.default_device): target_result = gates.M(0, 1, 2, 3)(target_state) target_samples.append(target_result.decimal[0]) target_samples = K.stack(target_samples) K.assert_allclose(final_samples, target_samples)
def assert_gates_equivalent(qibo_gate, cirq_gates, nqubits, ndevices=None, atol=1e-7): """Asserts that QIBO and Cirq gates have equivalent action on a random state. Args: qibo_gate: QIBO gate. cirq_gates: List of tuples (cirq gate, target qubit IDs). nqubits: Total number of qubits in the circuit. atol: Absolute tolerance in state vector comparsion. """ initial_state = random_state(nqubits) target_state, target_depth = execute_cirq(cirq_gates, nqubits, np.copy(initial_state)) accelerators = None if ndevices is not None: accelerators = {"/GPU:0": ndevices} if accelerators: if not K.supports_multigpu: with pytest.raises(NotImplementedError): c = models.Circuit(nqubits, accelerators) elif K.get_platform() == "numba" and len( K.available_platforms) > 1: # pragma: no cover pytest.skip("Skipping distributed cirq test for numba platform.") else: c = models.Circuit(nqubits, accelerators) c.add(qibo_gate) final_state = c(np.copy(initial_state)) assert c.depth == target_depth K.assert_allclose(final_state, target_state, atol=atol)
def test_qft(backend, accelerators, nqubits): c = models.QFT(nqubits, accelerators=accelerators) initial_state = random_state(nqubits) final_state = c(np.copy(initial_state)) cirq_gates = [(cirq.qft, list(range(nqubits)))] target_state, _ = execute_cirq(cirq_gates, nqubits, np.copy(initial_state)) K.assert_allclose(target_state, final_state, atol=1e-6)
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_distributed_circuit_empty_execution(backend, accelerators): # test executing a circuit with the default initial state c = DistributedCircuit(5, accelerators) final_state = c().state() target_state = np.zeros_like(final_state) target_state[0] = 1 K.assert_allclose(final_state, target_state) # test re-executing the circuit with a given initial state initial_state = random_state(c.nqubits) K.assert_allclose(c(initial_state), initial_state) # test executing a new circuit with a given initial state c = DistributedCircuit(5, accelerators) initial_state = random_state(c.nqubits) K.assert_allclose(c(initial_state), initial_state) # test re-executing the circuit with the default initial state K.assert_allclose(c(), target_state)
def test_dagger_consistency(gate_1, gate_2, qubit): gate_1 = getattr(gates, gate_1)(qubit) gate_2 = getattr(gates, gate_2)(qubit) c = Circuit(qubit+1) c.add((gate_1, gate_2)) initial_state = random_state(qubit+1) final_state = c(np.copy(initial_state)) K.assert_allclose(final_state, initial_state)
def test_distributed_circuit_get_initial_state_bad_type(backend, accelerators): import itertools from qibo.tests.utils import random_state target_state = random_state(5) c = DistributedCircuit(5, accelerators) c.queues.qubits = DistributedQubits(range(c.nglobal), c.nqubits) with pytest.raises(TypeError): c.get_initial_state("test")
def test_dagger(backend, gate, args): gate = getattr(gates, gate)(*args) nqubits = len(gate.qubits) c = Circuit(nqubits) c.add((gate, gate.dagger())) initial_state = random_state(nqubits) final_state = c(np.copy(initial_state)) K.assert_allclose(final_state, initial_state)
def test_controlled_unitary_matrix(backend): initial_state = random_state(2) matrix = np.random.random((2, 2)) gate = gates.Unitary(matrix, 1).controlled_by(0) c = Circuit(2) c.add(gate) target_state = c(np.copy(initial_state)) final_state = np.dot(K.to_numpy(gate.matrix), initial_state) K.assert_allclose(final_state, target_state)
def test_density_matrix_circuit_initial_state(backend): from qibo.tests.utils import random_state initial_psi = random_state(3) c = Circuit(3, density_matrix=True) final_rho = c(np.copy(initial_psi)) target_rho = np.outer(initial_psi, initial_psi.conj()) K.assert_allclose(final_rho, target_rho) final_rho = c(initial_psi) K.assert_allclose(final_rho, target_rho)
def test_unitary_dagger(backend, nqubits): matrix = np.random.random((2**nqubits, 2**nqubits)) gate = gates.Unitary(matrix, *range(nqubits)) c = Circuit(nqubits) c.add((gate, gate.dagger())) initial_state = random_state(nqubits) final_state = c(np.copy(initial_state)) target_state = np.dot(matrix, initial_state) target_state = np.dot(np.conj(matrix).T, target_state) K.assert_allclose(final_state, target_state)
def test_qft_execution(backend, accelerators, nqubits, random): c = models.QFT(nqubits) if random: initial_state = random_state(nqubits) final_state = c(K.cast(np.copy(initial_state))) else: initial_state = c.get_initial_state() final_state = c() target_state = exact_qft(K.to_numpy(initial_state)) K.assert_allclose(final_state, target_state)
def test_controlled_unitary_dagger(backend): from scipy.linalg import expm matrix = np.random.random((2, 2)) matrix = expm(1j * (matrix + matrix.T)) gate = gates.Unitary(matrix, 0).controlled_by(1, 2, 3, 4) c = Circuit(5) c.add((gate, gate.dagger())) initial_state = random_state(5) final_state = c(np.copy(initial_state)) K.assert_allclose(final_state, initial_state)
def test_distributed_circuit_execution_special_gate(backend, accelerators): dist_c = DistributedCircuit(6, accelerators) initial_state = random_state(dist_c.nqubits) dist_c.add(gates.Flatten(np.copy(initial_state))) dist_c.add((gates.H(i) for i in range(dist_c.nlocal))) dist_c.global_qubits = range(dist_c.nlocal, dist_c.nqubits) c = Circuit(6) c.add(gates.Flatten(np.copy(initial_state))) c.add((gates.H(i) for i in range(dist_c.nlocal))) np.testing.assert_allclose(dist_c(), c())
def test_variational_layer_dagger(backend, nqubits): theta = 2 * np.pi * np.random.random((2, nqubits)) pairs = list((i, i + 1) for i in range(0, nqubits - 1, 2)) gate = gates.VariationalLayer(range(nqubits), pairs, gates.RY, gates.CZ, theta[0], theta[1]) c = Circuit(nqubits) c.add((gate, gate.dagger())) initial_state = random_state(nqubits) final_state = c(np.copy(initial_state)) K.assert_allclose(final_state, initial_state)
def test_generalizedfsim_dagger(backend): from scipy.linalg import expm phi = 0.2 matrix = np.random.random((2, 2)) matrix = expm(1j * (matrix + matrix.T)) gate = gates.GeneralizedfSim(0, 1, matrix, phi) c = Circuit(2) c.add((gate, gate.dagger())) initial_state = random_state(2) final_state = c(np.copy(initial_state)) K.assert_allclose(final_state, initial_state)
def test_x_decomposition_execution(backend, target, controls, free, use_toffolis): """Check that applying the decomposition is equivalent to applying the multi-control gate.""" gate = gates.X(target).controlled_by(*controls) nqubits = max((target,) + controls + free) + 1 initial_state = random_state(nqubits) targetc = Circuit(nqubits) targetc.add(gate) target_state = targetc(np.copy(initial_state)) c = Circuit(nqubits) c.add(gate.decompose(*free, use_toffolis=use_toffolis)) final_state = c(np.copy(initial_state)) K.assert_allclose(final_state, target_state, atol=1e-6)
def test_cz(backend, controlled_by): initial_state = random_state(2) matrix = np.eye(4) matrix[3, 3] = -1 target_state = matrix.dot(initial_state) if controlled_by: gate = gates.Z(1).controlled_by(0) else: gate = gates.CZ(0, 1) final_state = apply_gates([gate], initial_state=initial_state) assert gate.name == "cz" K.assert_allclose(final_state, target_state)
def test_u2(backend): phi = 0.1234 lam = 0.4321 initial_state = random_state(1) final_state = apply_gates([gates.U2(0, phi, lam)], initial_state=initial_state) matrix = np.array( [[np.exp(-1j * (phi + lam) / 2), -np.exp(-1j * (phi - lam) / 2)], [np.exp(1j * (phi - lam) / 2), np.exp(1j * (phi + lam) / 2)]]) target_state = matrix.dot(initial_state) / np.sqrt(2) K.assert_allclose(final_state, target_state)
def test_distributed_circuit_execution_controlled_gate(backend, accelerators): dist_c = DistributedCircuit(4, accelerators) dist_c.add((gates.H(i) for i in range(dist_c.nglobal, 4))) dist_c.add(gates.CNOT(0, 2)) c = Circuit(4) c.add((gates.H(i) for i in range(dist_c.nglobal, 4))) c.add(gates.CNOT(0, 2)) initial_state = random_state(c.nqubits) final_state = dist_c(np.copy(initial_state)) target_state = c(np.copy(initial_state)) np.testing.assert_allclose(target_state, final_state)
def test_distributed_circuit_get_initial_state_random(backend, accelerators): import itertools from qibo.tests.utils import random_state target_state = random_state(5) c = DistributedCircuit(5, accelerators) c.queues.qubits = DistributedQubits(range(c.nglobal), c.nqubits) state = c.get_initial_state(target_state) np.testing.assert_allclose(state, target_state) target_state = np.reshape(target_state, 5 * (2, )) for i, s in enumerate(itertools.product([0, 1], repeat=c.nglobal)): target_piece = target_state[s].flatten() np.testing.assert_allclose(target_piece.ravel(), state.pieces[i])
def test_hamiltonian_term_exponentiation(backend): """Test exp gate application of ``HamiltonianTerm``.""" from scipy.linalg import expm matrix = np.random.random((2, 2)) term = terms.HamiltonianTerm(matrix, 1) exp_matrix = expm(-0.5j * matrix) K.assert_allclose(term.exp(0.5), exp_matrix) initial_state = random_state(2) final_state = term.expgate(0.5)(np.copy(initial_state)) exp_gate = gates.Unitary(exp_matrix, 1) target_state = exp_gate(np.copy(initial_state)) K.assert_allclose(final_state, target_state)
def test_hamiltonian_term_gates(backend): """Test gate application of ``HamiltonianTerm``.""" matrix = np.random.random((4, 4)) term = terms.HamiltonianTerm(matrix, 1, 2) gate = term.gate assert gate.target_qubits == (1, 2) K.assert_allclose(gate.matrix, matrix) initial_state = random_state(4) final_state = term(np.copy(initial_state)) c = models.Circuit(4) c.add(gates.Unitary(matrix, 1, 2)) target_state = c(np.copy(initial_state)) K.assert_allclose(final_state, target_state)