def test_lookahead_swap_finds_minimal_swap_solution(self): """Of many valid SWAPs, test that LookaheadSwap finds the cheapest path. For a two CNOT circuit: cx q[0],q[2]; cx q[0],q[1] on the initial layout: qN -> qN (At least) two solutions exist: - SWAP q[0],[1], cx q[0],q[2], cx q[0],q[1] - SWAP q[1],[2], cx q[0],q[2], SWAP q[1],q[2], cx q[0],q[1] Verify that we find the first solution, as it requires fewer SWAPs. """ qr = QuantumRegister(3, "q") circuit = QuantumCircuit(qr) circuit.cx(qr[0], qr[2]) circuit.cx(qr[0], qr[1]) dag_circuit = circuit_to_dag(circuit) coupling_map = CouplingMap([[0, 1], [1, 2]]) mapped_dag = LookaheadSwap(coupling_map).run(dag_circuit) self.assertEqual( mapped_dag.count_ops().get("swap", 0), dag_circuit.count_ops().get("swap", 0) + 1 )
def test_lookahead_swap_higher_depth_width_is_better(self): """Test that lookahead swap finds better circuit with increasing search space. Increasing the tree width and depth is expected to yield a better (or same) quality circuit, in the form of fewer SWAPs. """ qr = QuantumRegister(8, name='q') circuit = QuantumCircuit(qr) circuit.cx(qr[0], qr[1]) circuit.cx(qr[1], qr[2]) circuit.cx(qr[2], qr[3]) circuit.cx(qr[3], qr[4]) circuit.cx(qr[4], qr[5]) circuit.cx(qr[5], qr[6]) circuit.cx(qr[6], qr[7]) circuit.cx(qr[0], qr[3]) circuit.cx(qr[6], qr[4]) circuit.cx(qr[7], qr[1]) circuit.cx(qr[4], qr[2]) circuit.cx(qr[3], qr[7]) circuit.cx(qr[5], qr[3]) circuit.cx(qr[6], qr[2]) circuit.cx(qr[2], qr[7]) circuit.cx(qr[0], qr[6]) circuit.cx(qr[5], qr[7]) original_dag = circuit_to_dag(circuit) # Create a ring of 8 connected qubits coupling_map = CouplingMap.from_grid(num_rows=2, num_columns=4) mapped_dag_1 = LookaheadSwap(coupling_map, search_depth=3, search_width=3).run(original_dag) mapped_dag_2 = LookaheadSwap(coupling_map, search_depth=5, search_width=5).run(original_dag) num_swaps_1 = mapped_dag_1.count_ops().get('swap', 0) num_swaps_2 = mapped_dag_2.count_ops().get('swap', 0) self.assertLessEqual(num_swaps_2, num_swaps_1)
def test_global_phase_preservation(self): """Test that LookaheadSwap preserves global phase""" qr = QuantumRegister(3, "q") circuit = QuantumCircuit(qr) circuit.global_phase = pi / 3 circuit.cx(qr[0], qr[2]) dag_circuit = circuit_to_dag(circuit) coupling_map = CouplingMap([[0, 1], [1, 2]]) mapped_dag = LookaheadSwap(coupling_map).run(dag_circuit) self.assertEqual(mapped_dag.global_phase, circuit.global_phase) self.assertEqual(mapped_dag.count_ops().get("swap", 0), dag_circuit.count_ops().get("swap", 0) + 1)
def test_lookahead_swap_should_add_a_single_swap(self): """Test that LookaheadSwap will insert a SWAP to match layout. For a single cx gate which is not available in the current layout, test that the mapper inserts a single swap to enable the gate. """ qr = QuantumRegister(3, 'q') circuit = QuantumCircuit(qr) circuit.cx(qr[0], qr[2]) dag_circuit = circuit_to_dag(circuit) coupling_map = CouplingMap([[0, 1], [1, 2]]) mapped_dag = LookaheadSwap(coupling_map).run(dag_circuit) self.assertEqual(mapped_dag.count_ops().get('swap', 0), dag_circuit.count_ops().get('swap', 0) + 1)
def test_lookahead_swap_higher_depth_width_is_better(self): """Test that lookahead swap finds better circuit with increasing search space. Increasing the tree width and depth is expected to yield a better (or same) quality circuit, in the form of fewer SWAPs. """ # q_0: ──■───────────────────■───────────────────────────────────────────────» # ┌─┴─┐ │ ┌───┐ » # q_1: ┤ X ├──■──────────────┼─────────────────┤ X ├─────────────────────────» # └───┘┌─┴─┐ │ └─┬─┘┌───┐ ┌───┐ » # q_2: ─────┤ X ├──■─────────┼───────────────────┼──┤ X ├──────────┤ X ├──■──» # └───┘┌─┴─┐ ┌─┴─┐ │ └─┬─┘ ┌───┐└─┬─┘ │ » # q_3: ──────────┤ X ├──■──┤ X ├─────────────────┼────┼────■──┤ X ├──┼────┼──» # └───┘┌─┴─┐└───┘ ┌───┐ │ │ │ └─┬─┘ │ │ » # q_4: ───────────────┤ X ├──■────────────┤ X ├──┼────■────┼────┼────┼────┼──» # └───┘┌─┴─┐ └─┬─┘ │ │ │ │ │ » # q_5: ────────────────────┤ X ├──■─────────┼────┼─────────┼────■────┼────┼──» # └───┘┌─┴─┐ │ │ │ │ │ » # q_6: ─────────────────────────┤ X ├──■────■────┼─────────┼─────────■────┼──» # └───┘┌─┴─┐ │ ┌─┴─┐ ┌─┴─┐» # q_7: ──────────────────────────────┤ X ├───────■───────┤ X ├──────────┤ X ├» # └───┘ └───┘ └───┘» # «q_0: ──■─────── # « │ # «q_1: ──┼─────── # « │ # «q_2: ──┼─────── # « │ # «q_3: ──┼─────── # « │ # «q_4: ──┼─────── # « │ # «q_5: ──┼────■── # « ┌─┴─┐ │ # «q_6: ┤ X ├──┼── # « └───┘┌─┴─┐ # «q_7: ─────┤ X ├ # « └───┘ qr = QuantumRegister(8, name="q") circuit = QuantumCircuit(qr) circuit.cx(qr[0], qr[1]) circuit.cx(qr[1], qr[2]) circuit.cx(qr[2], qr[3]) circuit.cx(qr[3], qr[4]) circuit.cx(qr[4], qr[5]) circuit.cx(qr[5], qr[6]) circuit.cx(qr[6], qr[7]) circuit.cx(qr[0], qr[3]) circuit.cx(qr[6], qr[4]) circuit.cx(qr[7], qr[1]) circuit.cx(qr[4], qr[2]) circuit.cx(qr[3], qr[7]) circuit.cx(qr[5], qr[3]) circuit.cx(qr[6], qr[2]) circuit.cx(qr[2], qr[7]) circuit.cx(qr[0], qr[6]) circuit.cx(qr[5], qr[7]) original_dag = circuit_to_dag(circuit) # Create a ring of 8 connected qubits coupling_map = CouplingMap.from_grid(num_rows=2, num_columns=4) mapped_dag_1 = LookaheadSwap(coupling_map, search_depth=3, search_width=3).run(original_dag) mapped_dag_2 = LookaheadSwap(coupling_map, search_depth=5, search_width=5).run(original_dag) num_swaps_1 = mapped_dag_1.count_ops().get("swap", 0) num_swaps_2 = mapped_dag_2.count_ops().get("swap", 0) self.assertLessEqual(num_swaps_2, num_swaps_1)