def test_coupling_distance(self):
     coupling_dict = {0: [1, 2], 1: [2]}
     coupling = Coupling(coupling_dict)
     self.assertTrue(coupling.is_connected())
     physical_qubits = coupling.physical_qubits
     result = coupling.distance(physical_qubits[0], physical_qubits[1])
     self.assertEqual(1, result)
Ejemplo n.º 2
0
 def test_coupling_distance(self):
     coupling_list = [(0, 1), (0, 2), (1, 2)]
     coupling = Coupling(couplinglist=coupling_list)
     self.assertTrue(coupling.is_connected())
     physical_qubits = coupling.physical_qubits
     result = coupling.distance(physical_qubits[0], physical_qubits[1])
     self.assertEqual(1, result)
 def test_empty_coupling_class(self):
     coupling = Coupling()
     self.assertEqual(0, coupling.size())
     self.assertEqual([], coupling.physical_qubits)
     self.assertEqual([], coupling.get_edges())
     self.assertFalse(coupling.is_connected())
     self.assertEqual("", str(coupling))
Ejemplo n.º 4
0
    def test_init_with_couplinglist(self):
        coupling_list = [[0, 1], [1, 2]]
        coupling = Coupling(couplinglist=coupling_list)

        qubits_expected = [0, 1, 2]
        edges_expected = [(0, 1), (1, 2)]

        self.assertEqual(coupling.physical_qubits, qubits_expected)
        self.assertEqual(coupling.get_edges(), edges_expected)
        self.assertEqual(2, coupling.distance(0, 2))
