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_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_circuit_set_parameters_ungates(backend, accelerators, trainable): """Check updating parameters of circuit with list.""" original_backend = qibo.get_backend() qibo.set_backend(backend) params = [0.1, 0.2, 0.3, (0.4, 0.5), (0.6, 0.7, 0.8)] if trainable: trainable_params = list(params) else: trainable_params = [0.1, 0.3, (0.4, 0.5)] c = Circuit(3, accelerators) c.add(gates.RX(0, theta=0)) if trainable: c.add(gates.CRY(0, 1, theta=0, trainable=trainable)) else: c.add(gates.CRY(0, 1, theta=params[1], trainable=trainable)) c.add(gates.CZ(1, 2)) c.add(gates.U1(2, theta=0)) c.add(gates.CU2(0, 2, phi=0, lam=0)) if trainable: c.add(gates.U3(1, theta=0, phi=0, lam=0, trainable=trainable)) else: c.add(gates.U3(1, *params[4], trainable=trainable)) # execute once final_state = c() target_c = Circuit(3) target_c.add(gates.RX(0, theta=params[0])) target_c.add(gates.CRY(0, 1, theta=params[1])) target_c.add(gates.CZ(1, 2)) target_c.add(gates.U1(2, theta=params[2])) target_c.add(gates.CU2(0, 2, *params[3])) target_c.add(gates.U3(1, *params[4])) c.set_parameters(trainable_params) np.testing.assert_allclose(c(), target_c()) # Attempt using a flat list npparams = np.random.random(8) if trainable: trainable_params = np.copy(npparams) else: npparams[1] = params[1] npparams[5:] = params[4] trainable_params = np.delete(npparams, [1, 5, 6, 7]) target_c = Circuit(3) target_c.add(gates.RX(0, theta=npparams[0])) target_c.add(gates.CRY(0, 1, theta=npparams[1])) target_c.add(gates.CZ(1, 2)) target_c.add(gates.U1(2, theta=npparams[2])) target_c.add(gates.CU2(0, 2, *npparams[3:5])) target_c.add(gates.U3(1, *npparams[5:])) c.set_parameters(trainable_params) np.testing.assert_allclose(c(), target_c()) qibo.set_backend(original_backend)
def test_controlled_u1(backend): theta = 0.1234 c = Circuit(3) c.add(gates.X(0)) c.add(gates.X(1)) c.add(gates.X(2)) c.add(gates.U1(2, theta).controlled_by(0, 1)) c.add(gates.X(0)) c.add(gates.X(1)) final_state = c.execute() target_state = np.zeros_like(final_state) target_state[1] = np.exp(1j * theta) K.assert_allclose(final_state, target_state) gate = gates.U1(0, theta).controlled_by(1) assert gate.__class__.__name__ == "CU1"
def test_u1_gate(backend, nqubits, ndevices): """Check U1 gate.""" theta = 0.1234 targets = random_active_qubits(nqubits, nactive=1) qibo_gate = gates.U1(*targets, theta) cirq_gate = [(cirq.ZPowGate(exponent=theta / np.pi), targets)] assert_gates_equivalent(qibo_gate, cirq_gate, nqubits, ndevices)
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_u1(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) theta = 0.1234 final_state = apply_gates([gates.X(0), gates.U1(0, theta)], nqubits=1) 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 i_phi_adder(b, angles): """(Inverse) Quantum adder in Fourier space. Args: b (list): quantum register where the addition is implemented. angles (list): list of angles that encode the number to be added. Returns: generator with the required quantum gates applied on the quantum circuit. """ for i in reversed(range(0, len(b))): yield gates.U1(b[i], -angles[i])
def c_phi_adder(c, b, angles): """(1 Control) Quantum adder in Fourier space. Args: c (int): qubit acting as control. b (list): quantum register where the addition is implemented. angles (list): list of angles that encode the number to be added. Returns: generator with the required quantum gates applied on the quantum circuit. """ for i in range(0, len(b)): yield gates.U1(b[i], angles[i]).controlled_by(c)
def test_controlled_u1(backend): """Check controlled U1 and fallback to CU1.""" original_backend = qibo.get_backend() qibo.set_backend(backend) theta = 0.1234 c = Circuit(3) c.add(gates.X(0)) c.add(gates.X(1)) c.add(gates.X(2)) c.add(gates.U1(2, theta).controlled_by(0, 1)) c.add(gates.X(0)) c.add(gates.X(1)) 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) gate = gates.U1(0, theta).controlled_by(1) assert gate.__class__.__name__ == "CU1" qibo.set_backend(original_backend)
def test_construct_unitary(backend): original_backend = qibo.get_backend() qibo.set_backend(backend) target_matrix = np.array([[1, 1], [1, -1]]) / np.sqrt(2) np.testing.assert_allclose(gates.H(0).unitary, target_matrix) target_matrix = np.array([[0, 1], [1, 0]]) np.testing.assert_allclose(gates.X(0).unitary, target_matrix) target_matrix = np.array([[0, -1j], [1j, 0]]) np.testing.assert_allclose(gates.Y(0).unitary, target_matrix) target_matrix = np.array([[1, 0], [0, -1]]) np.testing.assert_allclose(gates.Z(1).unitary, target_matrix) target_matrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) np.testing.assert_allclose(gates.CNOT(0, 1).unitary, target_matrix) target_matrix = np.diag([1, 1, 1, -1]) np.testing.assert_allclose(gates.CZ(1, 3).unitary, target_matrix) target_matrix = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]) np.testing.assert_allclose(gates.SWAP(2, 4).unitary, target_matrix) target_matrix = np.array([[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 1, 0]]) np.testing.assert_allclose(gates.TOFFOLI(1, 2, 3).unitary, target_matrix) theta = 0.1234 target_matrix = np.array([[np.cos(theta / 2.0), -1j * np.sin(theta / 2.0)], [-1j * np.sin(theta / 2.0), np.cos(theta / 2.0)]]) np.testing.assert_allclose(gates.RX(0, theta).unitary, target_matrix) target_matrix = np.array([[np.cos(theta / 2.0), -np.sin(theta / 2.0)], [np.sin(theta / 2.0), np.cos(theta / 2.0)]]) np.testing.assert_allclose(gates.RY(0, theta).unitary, target_matrix) target_matrix = np.diag( [np.exp(-1j * theta / 2.0), np.exp(1j * theta / 2.0)]) np.testing.assert_allclose(gates.RZ(0, theta).unitary, target_matrix) target_matrix = np.diag([1, np.exp(1j * theta)]) np.testing.assert_allclose(gates.U1(0, theta).unitary, target_matrix) target_matrix = np.diag([1, 1, 1, np.exp(1j * theta)]) np.testing.assert_allclose(gates.CU1(0, 1, theta).unitary, target_matrix) from qibo import matrices target_matrix = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]) np.testing.assert_allclose(matrices.SWAP, target_matrix) qibo.set_backend(original_backend)
def i_cc_phi_adder(c1, c2, b, angles): """(Inverse) (2 Controls) Quantum adder in Fourier space. Args: c1 (int): qubit acting as first control. c2 (int): qubit acting as second control. b (list): quantum register where the addition is implemented. angles (list): list of angles that encode the number to be added. Returns: generator with the required quantum gates applied on the quantum circuit. """ for i in reversed(range(0, len(b))): yield gates.U1(b[i], -angles[i]).controlled_by(c1, c2)
def test_circuit_set_parameters_ungates(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.RX(0, theta=0)) c.add(gates.CRY(0, 1, theta=0)) c.add(gates.CZ(1, 2)) c.add(gates.U1(2, theta=0)) c.add(gates.CU2(0, 2, phi=0, lam=0)) c.add(gates.U3(1, theta=0, phi=0, lam=0)) # execute once final_state = c() params = [0.1, 0.2, 0.3, (0.4, 0.5), (0.6, 0.7, 0.8)] target_c = Circuit(3) target_c.add(gates.RX(0, theta=params[0])) target_c.add(gates.CRY(0, 1, theta=params[1])) target_c.add(gates.CZ(1, 2)) target_c.add(gates.U1(2, theta=params[2])) target_c.add(gates.CU2(0, 2, *params[3])) target_c.add(gates.U3(1, *params[4])) c.set_parameters(params) np.testing.assert_allclose(c(), target_c()) # Attempt using a flat list params = np.random.random(8) target_c = Circuit(3) target_c.add(gates.RX(0, theta=params[0])) target_c.add(gates.CRY(0, 1, theta=params[1])) target_c.add(gates.CZ(1, 2)) target_c.add(gates.U1(2, theta=params[2])) target_c.add(gates.CU2(0, 2, *params[3:5])) target_c.add(gates.U3(1, *params[5:])) c.set_parameters(params) 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 print(f' - Total number of qubits used: {2*n+3}.\n') results = [] exponents = [] exp = a % N for i in range(2 * n): exponents.append(exp) exp = (exp**2) % N circuit = Circuit(2 * n + 3) # 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)) results.append(circuit.add(gates.M(q_reg, collapse=True))) # Using multiple measurements for the semiclassical QFT. for i in range(1, 2 * n): # reset measured qubit to |0> circuit.add(gates.RX(q_reg, theta=np.pi * results[-1])) 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 * results[i + 1 - k] / (2**k) circuit.add(gates.U1(q_reg, -angle)) circuit.add(gates.H(q_reg)) results.append(circuit.add(gates.M(q_reg, collapse=True))) circuit() # execute s = sum(int(r.outcome()) * (2**i) for i, r in enumerate(results)) print(f"The quantum circuit measures s = {s}.\n") return s
def test_u1(backend): """Check U1 gate is working properly when qubit is on |1>.""" original_backend = qibo.get_backend() qibo.set_backend(backend) theta = 0.1234 c = Circuit(1) c.add(gates.X(0)) c.add(gates.U1(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) qibo.set_backend(original_backend)
def test_from_qasm_ugates(): import numpy as np target = """OPENQASM 2.0; qreg q[2]; u1(0.1) q[0]; u2(0.2,0.6) q[1]; cu3(0.3,0.4,0.5) q[0],q[1];""" c = Circuit.from_qasm(target) assert c.depth == 2 assert isinstance(c.queue[0], gates.U1) assert isinstance(c.queue[1], gates.U2) assert isinstance(c.queue[2], gates.CU3) c2 = Circuit(2) c2.add([gates.U1(0, 0.1), gates.U2(1, 0.2, 0.6)]) c2.add(gates.U3(1, 0.3, 0.4, 0.5).controlled_by(0)) np.testing.assert_allclose(c2().numpy(), c().numpy())
def test_u1(backend): theta = 0.1234 final_state = apply_gates([gates.X(0), gates.U1(0, theta)], nqubits=1) target_state = np.zeros_like(final_state) target_state[1] = np.exp(1j * theta) K.assert_allclose(final_state, target_state)