def inverse_quantum_fourier_transform(q_ids, computing_host_ids, layers): """ Performs inverse quantum fourier transform """ q_ids.reverse() for i in range(len(q_ids)): target_qubit_id = q_ids[i] for j in range(i): control_qubit_id = q_ids[j] op = Operation(name=Constants.TWO_QUBIT, qids=[control_qubit_id, target_qubit_id], gate=Operation.CUSTOM_CONTROLLED, gate_param=phase_gate(-np.pi * (2**j) / (2**i)), computing_host_ids=[computing_host_ids[0]]) layers.append(Layer([op])) op = Operation(name=Constants.SINGLE, qids=[target_qubit_id], gate=Operation.H, computing_host_ids=[computing_host_ids[0]]) layers.append(Layer([op])) return layers
def create_circuit(q_map): """ Create the necessary circuit here """ layers = [] computing_host_ids = list(q_map.keys()) # Circuit input should be added # Prepare the qubits on both computing hosts ops = [] for host_id in computing_host_ids: op = Operation(name=Constants.PREPARE_QUBITS, qids=q_map[host_id], computing_host_ids=[host_id]) ops.append(op) layers.append(Layer(ops)) # Put qubit "q_0_0" in |1> state op = Operation(name=Constants.SINGLE, qids=[q_map[computing_host_ids[0]][0]], gate=Operation.X, computing_host_ids=[computing_host_ids[0]]) ops.append(op) layers.append(Layer(ops)) # Apply cnot gate from "q_0_0" to "q_1_0" control_qubit_id = q_map[computing_host_ids[0]][0] target_qubit_id = q_map[computing_host_ids[1]][0] op = Operation(name=Constants.TWO_QUBIT, qids=[control_qubit_id, target_qubit_id], gate=Operation.CNOT, computing_host_ids=computing_host_ids) layers.append(Layer([op])) # Measure the qubits ops = [] for host_id in computing_host_ids: op = Operation(name=Constants.MEASURE, qids=[q_map[host_id][0]], cids=[q_map[host_id][0]], computing_host_ids=[host_id]) ops.append(op) layers.append(Layer(ops)) circuit = Circuit(q_map, layers) return circuit
def quantum_phase_estimation_circuit(q_map, client_input_gate): """ Returns the monolithic circuit for quantum phase estimation algorithm """ layers = [] computing_host_ids = list(q_map.keys()) # Prepare the qubits on both computing hosts ops = [] for host_id in computing_host_ids: op = Operation(name=Constants.PREPARE_QUBITS, qids=q_map[host_id], computing_host_ids=[host_id]) ops.append(op) layers.append(Layer(ops)) # Setup the qubits by apply Hadamard gates on qubits of QPU_1 # and applying X gate to initialise qubit on QPU_2 ops = [] for q_id in q_map[computing_host_ids[0]]: op = Operation(name=Constants.SINGLE, qids=[q_id], gate=Operation.H, computing_host_ids=[computing_host_ids[0]]) ops.append(op) op = Operation(name=Constants.SINGLE, qids=[q_map[computing_host_ids[1]][0]], gate=Operation.X, computing_host_ids=[computing_host_ids[1]]) ops.append(op) layers.append(Layer(ops)) # Apply controlled unitaries for i in range(len(q_map[computing_host_ids[0]])): max_iter = 2**i control_qubit_id = q_map[computing_host_ids[0]][i] target_qubit_id = q_map[computing_host_ids[1]][0] for _ in range(max_iter): op = Operation(name=Constants.TWO_QUBIT, qids=[control_qubit_id, target_qubit_id], gate=Operation.CUSTOM_CONTROLLED, gate_param=client_input_gate, computing_host_ids=computing_host_ids) layers.append(Layer([op])) # Inverse Fourier Transform circuit q_ids = q_map[computing_host_ids[0]].copy() layers = inverse_quantum_fourier_transform(q_ids, computing_host_ids, layers) # Measure the qubits ops = [] for q_id in q_ids: op = Operation(name=Constants.MEASURE, qids=[q_id], cids=[q_id], computing_host_ids=[computing_host_ids[0]]) ops.append(op) layers.append(Layer(ops)) circuit = Circuit(q_map, layers) return circuit
def main(): network = Network.get_instance() network.delay = 0.1 network.start() clock = Clock() controller_host = ControllerHost( host_id="host_1", clock=clock, ) computing_hosts, q_map = controller_host.create_distributed_network( num_computing_hosts=2, num_qubits_per_host=10) controller_host.start() network.add_hosts( [computing_hosts[0], computing_hosts[1], controller_host]) layers = [] op_1 = Operation(name="PREPARE_QUBITS", qids=["q_0_0"], computing_host_ids=["QPU_0"]) op_2 = Operation(name="PREPARE_QUBITS", qids=["q_1_0"], computing_host_ids=["QPU_1"]) layers.append(Layer([op_1, op_2])) op_1 = Operation(name="SINGLE", qids=["q_0_0"], gate=Operation.I, computing_host_ids=["QPU_0"]) layers.append(Layer([op_1])) op_1 = Operation(name="TWO_QUBIT", qids=["q_0_0", "q_1_0"], gate=Operation.CNOT, computing_host_ids=["QPU_0", "QPU_1"]) layers.append(Layer([op_1])) op_1 = Operation(name="MEASURE", qids=["q_0_0"], cids=["q_0_0"], computing_host_ids=["QPU_0"]) op_2 = Operation(name="MEASURE", qids=["q_1_0"], cids=["q_1_0"], computing_host_ids=["QPU_1"]) layers.append(Layer([op_1, op_2])) circuit = Circuit(q_map, layers) def controller_host_protocol(host): host.generate_and_send_schedules(circuit) host.receive_results() print(host.results) def computing_host_protocol(host): host.receive_schedule() host.send_results() print(host.host_id, host.bits) print('starting...') t = controller_host.run_protocol(controller_host_protocol) computing_hosts[0].run_protocol(computing_host_protocol) g = computing_hosts[1].run_protocol(computing_host_protocol) t.join() g.join() network.stop(True)