Ejemplo n.º 5
0
    def test_lookahead_mapper_finds_minimal_swap_solution(self):
        """Of many valid SWAPs, test that lookahead 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)
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[2])
        circuit.cx(qr[0], qr[1])

        dag_circuit = circuit_to_dag(circuit)

        coupling_map = Coupling(couplinglist=[(0, 1), (1, 2)])

        pass_manager = PassManager()
        pass_manager.append([LookaheadMapper(coupling_map)])
        mapped_dag = transpile_dag(dag_circuit, pass_manager=pass_manager)

        self.assertEqual(mapped_dag.count_ops().get('swap', 0),
                         dag_circuit.count_ops().get('swap', 0) + 1)
Ejemplo n.º 6
0
    def test_keep_layout(self):
        """After a swap, the following gates also change the wires.
         qr0:---.---[H]--
                |
         qr1:---|--------
                |
         qr2:--(+)-------

         Coupling map: [0]--[1]--[2]

         qr0:--X-----------
               |
         qr1:--X---.--[H]--
                   |
         qr2:-----(+)------
        """
        coupling = Coupling({1: [0, 2]})

        qr = QuantumRegister(3, 'q')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[2])
        circuit.h(qr[0])
        dag = circuit_to_dag(circuit)

        expected = QuantumCircuit(qr)
        expected.swap(qr[0], qr[1])
        expected.cx(qr[1], qr[2])
        expected.h(qr[1])

        pass_ = BasicMapper(coupling)
        after = pass_.run(dag)

        self.assertEqual(circuit_to_dag(expected), after)
Ejemplo n.º 7
0
def _qiskit_compiler(dag_circuit, coupling_map=None, gate_costs=None):
    import copy
    from qiskit.mapper import swap_mapper, direction_mapper, cx_cancellation, optimize_1q_gates, Coupling
    from qiskit import qasm, unroll
    initial_layout = None
    coupling = Coupling(coupling_map)

    # # paler 31.08.2018
    # # use heuristic to generate it
    # from startconfiguration import cuthill_order
    # y = cuthill_order(dag_circuit)
    # for i in range(len(y)):
    #     initial_layout[i] = y[i]  # qubit i@i
    # # end paler 31.08.2018

    # compiled_dag, final_layout = swap_mapper(copy.deepcopy(dag_circuit), coupling, initial_layout, trials=40, seed=19)
    compiled_dag, final_layout = swap_mapper(copy.deepcopy(dag_circuit), coupling, initial_layout,
                                             trials=40, seed=gate_costs['seed'])

    # Expand swaps
    basis_gates = "u1,u2,u3,cx,id"  # QE target basis
    program_node_circuit = qasm.Qasm(data=compiled_dag.qasm()).parse()
    unroller_circuit = unroll.Unroller(program_node_circuit,
                                       unroll.DAGBackend(
                                           basis_gates.split(",")))
    compiled_dag = unroller_circuit.execute()
    # Change cx directions
    compiled_dag = direction_mapper(compiled_dag, coupling)
    # Simplify cx gates
    cx_cancellation(compiled_dag)
    # Simplify single qubit gates
    compiled_dag = optimize_1q_gates(compiled_dag)
    # Return the compiled dag circuit
    return compiled_dag
Ejemplo n.º 8
0
def _qiskit_compiler(dag_circuit, coupling_map=None, gate_costs=None):
    import copy
    from qiskit.mapper import swap_mapper, direction_mapper, cx_cancellation, optimize_1q_gates, Coupling
    from qiskit import qasm, unroll
    initial_layout = None
    coupling = Coupling(coupling_map)
    compiled_dag, final_layout = swap_mapper(copy.deepcopy(dag_circuit),
                                             coupling,
                                             initial_layout,
                                             trials=40,
                                             seed=19)
    # Expand swaps
    basis_gates = "u1,u2,u3,cx,id"  # QE target basis
    program_node_circuit = qasm.Qasm(data=compiled_dag.qasm()).parse()
    unroller_circuit = unroll.Unroller(
        program_node_circuit, unroll.DAGBackend(basis_gates.split(",")))
    compiled_dag = unroller_circuit.execute()
    # Change cx directions
    compiled_dag = direction_mapper(compiled_dag, coupling)
    # Simplify cx gates
    cx_cancellation(compiled_dag)
    # Simplify single qubit gates
    compiled_dag = optimize_1q_gates(compiled_dag)
    # Return the compiled dag circuit
    return compiled_dag
Ejemplo n.º 9
0
    def test_a_single_swap(self):
        """ Adding a swap
         q0:-------

         q1:--(+)--
               |
         q2:---.---

         Coupling map: [1]--[0]--[2]

         q0:--X---.---
              |   |
         q1:--X---|---
                  |
         q2:-----(+)--

        """
        coupling = Coupling({0: [1, 2]})

        qr = QuantumRegister(3, 'q')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[1], qr[2])
        dag = circuit_to_dag(circuit)

        expected = QuantumCircuit(qr)
        expected.swap(qr[1], qr[0])
        expected.cx(qr[0], qr[2])

        pass_ = BasicMapper(coupling)
        after = pass_.run(dag)

        self.assertEqual(circuit_to_dag(expected), after)
    def test_direction_flip(self):
        """
         qr0:----.----
                 |
         qr1:---(+)---

         Coupling map: [0] -> [1]

         qr0:---(+)---
                 |
         qr1:----.----
        """
        qr = QuantumRegister(2, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[1], qr[0])
        coupling = Coupling({0: [1]})
        dag = circuit_to_dag(circuit)

        expected = QuantumCircuit(qr)
        expected.h(qr[0])
        expected.h(qr[1])
        expected.cx(qr[0], qr[1])
        expected.h(qr[0])
        expected.h(qr[1])

        pass_ = DirectionMapper(coupling)
        after = pass_.run(dag)

        self.assertEqual(circuit_to_dag(expected), after)
Ejemplo n.º 11
0
    def test_swap_between_qregs(self):
        """ Adding a swap affecting different qregs
         qr0_0:-------

         qr1_0:--(+)--
                  |
         qr1_1:---.---

         Coupling map: [1]--[0]--[2]

         qr0_0:--X--.---
                 |  |
         qr1_0:--|-(+)--
                 |
         qr1_1:--X------

        """
        coupling = Coupling({0: [1, 2]})

        qr0 = QuantumRegister(1, 'qr0')
        qr1 = QuantumRegister(2, 'qr1')

        circuit = QuantumCircuit(qr0, qr1)
        circuit.cx(qr1[0], qr1[1])
        dag = circuit_to_dag(circuit)

        expected = QuantumCircuit(qr0, qr1)
        expected.swap(qr1[1], qr0[0])
        expected.cx(qr1[1], qr0[0])

        pass_ = BasicMapper(coupling)
        after = pass_.run(dag)

        self.assertEqual(circuit_to_dag(expected), after)
Ejemplo n.º 12
0
    def test_lookahead_mapper_doesnt_modify_mapped_circuit(self):
        """Test that lookahead mapper is idempotent.

        It should not modify a circuit which is already compatible with the
        coupling map, and can be applied repeatedly without modifying the circuit.
        """

        qr = QuantumRegister(3, name='q')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[2])
        circuit.cx(qr[0], qr[1])
        original_dag = circuit_to_dag(circuit)

        # Create coupling map which contains all two-qubit gates in the circuit.
        coupling_map = Coupling(couplinglist=[(0, 1), (0, 2)])

        pass_manager = PassManager()
        pass_manager.append(LookaheadMapper(coupling_map))
        mapped_dag = transpile_dag(original_dag, pass_manager=pass_manager)

        self.assertEqual(original_dag, mapped_dag)

        second_pass_manager = PassManager()
        second_pass_manager.append(LookaheadMapper(coupling_map))
        remapped_dag = transpile_dag(mapped_dag,
                                     pass_manager=second_pass_manager)

        self.assertEqual(mapped_dag, remapped_dag)
def compiler_function(dag_circuit, coupling_map=None, gate_costs=None):
    """
    Modify a DAGCircuit based on a gate cost function.

    Instructions:
        Your submission involves filling in the implementation
        of this function. The function takes as input a DAGCircuit
        object, which can be generated from a QASM file by using the
        function 'qasm_to_dag_circuit' from the included 
        'submission_evaluation.py' module. For more information
        on the DAGCircuit object see the or QISKit documentation
        (eg. 'help(DAGCircuit)').

    Args:
        dag_circuit (DAGCircuit): DAGCircuit object to be compiled.
        coupling_circuit (list): Coupling map for device topology.
                                 A coupling map of None corresponds an
                                 all-to-all connected topology.
        gate_costs (dict) : dictionary of gate names and costs.

    Returns:
        A modified DAGCircuit object that satisfies an input coupling_map
        and has as low a gate_cost as possible.
    """

    #####################
    # Put your code here
    #####################
    # Example using mapper passes in Qiskit
    import copy
    from qiskit.mapper import swap_mapper, direction_mapper, cx_cancellation, optimize_1q_gates, Coupling
    from qiskit import qasm, unroll
    initial_layout = None
    coupling = Coupling(coupling_map)
    compiled_dag, final_layout = swap_mapper(copy.deepcopy(dag_circuit),
                                             coupling,
                                             initial_layout,
                                             trials=40,
                                             seed=19)
    # Expand swaps
    basis_gates = "u1,u2,u3,cx,id"  # QE target basis
    program_node_circuit = qasm.Qasm(data=compiled_dag.qasm()).parse()
    unroller_circuit = unroll.Unroller(
        program_node_circuit, unroll.DAGBackend(basis_gates.split(",")))
    compiled_dag = unroller_circuit.execute()
    # Change cx directions
    compiled_dag = direction_mapper(compiled_dag, coupling)
    # Simplify cx gates
    cx_cancellation(compiled_dag)
    # Simplify single qubit gates
    compiled_dag = optimize_1q_gates(compiled_dag)
    #####################
    # Put your code here
    #####################
    # Return the compiled dag circuit
    return compiled_dag
Ejemplo n.º 14
0
    def test_false_map(self):
        """ Needs [0]-[1] in a [0]--[2]--[1]
         qr0:--(+)--
                |
         qr1:---.---

         Coupling map: [0]--[2]--[1]
        """
        qr = QuantumRegister(2, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[1])
        coupling = Coupling(couplingdict={0: [2], 2: [1]})
        dag = DAGCircuit.fromQuantumCircuit(circuit)

        pass_ = CheckMap(coupling)
        pass_.run(dag)

        self.assertFalse(pass_.property_set['is_mapped'])
Ejemplo n.º 15
0
    def test_direction_correct(self):
        """ The CX is in the right direction
         qr0:---(+)---
                 |
         qr1:----.----

         Coupling map: [0] -> [1]
        """
        qr = QuantumRegister(2, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[1])
        coupling = Coupling({0: [1]})
        dag = circuit_to_dag(circuit)

        pass_ = DirectionMapper(coupling)
        after = pass_.run(dag)

        self.assertEqual(dag, after)
Ejemplo n.º 16
0
    def test_trivial_map(self):
        """ Trivial map in a circuit without entanglement
         qr0:---[H]---

         qr1:---[H]---

         qr2:---[H]---

         Coupling map: None
        """
        qr = QuantumRegister(3, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.h(qr)
        coupling = Coupling()
        dag = DAGCircuit.fromQuantumCircuit(circuit)
        pass_ = CheckMap(coupling)
        pass_.run(dag)
        self.assertTrue(pass_.property_set['is_mapped'])
Ejemplo n.º 17
0
    def test_lookahead_mapper_should_add_a_single_swap(self):
        """Test that lookahead mapper 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)
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[2])
        dag_circuit = circuit_to_dag(circuit)

        coupling_map = Coupling(couplinglist=[(0, 1), (1, 2)])

        pass_manager = PassManager()
        pass_manager.append([LookaheadMapper(coupling_map)])
        mapped_dag = transpile_dag(dag_circuit, pass_manager=pass_manager)

        self.assertEqual(mapped_dag.count_ops().get('swap', 0),
                         dag_circuit.count_ops().get('swap', 0) + 1)
    def test_no_cnots(self):
        """ Trivial map in a circuit without entanglement
         qr0:---[H]---

         qr1:---[H]---

         qr2:---[H]---

         Coupling map: None
        """
        qr = QuantumRegister(3, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.h(qr)
        coupling = Coupling()
        dag = circuit_to_dag(circuit)

        pass_ = DirectionMapper(coupling)
        after = pass_.run(dag)

        self.assertEqual(dag, after)
    def test_direction_error(self):
        """
         qr0:---------

         qr1:---(+)---
                 |
         qr2:----.----

         Coupling map: [2] <- [0] -> [1]
        """
        qr = QuantumRegister(3, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[1], qr[2])
        coupling = Coupling({0: [2, 1]})
        dag = circuit_to_dag(circuit)

        pass_ = DirectionMapper(coupling)

        with self.assertRaises(MapperError):
            pass_.run(dag)
Ejemplo n.º 20
0
    def test_far_swap_with_gate_the_middle(self):
        """ A far swap with a gate in the middle.
         qr0:--(+)-------.--
                |        |
         qr1:---|--------|--
                |
         qr2:---|--------|--
                |        |
         qr3:---.--[H]--(+)-

         Coupling map: [0]--[1]--[2]--[3]

         qr0:-------(+)-------.---
                     |        |
         qr1:-----X--.--[H]--(+)--
                  |
         qr2:--X--X---------------
               |
         qr3:--X------------------

        """
        coupling = Coupling({0: [1], 1: [2], 2: [3]})

        qr = QuantumRegister(4, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[3], qr[0])
        circuit.h(qr[3])
        circuit.cx(qr[0], qr[3])
        dag = circuit_to_dag(circuit)

        expected = QuantumCircuit(qr)
        expected.swap(qr[3], qr[2])
        expected.swap(qr[2], qr[1])
        expected.cx(qr[1], qr[0])
        expected.h(qr[1])
        expected.cx(qr[0], qr[1])

        pass_ = BasicMapper(coupling)
        after = pass_.run(dag)

        self.assertEqual(circuit_to_dag(expected), after)
Ejemplo n.º 21
0
    def test_far_swap(self):
        """ A far swap that affects coming CXs.
         qr0:--(+)---.--
                |    |
         qr1:---|----|--
                |    |
         qr2:---|----|--
                |    |
         qr3:---.---(+)-

         Coupling map: [0]--[1]--[2]--[3]

         qr0:--X--------------
               |
         qr1:--X--X-----------
                  |
         qr2:-----X--(+)---.--
                      |    |
         qr3:---------.---(+)-

        """
        coupling = Coupling({0: [1], 1: [2], 2: [3]})

        qr = QuantumRegister(4, 'q')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[3])
        circuit.cx(qr[3], qr[0])
        dag = circuit_to_dag(circuit)

        expected = QuantumCircuit(qr)
        expected.swap(qr[0], qr[1])
        expected.swap(qr[1], qr[2])
        expected.cx(qr[2], qr[3])
        expected.cx(qr[3], qr[2])

        pass_ = BasicMapper(coupling)
        after = pass_.run(dag)

        self.assertEqual(circuit_to_dag(expected), after)
