def predicate_route_device(my_circuit, my_device): gp = GraphPlacement(my_device) gp.place(my_circuit) cu = CompilationUnit(my_circuit, [ConnectivityPredicate(my_device)]) routing_passes = SequencePass( [RoutingPass(my_device), DecomposeSwapsToCXs(my_device, False)]) routing_passes.apply(cu) return cu.circuit, cu.check_all_predicates()
def gen_tket_pass(optimisepass, backend: str): if backend == _BACKEND_FULL: return optimisepass elif backend == _BACKEND_RIGETTI: final_pass = RebaseQuil() device = rigetti_device elif backend == _BACKEND_GOOGLE: final_pass = RebaseCirq() device = google_sycamore_device elif backend == _BACKEND_IBM: final_pass = RebaseIBM() device = ibm_rochester_device mapper = CXMappingPass(device, GraphPlacement(device)) total_pass = SequencePass( [optimisepass, mapper, SynthesiseIBM(), final_pass]) return total_pass
def place_on_device( circuit: cirq.Circuit, device: cirq.google.XmonDevice, ) -> Tuple[cirq.Circuit, Dict[cirq.Qid, cirq.Qid], Dict[cirq.Qid, cirq.Qid]]: """Place a circuit on an device. Converts a circuit to a new circuit that respects the adjacency of a given device and is equivalent to the given circuit up to qubit ordering. Args: circuit: The circuit to place on a grid. device: The device to place the circuit on. Returns: routed_circuit: The new circuit initial_map: Initial placement of qubits final_map: The final placement of qubits after action of the circuit """ index_to_qubit = sorted(device.qubit_set()) qubit_to_index = {q: i for i, q in enumerate(index_to_qubit)} tk_circuit = pytket.cirq.cirq_to_tk(circuit) tk_device = _device_to_tket_device(device, qubit_to_index) unit = CompilationUnit(tk_circuit, [ConnectivityPredicate(tk_device)]) passes = SequencePass( [PlacementPass(GraphPlacement(tk_device)), RoutingPass(tk_device)]) passes.apply(unit) valid = unit.check_all_predicates() if not valid: raise RuntimeError("Routing failed") initial_map = { cirq.LineQubit(_tk_to_i(n1)): index_to_qubit[_tk_to_i(n2)] for n1, n2 in unit.initial_map.items() } final_map = { cirq.LineQubit(_tk_to_i(n1)): index_to_qubit[_tk_to_i(n2)] for n1, n2 in unit.final_map.items() } routed_circuit = pytket.cirq.tk_to_cirq(unit.circuit) routed_circuit = routed_circuit.transform_qubits( lambda q: index_to_qubit[q.x]) return routed_circuit, initial_map, final_map
def place_on_device( circuit: cirq.Circuit, device: cg.XmonDevice, ) -> Tuple[cirq.Circuit, Dict[cirq.Qid, cirq.Qid], Dict[cirq.Qid, cirq.Qid]]: """Place a circuit on an device. Converts a circuit to a new circuit that respects the adjacency of a given device and is equivalent to the given circuit up to qubit ordering. Args: circuit: The circuit to place on a grid. device: The device to place the circuit on. Returns: routed_circuit: The new circuit initial_map: Initial placement of qubits final_map: The final placement of qubits after action of the circuit """ tk_circuit = pytket.extensions.cirq.cirq_to_tk(circuit) tk_device = _device_to_tket_device(device) unit = CompilationUnit(tk_circuit, [ConnectivityPredicate(tk_device)]) passes = SequencePass( [PlacementPass(GraphPlacement(tk_device)), RoutingPass(tk_device)]) passes.apply(unit) valid = unit.check_all_predicates() if not valid: raise RuntimeError("Routing failed") initial_map = { tk_to_cirq_qubit(n1): tk_to_cirq_qubit(n2) for n1, n2 in unit.initial_map.items() } final_map = { tk_to_cirq_qubit(n1): tk_to_cirq_qubit(n2) for n1, n2 in unit.final_map.items() } routed_circuit = pytket.extensions.cirq.tk_to_cirq(unit.circuit) return routed_circuit, initial_map, final_map
# # Let's switch to using our ```athens_device``` as it has heterogeneous device information. For our ```example_circuit``` each method produces the following maps: # Define a function for printing our maps: def print_qubit_mapping(the_map): print("Qubit to Node mapping:") for k, v in the_map.items(): print(k, v) # We can use the Placement objects to either modify the circuit in place, or return the mapping as a QubitMap. lp_athens = LinePlacement(athens_device) graph_athens = GraphPlacement(athens_device) noise_athens = NoiseAwarePlacement(athens_device) print("LinePlacement map:") print_qubit_mapping(lp_athens.get_placement_map(example_circuit)) print("GraphPlacement map:") print_qubit_mapping(graph_athens.get_placement_map(example_circuit)) print("NoiseAwarePlacement map:") print_qubit_mapping(noise_athens.get_placement_map(example_circuit)) # Each of these methods produces a different qubit->node mapping. Lets compare their performance: lp_ex_circ = example_circuit.copy() lp_athens.place(lp_ex_circ) gp_ex_circ = example_circuit.copy() graph_athens.place(gp_ex_circ)
(15, 16), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (12, 23), (16, 24), (20, 25), (23, 26), (24, 30), (25, 34), (26, 27), (27, 28), (28, 29), (29, 30), (30, 31), (31, 32), (32, 33), (33, 34), (34, 35), (35, 36), (28, 37), (32, 38), (36, 39), (37, 42), (38, 46), (39, 50), (40, 41), (41, 42), (42, 43), (43, 44), (44, 45), (45, 46), (46, 47), (47, 48), (48, 49), (49, 50), (40, 51), (44, 52), (48, 53), (51, 54), (52, 58), (53, 62), (54, 55), (55, 56), (56, 57), (57, 58), (58, 59), (59, 60), (60, 61), (61, 62), (62, 63), (63, 64), (56, 65), (60, 66), (64, 67), (65, 70), (66, 74), (67, 78), (68, 69), (69, 70), (70, 71), (71, 72), (72, 73), (73, 74), (74, 75), (75, 76), (76, 77), (77, 78), (68, 79), (72, 80), (76, 81)] tk_circuit = pytket.cirq.cirq_to_tk(circuit) tk_device = _device_connection_list_to_tket_device(device_connection_list) unit = CompilationUnit(tk_circuit, [ConnectivityPredicate(tk_device)]) passes = SequencePass([ PlacementPass(GraphPlacement(tk_device)), RoutingPass(tk_device, bridge_lookahead=0, bridge_interactions=0) ]) # NO BRIDGE passes.apply(unit) valid = unit.check_all_predicates() assert valid routed_circuit = pytket.cirq.tk_to_cirq(unit.circuit)