def test_controlled_by_swap(backend): """Check controlled SWAP using controlled by for ``nqubits=4``.""" original_backend = qibo.get_backend() qibo.set_backend(backend) c = Circuit(4) c.add(gates.RX(2, theta=0.1234)) c.add(gates.RY(3, theta=0.4321)) c.add(gates.SWAP(2, 3).controlled_by(0)) final_state = c.execute().numpy() c = Circuit(4) c.add(gates.RX(2, theta=0.1234)) c.add(gates.RY(3, theta=0.4321)) target_state = c.execute().numpy() np.testing.assert_allclose(final_state, target_state) c = Circuit(4) c.add(gates.X(0)) c.add(gates.RX(2, theta=0.1234)) c.add(gates.RY(3, theta=0.4321)) c.add(gates.SWAP(2, 3).controlled_by(0)) c.add(gates.X(0)) final_state = c.execute().numpy() c = Circuit(4) c.add(gates.RX(2, theta=0.1234)) c.add(gates.RY(3, theta=0.4321)) c.add(gates.SWAP(2, 3)) target_state = c.execute().numpy() np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_zpow_gate(backend): """Check ZPow and CZPow gate fall back to U1 and CU1 respectively.""" original_backend = qibo.get_backend() qibo.set_backend(backend) theta = 0.1234 c = Circuit(1) c.add(gates.X(0)) c.add(gates.ZPow(0, theta)) final_state = c.execute().numpy() target_state = np.zeros_like(final_state) target_state[1] = np.exp(1j * theta) np.testing.assert_allclose(final_state, target_state) assert c.queue[1].name == "u1" c = Circuit(2) c.add([gates.X(0), gates.X(1)]) c.add(gates.CZPow(0, 1, theta)) final_state = c.execute().numpy() target_state = np.zeros_like(final_state) target_state[-1] = np.exp(1j * theta) np.testing.assert_allclose(final_state, target_state) assert c.queue[2].name == "cu1" qibo.set_backend(original_backend)
def test_measurement_qubit_order_simple(): """Check that measurement results follow order defined by user.""" c = models.Circuit(2) c.add(gates.X(0)) c.add(gates.M(1, 0)) result1 = c(nshots=100) c = models.Circuit(2) c.add(gates.X(0)) c.add(gates.M(1)) c.add(gates.M(0)) result2 = c(nshots=100) target_binary_samples = np.zeros((100, 2)) target_binary_samples[:, 1] = 1 target = { "decimal_samples": np.ones((100, )), "binary_samples": target_binary_samples, "decimal_frequencies": { 1: 100 }, "binary_frequencies": { "01": 100 } } assert_results(result1, **target) assert_results(result2, **target)
def rw_circuit(qubits, parameters, X=True): """Circuit that implements the amplitude distributor part of the option pricing algorithm. Args: qubits (int): number of qubits used for the unary basis. paramters (list): values to be introduces into the fSim gates for amplitude distribution. X (bool): whether or not the first X gate is executed. Returns: generator that yield the gates needed for the amplitude distributor circuit """ if qubits % 2 == 0: mid1 = int(qubits / 2) mid0 = int(mid1 - 1) if X: yield gates.X(mid1) yield gates.fSim(mid1, mid0, parameters[mid0] / 2, 0) for i in range(mid0): yield gates.fSim(mid0 - i, mid0 - i - 1, parameters[mid0 - i - 1] / 2, 0) yield gates.fSim(mid1 + i, mid1 + i + 1, parameters[mid1 + i] / 2, 0) else: mid = int((qubits - 1) / 2) if X: yield gates.X(mid) for i in range(mid): yield gates.fSim(mid - i, mid - i - 1, parameters[mid - i - 1] / 2, 0) yield gates.fSim(mid + i, mid + i + 1, parameters[mid + i] / 2, 0)
def diffuser(q, work, err): """Generator that performs the inversion over the average step in Grover's search algorithm. Args: q (list): quantum register that encodes the problem. work (int): ancilliary qubit used for the multi-controlled gate. err (float): error probability. Returns: quantum gate generator that applies the diffusion step. """ n = len(q) for i in range(n): yield gates.H(q[i]) yield error_gate(q[i], err) yield gates.X(q[i]) yield error_gate(q[i], err) yield gates.H(q[0]) yield error_gate(q[0], err) yield n_2CNOT(q[1:n], q[0], work, err) yield gates.H(q[0]) yield error_gate(q[0], err) for i in range(n): yield gates.X(q[i]) yield error_gate(q[i], err) yield gates.H(q[i]) yield error_gate(q[i], err)
def oracle(q, c, ancilla, clauses): """Generator that acts as the oracle for a 3SAT problem. Changes the sign of the amplitude of the quantum states that encode the solution. Args: q (list): quantum register that encodes the problem. c (list): quantum register that that records the satisfies clauses. ancilla (int): Grover ancillary qubit. Used to change the sign of the correct amplitudes. clauses (list): list of all clauses, with the qubits each clause acts upon. Returns: quantum gate generator for the 3SAT oracle """ k = 0 for clause in clauses: yield gates.CNOT(q[clause[0] - 1], c[k]) yield gates.CNOT(q[clause[1] - 1], c[k]) yield gates.CNOT(q[clause[2] - 1], c[k]) yield gates.X(c[k]).controlled_by(q[clause[0] - 1], q[clause[1] - 1], q[clause[2] - 1]) k += 1 yield gates.X(ancilla).controlled_by(*c) k = 0 for clause in clauses: yield gates.CNOT(q[clause[0] - 1], c[k]) yield gates.CNOT(q[clause[1] - 1], c[k]) yield gates.CNOT(q[clause[2] - 1], c[k]) yield gates.X(c[k]).controlled_by(q[clause[0] - 1], q[clause[1] - 1], q[clause[2] - 1]) k += 1
def test_circuit_vs_gate_execution(backend, compile): """Check consistency between executing circuit and stand alone gates.""" from qibo import K theta = 0.1234 target_c = Circuit(2) target_c.add(gates.X(0)) target_c.add(gates.X(1)) target_c.add(gates.CU1(0, 1, theta)) target_result = target_c() # custom circuit def custom_circuit(initial_state, theta): l1 = gates.X(0)(initial_state) l2 = gates.X(1)(l1) o = gates.CU1(0, 1, theta)(l2) return o initial_state = target_c.get_initial_state() if compile: c = K.compile(custom_circuit) else: c = custom_circuit result = c(initial_state, theta) K.assert_allclose(result, target_result)
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 quantum_order_finding_semiclassical(N, a): """Quantum circuit that performs the order finding algorithm using a semiclassical iQFT. Args: N (int): number to factorize. a (int): chosen number to use in the algorithm. Returns: s (float): value of the state measured by the quantum computer. """ print(' - Performing algorithm using a semiclassical iQFT.\n') # Creating the parts of the needed quantum circuit. n = int(np.ceil(np.log2(N))) b = [i for i in range(n+1)] x = [n+1+i for i in range(n)] ancilla = 2*n + 1 q_reg = 2*n + 2 circuit = Circuit(2*n+3) print(f' - Total number of qubits used: {2*n+3}.\n') r = [] exponents = [] exp = a%N for i in range(2*n): exponents.append(exp) exp = (exp**2)%N # Building the quantum circuit circuit.add(gates.H(q_reg)) circuit.add(gates.X(x[len(x)-1])) #a_i = (a**(2**(2*n - 1))) circuit.add(c_U(q_reg, x, b, exponents[-1], N, ancilla, n)) circuit.add(gates.H(q_reg)) circuit.add(gates.M(q_reg)) result = circuit(nshots=1) r.append(result.frequencies(binary=False).most_common()[0][0]) initial_state = circuit.final_state # Using multiple measurements for the semiclassical QFT. for i in range(1, 2*n): circuit = Circuit(2*n+3) circuit.add(gates.Collapse(q_reg, result=[r[-1]])) if r[-1] == 1: circuit.add(gates.X(q_reg)) circuit.add(gates.H(q_reg)) #a_i = (a**(2**(2*n - 1 - i))) circuit.add(c_U(q_reg, x, b, exponents[-1-i], N, ancilla, n)) angle = 0 for k in range(2, i+2): angle += 2*np.pi*r[i+1-k]/(2**k) circuit.add(gates.U1(q_reg, -angle)) circuit.add(gates.H(q_reg)) circuit.add(gates.M(q_reg)) result = circuit(initial_state, nshots=1) r.append(result.frequencies(binary=False).most_common()[0][0]) initial_state = circuit.final_state s = 0 for i in range(2*n): s += r[i]*2**(i) print(f"The quantum circuit measures s = {s}.\n") return s
def test_gate_after_measurement_error(backend, accelerators): c = models.Circuit(4, accelerators) c.add(gates.X(0)) c.add(gates.M(0)) c.add(gates.X(1)) # TODO: Change this to NotImplementedError with pytest.raises(ValueError): c.add(gates.H(0))
def test_controlled_x_vs_cnot(backend): c1 = Circuit(3) c1.add(gates.X(0)) c1.add(gates.X(2).controlled_by(0)) c2 = Circuit(3) c2.add(gates.X(0)) c2.add(gates.CNOT(0, 2)) K.assert_allclose(c1(), c2())
def sub_one(ancillas, controls): """Subtract 1 bit by bit. """ a = ancillas yield gates.X(a[0]).controlled_by(*controls) for i in range(1, len(a)): controls.append(a[i - 1]) yield gates.X(a[i]).controlled_by(*controls)
def test_gate_after_measurement_error(accelerators): """Check that reusing measured qubits is not allowed.""" c = models.Circuit(2, accelerators) c.add(gates.X(0)) c.add(gates.M(0)) c.add(gates.X(1)) # TODO: Change this to NotImplementedError with pytest.raises(ValueError): c.add(gates.H(0))
def test_multiple_swap(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) gatelist = [gates.X(0), gates.X(2), gates.SWAP(0, 1), gates.SWAP(2, 3)] final_state = apply_gates(gatelist, nqubits=4) gatelist = [gates.X(1), gates.X(3)] target_state = apply_gates(gatelist, nqubits=4) np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_controlled_x_vs_toffoli(backend): c1 = Circuit(3) c1.add(gates.X(0)) c1.add(gates.X(2)) c1.add(gates.X(1).controlled_by(0, 2)) c2 = Circuit(3) c2.add(gates.X(0)) c2.add(gates.X(2)) c2.add(gates.TOFFOLI(0, 2, 1)) K.assert_allclose(c1(), c2())
def test_czpow(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) theta = 0.1234 gatelist = [gates.X(0), gates.X(1), gates.CZPow(0, 1, theta)] final_state = apply_gates(gatelist, nqubits=2) target_state = np.zeros_like(final_state) target_state[-1] = np.exp(1j * theta) np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def add_negates_for_check(ancillas, num): """Adds the negates needed for control-on-zero. """ ind = 0 for i in reversed(bin(num)[2:]): if int(i) == 0: yield gates.X(ancillas[ind]) ind += 1 for i in range(len(bin(num)[2:]), len(ancillas)): yield gates.X(ancillas[i])
def test_post_measurement_bitflips_on_circuit(accelerators, probs, target): """Check bitflip errors on circuit measurements.""" import tensorflow as tf tf.random.set_seed(123) c = models.Circuit(5, accelerators=accelerators) c.add([gates.X(0), gates.X(2), gates.X(3)]) c.add(gates.M(0, 1, p0={0: probs[0], 1: probs[1]})) c.add(gates.M(3, p0=probs[2])) result = c(nshots=30).frequencies(binary=False) assert result == target
def test_post_measurement_bitflips_on_circuit(backend, accelerators, i, probs): """Check bitflip errors on circuit measurements.""" K.set_seed(123) c = models.Circuit(5, accelerators=accelerators) c.add([gates.X(0), gates.X(2), gates.X(3)]) c.add(gates.M(0, 1, p0={0: probs[0], 1: probs[1]})) c.add(gates.M(3, p0=probs[2])) result = c(nshots=30).frequencies(binary=False) targets = K.test_regressions("test_post_measurement_bitflips_on_circuit") assert result == targets[i]
def test_controlled_x_vs_cnot(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) c1 = Circuit(3) c1.add(gates.X(0)) c1.add(gates.X(2).controlled_by(0)) c2 = Circuit(3) c2.add(gates.X(0)) c2.add(gates.CNOT(0, 2)) np.testing.assert_allclose(c1(), c2()) qibo.set_backend(original_backend)
def test_grover_initial_state(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) oracle = Circuit(5 + 1) oracle.add(gates.X(5).controlled_by(*range(5))) initial_state = Circuit(5) initial_state.add(gates.X(4)) grover = Grover(oracle, superposition_qubits=5, initial_state_circuit=initial_state, number_solutions=1) assert grover.initial_state_circuit == initial_state solution, iterations = grover(logs=True) assert solution == ["11111"] qibo.set_backend(original_backend)
def test_toffoli(backend, applyx): if applyx: gatelist = [gates.X(0), gates.X(1), gates.TOFFOLI(0, 1, 2)] else: gatelist = [gates.X(1), gates.TOFFOLI(0, 1, 2)] final_state = apply_gates(gatelist, nqubits=3) target_state = np.zeros_like(final_state) if applyx: target_state[-1] = 1 else: target_state[2] = 1 K.assert_allclose(final_state, target_state)
def test_measurement_qubit_order(backend, accelerators, nshots): c = models.Circuit(6, accelerators) c.add(gates.X(0)) c.add(gates.X(1)) c.add(gates.M(1, 5, 2, 0)) result = c(nshots=nshots) target_binary_samples = np.zeros((nshots, 4)) target_binary_samples[:, 0] = 1 target_binary_samples[:, 3] = 1 assert_result(result, 9 * np.ones(nshots), target_binary_samples, {9: nshots}, {"1001": nshots})
def test_measurement_result_parameters(backend, accelerators, effect): c = models.Circuit(4, accelerators) if effect: c.add(gates.X(0)) output = c.add(gates.M(0, collapse=True)) c.add(gates.RX(1, theta=np.pi * output / 4)) target_c = models.Circuit(4) if effect: target_c.add(gates.X(0)) target_c.add(gates.RX(1, theta=np.pi / 4)) K.assert_allclose(c(), target_c())
def test_copied_circuit_execution(backend, accelerators, deep): """Check that circuit copy execution is equivalent to original circuit.""" theta = 0.1234 c1 = Circuit(4, accelerators) c1.add([gates.X(0), gates.X(1), gates.CU1(0, 1, theta)]) c1.add([gates.H(2), gates.H(3), gates.CU1(2, 3, theta)]) if not deep and accelerators is not None: with pytest.raises(ValueError): c2 = c1.copy(deep) else: c2 = c1.copy(deep) K.assert_allclose(c2(), c1())
def sum_circuit(qubits): sum_qubits = int(np.ceil(np.log2(qubits))) + 1 sum_circuit = Circuit(qubits + sum_qubits) sum_circuit.add(gates.X(qubits).controlled_by(0)) sum_circuit.add(gates.X(qubits).controlled_by(1)) sum_circuit.add(gates.X(qubits + 1).controlled_by(*[0, 1])) for qub in range(2, qubits): sum_circuit.add( one_sum(sum_qubits).on_qubits( *([qub] + list(range(qubits, qubits + sum_qubits))))) return sum_circuit
def test_controlled_x_vs_toffoli(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) c1 = Circuit(3) c1.add(gates.X(0)) c1.add(gates.X(2)) c1.add(gates.X(1).controlled_by(0, 2)) c2 = Circuit(3) c2.add(gates.X(0)) c2.add(gates.X(2)) c2.add(gates.TOFFOLI(0, 2, 1)) np.testing.assert_allclose(c1(), c2()) qibo.set_backend(original_backend)
def test_fusedgate_matrix_calculation(backend): queue = [gates.H(0), gates.H(1), gates.CNOT(0, 1), gates.X(0), gates.X(1)] circuit = Circuit(2) circuit.add(queue) circuit = circuit.fuse() assert len(circuit.queue) == 1 fused_gate = circuit.queue[0] x = np.array([[0, 1], [1, 0]]) 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]]) target_matrix = np.kron(x, x) @ cnot @ np.kron(h, h) K.assert_allclose(fused_gate.matrix, target_matrix)
def test_toffoli(backend): """Check Toffoli gate is working properly on |110>.""" original_backend = qibo.get_backend() qibo.set_backend(backend) c = Circuit(3) c.add(gates.X(0)) c.add(gates.X(1)) c.add(gates.TOFFOLI(0, 1, 2)) final_state = c.execute().numpy() target_state = np.zeros_like(final_state) target_state[-1] = 1.0 np.testing.assert_allclose(final_state, target_state) qibo.set_backend(original_backend)
def test_multiple_measurement_gates_circuit(backend): c = models.Circuit(4) c.add(gates.X(1)) c.add(gates.X(2)) c.add(gates.M(0, 1)) c.add(gates.M(2)) c.add(gates.X(3)) result = c(nshots=100) target_binary_samples = np.ones((100, 3)) target_binary_samples[:, 0] = 0 assert_result(result, 3 * np.ones(100), target_binary_samples, {3: 100}, {"011": 100})