Ejemplo n.º 22
0
    def test_true_map(self):
        """ Mapped is easy to check
         qr0:--(+)-[H]-(+)-
                |       |
         qr1:---.-------|--
                        |
         qr2:-----------.--

         Coupling map: [1]--[0]--[2]
        """
        qr = QuantumRegister(3, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[1])
        circuit.h(qr[0])
        circuit.cx(qr[0], qr[2])
        coupling = Coupling(couplingdict={0: [1, 2]})
        dag = DAGCircuit.fromQuantumCircuit(circuit)

        pass_ = CheckMap(coupling)
        pass_.run(dag)

        self.assertTrue(pass_.property_set['is_mapped'])
Ejemplo n.º 23
0
    def test_true_map_in_same_layer(self):
        """ Two CXs distance 1 to each other, in the same layer
         qr0:--(+)--
               |
         qr1:---.---

         qr2:--(+)--
               |
         qr3:---.---

         Coupling map: [0]--[1]--[2]--[3]
        """
        qr = QuantumRegister(4, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[1])
        circuit.cx(qr[2], qr[3])
        coupling = Coupling(couplingdict={0: [1], 1: [2], 2: [3]})
        dag = DAGCircuit.fromQuantumCircuit(circuit)

        pass_ = CheckMap(coupling)
        pass_.run(dag)

        self.assertTrue(pass_.property_set['is_mapped'])
