def run(self, dag): """Run the SabreLayout pass on `dag`. Args: dag (DAGCircuit): DAG to find layout for. Raises: TranspilerError: if dag wider than self.coupling_map """ if len(dag.qubits) > self.coupling_map.size(): raise TranspilerError("More virtual qubits exist than physical.") # Choose a random initial_layout. if self.seed is None: self.seed = np.random.randint(0, np.iinfo(np.int32).max) rng = np.random.default_rng(self.seed) physical_qubits = rng.choice(self.coupling_map.size(), len(dag.qubits), replace=False) physical_qubits = rng.permutation(physical_qubits) initial_layout = Layout( {q: dag.qubits[i] for i, q in enumerate(physical_qubits)}) if self.routing_pass is None: self.routing_pass = SabreSwap(self.coupling_map, "decay", seed=self.seed, fake_run=True) else: self.routing_pass.fake_run = True # Do forward-backward iterations. circ = dag_to_circuit(dag) rev_circ = circ.reverse_ops() for _ in range(self.max_iterations): for _ in ("forward", "backward"): pm = self._layout_and_route_passmanager(initial_layout) new_circ = pm.run(circ) # Update initial layout and reverse the unmapped circuit. pass_final_layout = pm.property_set["final_layout"] final_layout = self._compose_layouts( initial_layout, pass_final_layout, new_circ.qregs # pylint: disable=no-member ) initial_layout = final_layout circ, rev_circ = rev_circ, circ # Diagnostics logger.info("new initial layout") logger.info(initial_layout) for qreg in dag.qregs.values(): initial_layout.add_register(qreg) self.property_set["layout"] = initial_layout self.routing_pass.fake_run = False
def test_layout_add_register(self): """add_register() method""" layout = Layout() layout.add_register(QuantumRegister(2, 'q0')) layout.add_register(QuantumRegister(1, 'qr1')) self.assertEqual(layout[(QuantumRegister(2, 'q0'), 0)], 0) self.assertEqual(layout[(QuantumRegister(2, 'q0'), 1)], 1) self.assertEqual(layout[(QuantumRegister(1, 'qr1'), 0)], 2)
def run(self, dag): """Run the SabreLayout pass on `dag`. Args: dag (DAGCircuit): DAG to find layout for. Raises: TranspilerError: if dag wider than self.coupling_map """ if len(dag.qubits) > self.coupling_map.size(): raise TranspilerError('More virtual qubits exist than physical.') # Choose a random initial_layout. if self.seed is None: self.seed = np.random.randint(0, np.iinfo(np.int32).max) rng = np.random.default_rng(self.seed) physical_qubits = rng.choice(self.coupling_map.size(), len(dag.qubits), replace=False) physical_qubits = rng.permutation(physical_qubits) initial_layout = Layout( {q: dag.qubits[i] for i, q in enumerate(physical_qubits)}) if self.routing_pass is None: self.routing_pass = SabreSwap(self.coupling_map, 'decay', seed=self.seed) # Do forward-backward iterations. circ = dag_to_circuit(dag) for i in range(self.max_iterations): for _ in ('forward', 'backward'): pm = self._layout_and_route_passmanager(initial_layout) new_circ = pm.run(circ) # Update initial layout and reverse the unmapped circuit. pass_final_layout = pm.property_set['final_layout'] final_layout = self._compose_layouts(initial_layout, pass_final_layout, new_circ.qregs) # pylint: disable=no-member initial_layout = final_layout circ = circ.reverse_ops() # Diagnostics logger.info('After round %d, num_swaps: %d', i + 1, new_circ.count_ops().get('swap', 0)) # pylint: disable=no-member logger.info('new initial layout') logger.info(initial_layout) for qreg in dag.qregs.values(): initial_layout.add_register(qreg) self.property_set['layout'] = initial_layout
def test_layout_add_register(self): """add_register() method""" layout = Layout() qr0 = QuantumRegister(2, 'q0') qr1 = QuantumRegister(1, 'qr1') layout.add_register(qr0) layout.add_register(qr1) self.assertEqual(layout[qr0[0]], 0) self.assertEqual(layout[qr0[1]], 1) self.assertEqual(layout[qr1[0]], 2)
def test_layout_add_register(self): """add_register() method""" layout = Layout() qr0 = QuantumRegister(2, "q0") qr1 = QuantumRegister(1, "qr1") layout.add_register(qr0) layout.add_register(qr1) self.assertEqual(layout[qr0[0]], 0) self.assertEqual(layout[qr0[1]], 1) self.assertEqual(layout[qr1[0]], 2) self.assertIn(qr0, layout.get_registers()) self.assertIn(qr1, layout.get_registers())
def get_layout(self, t: int) -> Layout: """Get layout at time-step t. Args: t: Time-step Returns: Layout """ dic = {} for q in range(self.num_vqubits): for i in range(self.num_pqubits): if self.solution.get_value(f"w_{t}_{q}_{i}") > 0.5: dic[self._index_to_virtual[q]] = self.global_qubit[i] layout = Layout(dic) for reg in self._dag.qregs.values(): layout.add_register(reg) return layout
def run(self, dag): """Run the DenseLayout pass on `dag`. Pick a convenient layout depending on the best matching qubit connectivity, and set the property `layout`. Args: dag (DAGCircuit): DAG to find layout for. Raises: TranspilerError: if dag wider than self.coupling_map """ if self.coupling_map is None: raise TranspilerError( "A coupling_map or target with constrained qargs is necessary to run the pass." ) num_dag_qubits = len(dag.qubits) if num_dag_qubits > self.coupling_map.size(): raise TranspilerError("Number of qubits greater than device.") num_cx = 0 num_meas = 0 if self.target is not None: num_cx = 1 num_meas = 1 else: # Get avg number of cx and meas per qubit ops = dag.count_ops() if "cx" in ops.keys(): num_cx = ops["cx"] if "measure" in ops.keys(): num_meas = ops["measure"] best_sub = self._best_subset(num_dag_qubits, num_meas, num_cx) layout = Layout() map_iter = 0 for qreg in dag.qregs.values(): for i in range(qreg.size): layout[qreg[i]] = int(best_sub[map_iter]) map_iter += 1 layout.add_register(qreg) self.property_set["layout"] = layout
def run(self, dag): """Run the DenseLayout pass on `dag`. Pick a convenient layout depending on the best matching qubit connectivity, and set the property `layout`. Args: dag (DAGCircuit): DAG to find layout for. Raises: TranspilerError: if dag wider than self.coupling_map """ num_dag_qubits = sum([qreg.size for qreg in dag.qregs.values()]) if num_dag_qubits > self.coupling_map.size(): raise TranspilerError("Number of qubits greater than device.") # Get avg number of cx and meas per qubit ops = dag.count_ops() if "cx" in ops.keys(): self.num_cx = ops["cx"] if "measure" in ops.keys(): self.num_meas = ops["measure"] # Compute the sparse cx_err matrix and meas array device_qubits = self.coupling_map.size() if self.backend_prop: rows = [] cols = [] cx_err = [] for edge in self.coupling_map.get_edges(): for gate in self.backend_prop.gates: if gate.qubits == edge: rows.append(edge[0]) cols.append(edge[1]) cx_err.append(gate.parameters[0].value) break else: continue self.cx_mat = sp.coo_matrix( (cx_err, (rows, cols)), shape=(device_qubits, device_qubits) ).tocsr() # Set measurement array meas_err = [] for qubit_data in self.backend_prop.qubits: for item in qubit_data: if item.name == "readout_error": meas_err.append(item.value) break else: continue self.meas_arr = np.asarray(meas_err) best_sub = self._best_subset(num_dag_qubits) layout = Layout() map_iter = 0 for qreg in dag.qregs.values(): for i in range(qreg.size): layout[qreg[i]] = int(best_sub[map_iter]) map_iter += 1 layout.add_register(qreg) self.property_set["layout"] = layout
def run(self, dag): """Run the ApplyLayout pass on `dag`. Args: dag (DAGCircuit): DAG to map. Returns: DAGCircuit: A mapped DAG (with physical qubits). Raises: TranspilerError: if no layout is found in `property_set` or no full physical qubits. """ layout = self.property_set["layout"] if not layout: raise TranspilerError( "No 'layout' is found in property_set. Please run a Layout pass in advance." ) if len(layout) != (1 + max(layout.get_physical_bits())): raise TranspilerError("The 'layout' must be full (with ancilla).") post_layout = self.property_set["post_layout"] q = QuantumRegister(len(layout), "q") new_dag = DAGCircuit() new_dag.add_qreg(q) new_dag.metadata = dag.metadata new_dag.add_clbits(dag.clbits) for creg in dag.cregs.values(): new_dag.add_creg(creg) if post_layout is None: for qreg in dag.qregs.values(): self.property_set["layout"].add_register(qreg) virtual_phsyical_map = layout.get_virtual_bits() for node in dag.topological_op_nodes(): qargs = [q[virtual_phsyical_map[qarg]] for qarg in node.qargs] new_dag.apply_operation_back(node.op, qargs, node.cargs) else: # First build a new layout object going from: # old virtual -> old phsyical -> new virtual -> new physical # to: # old virtual -> new physical full_layout = Layout() old_phys_to_virtual = layout.get_physical_bits() new_virtual_to_physical = post_layout.get_virtual_bits() qubit_index_map = { bit: index for index, bit in enumerate(dag.qubits) } for new_virt, new_phys in new_virtual_to_physical.items(): old_phys = qubit_index_map[new_virt] old_virt = old_phys_to_virtual[old_phys] full_layout.add(old_virt, new_phys) for reg in layout.get_registers(): full_layout.add_register(reg) # Apply new layout to the circuit for node in dag.topological_op_nodes(): qargs = [ q[new_virtual_to_physical[qarg]] for qarg in node.qargs ] new_dag.apply_operation_back(node.op, qargs, node.cargs) self.property_set["layout"] = full_layout new_dag._global_phase = dag._global_phase return new_dag
def run(self, dag): """Run the NoiseAdaptiveLayout pass on `dag`.""" self.swap_graph = rx.PyDiGraph() self.cx_reliability = {} self.readout_reliability = {} self.available_hw_qubits = [] self.gate_list = [] self.gate_reliability = {} self.swap_reliabs = {} self.prog_graph = rx.PyGraph() self.prog_neighbors = {} self.qarg_to_id = {} self.pending_program_edges = [] self.prog2hw = {} self._initialize_backend_prop() num_qubits = self._create_program_graph(dag) if num_qubits > len(self.swap_graph): raise TranspilerError('Number of qubits greater than device.') # sort by weight, then edge name for determinism (since networkx on python 3.5 returns # different order of edges) self.pending_program_edges = sorted(self.prog_graph.weighted_edge_list(), key=lambda x: [x[2], -x[0], -x[1]], reverse=True) while self.pending_program_edges: edge = self._select_next_edge() q1_mapped = edge[0] in self.prog2hw q2_mapped = edge[1] in self.prog2hw if (not q1_mapped) and (not q2_mapped): best_hw_edge = self._select_best_remaining_cx() if best_hw_edge is None: raise TranspilerError("CNOT({}, {}) could not be placed " "in selected device.".format(edge[0], edge[1])) self.prog2hw[edge[0]] = best_hw_edge[0] self.prog2hw[edge[1]] = best_hw_edge[1] self.available_hw_qubits.remove(best_hw_edge[0]) self.available_hw_qubits.remove(best_hw_edge[1]) elif not q1_mapped: best_hw_qubit = self._select_best_remaining_qubit(edge[0]) if best_hw_qubit is None: raise TranspilerError( "CNOT({}, {}) could not be placed in selected device. " "No qubit near qr[{}] available".format(edge[0], edge[1], edge[0])) self.prog2hw[edge[0]] = best_hw_qubit self.available_hw_qubits.remove(best_hw_qubit) else: best_hw_qubit = self._select_best_remaining_qubit(edge[1]) if best_hw_qubit is None: raise TranspilerError( "CNOT({}, {}) could not be placed in selected device. " "No qubit near qr[{}] available".format(edge[0], edge[1], edge[1])) self.prog2hw[edge[1]] = best_hw_qubit self.available_hw_qubits.remove(best_hw_qubit) new_edges = [x for x in self.pending_program_edges if not (x[0] in self.prog2hw and x[1] in self.prog2hw)] self.pending_program_edges = new_edges for qid in self.qarg_to_id.values(): if qid not in self.prog2hw: self.prog2hw[qid] = self.available_hw_qubits[0] self.available_hw_qubits.remove(self.prog2hw[qid]) layout = Layout() for q in dag.qubits: pid = self._qarg_to_id(q) hwid = self.prog2hw[pid] layout[q] = hwid for qreg in dag.qregs.values(): layout.add_register(qreg) self.property_set['layout'] = layout