def generate_program(cls, nqbits: int): pr = Program() # TODO extend to nqbits nqbits = 1 to_teleport = pr.qalloc(nqbits) to_teleport_c = pr.calloc(nqbits) epr_pair_a = pr.qalloc() epr_pair_a_c = pr.calloc() epr_pair_b = pr.qalloc() # Prepare EPR pair pr.apply(H, *epr_pair_a) pr.apply(CNOT, *epr_pair_a, *epr_pair_b) # Prepare random state using 3 random rotation around the 3 axis pr.apply(RY(random() * pi), *to_teleport) pr.apply(RX(random() * pi), *to_teleport) pr.apply(RZ(random() * pi), *to_teleport) # Encode pr.apply(CNOT, *to_teleport, *epr_pair_a) pr.apply(H, *to_teleport) # Teleport pr.measure(to_teleport, to_teleport_c) pr.measure(epr_pair_a, epr_pair_a_c) # Decode pr.cc_apply(epr_pair_a_c[0], X, epr_pair_b[0]) pr.cc_apply(to_teleport_c[0], Z, epr_pair_b[0]) return pr, None
def main(): # _a is for Alice, _b is for Bob, _c is for classical pr = Program() to_teleport = pr.qalloc() epr_pair_a = pr.qalloc() epr_pair_a_c = pr.calloc() to_teleport_c = pr.calloc() epr_pair_b = pr.qalloc() # Prepare EPR pair pr.apply(H, *epr_pair_a) pr.apply(CNOT, *epr_pair_a, *epr_pair_b) # Now Alice has her half of the EPR pair (epr_pair_a) and Bob the other one # (epr_pair_b qubit) # Prepare random state on the qubit(s) to teleport pr.apply(RY(random() * pi), *to_teleport) pr.apply(RX(random() * pi), *to_teleport) pr.apply(RZ(random() * pi), *to_teleport) # At this point we make a copy of the original program. The idea is to show # the state we would obtain if we would stop at this stage, before the # teleportation. pr2 = deepcopy(pr) # We continue with the teleportation circuit # Alice interact her to_teleport_qubit with her half of the EPR pair pr.apply(CNOT, *to_teleport, *epr_pair_a) pr.apply(H, *to_teleport) # ... and then she measures her 2 qubits pr.measure(to_teleport, to_teleport_c) pr.measure(epr_pair_a, epr_pair_a_c) # She then sends her measured qubits to Bob which, depending on their value # being 0 or 1, performs the classically controlled X and Z on his own half of the EPR pair pr.cc_apply(epr_pair_a_c[0], X, epr_pair_b[0]) pr.cc_apply(to_teleport_c[0], Z, epr_pair_b[0]) # circ = pr.to_circ() circ2 = pr2.to_circ() # simulation qpu = PyLinalg() res = qpu.submit(circ.to_job(qubits=[epr_pair_b])) res2 = qpu.submit(circ2.to_job(qubits=[to_teleport])) print("Original state, measured on to_teleport qubit") for sample in res2: # print(f"state {sample.state} with amplitude {sample.amplitude} and probability {sample.probability}") print(f"state {sample.state} with amplitude {sample.probability}") print("Teleported state, measured on ") for sample in res: print(f"state {sample.state} with probability {sample.probability}")
def test_multiple_measurements(): """ Submit a circuit composed to 2 intermediate measurements """ # Build a program prog = Program() qbits = prog.qalloc(2) cbits = prog.calloc(2) prog.apply(X, qbits[0]) prog.measure(qbits, cbits) prog.apply(CNOT, qbits) prog.measure(qbits, cbits) circ = prog.to_circ() # Submit circuit result = PyLinalg().submit(circ.to_job()) # Check result assert len(result) == 1 sample = result.raw_data[0] assert sample.state.int == 3 # Check intermediate measurements assert len(sample.intermediate_measurements) == 2 assert sample.intermediate_measurements[0].cbits == [True, False] assert sample.intermediate_measurements[1].cbits == [True, True]
def test1_qiskit_qpu_4states(self): """ In the case of two H gates, 4 states are expected in output. """ nbqubits = 2 prog = Program() qreg = prog.qalloc(nbqubits) creg = prog.calloc(nbqubits) prog.apply(H, qreg[0]) prog.apply(H, qreg[1]) prog.measure(qreg, creg) qlm_circuit = prog.to_circ() qlm_job = qlm_circuit.to_job(nbshots=1024) # no backend is specified qpu = BackendToQPU() result = qpu.submit(qlm_job) string = "\nBackendToQPU with a Hadamard on each qubit " \ + "(expects four different measured states):" LOGGER.debug(string) for entry in result.raw_data: LOGGER.debug("State: %s\t probability: %s", entry.state, entry.probability) self.assertEqual(4, len(result.raw_data))
def make_c_control_circuit(): prog = Program() qbits = prog.qalloc(2) cbits = prog.calloc(2) prog.apply(X, qbits[0]) prog.measure(qbits[0], cbits[0]) prog.cc_apply(cbits[0], X, qbits[1]) prog.measure(qbits[1], cbits[1]) return prog.to_circ()
def generate_break(): prog = Program() qbits = prog.qalloc(3) cbits = prog.calloc(3) prog.apply(X, qbits[1]) prog.measure(qbits[0], cbits[0]) prog.measure(qbits[1], cbits[1]) prog.cbreak(cbits[1] & (~cbits[0])) return prog.to_circ()
def generate_boolean(): prog = Program() qbits = prog.qalloc(3) cbits = prog.calloc(3) prog.apply(X, qbits[1]) prog.measure(qbits[0], cbits[0]) prog.measure(qbits[1], cbits[1]) prog.logic(cbits[2], cbits[1] & ~cbits[0]) prog.cc_apply(cbits[2], X, qbits[2]) prog.apply(X, qbits[0]) return prog.to_circ()
def make_simple_logic(): prog = Program() qbits = prog.qalloc(2) cbits = prog.calloc(5) prog.apply(X, qbits[0]) prog.measure(qbits[0], cbits[0]) prog.measure(qbits[1], cbits[1]) prog.logic(cbits[2], cbits[1] | cbits[0]) prog.logic(cbits[3], cbits[2] & cbits[1]) prog.logic(cbits[4], cbits[0] ^ cbits[1]) return prog.to_circ()
def test_default_gates_and_qbit_reorder(self): aq = AqasmPrinter(MainEngine) eng = AqasmEngine(aq, engine_list=[aq]) qreg1 = eng.allocate_qureg(2) qreg2 = eng.allocate_qureg(1) qreg3 = eng.allocate_qureg(2) for op in gates_1qb: op | qreg2[0] for op in gates_2qb: op | (qreg3[0], qreg1[1]) ControlledGate(ops.Swap, n=1) | (qreg3[1], qreg1[0], qreg2[0]) Toffoli | (qreg3[1], qreg1[0], qreg2[0]) All(Measure) | qreg1 All(Measure) | qreg2 All(Measure) | qreg3 # Generating qlm circuit result = eng.projectq_to_qlm() # Generating equivalent qlm circuit prog = Program() qubits = prog.qalloc(5) cbits = prog.calloc(5) for op in pygates_1qb: prog.apply(op, qubits[2]) for op in pygates_2qb: prog.apply(op, qubits[3], qubits[1]) prog.apply(SWAP, qubits[1], qubits[3]) prog.apply(SWAP.ctrl(), qubits[4], qubits[0], qubits[2]) prog.apply(X.ctrl().ctrl(), qubits[0], qubits[4], qubits[2]) for i in range(5): prog.measure(qubits[i], cbits[i]) expected = prog.to_circ() self.assertEqual(len(result.ops), len(expected.ops)) for i in range(len(result.ops)): res_op = result.ops[i] exp_op = expected.ops[i] if res_op.type == OpType.MEASURE: self.assertEqual(res_op, exp_op) continue result_gate_name, result_gate_params = extract_syntax( result.gateDic[res_op.gate], result.gateDic) # print("got gate {} with params {} on qbits {}" # .format(result_gate_name, result_gate_params, # res_op.qbits)) expected_gate_name, expected_gate_params = extract_syntax( expected.gateDic[exp_op.gate], expected.gateDic) # print("expected gate {} with params {} on qbits {}" # .format(expected_gate_name, expected_gate_params, # exp_op.qbits)) self.assertEqual(expected_gate_name, result_gate_name) self.assertEqual(expected_gate_params, result_gate_params) self.assertEqual(exp_op.qbits, res_op.qbits)
def test0_asyncqiskit_qpu_2states(self): """ In the case of a H and a CNOT gate, 2 states are expected in output. """ nbqubits = 2 prog = Program() qreg = prog.qalloc(nbqubits) creg = prog.calloc(nbqubits) prog.apply(H, qreg[0]) prog.apply(CNOT, qreg[0], qreg[1]) prog.measure(qreg, creg) qlm_circuit = prog.to_circ() qlm_job1 = qlm_circuit.to_job(nbshots=1024) qlm_job2 = qlm_circuit.to_job(nbshots=1024) batch = Batch(jobs=[qlm_job1, qlm_job2]) # a backend is specified backend = Aer.get_backend('qasm_simulator') qpu = AsyncBackendToQPU(backend) job = qpu.submit(batch) string = "\nAsyncBackendToQPU test with a Hadamard and a CNOT " \ + "(expects two different measured states):" LOGGER.debug(string) LOGGER.debug("ID: %s\t status : %s", job.job_id(), job.status()) time.sleep(0.01) LOGGER.debug("ID: %s\t status : %s", job.job_id(), job.status()) time.sleep(0.2) LOGGER.debug("ID: %s\t status : %s", job.job_id(), job.status()) while job.result() is None: time.sleep(5) results = job.result() for result in results: for entry in result.raw_data: LOGGER.debug("State: %s\t probability: %s", entry.state, entry.probability) self.assertEqual(2, len(result.raw_data)) self.assertTrue( "|00>" in [str(result.raw_data[i].state) for i in range(2)]) self.assertTrue( "|11>" in [str(result.raw_data[i].state) for i in range(2)])
def test1_asyncqiskit_qpu_4states(self): """ In the case of two H gates, 4 states are expected in output. """ nbqubits = 2 prog = Program() qreg = prog.qalloc(nbqubits) creg = prog.calloc(nbqubits) prog.apply(H, qreg[0]) prog.apply(H, qreg[1]) prog.measure(qreg, creg) qlm_circuit = prog.to_circ() qlm_job = qlm_circuit.to_job(nbshots=1024) # no backend is specified qpu = AsyncBackendToQPU() async_job = qpu.submit_job(qlm_job) string = "\nAsyncBackendToQPU test with a Hadamard on each qubit " \ + "(expects four different measured states):" LOGGER.debug(string) LOGGER.debug("ID: %s\t status : %s", async_job.job_id(), async_job.status()) time.sleep(0.01) LOGGER.debug("ID: %s\t status : %s", async_job.job_id(), async_job.status()) time.sleep(0.2) LOGGER.debug("ID: %s\t status : %s", async_job.job_id(), async_job.status()) loop_nb = 0 while async_job.result() is None: time.sleep(5) loop_nb += 1 if loop_nb > 4: return result = async_job.result() for entry in result.raw_data: LOGGER.debug("State: %s\t probability: %s", entry.state, entry.probability) self.assertEqual(4, len(result.raw_data))
def test_measure(self): """test that state indexing is same as other simulation services""" # program with final state: qbit 0 : 0 or 1 with 50% proba prog = Program() reg = prog.qalloc(1) creg = prog.calloc(1) prog.apply(H, reg) prog.measure(reg, creg) circ = prog.to_circ() qpu = PyLinalg() result = qpu.submit(circ.to_job(nbshots=5, aggregate_data=False)) for res in result: self.assertAlmostEqual( res.intermediate_measurements[0].probability, 0.5, delta=1e-10) self.assertEqual(res.intermediate_measurements[0].cbits[0], res.state.int)
def generate_teleportation(split_measures: bool): """ Generates a circuit corresponding to the teleportation circuit Args: split_measures (bool): split measures Returns: :class:`~qat.core.Circuit`: generated circuit """ # Init program prog = Program() source = prog.qalloc(1) bell_pair = prog.qalloc(2) cbits = prog.calloc(2) # Init source qubit prog.apply(RX(1.23), source) prog.apply(RZ(4.56), source) # Init Bell pair prog.apply(H, bell_pair[0]) prog.apply(CNOT, bell_pair) # Bell pair measurement between source qubit and bell_pair[0] prog.apply(CNOT, source, bell_pair[0]) prog.apply(H, source) if split_measures: prog.measure(source[0], cbits[0]) prog.measure(bell_pair[0], cbits[1]) else: prog.measure([source[0], bell_pair[0]], cbits) # Classic control prog.cc_apply(cbits[1], X, bell_pair[1]) prog.cc_apply(cbits[0], Z, bell_pair[1]) # Return circuit return prog.to_circ()
def qiskit_to_qlm(qiskit_circuit, sep_measures=False, **kwargs): """ Converts a Qiskit circuit into a QLM circuit. Args: qiskit_circuit: The Qiskit circuit to convert sep_measures: If set to True measures won't be included in the resulting circuits, qubits to be measured will be put in a list, the resulting measureless circuit and this list will be returned in a tuple : (resulting_circuit, list_qubits). If set to False, measures will be converted normally (Defaults to False) kwargs: These are the options that you would use on a regular to_circ function, to generate a QLM circuit from a PyAQASM program these are added for more flexibility, for advanced users Returns: If sep_measures is True a tuple of two elements will be returned, first element is the QLM resulting circuit with no measures, and the second element of the returned tuple is a list of all qubits that should be measured. if sep_measures is False, the QLM resulting circuit is returned directly """ prog = Program() qbits_num = 0 to_measure = [] for reg in qiskit_circuit.qregs: qbits_num = qbits_num + reg.size qbits = prog.qalloc(qbits_num) cbits_num = 0 for reg in qiskit_circuit.cregs: cbits_num = cbits_num + reg.size cbits = prog.calloc(cbits_num) variables = [] for gate_op in qiskit_circuit.data: if gate_op[0].name == "barrier" or gate_op[0].name == "opaque": continue qbit_args = [] cbit_args = [] prms = [] # gate parameters # Get qbit arguments for qarg in gate_op[1]: qbit_args.append( _get_qindex(qiskit_circuit, qarg.register.name, qarg.index)) # Get cbit arguments for carg in gate_op[2]: cbit_args.append( _get_cindex(qiskit_circuit, carg.register.name, carg.index)) # Get parameters for param in gate_op[0]._params: if isinstance(param, (Parameter, ParameterExpression)): prms.append(_qiskit_to_qlm_param(prog, variables, param)) else: prms.append(float(param)) # Apply measure # if gate_op[0].name == "measure": if sep_measures: to_measure.extend(qbit_args) else: prog.measure([qbits[i] for i in qbit_args], [cbits[i] for i in cbit_args]) else: if gate_op[0].name == "ms": # In this case, the process function needs the number of qubits prms.append(len(qbit_args)) # Apply gates # num_ctrl_qubits = None try: num_ctrl_qubits = gate_op[0].num_ctrl_qubits except: None gate = get_gate(gate_op[0].name, prms, num_ctrl_qubits) prog.apply(gate, *[qbits[i] for i in qbit_args][:gate.arity]) if sep_measures: return prog.to_circ(**kwargs), list(set(to_measure)) return prog.to_circ(**kwargs)
def test0_default_gates_and_qbit_reorder(self): """ Tries out every default gate and check that they match once the Qiskit circuit is translated into a QLM circuit. """ qreg1 = QuantumRegister(2) qreg2 = QuantumRegister(1) qreg3 = QuantumRegister(2) creg = ClassicalRegister(5) ocirc = QuantumCircuit(qreg1, qreg2, qreg3, creg) gates_1qb_0prm, gates_1qb_1prm, gates_2qb_0prm, \ gates_2qb_1prm, gates_3qb_0prm = gen_gates(ocirc) for gate_op in gates_1qb_0prm: gate_op(qreg2[0]) for gate_op in gates_1qb_1prm: gate_op(3.14, qreg2[0]) for gate_op in gates_2qb_0prm: gate_op(qreg3[0], qreg1[1]) for gate_op in gates_2qb_1prm: gate_op(3.14, qreg3[0], qreg1[1]) for gate_op in gates_3qb_0prm: gate_op(qreg2[0], qreg3[1], qreg1[1]) ocirc.u(3.14, 3.14, 3.14, qreg3[0]) ocirc.r(3.14, 3.14, qreg3[0]) ocirc.ms(3.14, [qreg1[1], qreg2[0], qreg3[0]]) ocirc.measure(qreg1[0], creg[4]) ocirc.measure(qreg1[1], creg[3]) ocirc.measure(qreg2[0], creg[2]) ocirc.measure(qreg3[0], creg[1]) ocirc.measure(qreg3[1], creg[0]) result = qiskit_to_qlm(ocirc) prog = Program() qubits = prog.qalloc(5) cbits = prog.calloc(5) for gate_op in PYGATES_1QB: prog.apply(gate_op, qubits[2]) for gate_op in PYGATES_2QB: prog.apply(gate_op, qubits[3], qubits[1]) prog.apply(SWAP.ctrl(), qubits[2], qubits[4], qubits[1]) prog.apply(X.ctrl().ctrl(), qubits[2], qubits[4], qubits[1]) prog.apply(U3(3.14, 3.14, 3.14), qubits[3]) prog.apply(R(3.14, 3.14), qubits[3]) prog.apply(MS(3.14, 3), qubits[1], qubits[2], qubits[3]) for i in range(5): prog.measure(qubits[i], cbits[4 - i]) expected = prog.to_circ() self.assertEqual(len(result.ops), len(expected.ops)) for res_op, exp_op in zip(result.ops, expected.ops): if res_op.type == OpType.MEASURE: self.assertEqual(res_op, exp_op) continue result_gate_name, result_gate_params = extract_syntax( result.gateDic[res_op.gate], result.gateDic) LOGGER.debug("got gate {} with params {} on qbits {}".format( result_gate_name, result_gate_params, res_op.qbits)) expected_gate_name, expected_gate_params = extract_syntax( expected.gateDic[exp_op.gate], expected.gateDic) LOGGER.debug("expected gate {} with params {} on qbits {}".format( expected_gate_name, expected_gate_params, exp_op.qbits)) self.assertEqual(expected_gate_name, result_gate_name) self.assertEqual(expected_gate_params, result_gate_params) self.assertEqual(exp_op.qbits, res_op.qbits) LOGGER.debug("\nResults obtained:") qpu = BackendToQPU() result_job = result.to_job(nbshots=1024) qiskit_result = qpu.submit(result_job) for entry in qiskit_result.raw_data: LOGGER.debug("State: {}\t probability: {}".format( entry.state, entry.probability)) LOGGER.debug("\nResults expected:") expected_job = expected.to_job(nbshots=1024) qlm_result = qpu.submit(expected_job) for entry in qlm_result.raw_data: LOGGER.debug("State: {}\t probability: {}".format( entry.state, entry.probability)) self.assertEqual(len(qiskit_result.raw_data), len(qlm_result.raw_data)) states_expected = [str(entry.state) for entry in qlm_result.raw_data] for entry in qiskit_result.raw_data: self.assertTrue(str(entry.state) in states_expected)
def qiskit_to_qlm(qiskit_circuit, sep_measures=False, **kwargs): """ Converts a Qiskit circuit into a QLM circuit. Args: qiskit_circuit: The Qiskit circuit to convert sep_measures: Separates measures from the circuit: - if set to :code:`True`, measures won't be included in the resulting circuit, qubits to be measured will be put in a list, the resulting measureless circuit and this list will be returned in a tuple: (resulting_circuit, list_qubits) - if set to :code:`False`, measures will be converted normally (Default, set to False) kwargs: These are the options that you would use on a regular to_circ function, to generate a QLM circuit from a PyAQASM program these are added for more flexibility, for advanced users Returns: :code:`tuple` or :class:`~qat.core.Circuit`: If :code:`sep_measures` is set to: - :code:`True`: the result is a tuple composed of a :class:`~qat.core.Circuit` and a list of qubits that should be measured - :code:`False`: the result is a :class:`~qat.core.Circuit` """ prog = Program() qbits_num = 0 to_measure = [] for reg in qiskit_circuit.qregs: qbits_num = qbits_num + reg.size qbits = prog.qalloc(qbits_num) cbits_num = 0 for reg in qiskit_circuit.cregs: cbits_num = cbits_num + reg.size cbits = prog.calloc(cbits_num) variables = [] for gate_op in qiskit_circuit.data: if gate_op[0].name in ("barrier", "opaque"): continue qbit_args = [] cbit_args = [] prms = [] # gate parameters # Get qbit arguments for qarg in gate_op[1]: qbit_args.append( _get_qindex(qiskit_circuit, qarg.register.name, qarg.index)) # Get cbit arguments for carg in gate_op[2]: cbit_args.append( _get_cindex(qiskit_circuit, carg.register.name, carg.index)) # Get parameters for param in gate_op[0].params: if isinstance(param, (Parameter, ParameterExpression)): prms.append(_qiskit_to_qlm_param(prog, variables, param)) else: prms.append(float(param)) # Apply measure # if gate_op[0].name == "measure": if sep_measures: to_measure.extend(qbit_args) else: prog.measure([qbits[i] for i in qbit_args], [cbits[i] for i in cbit_args]) elif gate_op[0].name == "reset": prog.reset([qbits[i] for i in qbit_args], [cbits[i] for i in cbit_args]) else: if gate_op[0].name == "ms": # In this case, the process function needs the number of qubits prms.append(len(qbit_args)) # Apply gates # num_ctrl_qubits = None try: num_ctrl_qubits = gate_op[0].num_ctrl_qubits except AttributeError: pass gate = get_gate(gate_op[0].name, prms, num_ctrl_qubits) prog.apply(gate, *[qbits[i] for i in qbit_args][:gate.arity]) if sep_measures: return prog.to_circ(**kwargs), list(set(to_measure)) return prog.to_circ(**kwargs)
def test2_asyncqiskit_qpu_ibmq_experience(self): """ Same as test0 of the same class, but using ibmq token if it is provided in the file tests/ibmq_token. Only create this file if you do want to test the ibmq service. If it is not provided, it will simply run a test identical to test0. """ nbqubits = 2 prog = Program() qreg = prog.qalloc(nbqubits) creg = prog.calloc(nbqubits) prog.apply(H, qreg[0]) prog.apply(CNOT, qreg[0], qreg[1]) prog.measure(qreg, creg) qlm_circuit = prog.to_circ() qlm_job1 = qlm_circuit.to_job(nbshots=1024) qlm_job2 = qlm_circuit.to_job(nbshots=1024) batch = Batch(jobs=[qlm_job1, qlm_job2]) # a backend is specified backend = Aer.get_backend('qasm_simulator') qpu = AsyncBackendToQPU(backend) path_to_file = os.path.join(os.path.dirname(__file__), './ibmq_token') LOGGER.warning("This may take a few seconds...") if os.path.exists(path_to_file) and os.path.getsize(path_to_file) > 0: with open(path_to_file, 'r') as token: qpu.set_backend(token=token.read(), ibmq_backend='ibmq_qasm_simulator') job = qpu.submit(batch) string = "\nAsyncBackendToQPU test with a Hadamard and a CNOT " \ + "(expects two different measured states):" LOGGER.debug(string) LOGGER.debug("ID: %s\t status : %s", job.job_id(), job.status()) time.sleep(0.01) LOGGER.debug("ID: %s\t status : %s", job.job_id(), job.status()) time.sleep(0.2) LOGGER.debug("ID: %s\t status : %s", job.job_id(), job.status()) while job.result() is None: time.sleep(5) results = job.result() for result in results: for entry in result.raw_data: LOGGER.debug("State: %s\t probability: %s", entry.state, entry.probability) self.assertEqual(2, len(result.raw_data)) self.assertTrue( "|00>" in [str(result.raw_data[i].state) for i in range(2)]) self.assertTrue( "|11>" in [str(result.raw_data[i].state) for i in range(2)])