Ejemplo n.º 24
0
    def test_true_map_undirected(self):
        """ Mapped but with wrong direction
         qr0:--(+)-[H]--.--
                |       |
         qr1:---.-------|--
                        |
         qr2:----------(+)-

         Coupling map: [1]<-[0]->[2]
        """
        qr = QuantumRegister(3, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[1])
        circuit.h(qr[0])
        circuit.cx(qr[2], qr[0])
        coupling = Coupling(couplingdict={0: [1, 2]})
        dag = circuit_to_dag(circuit)

        pass_ = CheckMap(coupling)
        pass_.run(dag)

        self.assertTrue(pass_.property_set['is_mapped'])
        self.assertFalse(pass_.property_set['is_direction_mapped'])
Ejemplo n.º 25
0
    def test_trivial_case(self):
        """No need to have any swap, the CX are distance 1 to each other
         q0:--(+)-[U]-(+)-
               |       |
         q1:---.-------|--
                       |
         q2:-----------.--

         Coupling map: [1]--[0]--[2]
        """
        coupling = Coupling({0: [1, 2]})

        qr = QuantumRegister(3, 'q')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[1])
        circuit.h(qr[0])
        circuit.cx(qr[0], qr[2])

        dag = circuit_to_dag(circuit)
        pass_ = BasicMapper(coupling)
        after = pass_.run(dag)

        self.assertEqual(dag, after)
