def test_circuit_set_parameters_with_unitary(backend, accelerators): """Check updating parameters of circuit that contains ``Unitary`` gate.""" original_backend = qibo.get_backend() qibo.set_backend(backend) c = Circuit(3, accelerators) c.add(gates.RX(0, theta=0)) c.add(gates.Unitary(np.zeros((4, 4)), 1, 2)) # execute once final_state = c() params = [0.1234, np.random.random((4, 4))] target_c = Circuit(3) target_c.add(gates.RX(0, theta=params[0])) target_c.add(gates.Unitary(params[1], 1, 2)) c.set_parameters(params) np.testing.assert_allclose(c(), target_c()) # Attempt using a flat list / np.ndarray params = np.random.random(17) target_c = Circuit(3) target_c.add(gates.RX(0, theta=params[0])) target_c.add(gates.Unitary(params[1:].reshape((4, 4)), 1, 2)) c.set_parameters(params) np.testing.assert_allclose(c(), target_c()) qibo.set_backend(original_backend)
def test_circuit_set_parameters_with_dictionary(backend, accelerators): """Check updating parameters of circuit with list.""" original_backend = qibo.get_backend() qibo.set_backend(backend) c = Circuit(3, accelerators) c.add(gates.X(0)) c.add(gates.X(2)) c.add(gates.U1(0, theta=0)) c.add(gates.RZ(1, theta=0)) c.add(gates.CZ(1, 2)) c.add(gates.CU1(0, 2, theta=0)) c.add(gates.H(2)) c.add(gates.Unitary(np.eye(2), 1)) final_state = c() params = [0.123, 0.456, 0.789, np.random.random((2, 2))] target_c = Circuit(3, accelerators) target_c.add(gates.X(0)) target_c.add(gates.X(2)) target_c.add(gates.U1(0, theta=params[0])) target_c.add(gates.RZ(1, theta=params[1])) target_c.add(gates.CZ(1, 2)) target_c.add(gates.CU1(0, 2, theta=params[2])) target_c.add(gates.H(2)) target_c.add(gates.Unitary(params[3], 1)) param_dict = {c.queue[i]: p for i, p in zip([2, 3, 5, 7], params)} c.set_parameters(param_dict) np.testing.assert_allclose(c(), target_c()) qibo.set_backend(original_backend)
def test_unitary_common_gates(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) target_state = apply_gates([gates.X(0), gates.H(1)], nqubits=2) gatelist = [gates.Unitary(np.array([[0, 1], [1, 0]]), 0), gates.Unitary(np.array([[1, 1], [1, -1]]) / np.sqrt(2), 1)] final_state = apply_gates(gatelist, nqubits=2) np.testing.assert_allclose(final_state, target_state) thetax = 0.1234 thetay = 0.4321 gatelist = [gates.RX(0, theta=thetax), gates.RY(1, theta=thetay), gates.CNOT(0, 1)] target_state = apply_gates(gatelist, nqubits=2) rx = np.array([[np.cos(thetax / 2), -1j * np.sin(thetax / 2)], [-1j * np.sin(thetax / 2), np.cos(thetax / 2)]]) ry = np.array([[np.cos(thetay / 2), -np.sin(thetay / 2)], [np.sin(thetay / 2), np.cos(thetay / 2)]]) cnot = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) gatelist = [gates.Unitary(rx, 0), gates.Unitary(ry, 1), gates.Unitary(cnot, 0, 1)] final_state = apply_gates(gatelist, nqubits=2) np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_circuit_set_parameters_with_unitary(backend, trainable, accelerators): """Check updating parameters of circuit that contains ``Unitary`` gate.""" params = [0.1234, np.random.random((4, 4))] c = Circuit(4, accelerators) c.add(gates.RX(0, theta=0)) if trainable: c.add(gates.Unitary(np.zeros((4, 4)), 1, 2, trainable=trainable)) trainable_params = list(params) else: c.add(gates.Unitary(params[1], 1, 2, trainable=trainable)) trainable_params = [params[0]] # execute once final_state = c() target_c = Circuit(4) target_c.add(gates.RX(0, theta=params[0])) target_c.add(gates.Unitary(params[1], 1, 2)) c.set_parameters(trainable_params) K.assert_allclose(c(), target_c()) # Attempt using a flat list / np.ndarray new_params = np.random.random(17) if trainable: c.set_parameters(new_params) else: c.set_parameters(new_params[:1]) new_params[1:] = params[1].ravel() target_c = Circuit(4) target_c.add(gates.RX(0, theta=new_params[0])) target_c.add(gates.Unitary(new_params[1:].reshape((4, 4)), 1, 2)) K.assert_allclose(c(), target_c())
def test_unitary_common_gates(backend): """Check that `Unitary` gate can create common gates.""" original_backend = qibo.get_backend() qibo.set_backend(backend) c = Circuit(2) c.add(gates.X(0)) c.add(gates.H(1)) target_state = c.execute().numpy() c = Circuit(2) c.add(gates.Unitary(np.array([[0, 1], [1, 0]]), 0)) c.add(gates.Unitary(np.array([[1, 1], [1, -1]]) / np.sqrt(2), 1)) final_state = c.execute().numpy() np.testing.assert_allclose(final_state, target_state) thetax = 0.1234 thetay = 0.4321 c = Circuit(2) c.add(gates.RX(0, theta=thetax)) c.add(gates.RY(1, theta=thetay)) c.add(gates.CNOT(0, 1)) target_state = c.execute().numpy() c = Circuit(2) rx = np.array([[np.cos(thetax / 2), -1j * np.sin(thetax / 2)], [-1j * np.sin(thetax / 2), np.cos(thetax / 2)]]) ry = np.array([[np.cos(thetay / 2), -np.sin(thetay / 2)], [np.sin(thetay / 2), np.cos(thetay / 2)]]) cnot = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) c.add(gates.Unitary(rx, 0)) c.add(gates.Unitary(ry, 1)) c.add(gates.Unitary(cnot, 0, 1)) final_state = c.execute().numpy() np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_unitary_various_type_initialization(backend): import tensorflow as tf original_backend = qibo.get_backend() qibo.set_backend(backend) matrix = utils.random_tensorflow_complex((4, 4), dtype=tf.float64) gate = gates.Unitary(matrix, 0, 1) with pytest.raises(TypeError): gate = gates.Unitary("abc", 0, 1) qibo.set_backend(original_backend)
def test_unitary_initialization(backend): matrix = np.random.random((4, 4)) gate = gates.Unitary(matrix, 0, 1) K.assert_allclose(gate.parameters, matrix) matrix = np.random.random((8, 8)) with pytest.raises(ValueError): gate = gates.Unitary(matrix, 0, 1) with pytest.raises(TypeError): gate = gates.Unitary("abc", 0, 1)
def test_circuit_set_parameters_with_dictionary(backend, accelerators, trainable): """Check updating parameters of circuit with list.""" original_backend = qibo.get_backend() qibo.set_backend(backend) params = [0.123, 0.456, 0.789, np.random.random((2, 2))] c1 = Circuit(3, accelerators) c1.add(gates.X(0)) c1.add(gates.X(2)) if trainable: c1.add(gates.U1(0, theta=0, trainable=trainable)) else: c1.add(gates.U1(0, theta=params[0], trainable=trainable)) c2 = Circuit(3, accelerators) c2.add(gates.RZ(1, theta=0)) c2.add(gates.CZ(1, 2)) c2.add(gates.CU1(0, 2, theta=0)) c2.add(gates.H(2)) if trainable: c2.add(gates.Unitary(np.eye(2), 1, trainable=trainable)) else: c2.add(gates.Unitary(params[3], 1, trainable=trainable)) c = c1 + c2 final_state = c() target_c = Circuit(3, accelerators) target_c.add(gates.X(0)) target_c.add(gates.X(2)) target_c.add(gates.U1(0, theta=params[0])) target_c.add(gates.RZ(1, theta=params[1])) target_c.add(gates.CZ(1, 2)) target_c.add(gates.CU1(0, 2, theta=params[2])) target_c.add(gates.H(2)) target_c.add(gates.Unitary(params[3], 1)) if trainable: params_dict = {c.queue[i]: p for i, p in zip([2, 3, 5, 7], params)} else: params_dict = {c.queue[3]: params[1], c.queue[5]: params[2]} c.set_parameters(params_dict) np.testing.assert_allclose(c(), target_c()) # test not passing all parametrized gates target_c = Circuit(3, accelerators) target_c.add(gates.X(0)) target_c.add(gates.X(2)) target_c.add(gates.U1(0, theta=params[0])) target_c.add(gates.RZ(1, theta=params[1])) target_c.add(gates.CZ(1, 2)) target_c.add(gates.CU1(0, 2, theta=0.7891)) target_c.add(gates.H(2)) target_c.add(gates.Unitary(params[3], 1)) c.set_parameters({c.queue[5]: 0.7891}) np.testing.assert_allclose(c(), target_c()) qibo.set_backend(original_backend)
def test_unitary_bad_shape(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) matrix = np.random.random((8, 8)) with pytest.raises(ValueError): gate = gates.Unitary(matrix, 0, 1) if backend == "custom": with pytest.raises(NotImplementedError): gate = gates.Unitary(matrix, 0, 1, 2) qibo.set_backend(original_backend)
def test_unitary_matrix_gate(backend, nqubits, ndevices): """Check arbitrary unitary gate.""" matrix = random_unitary_matrix(1) targets = random_active_qubits(nqubits, nactive=1) qibo_gate = gates.Unitary(matrix, *targets) cirq_gate = [(cirq.MatrixGate(matrix), targets)] assert_gates_equivalent(qibo_gate, cirq_gate, nqubits) for _ in range(10): matrix = random_unitary_matrix(2) targets = random_active_qubits(nqubits, nactive=2) qibo_gate = gates.Unitary(matrix, *targets) cirq_gate = [(cirq.MatrixGate(matrix), targets)] assert_gates_equivalent(qibo_gate, cirq_gate, nqubits, ndevices)
def test_circuit_on_qubits_with_unitary_execution(backend, accelerators, controlled): unitaries = np.random.random((2, 2, 2)) smallc = Circuit(2) if controlled: smallc.add(gates.Unitary(unitaries[0], 0).controlled_by(1)) smallc.add(gates.Unitary(unitaries[1], 1).controlled_by(0)) else: smallc.add(gates.Unitary(unitaries[0], 0)) smallc.add(gates.Unitary(unitaries[1], 1)) smallc.add(gates.CNOT(0, 1)) largec = Circuit(4, accelerators=accelerators) largec.add(gates.RY(0, theta=0.1)) largec.add(gates.RY(1, theta=0.2)) largec.add(gates.RY(2, theta=0.3)) largec.add(gates.RY(3, theta=0.2)) largec.add(smallc.on_qubits(3, 0)) targetc = Circuit(4) targetc.add(gates.RY(0, theta=0.1)) targetc.add(gates.RY(1, theta=0.2)) targetc.add(gates.RY(2, theta=0.3)) targetc.add(gates.RY(3, theta=0.2)) if controlled: targetc.add(gates.Unitary(unitaries[0], 3).controlled_by(0)) targetc.add(gates.Unitary(unitaries[1], 0).controlled_by(3)) else: targetc.add(gates.Unitary(unitaries[0], 3)) targetc.add(gates.Unitary(unitaries[1], 0)) targetc.add(gates.CNOT(3, 0)) assert largec.depth == targetc.depth K.assert_allclose(largec(), targetc())
def test_unitary_initialization(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) matrix = np.random.random((4, 4)) gate = gates.Unitary(matrix, 0, 1) np.testing.assert_allclose(gate.parameters, matrix) matrix = np.random.random((8, 8)) with pytest.raises(ValueError): gate = gates.Unitary(matrix, 0, 1) with pytest.raises(TypeError): gate = gates.Unitary("abc", 0, 1) if backend == "custom": with pytest.raises(NotImplementedError): gate = gates.Unitary(matrix, 0, 1, 2) qibo.set_backend(original_backend)
def test_unitary_gate(backend, nqubits): """Check applying `gates.Unitary` to density matrix.""" shape = 2 * (2 ** nqubits,) matrix = np.random.random(shape) + 1j * np.random.random(shape) initial_rho = random_density_matrix(nqubits) from qibo import K if K.op is not None and nqubits > 2: with pytest.raises(NotImplementedError): gate = gates.Unitary(matrix, *range(nqubits)) else: gate = gates.Unitary(matrix, *range(nqubits)) gate.density_matrix = True final_rho = gate(np.copy(initial_rho)) target_rho = np.einsum("ab,bc,cd->ad", matrix, initial_rho, matrix.conj().T) K.assert_allclose(final_rho, target_rho)
def test_get_parameters(): c = Circuit(3) c.add(gates.RX(0, theta=0.123)) c.add(gates.RY(1, theta=0.456)) c.add(gates.CZ(1, 2)) c.add(gates.fSim(0, 2, theta=0.789, phi=0.987)) c.add(gates.H(2)) unitary = np.array([[0.123, 0.123], [0.123, 0.123]]) c.add(gates.Unitary(unitary, 1)) params = [0.123, 0.456, (0.789, 0.987), unitary] assert params == c.get_parameters() params = [0.123, 0.456, (0.789, 0.987), unitary] assert params == c.get_parameters() params = { c.queue[0]: 0.123, c.queue[1]: 0.456, c.queue[3]: (0.789, 0.987), c.queue[5]: unitary } assert params == c.get_parameters("dict") params = [0.123, 0.456, 0.789, 0.987] params.extend(unitary.ravel()) assert params == c.get_parameters("flatlist") with pytest.raises(ValueError): c.get_parameters("test")
def test_unitary(backend, nqubits): initial_state = np.ones(2**nqubits) / np.sqrt(2**nqubits) matrix = np.random.random(2 * (2**(nqubits - 1), )) target_state = np.kron(np.eye(2), matrix).dot(initial_state) gatelist = [gates.H(i) for i in range(nqubits)] gatelist.append(gates.Unitary(matrix, *range(1, nqubits), name="random")) final_state = apply_gates(gatelist, nqubits=nqubits) K.assert_allclose(final_state, target_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_unitary_gate(backend, nqubits): """Check applying `gates.Unitary` to density matrix.""" original_backend = qibo.get_backend() qibo.set_backend(backend) shape = 2 * (2**nqubits, ) matrix = np.random.random(shape) + 1j * np.random.random(shape) initial_rho = random_density_matrix(nqubits) if backend == "custom" and nqubits > 2: with pytest.raises(NotImplementedError): gate = gates.Unitary(matrix, *range(nqubits)) else: gate = gates.Unitary(matrix, *range(nqubits)) gate.density_matrix = True final_rho = gate(np.copy(initial_rho)) target_rho = np.einsum("ab,bc,cd->ad", matrix, initial_rho, matrix.conj().T) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
def test__control_unitary(backend): matrix = K.cast(np.random.random((2, 2))) gate = gates.Unitary(matrix, 0) unitary = gate._control_unitary(matrix) target_unitary = np.eye(4, dtype=K._dtypes.get('DTYPECPX')) target_unitary[2:, 2:] = K.to_numpy(matrix) K.assert_allclose(unitary, target_unitary) with pytest.raises(ValueError): unitary = gate._control_unitary(np.random.random((16, 16)))
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_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_controlled_unitary(backend, accelerators): matrix = np.random.random((2, 2)) c = Circuit(2) c.add(gates.H(0)) c.add(gates.H(1)) c.add(gates.Unitary(matrix, 1).controlled_by(0)) final_state = c.execute() target_state = np.ones_like(final_state) / 2.0 target_state[2:] = matrix.dot(target_state[2:]) K.assert_allclose(final_state, target_state) matrix = np.random.random((4, 4)) c = Circuit(4, accelerators) c.add((gates.H(i) for i in range(4))) c.add(gates.Unitary(matrix, 1, 3).controlled_by(0, 2)) final_state = c.execute() target_state = np.ones_like(final_state) / 4.0 ids = [10, 11, 14, 15] target_state[ids] = matrix.dot(target_state[ids]) K.assert_allclose(final_state, target_state)
def _create_circuit(self, dt, accelerators=None, memory_device="/CPU:0"): """Creates circuit that implements the Trotterized evolution.""" from qibo.models import Circuit self._circuit = Circuit(self.nqubits, accelerators=accelerators, memory_device=memory_device) self._circuit.check_initial_state_shape = False self._circuit.dt = None for part in itertools.chain(self.parts, self.parts[::-1]): for targets, term in part.items(): gate = gates.Unitary(term.exp(dt / 2.0), *targets) self.expgate_sets[term].add(gate) self._circuit.add(gate)
def test_controlled_unitary_matrix(backend): original_backend = qibo.get_backend() qibo.set_backend(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(gate.unitary, initial_state) np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_control_unitary(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) matrix = np.random.random((2, 2)) gate = gates.Unitary(matrix, 0) unitary = np.array(gate.control_unitary(matrix)) target_unitary = np.eye(4, dtype=unitary.dtype) target_unitary[2:, 2:] = matrix np.testing.assert_allclose(unitary, target_unitary) with pytest.raises(ValueError): unitary = gate.control_unitary(np.random.random((16, 16))) qibo.set_backend(original_backend)
def test_unitary_matrix_gate_controlled_by(backend, nqubits, ntargets, ndevices): """Check arbitrary unitary gate controlled on arbitrary number of qubits.""" original_backend = qibo.get_backend() qibo.set_backend(backend) all_qubits = np.arange(nqubits) for _ in range(10): activeq = random_active_qubits(nqubits, nactive=5) matrix = random_unitary_matrix(ntargets) qibo_gate = gates.Unitary(matrix, *activeq[-ntargets:]).controlled_by(*activeq[:-ntargets]) cirq_gate = [(cirq.MatrixGate(matrix).controlled(len(activeq) - ntargets), activeq)] assert_gates_equivalent(qibo_gate, cirq_gate, nqubits, ndevices) qibo.set_backend(original_backend)
def test_controlled_by_unitary_action(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) init_state = utils.random_numpy_state(2) matrix = utils.random_numpy_complex((2, 2)) gate = gates.Unitary(matrix, 1).controlled_by(0) c = Circuit(2) c.add(gate) target_state = c(np.copy(init_state)).numpy() final_state = gate.unitary.numpy().dot(init_state) np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_unitary_gate(backend, nqubits): """Check applying `gates.Unitary` to density matrix.""" original_backend = qibo.get_backend() qibo.set_backend(backend) shape = 2 * (2**nqubits, ) matrix = utils.random_numpy_complex(shape) initial_psi = utils.random_numpy_state(nqubits) initial_rho = np.outer(initial_psi, initial_psi.conj()) circuit = models.Circuit(nqubits, density_matrix=True) if backend == "custom" and nqubits > 2: with pytest.raises(NotImplementedError): circuit.add(gates.Unitary(matrix, *range(nqubits))) else: circuit.add(gates.Unitary(matrix, *range(nqubits))) final_rho = circuit(np.copy(initial_rho)).numpy() circuit = models.Circuit(nqubits) circuit.add(gates.Unitary(matrix, *range(nqubits))) target_psi = circuit(np.copy(initial_psi)).numpy() target_rho = np.outer(target_psi, target_psi.conj()) np.testing.assert_allclose(final_rho, target_rho) qibo.set_backend(original_backend)
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_circuit_gate_generator_with_unitary(backend, accelerators): original_backend = qibo.get_backend() qibo.set_backend(backend) unitaries = np.random.random((2, 2, 2)) smallc = Circuit(2) smallc.add((gates.Unitary(u, i) for i, u in enumerate(unitaries))) smallc.add(gates.CNOT(0, 1)) largec = Circuit(4, accelerators=accelerators) largec.add(gates.RY(1, theta=0.1)) largec.add(gates.RY(2, theta=0.2)) largec.add(smallc.on_qubits(0, 3)) targetc = Circuit(4) targetc.add(gates.RY(1, theta=0.1)) targetc.add(gates.RY(2, theta=0.2)) targetc.add(gates.Unitary(unitaries[0], 0)) targetc.add(gates.Unitary(unitaries[1], 3)) targetc.add(gates.CNOT(0, 3)) assert largec.depth == targetc.depth np.testing.assert_allclose(largec(), targetc()) qibo.set_backend(original_backend)
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)