def test_lookahead_mode(self): """Test lookahead mode's lookahead finds single SWAP gate. ┌───┐ q_0: ──■──┤ H ├─────────────── ┌─┴─┐└───┘ q_1: ┤ X ├──■────■─────────■── └───┘┌─┴─┐ │ │ q_2: ──■──┤ X ├──┼────■────┼── ┌─┴─┐└───┘┌─┴─┐┌─┴─┐┌─┴─┐ q_3: ┤ X ├─────┤ X ├┤ X ├┤ X ├ └───┘ └───┘└───┘└───┘ q_4: ───────────────────────── """ coupling = CouplingMap.from_line(5) qr = QuantumRegister(5, 'q') qc = QuantumCircuit(qr) qc.cx(0, 1) # free qc.cx(2, 3) # free qc.h(0) # free qc.cx(1, 2) # free qc.cx(1, 3) # F qc.cx(2, 3) # E qc.cx(1, 3) # E pm = PassManager(SabreSwap(coupling, 'lookahead')) new_qc = pm.run(qc) self.assertEqual(new_qc.num_nonlocal_gates(), 7)
def test_swaps_in_dummy_steps(self): """Test the case when swaps are inserted in dummy steps.""" circuit = QuantumCircuit(4) circuit.cx(0, 1) circuit.cx(2, 3) circuit.h([0, 1, 2, 3]) circuit.barrier() circuit.cx(0, 3) circuit.cx(1, 2) circuit.barrier() circuit.cx(0, 2) circuit.cx(1, 3) coupling = CouplingMap.from_line(4) property_set = {} actual = BIPMapping(coupling, objective="depth")(circuit, property_set) self.assertEqual(7, actual.depth()) CheckMap(coupling)(actual, property_set) self.assertTrue(property_set["is_swap_mapped"]) # no swaps before the first barrier for inst, _, _ in actual.data: if isinstance(inst, Barrier): break self.assertFalse(isinstance(inst, SwapGate))
def test_subgraph(self): coupling = CouplingMap.from_line(6, bidirectional=False) with self.assertWarns(DeprecationWarning): subgraph = coupling.subgraph([4, 2, 3, 5]) self.assertEqual(subgraph.size(), 4) self.assertEqual([0, 1, 2, 3], subgraph.physical_qubits) edge_list = subgraph.get_edges() expected = [(0, 1), (1, 2), (2, 3)] self.assertEqual(expected, edge_list, f"{edge_list} does not match {expected}")
def test_different_number_of_virtual_and_physical_qubits(self): """Test the case when number of virtual and physical qubits are different.""" circuit = QuantumCircuit(4) circuit.cx(0, 1) circuit.cx(2, 3) circuit.cx(0, 3) circuit.cx(1, 2) coupling = CouplingMap.from_line(5) with self.assertRaises(TranspilerError): BIPMapping(coupling)(circuit)
def test_target_too_small_for_circuit(self): """Test error is raised when target is too small for circuit.""" target = Target() target.add_instruction( CXGate(), {edge: None for edge in CouplingMap.from_line(3).get_edges()}) dag = circuit_to_dag(QuantumCircuit(5)) layout_pass = DenseLayout(target=target) with self.assertRaises(TranspilerError): layout_pass.run(dag)
def test_no_infinite_loop(self, method): """Test that the 'release value' mechanisms allow SabreSwap to make progress even on circuits that get stuck in a stable local minimum of the lookahead parameters.""" qc = looping_circuit(3, 1) qc.measure_all() coupling_map = CouplingMap.from_line(qc.num_qubits) routing_pass = PassManager(SabreSwap(coupling_map, method)) n_swap_gates = 0 def leak_number_of_swaps(cls, *args, **kwargs): nonlocal n_swap_gates n_swap_gates += 1 if n_swap_gates > 1_000: raise Exception("SabreSwap seems to be stuck in a loop") # pylint: disable=bad-super-call return super(SwapGate, cls).__new__(cls, *args, **kwargs) with unittest.mock.patch.object(SwapGate, "__new__", leak_number_of_swaps): routed = routing_pass.run(qc) routed_ops = routed.count_ops() del routed_ops["swap"] self.assertEqual(routed_ops, qc.count_ops()) couplings = { tuple(routed.find_bit(bit).index for bit in instruction.qubits) for instruction in routed.data if len(instruction.qubits) == 2 } # Asserting equality to the empty set gives better errors on failure than asserting that # `couplings <= coupling_map`. self.assertEqual(couplings - set(coupling_map.get_edges()), set()) # Assert that the same keys are produced by a simulation - this is a test that the inserted # swaps route the qubits correctly. if not optionals.HAS_AER: return from qiskit import Aer sim = Aer.get_backend("aer_simulator") in_results = sim.run(qc, shots=4096).result().get_counts() out_results = sim.run(routed, shots=4096).result().get_counts() self.assertEqual(set(in_results), set(out_results))
def test_different_number_of_virtual_and_physical_qubits(self): """Test the case when number of virtual and physical qubits are different.""" # q_0: ──■────■─────── # ┌─┴─┐ │ # q_1: ┤ X ├──┼────■── # └───┘ │ ┌─┴─┐ # q_2: ──■────┼──┤ X ├ # ┌─┴─┐┌─┴─┐└───┘ # q_3: ┤ X ├┤ X ├───── # └───┘└───┘ circuit = QuantumCircuit(4) circuit.cx(0, 1) circuit.cx(2, 3) circuit.cx(0, 3) circuit.cx(1, 2) coupling = CouplingMap.from_line(5) with self.assertRaises(TranspilerError): BIPMapping(coupling)(circuit)
def test_swaps_in_dummy_steps(self): """Test the case when swaps are inserted in dummy steps.""" # ┌───┐ ░ ░ # q_0: ──■──┤ H ├─░───■────────░───■─────── # ┌─┴─┐├───┤ ░ │ ░ │ # q_1: ┤ X ├┤ H ├─░───┼────■───░───┼────■── # └───┘├───┤ ░ │ ┌─┴─┐ ░ ┌─┴─┐ │ # q_2: ──■──┤ H ├─░───┼──┤ X ├─░─┤ X ├──┼── # ┌─┴─┐├───┤ ░ ┌─┴─┐└───┘ ░ └───┘┌─┴─┐ # q_3: ┤ X ├┤ H ├─░─┤ X ├──────░──────┤ X ├ # └───┘└───┘ ░ └───┘ ░ └───┘ circuit = QuantumCircuit(4) circuit.cx(0, 1) circuit.cx(2, 3) circuit.h([0, 1, 2, 3]) circuit.barrier() circuit.cx(0, 3) circuit.cx(1, 2) circuit.barrier() circuit.cx(0, 2) circuit.cx(1, 3) coupling = CouplingMap.from_line(4) property_set = {} actual = BIPMapping(coupling, objective="depth")(circuit, property_set) self.assertEqual(7, actual.depth()) CheckMap(coupling)(actual, property_set) self.assertTrue(property_set["is_swap_mapped"]) # no swaps before the first barrier for inst, _, _ in actual.data: if isinstance(inst, Barrier): break self.assertFalse(isinstance(inst, SwapGate))
def test_line_factory(self): coupling = CouplingMap.from_line(4) edges = coupling.get_edges() expected = [(0, 1), (1, 0), (1, 2), (2, 1), (2, 3), (3, 2)] self.assertEqual(set(edges), set(expected))
def test_initialize_gate_error_objective_without_backend_prop(self): """Fails if ``objective`` that requires ``backend_prop`` is specified but it is not supplied.""" with self.assertRaises(TranspilerError): BIPMapping(coupling_map=CouplingMap.from_line(3), objective="gate_error")