Ejemplo n.º 26
0
    def test_flip_with_measure(self):
        """
         qr0: -(+)-[m]-
                |   |
         qr1: --.---|--
                    |
         cr0: ------.--

         Coupling map: [0] -> [1]

         qr0: -[H]--.--[H]-[m]-
                    |       |
         qr1: -[H]-(+)-[H]--|--
                            |
         cr0: --------------.--
        """
        qr = QuantumRegister(2, 'qr')
        cr = ClassicalRegister(1, 'cr')

        circuit = QuantumCircuit(qr, cr)
        circuit.cx(qr[1], qr[0])
        circuit.measure(qr[0], cr[0])
        coupling = Coupling({0: [1]})
        dag = circuit_to_dag(circuit)

        expected = QuantumCircuit(qr, cr)
        expected.h(qr[0])
        expected.h(qr[1])
        expected.cx(qr[0], qr[1])
        expected.h(qr[0])
        expected.h(qr[1])
        expected.measure(qr[0], cr[0])

        pass_ = DirectionMapper(coupling)
        after = pass_.run(dag)

        self.assertEqual(circuit_to_dag(expected), after)
Ejemplo n.º 27
0
    def test_true_map_in_same_layer_undirected(self):
        """ Two CXs in the same layer, but one is wrongly directed
         qr0:--(+)--
                |
         qr1:---.---

         qr2:---.---
                |
         qr3:--(+)--

         Coupling map: [0]->[1]->[2]->[3]
        """
        qr = QuantumRegister(4, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[0], qr[1])
        circuit.cx(qr[3], qr[2])
        coupling = Coupling(couplingdict={0: [1], 1: [2], 2: [3]})
        dag = circuit_to_dag(circuit)

        pass_ = CheckMap(coupling)
        pass_.run(dag)

        self.assertTrue(pass_.property_set['is_mapped'])
        self.assertFalse(pass_.property_set['is_direction_mapped'])
