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)
Esempio n. 3
0
    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)
Esempio n. 4
0
    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)
Esempio n. 5
0
    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)