Ejemplo n.º 28
0
    def test_trivial_in_same_layer(self):
        """ No need to have any swap, two CXs distance 1 to each other, in the same layer
         q0:--(+)--
               |
         q1:---.---

         q2:--(+)--
               |
         q3:---.---

         Coupling map: [0]--[1]--[2]--[3]
        """
        coupling = Coupling({0: [1], 1: [2], 2: [3]})

        qr = QuantumRegister(4, 'q')
        circuit = QuantumCircuit(qr)
        circuit.cx(qr[2], qr[3])
        circuit.cx(qr[0], qr[1])

        dag = circuit_to_dag(circuit)
        pass_ = BasicMapper(coupling)
        after = pass_.run(dag)

        self.assertEqual(dag, after)
Ejemplo n.º 29
0
def transpile(dag,
              basis_gates='u1,u2,u3,cx,id',
              coupling_map=None,
              initial_layout=None,
              get_layout=False,
              format='dag',
              seed=None,
              pass_manager=None):
    """Transform a dag circuit into another dag circuit (transpile), through
    consecutive passes on the dag.

    Args:
        dag (DAGCircuit): dag circuit to transform via transpilation
        basis_gates (str): a comma separated string for the target basis gates
        coupling_map (list): A graph of coupling::

            [
             [control0(int), target0(int)],
             [control1(int), target1(int)],
            ]

            eg. [[0, 2], [1, 2], [1, 3], [3, 4]}

        initial_layout (dict): A mapping of qubit to qubit::

                              {
                                ("q", start(int)): ("q", final(int)),
                                ...
                              }
                              eg.
                              {
                                ("q", 0): ("q", 0),
                                ("q", 1): ("q", 1),
                                ("q", 2): ("q", 2),
                                ("q", 3): ("q", 3)
                              }
        get_layout (bool): flag for returning the final layout after mapping
        format (str): The target format of the compilation:
            {'dag', 'json', 'qasm'}
        seed (int): random seed for the swap mapper
        pass_manager (PassManager): pass manager instance for the transpilation process
            If None, a default set of passes are run.
            Otherwise, the passes defined in it will run.
            If contains no passes in it, no dag transformations occur.

    Returns:
        DAGCircuit: transformed dag
        DAGCircuit, dict: transformed dag along with the final layout on backend qubits

    Raises:
        TranspilerError: if the format is not valid.
    """
    # TODO: `basis_gates` will be removed after we have the unroller pass.
    # TODO: `coupling_map`, `initial_layout`, `get_layout`, `seed` removed after mapper pass.

    # TODO: move this to the mapper pass
    num_qubits = sum(dag.qregs.values())
    if num_qubits == 1 or coupling_map == "all-to-all":
        coupling_map = None

    final_layout = None

    if pass_manager:
        # run the passes specified by the pass manager
        # TODO return the property set too. See #1086
        dag = pass_manager.run_passes(dag)
    else:
        # default set of passes
        # TODO: move each step here to a pass, and use a default passmanager below
        basis = basis_gates.split(',') if basis_gates else []
        dag_unroller = DagUnroller(dag, DAGBackend(basis))
        dag = dag_unroller.expand_gates()
        # if a coupling map is given compile to the map
        if coupling_map:
            logger.info("pre-mapping properties: %s", dag.property_summary())
            # Insert swap gates
            coupling = Coupling(coupling_list2dict(coupling_map))
            removed_meas = remove_last_measurements(dag)
            logger.info("measurements moved: %s", removed_meas)
            logger.info("initial layout: %s", initial_layout)
            dag, final_layout, last_layout = swap_mapper(dag,
                                                         coupling,
                                                         initial_layout,
                                                         trials=20,
                                                         seed=seed)
            logger.info("final layout: %s", final_layout)
            # Expand swaps
            dag_unroller = DagUnroller(dag, DAGBackend(basis))
            dag = dag_unroller.expand_gates()
            # Change cx directions
            dag = direction_mapper(dag, coupling)
            # Simplify cx gates
            cx_cancellation(dag)
            # Simplify single qubit gates
            dag = optimize_1q_gates(dag)
            return_last_measurements(dag, removed_meas, last_layout)
            logger.info("post-mapping properties: %s", dag.property_summary())

    # choose output format
    # TODO: do we need all of these formats, or just the dag?
    if format == 'dag':
        compiled_circuit = dag
    elif format == 'json':
        # FIXME: JsonBackend is wrongly taking an ordered dict as basis, not list
        dag_unroller = DagUnroller(dag, JsonBackend(dag.basis))
        compiled_circuit = dag_unroller.execute()
    elif format == 'qasm':
        compiled_circuit = dag.qasm()
    else:
        raise TranspilerError('unrecognized circuit format')

    if get_layout:
        return compiled_circuit, final_layout
    return compiled_circuit
Ejemplo n.º 30
0
def transpile_dag(dag,
                  basis_gates='u1,u2,u3,cx,id',
                  coupling_map=None,
                  initial_layout=None,
                  get_layout=False,
                  format='dag',
                  seed_mapper=None,
                  pass_manager=None):
    """Transform a dag circuit into another dag circuit (transpile), through
    consecutive passes on the dag.

    Args:
        dag (DAGCircuit): dag circuit to transform via transpilation
        basis_gates (str): a comma separated string for the target basis gates
        coupling_map (list): A graph of coupling::

            [
             [control0(int), target0(int)],
             [control1(int), target1(int)],
            ]

            eg. [[0, 2], [1, 2], [1, 3], [3, 4]}

        initial_layout (dict): A mapping of qubit to qubit::

                              {
                                ("q", start(int)): ("q", final(int)),
                                ...
                              }
                              eg.
                              {
                                ("q", 0): ("q", 0),
                                ("q", 1): ("q", 1),
                                ("q", 2): ("q", 2),
                                ("q", 3): ("q", 3)
                              }
        get_layout (bool): flag for returning the final layout after mapping
        format (str): DEPRECATED The target format of the compilation: {'dag', 'json', 'qasm'}
        seed_mapper (int): random seed_mapper for the swap mapper
        pass_manager (PassManager): pass manager instance for the transpilation process
            If None, a default set of passes are run.
            Otherwise, the passes defined in it will run.
            If contains no passes in it, no dag transformations occur.

    Returns:
        DAGCircuit: transformed dag
        DAGCircuit, dict: transformed dag along with the final layout on backend qubits
    """
    # TODO: `basis_gates` will be removed after we have the unroller pass.
    # TODO: `coupling_map`, `initial_layout`, `get_layout`, `seed_mapper` removed after mapper pass.

    # TODO: move this to the mapper pass
    num_qubits = sum([qreg.size for qreg in dag.qregs.values()])
    if num_qubits == 1 or coupling_map == "all-to-all":
        coupling_map = None

    final_layout = None

    if pass_manager:
        # run the passes specified by the pass manager
        # TODO return the property set too. See #1086
        dag = pass_manager.run_passes(dag)
    else:
        # default set of passes
        # TODO: move each step here to a pass, and use a default passmanager below
        basis = basis_gates.split(',') if basis_gates else []
        dag = Unroller(basis).run(dag)
        # if a coupling map is given compile to the map
        if coupling_map:
            logger.info("pre-mapping properties: %s", dag.properties())
            # Insert swap gates
            coupling = Coupling(couplinglist=coupling_map)
            removed_meas = remove_last_measurements(dag)
            logger.info("measurements moved: %s", removed_meas)
            logger.info("initial layout: %s", initial_layout)
            dag, final_layout, last_layout = swap_mapper(dag,
                                                         coupling,
                                                         initial_layout,
                                                         trials=20,
                                                         seed=seed_mapper)
            logger.info("final layout: %s", final_layout)
            # Expand swaps
            dag = Unroller(basis).run(dag)
            # Change cx directions
            dag = direction_mapper(dag, coupling)
            # Simplify cx gates
            cx_cancellation(dag)
            # Simplify single qubit gates
            dag = optimize_1q_gates(dag)
            return_last_measurements(dag, removed_meas, last_layout)
            logger.info("post-mapping properties: %s", dag.properties())

    if format != 'dag':
        warnings.warn(
            "transpiler no longer supports different formats. "
            "only dag to dag transformations are supported.",
            DeprecationWarning)

    if get_layout:
        return dag, final_layout
    return dag