def test_two_qregs_to_a_single_creg(self):
        """Two measurements in different qregs to the same creg
                                          |
        q0:--[H]--[m]------     q0:--[H]--|--[m]------
                   |                      |   |
        q1:--------|--[m]--  -> q1:-------|---|--[m]--
                   |   |                  |   |   |
        c0:--------.---|---     c0:-----------.---|---
           ------------.---        ---------------.---
        """
        qr0 = QuantumRegister(1, "q0")
        qr1 = QuantumRegister(1, "q1")
        cr0 = ClassicalRegister(2, "c0")

        circuit = QuantumCircuit(qr0, qr1, cr0)
        circuit.h(qr0)
        circuit.measure(qr0, cr0[0])
        circuit.measure(qr1, cr0[1])

        expected = QuantumCircuit(qr0, qr1, cr0)
        expected.h(qr0)
        expected.barrier(qr0, qr1)
        expected.measure(qr0, cr0[0])
        expected.measure(qr1, cr0[1])

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
    def test_should_merge_with_smaller_duplicate_barrier(self):
        """If an equivalent barrier exists covering a subset of the qubits
        covered by the new barrier, it should be replaced.

         q:---|--[m]-------------     q:---|--[m]-------------
           ---|---|---[m]--------  ->   ---|---|---[m]--------
           -------|----|---[m]---       ---|---|----|---[m]---
                  |    |    |                  |    |    |
         c:-------.----|----|----     c:-------.----|----|----
           ------------.----|----       ------------.----|----
           -----------------.----       -----------------.----
        """
        qr = QuantumRegister(3, 'q')
        cr = ClassicalRegister(3, 'c')

        circuit = QuantumCircuit(qr, cr)
        circuit.barrier(qr[0], qr[1])
        circuit.measure(qr, cr)

        expected = QuantumCircuit(qr, cr)
        expected.barrier(qr)
        expected.measure(qr, cr)

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
    def test_should_merge_with_larger_duplicate_barrier(self):
        """If a barrier exists and is stronger than the barrier to be inserted,
        preserve the existing barrier and do not insert a new barrier.

         q:---|--[m]--|-------     q:---|--[m]-|-------
           ---|---|---|--[m]--  ->   ---|---|--|--[m]--
           ---|---|---|---|---       ---|---|--|---|---
                  |       |                 |      |
         c:-------.-------|---     c:-------.------|---
           ---------------.---       --------------.---
           -------------------       ------------------
        """
        qr = QuantumRegister(3, 'q')
        cr = ClassicalRegister(3, 'c')

        circuit = QuantumCircuit(qr, cr)
        circuit.barrier(qr)
        circuit.measure(qr[0], cr[0])
        circuit.barrier(qr)
        circuit.measure(qr[1], cr[1])

        expected = circuit

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
    def test_preserve_barriers_for_measurement_ordering(self):
        """If the circuit has a barrier to enforce a measurement order,
        preserve it in the output.

         q:---[m]--|-------     q:---|--[m]--|-------
           ----|---|--[m]--  ->   ---|---|---|--[m]--
               |       |                 |       |
         c:----.-------|---     c:-------.-------|---
           ------------.---       ---------------.---
        """
        qr = QuantumRegister(2, 'q')
        cr = ClassicalRegister(2, 'c')

        circuit = QuantumCircuit(qr, cr)
        circuit.measure(qr[0], cr[0])
        circuit.barrier(qr)
        circuit.measure(qr[1], cr[1])

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

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
    def test_measures_followed_by_barriers_should_be_final(self):
        """If a measurement is followed only by a barrier,
        insert the barrier before it.

         q:---[H]--|--[m]--|-------     q:---[H]--|--[m]-|-------
           ---[H]--|---|---|--[m]--  ->   ---[H]--|---|--|--[m]--
                       |       |                      |      |
         c:------------.-------|---     c:------------.------|---
           --------------------.---       -------------------.---
        """
        qr = QuantumRegister(2, 'q')
        cr = ClassicalRegister(2, 'c')

        circuit = QuantumCircuit(qr, cr)
        circuit.h(qr)
        circuit.barrier(qr)
        circuit.measure(qr[0], cr[0])
        circuit.barrier(qr)
        circuit.measure(qr[1], cr[1])

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

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
    def test_preserve_measure_for_conditional(self):
        """Test barrier is inserted after any measurements used for conditionals

         q0:--[H]--[m]------------     q0:--[H]--[m]---------------
                    |                             |
         q1:--------|--[ z]--[m]--  -> q1:--------|--[ z]--|--[m]--
                    |    |    |                   |    |       |
         c0:--------.--[=1]---|---     c0:--------.--[=1]------|---
                              |                                |
         c1:------------------.---     c1:---------------------.---
        """
        qr0 = QuantumRegister(1, 'q0')
        qr1 = QuantumRegister(1, 'q1')
        cr0 = ClassicalRegister(1, 'c0')
        cr1 = ClassicalRegister(1, 'c1')
        circuit = QuantumCircuit(qr0, qr1, cr0, cr1)

        circuit.h(qr0)
        circuit.measure(qr0, cr0)
        circuit.z(qr1).c_if(cr0, 1)
        circuit.measure(qr1, cr1)

        expected = QuantumCircuit(qr0, qr1, cr0, cr1)
        expected.h(qr0)
        expected.measure(qr0, cr0)
        expected.z(qr1).c_if(cr0, 1)
        expected.barrier(qr1)
        expected.measure(qr1, cr1)

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
    def test_remove_barrier_in_different_qregs(self):
        """Two measurements in different qregs to the same creg

         q0:--|--[m]------     q0:---|--[m]------
                  |                  |   |
         q1:--|---|--[m]--  -> q1:---|---|--[m]--
                  |   |                  |   |
         c0:------.---|---     c0:-------.---|---
            ----------.---        -----------.---
        """
        qr0 = QuantumRegister(1, 'q0')
        qr1 = QuantumRegister(1, 'q1')
        cr0 = ClassicalRegister(2, 'c0')

        circuit = QuantumCircuit(qr0, qr1, cr0)
        circuit.barrier(qr0)
        circuit.barrier(qr1)
        circuit.measure(qr0, cr0[0])
        circuit.measure(qr1, cr0[1])

        expected = QuantumCircuit(qr0, qr1, cr0)
        expected.barrier(qr0, qr1)
        expected.measure(qr0, cr0[0])
        expected.measure(qr1, cr0[1])

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
    def test_two_qregs(self):
        """Two measurements in different qregs to different cregs
                                           |
         q0:--[H]--[m]------     q0:--[H]--|--[m]------
                    |                      |   |
         q1:--------|--[m]--  -> q1:-------|---|--[m]--
                    |   |                  |   |   |
         c0:--------.---|---      c0:----------.---|---
                        |                          |
         c1:------------.---      c0:--------------.---
        """
        qr0 = QuantumRegister(1, 'q0')
        qr1 = QuantumRegister(1, 'q1')
        cr0 = ClassicalRegister(1, 'c0')
        cr1 = ClassicalRegister(1, 'c1')

        circuit = QuantumCircuit(qr0, qr1, cr0, cr1)
        circuit.h(qr0)
        circuit.measure(qr0, cr0)
        circuit.measure(qr1, cr1)

        expected = QuantumCircuit(qr0, qr1, cr0, cr1)
        expected.h(qr0)
        expected.barrier(qr0, qr1)
        expected.measure(qr0, cr0)
        expected.measure(qr1, cr1)

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
    def test_single_measure_mix(self):
        """Two measurements, but only one is at the end
                                                 |
         q0:--[m]--[H]--[m]--     q0:--[m]--[H]--|-[m]---
               |         |    ->        |        |  |
          c:---.---------.---      c:---.-----------.---
        """
        qr = QuantumRegister(1, 'q')
        cr = ClassicalRegister(1, 'c')

        circuit = QuantumCircuit(qr, cr)
        circuit.measure(qr, cr)
        circuit.h(qr)
        circuit.measure(qr, cr)

        expected = QuantumCircuit(qr, cr)
        expected.measure(qr, cr)
        expected.h(qr)
        expected.barrier(qr)
        expected.measure(qr, cr)

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
예제 #10
0
파일: default.py 프로젝트: danmills0/qiskit
def default_pass_manager(transpile_config):
    """
    The default pass manager that maps to the coupling map.

    Args:
        transpile_config (TranspileConfig)

    Returns:
        PassManager: A pass manager to map and optimize.
    """
    basis_gates = transpile_config.basis_gates
    coupling_map = transpile_config.coupling_map
    initial_layout = transpile_config.initial_layout
    seed_transpiler = transpile_config.seed_transpiler
    pass_manager = PassManager()
    pass_manager.append(SetLayout(initial_layout))
    pass_manager.append(Unroller(basis_gates))

    # Use the trivial layout if no layout is found
    pass_manager.append(
        TrivialLayout(coupling_map),
        condition=lambda property_set: not property_set['layout'])

    # if the circuit and layout already satisfy the coupling_constraints, use that layout
    # otherwise layout on the most densely connected physical qubit subset
    pass_manager.append(CheckMap(coupling_map))
    pass_manager.append(
        DenseLayout(coupling_map),
        condition=lambda property_set: not property_set['is_swap_mapped'])

    # Extend the the dag/layout with ancillas using the full coupling map
    pass_manager.append(FullAncillaAllocation(coupling_map))
    pass_manager.append(EnlargeWithAncilla())

    # Circuit must only contain 1- or 2-qubit interactions for swapper to work
    pass_manager.append(Unroll3qOrMore())

    # Swap mapper
    pass_manager.append(BarrierBeforeFinalMeasurements())
    pass_manager.append(
        LegacySwap(coupling_map, trials=20, seed=seed_transpiler))

    # Expand swaps
    pass_manager.append(Decompose(SwapGate))

    # Change CX directions
    pass_manager.append(CXDirection(coupling_map))

    # Simplify single qubit gates and CXs
    simplification_passes = [
        Optimize1qGates(),
        CXCancellation(),
        RemoveResetInZeroState()
    ]

    pass_manager.append(
        simplification_passes + [Depth(), FixedPoint('depth')],
        do_while=lambda property_set: not property_set['depth_fixed_point'])

    return pass_manager
예제 #11
0
    def __init__(self, coupling_map):
        """Initialize a LookaheadSwap instance.

        Arguments:
            coupling_map (CouplingMap): CouplingMap of the target backend.
        """

        super().__init__()
        self._coupling_map = coupling_map
        self.requires.append(BarrierBeforeFinalMeasurements())
예제 #12
0
    def test_final_measurement_barrier_for_devices(self):
        """Verify BarrierBeforeFinalMeasurements pass is called in default pipeline for devices."""

        circ = QuantumCircuit.from_qasm_file(self._get_resource_path('example.qasm', Path.QASMS))
        layout = Layout.generate_trivial_layout(*circ.qregs)
        orig_pass = BarrierBeforeFinalMeasurements()
        with patch.object(BarrierBeforeFinalMeasurements, 'run', wraps=orig_pass.run) as mock_pass:
            transpile(circ, coupling_map=FakeRueschlikon().configuration().coupling_map,
                      initial_layout=layout)
            self.assertTrue(mock_pass.called)
    def test_single_measure(self):
        """A single measurement at the end
                          |
        q:--[m]--     q:--|-[m]---
             |    ->      |  |
        c:---.---     c:-----.---
        """
        qr = QuantumRegister(1, "q")
        cr = ClassicalRegister(1, "c")

        circuit = QuantumCircuit(qr, cr)
        circuit.measure(qr, cr)

        expected = QuantumCircuit(qr, cr)
        expected.barrier(qr)
        expected.measure(qr, cr)

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
    def test_ignore_single_measure(self):
        """Ignore single measurement because it is not at the end
         q:--[m]-[H]-      q:--[m]-[H]-
              |        ->       |
         c:---.------      c:---.------
        """
        qr = QuantumRegister(1, 'q')
        cr = ClassicalRegister(1, 'c')

        circuit = QuantumCircuit(qr, cr)
        circuit.measure(qr, cr)
        circuit.h(qr[0])

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

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
 def __init__(self, coupling_map, initial_layout=None):
     """
     Maps a DAGCircuit onto a `coupling_map` using swap gates.
     Args:
         coupling_map (CouplingMap): Directed graph represented a coupling map.
         initial_layout (Layout): initial layout of qubits in mapping
     """
     super().__init__()
     self.coupling_map = coupling_map
     self.initial_layout = initial_layout
     self.swap_gate = SwapGate
     self.requires.append(BarrierBeforeFinalMeasurements())
    def test_handle_redundancy(self):
        """The pass is idempotent
             |                |
         q:--|-[m]--      q:--|-[m]---
             |  |     ->      |  |
         c:-----.---      c:-----.---
        """
        qr = QuantumRegister(1, 'q')
        cr = ClassicalRegister(1, 'c')

        circuit = QuantumCircuit(qr, cr)
        circuit.barrier(qr)
        circuit.measure(qr, cr)

        expected = QuantumCircuit(qr, cr)
        expected.barrier(qr)
        expected.measure(qr, cr)

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(circuit))

        self.assertEqual(result, circuit_to_dag(expected))
    def test_barrier_doesnt_reorder_gates(self):
        """ A barrier should not allow the reordering of gates, as pointed out in #2102

         q:--[u1(0)]-----------[m]---------      q:--[u1(0)]------------|--[m]---------
           --[u1(1)]------------|-[m]------  ->    --[u1(1)]------------|---|-[m]------
           --[u1(2)]-|----------|--|-[m]----       --[u1(2)]-|----------|---|--|-[m]----
           ----------|-[u1(03)]-|--|--|-[m]-       ----------|-[u1(03)]-|---|--|--|-[m]-
                                |  |  |  |                                  |  |  |  |
         c:---------------------.--|--|--|-     c:--------------------------.--|--|--|-
           ------------------------.--|--|-       -----------------------------.--|--|-
           ---------------------------.--|-       --------------------------------.--|-
           ------------------------------.-       -----------------------------------.-

        """

        qr = QuantumRegister(4)
        cr = ClassicalRegister(4)
        circuit = QuantumCircuit(qr, cr)

        circuit.u1(0, qr[0])
        circuit.u1(1, qr[1])
        circuit.u1(2, qr[2])
        circuit.barrier(qr[2], qr[3])
        circuit.u1(3, qr[3])

        test_circuit = circuit.copy()
        test_circuit.measure(qr, cr)

        # expected circuit is the same, just with a barrier before the measurements
        expected = circuit.copy()
        expected.barrier(qr)
        expected.measure(qr, cr)

        pass_ = BarrierBeforeFinalMeasurements()
        result = pass_.run(circuit_to_dag(test_circuit))

        self.assertEqual(result, circuit_to_dag(expected))
예제 #18
0
    def setUp(self):
        coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]
        coupling_map = CouplingMap(couplinglist=coupling)
        basis_gates = ['u1', 'u3', 'u2', 'cx']
        qr = QuantumRegister(7, 'q')
        layout = Layout({qr[i]: i for i in range(coupling_map.size())})

        # Create a pass manager with a variety of passes and flow control structures
        self.pass_manager = PassManager()
        self.pass_manager.append(SetLayout(layout))
        self.pass_manager.append(TrivialLayout(coupling_map), condition=lambda x: True)
        self.pass_manager.append(FullAncillaAllocation(coupling_map))
        self.pass_manager.append(EnlargeWithAncilla())
        self.pass_manager.append(Unroller(basis_gates))
        self.pass_manager.append(CheckMap(coupling_map))
        self.pass_manager.append(BarrierBeforeFinalMeasurements(), do_while=lambda x: False)
        self.pass_manager.append(CXDirection(coupling_map))
        self.pass_manager.append(RemoveResetInZeroState())
예제 #19
0
        def construct_passmanager(basis_gates, coupling_map,
                                  synthesis_fidelity, pulse_optimize):
            def _repeat_condition(property_set):
                return not property_set["depth_fixed_point"]

            seed = 2
            _map = [SabreLayout(coupling_map, max_iterations=2, seed=seed)]
            _embed = [
                FullAncillaAllocation(coupling_map),
                EnlargeWithAncilla(),
                ApplyLayout()
            ]
            _unroll3q = Unroll3qOrMore()
            _swap_check = CheckMap(coupling_map)
            _swap = [
                BarrierBeforeFinalMeasurements(),
                SabreSwap(coupling_map, heuristic="lookahead", seed=seed),
            ]
            _check_depth = [Depth(), FixedPoint("depth")]
            _optimize = [
                Collect2qBlocks(),
                ConsolidateBlocks(basis_gates=basis_gates),
                UnitarySynthesis(
                    basis_gates,
                    synthesis_fidelity,
                    coupling_map,
                    pulse_optimize=pulse_optimize,
                    natural_direction=True,
                ),
                Optimize1qGates(basis_gates),
            ]

            pm = PassManager()
            pm.append(_map)  # map to hardware by inserting swaps
            pm.append(_embed)
            pm.append(_unroll3q)
            pm.append(_swap_check)
            pm.append(_swap)
            pm.append(_check_depth + _optimize, do_while=_repeat_condition
                      )  # translate to & optimize over hardware native gates
            return pm
예제 #20
0
    def __init__(self, coupling_map, initial_layout=None,
                 trials=20, seed=None):
        """
        Map a DAGCircuit onto a `coupling_map` using swap gates.

        If initial_layout is not None, we assume the input circuit
        has been layed out before running this pass, and that
        the layout process yields a DAG, coupling map, and layout
        with the following properties:

        1. All three have the same number of qubits
        2. The layout a bijection from the DAG qubits to the coupling map

        For this mapping pass, it may also be necessary that

        3. The coupling map is a connected graph

        If these are not satisfied, the behavior is undefined.

        Args:
            coupling_map (CouplingMap): Directed graph representing a coupling
                map.
            initial_layout (Layout): initial layout of qubits in mapping
            trials (int): maximum number of iterations to attempt
            seed (int): seed for random number generator
        """
        super().__init__()
        self.coupling_map = coupling_map
        self.input_layout = initial_layout
        if initial_layout is not None:
            self.initial_layout = initial_layout.copy()
        else:
            self.initial_layout = None
        self.trials = trials
        self.seed = seed
        self.requires.append(BarrierBeforeFinalMeasurements())
예제 #21
0
파일: level0.py 프로젝트: danmills0/qiskit
def level_0_pass_manager(transpile_config):
    """
    Level 0 pass manager: no explicit optimization other than mapping to backend.

    This pass manager applies the user-given initial layout. If none is given, a trivial
    layout consisting of mapping the i-th virtual qubit to the i-th physical qubit is used.
    Any unused physical qubit is allocated as ancilla space.
    The pass manager then unrolls the circuit to the desired basis, and transforms the
    circuit to match the coupling map. Finally, extra resets are removed.
    Note: in simulators where coupling_map=None, only the unrolling and optimization
    stages are done.

    Args:
        transpile_config (TranspileConfig)

    Returns:
        PassManager: a level 0 pass manager.
    """
    basis_gates = transpile_config.basis_gates
    coupling_map = transpile_config.coupling_map
    initial_layout = transpile_config.initial_layout
    seed_transpiler = transpile_config.seed_transpiler

    # 1. Use trivial layout if no layout given
    _given_layout = SetLayout(initial_layout)

    def _choose_layout_condition(property_set):
        return not property_set['layout']

    _choose_layout = TrivialLayout(coupling_map)

    # 2. Extend dag/layout with ancillas using the full coupling map
    _embed = [FullAncillaAllocation(coupling_map), EnlargeWithAncilla()]

    # 3. Unroll to the basis
    _unroll = Unroller(basis_gates)

    # 4. Swap to fit the coupling map
    _swap_check = CheckMap(coupling_map)

    def _swap_condition(property_set):
        return not property_set['is_swap_mapped']

    _swap = [
        BarrierBeforeFinalMeasurements(),
        LegacySwap(coupling_map, trials=20, seed=seed_transpiler),
        Decompose(SwapGate)
    ]

    # 5. Fix any bad CX directions
    # _direction_check = CheckCXDirection(coupling_map)  # TODO
    def _direction_condition(property_set):
        return not property_set['is_direction_mapped']

    _direction = [CXDirection(coupling_map)]

    # 6. Remove zero-state reset
    _reset = RemoveResetInZeroState()

    pm0 = PassManager()
    if coupling_map:
        pm0.append(_given_layout)
        pm0.append(_choose_layout, condition=_choose_layout_condition)
        pm0.append(_embed)
    pm0.append(_unroll)
    if coupling_map:
        pm0.append(_swap_check)
        pm0.append(_swap, condition=_swap_condition)
        # pm0.append(_direction_check)  # TODO
        pm0.append(_direction, condition=_direction_condition)
    pm0.append(_reset)

    return pm0
예제 #22
0
def level_3_pass_manager(transpile_config):
    """
    Level 3 pass manager: heavy optimization by noise adaptive qubit mapping and
    gate cancellation using commutativity rules and unitary synthesis.

    This pass manager applies the user-given initial layout. If none is given, and
    device calibration information is available, the circuit is mapped to the qubits
    with best readouts and to CX gates with highest fidelity. Otherwise, a layout on
    the most densely connected qubits is used.
    The pass manager then transforms the circuit to match the coupling constraints.
    It is then unrolled to the basis, and any flipped cx directions are fixed.
    Finally, optimizations in the form of commutative gate cancellation, resynthesis
    of two-qubit unitary blocks, and redundant reset removal are performed.
    Note: in simulators where coupling_map=None, only the unrolling and optimization
    stages are done.

    Args:
        transpile_config (TranspileConfig)

    Returns:
        PassManager: a level 3 pass manager.
    """
    basis_gates = transpile_config.basis_gates
    coupling_map = transpile_config.coupling_map
    initial_layout = transpile_config.initial_layout
    seed_transpiler = transpile_config.seed_transpiler
    backend_properties = transpile_config.backend_properties

    # 1. Unroll to the basis first, to prepare for noise-adaptive layout
    _unroll = Unroller(basis_gates)

    # 2. Layout on good qubits if calibration info available, otherwise on dense links
    _given_layout = SetLayout(initial_layout)

    def _choose_layout_condition(property_set):
        return not property_set['layout']

    _choose_layout = DenseLayout(coupling_map)
    if backend_properties:
        _choose_layout = NoiseAdaptiveLayout(backend_properties)

    # 3. Extend dag/layout with ancillas using the full coupling map
    _embed = [
        FullAncillaAllocation(coupling_map),
        EnlargeWithAncilla(),
        ApplyLayout()
    ]

    # 4. Unroll to 1q or 2q gates, swap to fit the coupling map
    _swap_check = CheckMap(coupling_map)

    def _swap_condition(property_set):
        return not property_set['is_swap_mapped']

    _swap = [
        BarrierBeforeFinalMeasurements(),
        Unroll3qOrMore(),
        StochasticSwap(coupling_map, trials=20, seed=seed_transpiler),
        Decompose(SwapGate)
    ]

    _direction_check = [CheckCXDirection(coupling_map)]

    def _direction_condition(property_set):
        return not property_set['is_direction_mapped']

    _direction = [CXDirection(coupling_map)]

    # 5. 1q rotation merge and commutative cancellation iteratively until no more change in depth
    _depth_check = [Depth(), FixedPoint('depth')]

    def _opt_control(property_set):
        return not property_set['depth_fixed_point']

    _opt = [
        RemoveResetInZeroState(),
        Collect2qBlocks(),
        ConsolidateBlocks(),
        Unroller(basis_gates),  # unroll unitaries
        Optimize1qGates(),
        CommutativeCancellation(),
        OptimizeSwapBeforeMeasure(),
        RemoveDiagonalGatesBeforeMeasure()
    ]

    if coupling_map:
        _opt.append(CXDirection(coupling_map))
        # if a coupling map has been provided, match coupling

    pm3 = PassManager()
    pm3.append(_unroll)
    if coupling_map:
        pm3.append(_given_layout)
        pm3.append(_choose_layout, condition=_choose_layout_condition)
        pm3.append(_embed)
        pm3.append(_swap_check)
        pm3.append(_swap, condition=_swap_condition)
        if not coupling_map.is_symmetric:
            pm3.append(_direction_check)
            pm3.append(_direction, condition=_direction_condition)
    pm3.append(_depth_check + _opt, do_while=_opt_control)

    return pm3
예제 #23
0
def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> PassManager:
    """Level 3 pass manager: heavy optimization by noise adaptive qubit mapping and
    gate cancellation using commutativity rules and unitary synthesis.

    This pass manager applies the user-given initial layout. If none is given, a search
    for a perfect layout (i.e. one that satisfies all 2-qubit interactions) is conducted.
    If no such layout is found, and device calibration information is available, the
    circuit is mapped to the qubits with best readouts and to CX gates with highest fidelity.

    The pass manager then transforms the circuit to match the coupling constraints.
    It is then unrolled to the basis, and any flipped cx directions are fixed.
    Finally, optimizations in the form of commutative gate cancellation, resynthesis
    of two-qubit unitary blocks, and redundant reset removal are performed.

    Note:
        In simulators where ``coupling_map=None``, only the unrolling and
        optimization stages are done.

    Args:
        pass_manager_config: configuration of the pass manager.

    Returns:
        a level 3 pass manager.

    Raises:
        TranspilerError: if the passmanager config is invalid.
    """
    basis_gates = pass_manager_config.basis_gates
    inst_map = pass_manager_config.inst_map
    coupling_map = pass_manager_config.coupling_map
    initial_layout = pass_manager_config.initial_layout
    layout_method = pass_manager_config.layout_method or "sabre"
    routing_method = pass_manager_config.routing_method or "sabre"
    translation_method = pass_manager_config.translation_method or "translator"
    scheduling_method = pass_manager_config.scheduling_method
    instruction_durations = pass_manager_config.instruction_durations
    seed_transpiler = pass_manager_config.seed_transpiler
    backend_properties = pass_manager_config.backend_properties
    approximation_degree = pass_manager_config.approximation_degree
    unitary_synthesis_method = pass_manager_config.unitary_synthesis_method
    timing_constraints = pass_manager_config.timing_constraints or TimingConstraints()
    unitary_synthesis_plugin_config = pass_manager_config.unitary_synthesis_plugin_config
    target = pass_manager_config.target

    # 1. Unroll to 1q or 2q gates
    _unroll3q = [
        # Use unitary synthesis for basis aware decomposition of UnitaryGates
        UnitarySynthesis(
            basis_gates,
            approximation_degree=approximation_degree,
            method=unitary_synthesis_method,
            plugin_config=unitary_synthesis_plugin_config,
            min_qubits=3,
        ),
        Unroll3qOrMore(),
    ]

    # 2. Layout on good qubits if calibration info available, otherwise on dense links
    _given_layout = SetLayout(initial_layout)

    def _choose_layout_condition(property_set):
        # layout hasn't been set yet
        return not property_set["layout"]

    def _csp_not_found_match(property_set):
        # If a layout hasn't been set by the time we run csp we need to run layout
        if property_set["layout"] is None:
            return True
        # if CSP layout stopped for any reason other than solution found we need
        # to run layout since CSP didn't converge.
        if (
            property_set["CSPLayout_stop_reason"] is not None
            and property_set["CSPLayout_stop_reason"] != "solution found"
        ):
            return True
        return False

    # 2a. If layout method is not set, first try a trivial layout
    _choose_layout_0 = (
        []
        if pass_manager_config.layout_method
        else [
            TrivialLayout(coupling_map),
            Layout2qDistance(coupling_map, property_name="trivial_layout_score"),
        ]
    )
    # 2b. If trivial layout wasn't perfect (ie no swaps are needed) then try
    # using CSP layout to find a perfect layout
    _choose_layout_1 = (
        []
        if pass_manager_config.layout_method
        else CSPLayout(coupling_map, call_limit=10000, time_limit=60, seed=seed_transpiler)
    )

    def _trivial_not_perfect(property_set):
        # Verify that a trivial layout  is perfect. If trivial_layout_score > 0
        # the layout is not perfect. The layout property set is unconditionally
        # set by trivial layout so we clear that before running CSP
        if property_set["trivial_layout_score"] is not None:
            if property_set["trivial_layout_score"] != 0:
                return True
        return False

    # 2c. if CSP didn't converge on a solution use layout_method (dense).
    if layout_method == "trivial":
        _choose_layout_2 = TrivialLayout(coupling_map)
    elif layout_method == "dense":
        _choose_layout_2 = DenseLayout(coupling_map, backend_properties)
    elif layout_method == "noise_adaptive":
        _choose_layout_2 = NoiseAdaptiveLayout(backend_properties)
    elif layout_method == "sabre":
        _choose_layout_2 = SabreLayout(coupling_map, max_iterations=4, seed=seed_transpiler)
    else:
        raise TranspilerError("Invalid layout method %s." % layout_method)

    # 3. Extend dag/layout with ancillas using the full coupling map
    _embed = [FullAncillaAllocation(coupling_map), EnlargeWithAncilla(), ApplyLayout()]

    # 4. Swap to fit the coupling map
    _swap_check = CheckMap(coupling_map)

    def _swap_condition(property_set):
        return not property_set["is_swap_mapped"]

    _swap = [BarrierBeforeFinalMeasurements()]
    if routing_method == "basic":
        _swap += [BasicSwap(coupling_map)]
    elif routing_method == "stochastic":
        _swap += [StochasticSwap(coupling_map, trials=200, seed=seed_transpiler)]
    elif routing_method == "lookahead":
        _swap += [LookaheadSwap(coupling_map, search_depth=5, search_width=6)]
    elif routing_method == "sabre":
        _swap += [SabreSwap(coupling_map, heuristic="decay", seed=seed_transpiler)]
    elif routing_method == "none":
        _swap += [
            Error(
                msg=(
                    "No routing method selected, but circuit is not routed to device. "
                    "CheckMap Error: {check_map_msg}"
                ),
                action="raise",
            )
        ]
    else:
        raise TranspilerError("Invalid routing method %s." % routing_method)

    # 5. Unroll to the basis
    if translation_method == "unroller":
        _unroll = [Unroller(basis_gates)]
    elif translation_method == "translator":
        from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel

        _unroll = [
            UnitarySynthesis(
                basis_gates,
                approximation_degree=approximation_degree,
                coupling_map=coupling_map,
                backend_props=backend_properties,
                plugin_config=unitary_synthesis_plugin_config,
                method=unitary_synthesis_method,
            ),
            UnrollCustomDefinitions(sel, basis_gates),
            BasisTranslator(sel, basis_gates, target),
        ]
    elif translation_method == "synthesis":
        _unroll = [
            UnitarySynthesis(
                basis_gates,
                approximation_degree=approximation_degree,
                coupling_map=coupling_map,
                backend_props=backend_properties,
                method=unitary_synthesis_method,
                plugin_config=unitary_synthesis_plugin_config,
                min_qubits=3,
            ),
            Unroll3qOrMore(),
            Collect2qBlocks(),
            ConsolidateBlocks(basis_gates=basis_gates),
            UnitarySynthesis(
                basis_gates,
                approximation_degree=approximation_degree,
                coupling_map=coupling_map,
                backend_props=backend_properties,
                method=unitary_synthesis_method,
                plugin_config=unitary_synthesis_plugin_config,
            ),
        ]
    else:
        raise TranspilerError("Invalid translation method %s." % translation_method)

    # 6. Fix any CX direction mismatch
    _direction_check = [CheckGateDirection(coupling_map, target)]

    def _direction_condition(property_set):
        return not property_set["is_direction_mapped"]

    _direction = [GateDirection(coupling_map, target)]

    # 8. Optimize iteratively until no more change in depth. Removes useless gates
    # after reset and before measure, commutes gates and optimizes contiguous blocks.
    _depth_check = [Depth(), FixedPoint("depth")]

    def _opt_control(property_set):
        return not property_set["depth_fixed_point"]

    _reset = [RemoveResetInZeroState()]

    _meas = [OptimizeSwapBeforeMeasure(), RemoveDiagonalGatesBeforeMeasure()]

    _opt = [
        Collect2qBlocks(),
        ConsolidateBlocks(basis_gates=basis_gates),
        UnitarySynthesis(
            basis_gates,
            approximation_degree=approximation_degree,
            coupling_map=coupling_map,
            backend_props=backend_properties,
            method=unitary_synthesis_method,
            plugin_config=unitary_synthesis_plugin_config,
        ),
        Optimize1qGatesDecomposition(basis_gates),
        CommutativeCancellation(),
    ]

    # 9. Unify all durations (either SI, or convert to dt if known)
    # Schedule the circuit only when scheduling_method is supplied
    _time_unit_setup = [ContainsInstruction("delay")]
    _time_unit_conversion = [TimeUnitConversion(instruction_durations)]

    def _contains_delay(property_set):
        return property_set["contains_delay"]

    _scheduling = []
    if scheduling_method:
        _scheduling += _time_unit_conversion
        if scheduling_method in {"alap", "as_late_as_possible"}:
            _scheduling += [ALAPSchedule(instruction_durations)]
        elif scheduling_method in {"asap", "as_soon_as_possible"}:
            _scheduling += [ASAPSchedule(instruction_durations)]
        else:
            raise TranspilerError("Invalid scheduling method %s." % scheduling_method)

    # 10. Call measure alignment. Should come after scheduling.
    if (
        timing_constraints.granularity != 1
        or timing_constraints.min_length != 1
        or timing_constraints.acquire_alignment != 1
    ):
        _alignments = [
            ValidatePulseGates(
                granularity=timing_constraints.granularity, min_length=timing_constraints.min_length
            ),
            AlignMeasures(alignment=timing_constraints.acquire_alignment),
        ]
    else:
        _alignments = []

    # Build pass manager
    pm3 = PassManager()
    pm3.append(_unroll3q)
    pm3.append(_reset + _meas)
    if coupling_map or initial_layout:
        pm3.append(_given_layout)
        pm3.append(_choose_layout_0, condition=_choose_layout_condition)
        pm3.append(_choose_layout_1, condition=_trivial_not_perfect)
        pm3.append(_choose_layout_2, condition=_csp_not_found_match)
        pm3.append(_embed)
        pm3.append(_swap_check)
        pm3.append(_swap, condition=_swap_condition)
    pm3.append(_unroll)
    if (coupling_map and not coupling_map.is_symmetric) or (
        target is not None and target.get_non_global_operation_names(strict_direction=True)
    ):
        pm3.append(_direction_check)
        pm3.append(_direction, condition=_direction_condition)
        pm3.append(_reset)
        # For transpiling to a target we need to run GateDirection in the
        # optimization loop to correct for incorrect directions that might be
        # inserted by UnitarySynthesis which is direction aware but only via
        # the coupling map which with a target doesn't give a full picture
        if target is not None:
            pm3.append(_depth_check + _opt + _unroll + _direction, do_while=_opt_control)
        else:
            pm3.append(_depth_check + _opt + _unroll, do_while=_opt_control)
    else:
        pm3.append(_reset)
        pm3.append(_depth_check + _opt + _unroll, do_while=_opt_control)
    if inst_map and inst_map.has_custom_gate():
        pm3.append(PulseGates(inst_map=inst_map))
    if scheduling_method:
        pm3.append(_scheduling)
    elif instruction_durations:
        pm3.append(_time_unit_setup)
        pm3.append(_time_unit_conversion, condition=_contains_delay)
    pm3.append(_alignments)

    return pm3
예제 #24
0
class TestCompiler(QiskitTestCase):
    """Qiskit Compiler Tests."""

    def setUp(self):
        self.seed = 42
        self.backend = BasicAer.get_backend("qasm_simulator")

    def test_compile(self):
        """Test Compiler.

        If all correct some should exists.
        """
        backend = BasicAer.get_backend('qasm_simulator')

        qubit_reg = QuantumRegister(2, name='q')
        clbit_reg = ClassicalRegister(2, name='c')
        qc = QuantumCircuit(qubit_reg, clbit_reg, name="bell")
        qc.h(qubit_reg[0])
        qc.cx(qubit_reg[0], qubit_reg[1])
        qc.measure(qubit_reg, clbit_reg)

        circuits = transpile(qc, backend)
        self.assertIsInstance(circuits, QuantumCircuit)

    def test_compile_two(self):
        """Test Compiler.

        If all correct some should exists.
        """
        backend = BasicAer.get_backend('qasm_simulator')

        qubit_reg = QuantumRegister(2)
        clbit_reg = ClassicalRegister(2)
        qubit_reg2 = QuantumRegister(2)
        clbit_reg2 = ClassicalRegister(2)
        qc = QuantumCircuit(qubit_reg, clbit_reg, name="bell")
        qc.h(qubit_reg[0])
        qc.cx(qubit_reg[0], qubit_reg[1])
        qc.measure(qubit_reg, clbit_reg)
        qc_extra = QuantumCircuit(qubit_reg, qubit_reg2, clbit_reg, clbit_reg2, name="extra")
        qc_extra.measure(qubit_reg, clbit_reg)
        circuits = transpile([qc, qc_extra], backend)
        self.assertIsInstance(circuits[0], QuantumCircuit)
        self.assertIsInstance(circuits[1], QuantumCircuit)

    def test_mapping_correction(self):
        """Test mapping works in previous failed case.
        """
        backend = FakeRueschlikon()
        qr = QuantumRegister(name='qr', size=11)
        cr = ClassicalRegister(name='qc', size=11)
        circuit = QuantumCircuit(qr, cr)
        circuit.u3(1.564784764685993, -1.2378965763410095, 2.9746763177861713, qr[3])
        circuit.u3(1.2269835563676523, 1.1932982847014162, -1.5597357740824318, qr[5])
        circuit.cx(qr[5], qr[3])
        circuit.u1(0.856768317675967, qr[3])
        circuit.u3(-3.3911273825190915, 0.0, 0.0, qr[5])
        circuit.cx(qr[3], qr[5])
        circuit.u3(2.159209321625547, 0.0, 0.0, qr[5])
        circuit.cx(qr[5], qr[3])
        circuit.u3(0.30949966910232335, 1.1706201763833217, 1.738408691990081, qr[3])
        circuit.u3(1.9630571407274755, -0.6818742967975088, 1.8336534616728195, qr[5])
        circuit.u3(1.330181833806101, 0.6003162754946363, -3.181264980452862, qr[7])
        circuit.u3(0.4885914820775024, 3.133297443244865, -2.794457469189904, qr[8])
        circuit.cx(qr[8], qr[7])
        circuit.u1(2.2196187596178616, qr[7])
        circuit.u3(-3.152367609631023, 0.0, 0.0, qr[8])
        circuit.cx(qr[7], qr[8])
        circuit.u3(1.2646005789809263, 0.0, 0.0, qr[8])
        circuit.cx(qr[8], qr[7])
        circuit.u3(0.7517780502091939, 1.2828514296564781, 1.6781179605443775, qr[7])
        circuit.u3(0.9267400575390405, 2.0526277839695153, 2.034202361069533, qr[8])
        circuit.u3(2.550304293455634, 3.8250017126569698, -2.1351609599720054, qr[1])
        circuit.u3(0.9566260876600556, -1.1147561503064538, 2.0571590492298797, qr[4])
        circuit.cx(qr[4], qr[1])
        circuit.u1(2.1899329069137394, qr[1])
        circuit.u3(-1.8371715243173294, 0.0, 0.0, qr[4])
        circuit.cx(qr[1], qr[4])
        circuit.u3(0.4717053496327104, 0.0, 0.0, qr[4])
        circuit.cx(qr[4], qr[1])
        circuit.u3(2.3167620677708145, -1.2337330260253256, -0.5671322899563955, qr[1])
        circuit.u3(1.0468499525240678, 0.8680750644809365, -1.4083720073192485, qr[4])
        circuit.u3(2.4204244021892807, -2.211701932616922, 3.8297006565735883, qr[10])
        circuit.u3(0.36660280497727255, 3.273119149343493, -1.8003362351299388, qr[6])
        circuit.cx(qr[6], qr[10])
        circuit.u1(1.067395863586385, qr[10])
        circuit.u3(-0.7044917541291232, 0.0, 0.0, qr[6])
        circuit.cx(qr[10], qr[6])
        circuit.u3(2.1830003849921527, 0.0, 0.0, qr[6])
        circuit.cx(qr[6], qr[10])
        circuit.u3(2.1538343756723917, 2.2653381826084606, -3.550087952059485, qr[10])
        circuit.u3(1.307627685019188, -0.44686656993522567, -2.3238098554327418, qr[6])
        circuit.u3(2.2046797998462906, 0.9732961754855436, 1.8527865921467421, qr[9])
        circuit.u3(2.1665254613904126, -1.281337664694577, -1.2424905413631209, qr[0])
        circuit.cx(qr[0], qr[9])
        circuit.u1(2.6209599970201007, qr[9])
        circuit.u3(0.04680566321901303, 0.0, 0.0, qr[0])
        circuit.cx(qr[9], qr[0])
        circuit.u3(1.7728411151289603, 0.0, 0.0, qr[0])
        circuit.cx(qr[0], qr[9])
        circuit.u3(2.4866395967434443, 0.48684511243566697, -3.0069186877854728, qr[9])
        circuit.u3(1.7369112924273789, -4.239660866163805, 1.0623389015296005, qr[0])
        circuit.barrier(qr)
        circuit.measure(qr, cr)

        circuits = transpile(circuit, backend)

        self.assertIsInstance(circuits, QuantumCircuit)

    def test_transpiler_layout_from_intlist(self):
        """A list of ints gives layout to correctly map circuit.
        virtual  physical
         q1_0  -  4   ---[H]---
         q2_0  -  5
         q2_1  -  6   ---[H]---
         q3_0  -  8
         q3_1  -  9
         q3_2  -  10  ---[H]---

        """
        qr1 = QuantumRegister(1, 'qr1')
        qr2 = QuantumRegister(2, 'qr2')
        qr3 = QuantumRegister(3, 'qr3')
        qc = QuantumCircuit(qr1, qr2, qr3)
        qc.h(qr1[0])
        qc.h(qr2[1])
        qc.h(qr3[2])
        layout = [4, 5, 6, 8, 9, 10]

        cmap = [[1, 0], [1, 2], [2, 3], [4, 3], [4, 10],
                [5, 4], [5, 6], [5, 9], [6, 8], [7, 8],
                [9, 8], [9, 10], [11, 3], [11, 10],
                [11, 12], [12, 2], [13, 1], [13, 12]]

        new_circ = transpile(qc, backend=None,
                             coupling_map=cmap,
                             basis_gates=['u2'],
                             initial_layout=layout)
        mapped_qubits = []
        for _, qargs, _ in new_circ.data:
            mapped_qubits.append(qargs[0][1])

        self.assertEqual(mapped_qubits, [4, 6, 10])

    def test_mapping_multi_qreg(self):
        """Test mapping works for multiple qregs.
        """
        backend = FakeRueschlikon()
        qr = QuantumRegister(3, name='qr')
        qr2 = QuantumRegister(1, name='qr2')
        qr3 = QuantumRegister(4, name='qr3')
        cr = ClassicalRegister(3, name='cr')
        qc = QuantumCircuit(qr, qr2, qr3, cr)
        qc.h(qr[0])
        qc.cx(qr[0], qr2[0])
        qc.cx(qr[1], qr3[2])
        qc.measure(qr, cr)

        circuits = transpile(qc, backend)

        self.assertIsInstance(circuits, QuantumCircuit)

    def test_mapping_already_satisfied(self):
        """Test compiler doesn't change circuit already matching backend coupling
        """
        backend = FakeRueschlikon()
        qr = QuantumRegister(16)
        cr = ClassicalRegister(16)
        qc = QuantumCircuit(qr, cr)
        qc.h(qr[1])
        qc.x(qr[2])
        qc.x(qr[3])
        qc.x(qr[4])
        qc.cx(qr[1], qr[2])
        qc.cx(qr[2], qr[3])
        qc.cx(qr[3], qr[4])
        qc.cx(qr[3], qr[14])
        qc.measure(qr, cr)
        qobj = compile(qc, backend)
        compiled_ops = qobj.experiments[0].instructions
        original_cx_qubits = [[1, 2], [2, 3], [3, 4], [3, 14]]
        for operation in compiled_ops:
            if operation.name == 'cx':
                self.assertIn(operation.qubits, backend.configuration().coupling_map)
                self.assertIn(operation.qubits, original_cx_qubits)

    def test_compile_circuits_diff_registers(self):
        """Compile list of circuits with different qreg names.
        """
        backend = FakeRueschlikon()
        circuits = []
        for _ in range(2):
            qr = QuantumRegister(2)
            cr = ClassicalRegister(2)
            circuit = QuantumCircuit(qr, cr)
            circuit.h(qr[0])
            circuit.cx(qr[0], qr[1])
            circuit.measure(qr, cr)
            circuits.append(circuit)

        circuits = transpile(circuits, backend)
        self.assertIsInstance(circuits[0], QuantumCircuit)

    def test_example_multiple_compile(self):
        """Test a toy example compiling multiple circuits.

        Pass if the results are correct.
        """
        backend = BasicAer.get_backend('qasm_simulator')
        coupling_map = [[0, 1], [0, 2],
                        [1, 2],
                        [3, 2], [3, 4],
                        [4, 2]]

        qr = QuantumRegister(5)
        cr = ClassicalRegister(5)
        bell = QuantumCircuit(qr, cr)
        ghz = QuantumCircuit(qr, cr)
        # Create a GHZ state
        ghz.h(qr[0])
        for i in range(4):
            ghz.cx(qr[i], qr[i + 1])
        # Insert a barrier before measurement
        ghz.barrier()
        # Measure all of the qubits in the standard basis
        for i in range(5):
            ghz.measure(qr[i], cr[i])
        # Create a Bell state
        bell.h(qr[0])
        bell.cx(qr[0], qr[1])
        bell.barrier()
        bell.measure(qr[0], cr[0])
        bell.measure(qr[1], cr[1])
        shots = 2048
        bell_qobj = compile(bell, backend=backend,
                            shots=shots, seed=10)
        ghz_qobj = compile(ghz, backend=backend,
                           shots=shots, coupling_map=coupling_map,
                           seed=10)
        bell_result = backend.run(bell_qobj).result()
        ghz_result = backend.run(ghz_qobj).result()

        threshold = 0.05 * shots
        counts_bell = bell_result.get_counts()
        target_bell = {'00000': shots / 2, '00011': shots / 2}
        self.assertDictAlmostEqual(counts_bell, target_bell, threshold)

        counts_ghz = ghz_result.get_counts()
        target_ghz = {'00000': shots / 2, '11111': shots / 2}
        self.assertDictAlmostEqual(counts_ghz, target_ghz, threshold)

    def test_compile_coupling_map(self):
        """Test compile_coupling_map.
        If all correct should return data with the same stats. The circuit may
        be different.
        """
        backend = BasicAer.get_backend('qasm_simulator')

        qr = QuantumRegister(3, 'qr')
        cr = ClassicalRegister(3, 'cr')
        qc = QuantumCircuit(qr, cr)
        qc.h(qr[0])
        qc.cx(qr[0], qr[1])
        qc.cx(qr[0], qr[2])
        qc.measure(qr[0], cr[0])
        qc.measure(qr[1], cr[1])
        qc.measure(qr[2], cr[2])
        shots = 2048
        coupling_map = [[0, 1], [1, 2]]
        # TODO (luciano): this initial_layout should be replaced by
        #  {(qr, 0): 0, (qr, 1): 1, (qr, 2): 2} after 0.8
        initial_layout = {("qr", 0): ("q", 0), ("qr", 1): ("q", 1),
                          ("qr", 2): ("q", 2)}
        qobj = compile(qc, backend=backend, shots=shots,
                       coupling_map=coupling_map,
                       initial_layout=initial_layout, seed=88)
        job = backend.run(qobj)
        result = job.result()
        qasm_to_check = qc.qasm()
        self.assertEqual(len(qasm_to_check), 173)

        counts = result.get_counts(qc)
        target = {'000': shots / 2, '111': shots / 2}
        threshold = 0.05 * shots
        self.assertDictAlmostEqual(counts, target, threshold)

    def test_example_swap_bits(self):
        """Test a toy example swapping a set bit around.

        Uses the mapper. Pass if results are correct.
        """
        backend = BasicAer.get_backend('qasm_simulator')
        coupling_map = [[0, 1], [0, 8], [1, 2], [1, 9], [2, 3], [2, 10],
                        [3, 4], [3, 11], [4, 5], [4, 12], [5, 6], [5, 13],
                        [6, 7], [6, 14], [7, 15], [8, 9], [9, 10], [10, 11],
                        [11, 12], [12, 13], [13, 14], [14, 15]]

        n = 3  # make this at least 3
        qr0 = QuantumRegister(n)
        qr1 = QuantumRegister(n)
        ans = ClassicalRegister(2 * n)
        qc = QuantumCircuit(qr0, qr1, ans)
        # Set the first bit of qr0
        qc.x(qr0[0])
        # Swap the set bit
        qc.swap(qr0[0], qr0[n - 1])
        qc.swap(qr0[n - 1], qr1[n - 1])
        qc.swap(qr1[n - 1], qr0[1])
        qc.swap(qr0[1], qr1[1])
        # Insert a barrier before measurement
        qc.barrier()
        # Measure all of the qubits in the standard basis
        for j in range(n):
            qc.measure(qr0[j], ans[j])
            qc.measure(qr1[j], ans[j + n])
        # First version: no mapping
        result = execute(qc, backend=backend,
                         coupling_map=None, shots=1024,
                         seed=14).result()
        self.assertEqual(result.get_counts(qc), {'010000': 1024})
        # Second version: map to coupling graph
        result = execute(qc, backend=backend,
                         coupling_map=coupling_map, shots=1024,
                         seed=14).result()
        self.assertEqual(result.get_counts(qc), {'010000': 1024})

    def test_parallel_compile(self):
        """Trigger parallel routines in compile.
        """
        backend = FakeRueschlikon()
        qr = QuantumRegister(16)
        cr = ClassicalRegister(2)
        qc = QuantumCircuit(qr, cr)
        qc.h(qr[0])
        for k in range(1, 15):
            qc.cx(qr[0], qr[k])
        qc.measure(qr[5], cr[0])
        qlist = [qc for k in range(10)]
        qobj = compile(qlist, backend=backend)
        self.assertEqual(len(qobj.experiments), 10)

    def test_compile_pass_manager(self):
        """Test compile with and without an empty pass manager."""
        qr = QuantumRegister(2)
        cr = ClassicalRegister(2)
        qc = QuantumCircuit(qr, cr)
        qc.u1(3.14, qr[0])
        qc.u2(3.14, 1.57, qr[0])
        qc.barrier(qr)
        qc.measure(qr, cr)
        backend = BasicAer.get_backend('qasm_simulator')
        qrtrue = compile(qc, backend, seed=42)
        rtrue = backend.run(qrtrue).result()
        qrfalse = compile(qc, backend, seed=42, pass_manager=PassManager())
        rfalse = backend.run(qrfalse).result()
        self.assertEqual(rtrue.get_counts(), rfalse.get_counts())

    def test_compile_with_initial_layout(self):
        """Test compile with an initial layout.
        Regression test for #1711
        """
        qr = QuantumRegister(3)
        cr = ClassicalRegister(3)
        qc = QuantumCircuit(qr, cr)
        qc.cx(qr[2], qr[1])
        qc.cx(qr[2], qr[0])
        initial_layout = {0: (qr, 1), 2: (qr, 0), 15: (qr, 2)}
        backend = FakeRueschlikon()

        qobj = compile(qc, backend, seed=42, initial_layout=initial_layout)

        compiled_ops = qobj.experiments[0].instructions
        for operation in compiled_ops:
            if operation.name == 'cx':
                self.assertIn(operation.qubits, backend.configuration().coupling_map)
                self.assertIn(operation.qubits, [[15, 0], [15, 2]])

    def test_mapper_overoptimization(self):
        """Check mapper overoptimization.

        The mapper should not change the semantics of the input.
        An overoptimization introduced issue #81:
        https://github.com/Qiskit/qiskit-terra/issues/81
        """
        # -X-.-----
        # -Y-+-S-.-
        # -Z-.-T-+-
        # ---+-H---
        qr = QuantumRegister(4)
        cr = ClassicalRegister(4)
        circ = QuantumCircuit(qr, cr)
        circ.x(qr[0])
        circ.y(qr[1])
        circ.z(qr[2])
        circ.cx(qr[0], qr[1])
        circ.cx(qr[2], qr[3])
        circ.s(qr[1])
        circ.t(qr[2])
        circ.h(qr[3])
        circ.cx(qr[1], qr[2])
        circ.measure(qr[0], cr[0])
        circ.measure(qr[1], cr[1])
        circ.measure(qr[2], cr[2])
        circ.measure(qr[3], cr[3])

        coupling_map = [[0, 2], [1, 2], [2, 3]]
        shots = 1000

        result1 = execute(circ, backend=self.backend,
                          coupling_map=coupling_map, seed=self.seed, shots=shots)
        count1 = result1.result().get_counts()
        result2 = execute(circ, backend=self.backend,
                          coupling_map=None, seed=self.seed, shots=shots)
        count2 = result2.result().get_counts()
        self.assertDictAlmostEqual(count1, count2, shots * 0.02)

    def test_grovers_circuit(self):
        """Testing a circuit originated in the Grover algorithm"""
        shots = 1000
        coupling_map = None

        # 6-qubit grovers
        qr = QuantumRegister(6)
        cr = ClassicalRegister(2)
        circuit = QuantumCircuit(qr, cr, name='grovers')

        circuit.h(qr[0])
        circuit.h(qr[1])
        circuit.x(qr[2])
        circuit.x(qr[3])
        circuit.x(qr[0])
        circuit.cx(qr[0], qr[2])
        circuit.x(qr[0])
        circuit.cx(qr[1], qr[3])
        circuit.ccx(qr[2], qr[3], qr[4])
        circuit.cx(qr[1], qr[3])
        circuit.x(qr[0])
        circuit.cx(qr[0], qr[2])
        circuit.x(qr[0])
        circuit.x(qr[1])
        circuit.x(qr[4])
        circuit.h(qr[4])
        circuit.ccx(qr[0], qr[1], qr[4])
        circuit.h(qr[4])
        circuit.x(qr[0])
        circuit.x(qr[1])
        circuit.x(qr[4])
        circuit.h(qr[0])
        circuit.h(qr[1])
        circuit.h(qr[4])
        circuit.barrier(qr)
        circuit.measure(qr[0], cr[0])
        circuit.measure(qr[1], cr[1])

        result = execute(circuit, backend=self.backend,
                         coupling_map=coupling_map, seed=self.seed, shots=shots)
        counts = result.result().get_counts()

        expected_probs = {'00': 0.64,
                          '01': 0.117,
                          '10': 0.113,
                          '11': 0.13}

        target = {key: shots * val for key, val in expected_probs.items()}
        threshold = 0.04 * shots
        self.assertDictAlmostEqual(counts, target, threshold)

    def test_math_domain_error(self):
        """Check for floating point errors.

        The math library operates over floats and introduces floating point
        errors that should be avoided.
        See: https://github.com/Qiskit/qiskit-terra/issues/111
        """
        qr = QuantumRegister(4)
        cr = ClassicalRegister(4)
        circ = QuantumCircuit(qr, cr)
        circ.y(qr[0])
        circ.z(qr[2])
        circ.h(qr[2])
        circ.cx(qr[1], qr[0])
        circ.y(qr[2])
        circ.t(qr[2])
        circ.z(qr[2])
        circ.cx(qr[1], qr[2])
        circ.measure(qr[0], cr[0])
        circ.measure(qr[1], cr[1])
        circ.measure(qr[2], cr[2])
        circ.measure(qr[3], cr[3])

        coupling_map = [[0, 2], [1, 2], [2, 3]]
        shots = 2000
        job = execute(circ, backend=self.backend,
                      coupling_map=coupling_map, seed=self.seed, shots=shots)
        counts = job.result().get_counts()
        target = {'0001': shots / 2, '0101': shots / 2}
        threshold = 0.04 * shots
        self.assertDictAlmostEqual(counts, target, threshold)

    def test_random_parameter_circuit(self):
        """Run a circuit with randomly generated parameters."""
        circ = QuantumCircuit.from_qasm_file(
            self._get_resource_path('random_n5_d5.qasm', Path.QASMS))
        coupling_map = [[0, 1], [1, 2], [2, 3], [3, 4]]
        shots = 1024
        qobj = execute(circ, backend=self.backend,
                       coupling_map=coupling_map, shots=shots, seed=self.seed)
        counts = qobj.result().get_counts()
        expected_probs = {
            '00000': 0.079239867254200971,
            '00001': 0.032859032998526903,
            '00010': 0.10752610993531816,
            '00011': 0.018818532050952699,
            '00100': 0.054830807251011054,
            '00101': 0.0034141983951965164,
            '00110': 0.041649309748902276,
            '00111': 0.039967731207338125,
            '01000': 0.10516937819949743,
            '01001': 0.026635620063700002,
            '01010': 0.0053475143548793866,
            '01011': 0.01940513314416064,
            '01100': 0.0044028405481225047,
            '01101': 0.057524760052126644,
            '01110': 0.010795354134597078,
            '01111': 0.026491296821535528,
            '10000': 0.094827455395274859,
            '10001': 0.0008373965072688836,
            '10010': 0.029082297894094441,
            '10011': 0.012386622870598416,
            '10100': 0.018739140061148799,
            '10101': 0.01367656456536896,
            '10110': 0.039184170706009248,
            '10111': 0.062339335178438288,
            '11000': 0.00293674365989009,
            '11001': 0.012848433960739968,
            '11010': 0.018472497159499782,
            '11011': 0.0088903691234912003,
            '11100': 0.031305389080034329,
            '11101': 0.0004788556283690458,
            '11110': 0.002232419390471667,
            '11111': 0.017684822659235985
        }
        target = {key: shots * val for key, val in expected_probs.items()}
        threshold = 0.04 * shots
        self.assertDictAlmostEqual(counts, target, threshold)

    def test_already_mapped(self):
        """Circuit not remapped if matches topology.

        See: https://github.com/Qiskit/qiskit-terra/issues/342
        """
        backend = FakeRueschlikon()
        qr = QuantumRegister(16, 'qr')
        cr = ClassicalRegister(16, 'cr')
        qc = QuantumCircuit(qr, cr)
        qc.cx(qr[3], qr[14])
        qc.cx(qr[5], qr[4])
        qc.h(qr[9])
        qc.cx(qr[9], qr[8])
        qc.x(qr[11])
        qc.cx(qr[3], qr[4])
        qc.cx(qr[12], qr[11])
        qc.cx(qr[13], qr[4])
        for j in range(16):
            qc.measure(qr[j], cr[j])
        qobj = compile(qc, backend=backend)
        cx_qubits = [x.qubits
                     for x in qobj.experiments[0].instructions
                     if x.name == "cx"]

        self.assertEqual(sorted(cx_qubits), [[3, 4], [3, 14], [5, 4],
                                             [9, 8], [12, 11], [13, 4]])

    def test_yzy_zyz_cases(self):
        """yzy_to_zyz works in previously failed cases.

        See: https://github.com/Qiskit/qiskit-terra/issues/607
        """
        backend = FakeTenerife()
        qr = QuantumRegister(2)
        circ1 = QuantumCircuit(qr)
        circ1.cx(qr[0], qr[1])
        circ1.rz(0.7, qr[1])
        circ1.rx(1.570796, qr[1])
        qobj1 = compile(circ1, backend)
        self.assertIsInstance(qobj1, QasmQobj)

        circ2 = QuantumCircuit(qr)
        circ2.y(qr[0])
        circ2.h(qr[0])
        circ2.s(qr[0])
        circ2.h(qr[0])
        qobj2 = compile(circ2, backend)
        self.assertIsInstance(qobj2, QasmQobj)

    def test_move_measurements(self):
        """Measurements applied AFTER swap mapping.
        """
        backend = FakeRueschlikon()
        cmap = backend.configuration().coupling_map
        circ = QuantumCircuit.from_qasm_file(
            self._get_resource_path('move_measurements.qasm', Path.QASMS))

        dag_circuit = circuit_to_dag(circ)
        lay = Layout({('qa', 0): ('q', 0), ('qa', 1): ('q', 1), ('qb', 0): ('q', 15),
                      ('qb', 1): ('q', 2), ('qb', 2): ('q', 14), ('qN', 0): ('q', 3),
                      ('qN', 1): ('q', 13), ('qN', 2): ('q', 4), ('qc', 0): ('q', 12),
                      ('qNt', 0): ('q', 5), ('qNt', 1): ('q', 11), ('qt', 0): ('q', 6)})
        out_dag = transpile_dag(dag_circuit, initial_layout=lay, coupling_map=cmap)
        meas_nodes = out_dag.named_nodes('measure')
        for meas_node in meas_nodes:
            is_last_measure = all([after_measure.type == 'out'
                                   for after_measure in out_dag.quantum_successors(meas_node)])
            self.assertTrue(is_last_measure)

    def test_kak_decomposition(self):
        """Verify KAK decomposition for random Haar unitaries.
        """
        for _ in range(100):
            unitary = random_unitary_matrix(4)
            with self.subTest(unitary=unitary):
                try:
                    two_qubit_kak(unitary, verify_gate_sequence=True)
                except MapperError as ex:
                    self.fail(str(ex))

    barrier_pass = BarrierBeforeFinalMeasurements()

    @patch.object(BarrierBeforeFinalMeasurements, 'run', wraps=barrier_pass.run)
    def test_final_measurement_barrier_for_devices(self, mock_pass):
        """Verify BarrierBeforeFinalMeasurements pass is called in default pipeline for devices."""

        circ = QuantumCircuit.from_qasm_file(self._get_resource_path('example.qasm', Path.QASMS))
        dag_circuit = circuit_to_dag(circ)
        layout = Layout.generate_trivial_layout(*circ.qregs)
        transpile_dag(dag_circuit, coupling_map=FakeRueschlikon().configuration().coupling_map,
                      initial_layout=layout)

        self.assertTrue(mock_pass.called)

    @patch.object(BarrierBeforeFinalMeasurements, 'run', wraps=barrier_pass.run)
    def test_final_measurement_barrier_for_simulators(self, mock_pass):
        """Verify BarrierBeforeFinalMeasurements pass is in default pipeline for simulators."""
        circ = QuantumCircuit.from_qasm_file(self._get_resource_path('example.qasm', Path.QASMS))
        dag_circuit = circuit_to_dag(circ)
        transpile_dag(dag_circuit)

        self.assertTrue(mock_pass.called)

    def test_optimize_to_nothing(self):
        """ Optimze gates up to fixed point in the default pipeline
        See https://github.com/Qiskit/qiskit-terra/issues/2035 """
        qr = QuantumRegister(2)
        circ = QuantumCircuit(qr)
        circ.h(qr[0])
        circ.cx(qr[0], qr[1])
        circ.x(qr[0])
        circ.y(qr[0])
        circ.z(qr[0])
        circ.cx(qr[0], qr[1])
        circ.h(qr[0])
        circ.cx(qr[0], qr[1])
        circ.cx(qr[0], qr[1])
        dag_circuit = circuit_to_dag(circ)

        after = transpile_dag(dag_circuit, coupling_map=[[0, 1], [1, 0]])

        expected = QuantumCircuit(QuantumRegister(2, 'q'))
        self.assertEqual(after, circuit_to_dag(expected))
예제 #25
0
def level_0_pass_manager(
        pass_manager_config: PassManagerConfig) -> PassManager:
    """Level 0 pass manager: no explicit optimization other than mapping to backend.

    This pass manager applies the user-given initial layout. If none is given, a trivial
    layout consisting of mapping the i-th virtual qubit to the i-th physical qubit is used.
    Any unused physical qubit is allocated as ancilla space.

    The pass manager then unrolls the circuit to the desired basis, and transforms the
    circuit to match the coupling map.

    Note:
        In simulators where ``coupling_map=None``, only the unrolling and
        optimization stages are done.

    Args:
        pass_manager_config: configuration of the pass manager.

    Returns:
        a level 0 pass manager.

    Raises:
        TranspilerError: if the passmanager config is invalid.
    """
    basis_gates = pass_manager_config.basis_gates
    coupling_map = pass_manager_config.coupling_map
    initial_layout = pass_manager_config.initial_layout
    layout_method = pass_manager_config.layout_method or 'trivial'
    routing_method = pass_manager_config.routing_method or 'stochastic'
    translation_method = pass_manager_config.translation_method or 'translator'
    scheduling_method = pass_manager_config.scheduling_method
    instruction_durations = pass_manager_config.instruction_durations
    seed_transpiler = pass_manager_config.seed_transpiler
    backend_properties = pass_manager_config.backend_properties

    # 1. Choose an initial layout if not set by user (default: trivial layout)
    _given_layout = SetLayout(initial_layout)

    def _choose_layout_condition(property_set):
        return not property_set['layout']

    if layout_method == 'trivial':
        _choose_layout = TrivialLayout(coupling_map)
    elif layout_method == 'dense':
        _choose_layout = DenseLayout(coupling_map, backend_properties)
    elif layout_method == 'noise_adaptive':
        _choose_layout = NoiseAdaptiveLayout(backend_properties)
    elif layout_method == 'sabre':
        _choose_layout = SabreLayout(coupling_map,
                                     max_iterations=1,
                                     seed=seed_transpiler)
    else:
        raise TranspilerError("Invalid layout method %s." % layout_method)

    # 2. Extend dag/layout with ancillas using the full coupling map
    _embed = [
        FullAncillaAllocation(coupling_map),
        EnlargeWithAncilla(),
        ApplyLayout()
    ]

    # 3. Decompose so only 1-qubit and 2-qubit gates remain
    _unroll3q = Unroll3qOrMore()

    # 4. Swap to fit the coupling map
    _swap_check = CheckMap(coupling_map)

    def _swap_condition(property_set):
        return not property_set['is_swap_mapped']

    _swap = [BarrierBeforeFinalMeasurements()]
    if routing_method == 'basic':
        _swap += [BasicSwap(coupling_map)]
    elif routing_method == 'stochastic':
        _swap += [
            StochasticSwap(coupling_map, trials=20, seed=seed_transpiler)
        ]
    elif routing_method == 'lookahead':
        _swap += [LookaheadSwap(coupling_map, search_depth=2, search_width=2)]
    elif routing_method == 'sabre':
        _swap += [
            SabreSwap(coupling_map, heuristic='basic', seed=seed_transpiler)
        ]
    else:
        raise TranspilerError("Invalid routing method %s." % routing_method)

    # 5. Unroll to the basis
    if translation_method == 'unroller':
        _unroll = [Unroller(basis_gates)]
    elif translation_method == 'translator':
        from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel
        _unroll = [
            UnrollCustomDefinitions(sel, basis_gates),
            BasisTranslator(sel, basis_gates)
        ]
    elif translation_method == 'synthesis':
        _unroll = [
            Unroll3qOrMore(),
            Collect2qBlocks(),
            ConsolidateBlocks(basis_gates=basis_gates),
            UnitarySynthesis(basis_gates),
        ]
    else:
        raise TranspilerError("Invalid translation method %s." %
                              translation_method)

    # 6. Fix any bad CX directions
    _direction_check = [CheckCXDirection(coupling_map)]

    def _direction_condition(property_set):
        return not property_set['is_direction_mapped']

    _direction = [CXDirection(coupling_map)]

    # 7. Schedule the circuit only when scheduling_method is supplied
    if scheduling_method:
        _scheduling = [TimeUnitAnalysis(instruction_durations)]
        if scheduling_method in {'alap', 'as_late_as_possible'}:
            _scheduling += [ALAPSchedule(instruction_durations)]
        elif scheduling_method in {'asap', 'as_soon_as_possible'}:
            _scheduling += [ASAPSchedule(instruction_durations)]
        else:
            raise TranspilerError("Invalid scheduling method %s." %
                                  scheduling_method)

    # Build pass manager
    pm0 = PassManager()
    if coupling_map:
        pm0.append(_given_layout)
        pm0.append(_choose_layout, condition=_choose_layout_condition)
        pm0.append(_embed)
        pm0.append(_unroll3q)
        pm0.append(_swap_check)
        pm0.append(_swap, condition=_swap_condition)
    pm0.append(_unroll)
    if coupling_map and not coupling_map.is_symmetric:
        pm0.append(_direction_check)
        pm0.append(_direction, condition=_direction_condition)
    if scheduling_method:
        pm0.append(_scheduling)
    return pm0
예제 #26
0
def level_2_pass_manager(pass_manager_config: PassManagerConfig) -> PassManager:
    """Level 2 pass manager: medium optimization by initial layout selection and
    gate cancellation using commutativity rules.

    This pass manager applies the user-given initial layout. If none is given, a search
    for a perfect layout (i.e. one that satisfies all 2-qubit interactions) is conducted.
    If no such layout is found, qubits are laid out on the most densely connected subset
    which also exhibits the best gate fidelitites.

    The pass manager then transforms the circuit to match the coupling constraints.
    It is then unrolled to the basis, and any flipped cx directions are fixed.
    Finally, optimizations in the form of commutative gate cancellation and redundant
    reset removal are performed.

    Note:
        In simulators where ``coupling_map=None``, only the unrolling and
        optimization stages are done.

    Args:
        pass_manager_config: configuration of the pass manager.

    Returns:
        a level 2 pass manager.

    Raises:
        TranspilerError: if the passmanager config is invalid.
    """
    basis_gates = pass_manager_config.basis_gates
    coupling_map = pass_manager_config.coupling_map
    initial_layout = pass_manager_config.initial_layout
    layout_method = pass_manager_config.layout_method or 'dense'
    routing_method = pass_manager_config.routing_method or 'stochastic'
    translation_method = pass_manager_config.translation_method or 'translator'
    scheduling_method = pass_manager_config.scheduling_method
    instruction_durations = pass_manager_config.instruction_durations
    seed_transpiler = pass_manager_config.seed_transpiler
    backend_properties = pass_manager_config.backend_properties

    # 1. Search for a perfect layout, or choose a dense layout, if no layout given
    _given_layout = SetLayout(initial_layout)

    def _choose_layout_condition(property_set):
        return not property_set['layout']

    _choose_layout_1 = CSPLayout(coupling_map, call_limit=1000, time_limit=10)
    if layout_method == 'trivial':
        _choose_layout_2 = TrivialLayout(coupling_map)
    elif layout_method == 'dense':
        _choose_layout_2 = DenseLayout(coupling_map, backend_properties)
    elif layout_method == 'noise_adaptive':
        _choose_layout_2 = NoiseAdaptiveLayout(backend_properties)
    elif layout_method == 'sabre':
        _choose_layout_2 = SabreLayout(coupling_map, max_iterations=2, seed=seed_transpiler)
    else:
        raise TranspilerError("Invalid layout method %s." % layout_method)

    # 2. Extend dag/layout with ancillas using the full coupling map
    _embed = [FullAncillaAllocation(coupling_map), EnlargeWithAncilla(), ApplyLayout()]

    # 3. Unroll to 1q or 2q gates
    _unroll3q = Unroll3qOrMore()

    # 4. Swap to fit the coupling map
    _swap_check = CheckMap(coupling_map)

    def _swap_condition(property_set):
        return not property_set['is_swap_mapped']

    _swap = [BarrierBeforeFinalMeasurements()]
    if routing_method == 'basic':
        _swap += [BasicSwap(coupling_map)]
    elif routing_method == 'stochastic':
        _swap += [StochasticSwap(coupling_map, trials=20, seed=seed_transpiler)]
    elif routing_method == 'lookahead':
        _swap += [LookaheadSwap(coupling_map, search_depth=5, search_width=5)]
    elif routing_method == 'sabre':
        _swap += [SabreSwap(coupling_map, heuristic='decay', seed=seed_transpiler)]
    else:
        raise TranspilerError("Invalid routing method %s." % routing_method)

    # 5. Unroll to the basis
    if translation_method == 'unroller':
        _unroll = [Unroller(basis_gates)]
    elif translation_method == 'translator':
        from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel
        _unroll = [UnrollCustomDefinitions(sel, basis_gates),
                   BasisTranslator(sel, basis_gates)]
    elif translation_method == 'synthesis':
        _unroll = [
            Unroll3qOrMore(),
            Collect2qBlocks(),
            ConsolidateBlocks(basis_gates=basis_gates),
            UnitarySynthesis(basis_gates),
        ]
    else:
        raise TranspilerError("Invalid translation method %s." % translation_method)

    # 6. Fix any bad CX directions
    _direction_check = [CheckCXDirection(coupling_map)]

    def _direction_condition(property_set):
        return not property_set['is_direction_mapped']

    _direction = [CXDirection(coupling_map)]

    # 7. Remove zero-state reset
    _reset = RemoveResetInZeroState()

    # 8. 1q rotation merge and commutative cancellation iteratively until no more change in depth
    _depth_check = [Depth(), FixedPoint('depth')]

    def _opt_control(property_set):
        return not property_set['depth_fixed_point']

    _opt = [Optimize1qGates(basis_gates), CommutativeCancellation()]

    # 9. Schedule the circuit only when scheduling_method is supplied
    if scheduling_method:
        _scheduling = [TimeUnitAnalysis(instruction_durations)]
        if scheduling_method in {'alap', 'as_late_as_possible'}:
            _scheduling += [ALAPSchedule(instruction_durations)]
        elif scheduling_method in {'asap', 'as_soon_as_possible'}:
            _scheduling += [ASAPSchedule(instruction_durations)]
        else:
            raise TranspilerError("Invalid scheduling method %s." % scheduling_method)

    # Build pass manager
    pm2 = PassManager()
    if coupling_map:
        pm2.append(_given_layout)
        pm2.append(_choose_layout_1, condition=_choose_layout_condition)
        pm2.append(_choose_layout_2, condition=_choose_layout_condition)
        pm2.append(_embed)
        pm2.append(_unroll3q)
        pm2.append(_swap_check)
        pm2.append(_swap, condition=_swap_condition)
    pm2.append(_unroll)
    if coupling_map and not coupling_map.is_symmetric:
        pm2.append(_direction_check)
        pm2.append(_direction, condition=_direction_condition)
    pm2.append(_reset)
    pm2.append(_depth_check + _opt, do_while=_opt_control)
    if scheduling_method:
        pm2.append(_scheduling)

    return pm2
예제 #27
0
def level_3_pass_manager(
        pass_manager_config: PassManagerConfig) -> PassManager:
    """Level 3 pass manager: heavy optimization by noise adaptive qubit mapping and
    gate cancellation using commutativity rules and unitary synthesis.

    This pass manager applies the user-given initial layout. If none is given, a search
    for a perfect layout (i.e. one that satisfies all 2-qubit interactions) is conducted.
    If no such layout is found, and device calibration information is available, the
    circuit is mapped to the qubits with best readouts and to CX gates with highest fidelity.

    The pass manager then transforms the circuit to match the coupling constraints.
    It is then unrolled to the basis, and any flipped cx directions are fixed.
    Finally, optimizations in the form of commutative gate cancellation, resynthesis
    of two-qubit unitary blocks, and redundant reset removal are performed.

    Note:
        In simulators where ``coupling_map=None``, only the unrolling and
        optimization stages are done.

    Args:
        pass_manager_config: configuration of the pass manager.

    Returns:
        a level 3 pass manager.

    Raises:
        TranspilerError: if the passmanager config is invalid.
    """
    basis_gates = pass_manager_config.basis_gates
    coupling_map = pass_manager_config.coupling_map
    initial_layout = pass_manager_config.initial_layout
    layout_method = pass_manager_config.layout_method or 'dense'
    routing_method = pass_manager_config.routing_method or 'stochastic'
    translation_method = pass_manager_config.translation_method or 'translator'
    scheduling_method = pass_manager_config.scheduling_method
    instruction_durations = pass_manager_config.instruction_durations
    seed_transpiler = pass_manager_config.seed_transpiler
    backend_properties = pass_manager_config.backend_properties

    # 1. Unroll to 1q or 2q gates
    _unroll3q = Unroll3qOrMore()

    # 2. Layout on good qubits if calibration info available, otherwise on dense links
    _given_layout = SetLayout(initial_layout)

    def _choose_layout_condition(property_set):
        return not property_set['layout']

    _choose_layout_1 = [] if pass_manager_config.layout_method \
        else CSPLayout(coupling_map, call_limit=10000, time_limit=60, seed=seed_transpiler)
    if layout_method == 'trivial':
        _choose_layout_2 = TrivialLayout(coupling_map)
    elif layout_method == 'dense':
        _choose_layout_2 = DenseLayout(coupling_map, backend_properties)
    elif layout_method == 'noise_adaptive':
        _choose_layout_2 = NoiseAdaptiveLayout(backend_properties)
    elif layout_method == 'sabre':
        _choose_layout_2 = SabreLayout(coupling_map,
                                       max_iterations=4,
                                       seed=seed_transpiler)
    else:
        raise TranspilerError("Invalid layout method %s." % layout_method)

    # 3. Extend dag/layout with ancillas using the full coupling map
    _embed = [
        FullAncillaAllocation(coupling_map),
        EnlargeWithAncilla(),
        ApplyLayout()
    ]

    # 4. Swap to fit the coupling map
    _swap_check = CheckMap(coupling_map)

    def _swap_condition(property_set):
        return not property_set['is_swap_mapped']

    _swap = [BarrierBeforeFinalMeasurements()]
    if routing_method == 'basic':
        _swap += [BasicSwap(coupling_map)]
    elif routing_method == 'stochastic':
        _swap += [
            StochasticSwap(coupling_map, trials=200, seed=seed_transpiler)
        ]
    elif routing_method == 'lookahead':
        _swap += [LookaheadSwap(coupling_map, search_depth=5, search_width=6)]
    elif routing_method == 'sabre':
        _swap += [
            SabreSwap(coupling_map, heuristic='decay', seed=seed_transpiler)
        ]
    elif routing_method == 'none':
        _swap += [
            Error(
                msg=
                'No routing method selected, but circuit is not routed to device. '
                'CheckMap Error: {check_map_msg}',
                action='raise')
        ]
    else:
        raise TranspilerError("Invalid routing method %s." % routing_method)

    # 5. Unroll to the basis
    if translation_method == 'unroller':
        _unroll = [Unroller(basis_gates)]
    elif translation_method == 'translator':
        from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel
        _unroll = [
            UnrollCustomDefinitions(sel, basis_gates),
            BasisTranslator(sel, basis_gates)
        ]
    elif translation_method == 'synthesis':
        _unroll = [
            Unroll3qOrMore(),
            Collect2qBlocks(),
            ConsolidateBlocks(basis_gates=basis_gates),
            UnitarySynthesis(basis_gates),
        ]
    else:
        raise TranspilerError("Invalid translation method %s." %
                              translation_method)

    # 6. Fix any CX direction mismatch
    _direction_check = [CheckCXDirection(coupling_map)]

    def _direction_condition(property_set):
        return not property_set['is_direction_mapped']

    _direction = [CXDirection(coupling_map)]

    # 8. Optimize iteratively until no more change in depth. Removes useless gates
    # after reset and before measure, commutes gates and optimizes contiguous blocks.
    _depth_check = [Depth(), FixedPoint('depth')]

    def _opt_control(property_set):
        return not property_set['depth_fixed_point']

    _reset = [RemoveResetInZeroState()]

    _meas = [OptimizeSwapBeforeMeasure(), RemoveDiagonalGatesBeforeMeasure()]

    _opt = [
        Collect2qBlocks(),
        ConsolidateBlocks(basis_gates=basis_gates),
        UnitarySynthesis(basis_gates),
        Optimize1qGatesDecomposition(basis_gates),
        CommutativeCancellation(),
    ]

    # Schedule the circuit only when scheduling_method is supplied
    if scheduling_method:
        _scheduling = [TimeUnitAnalysis(instruction_durations)]
        if scheduling_method in {'alap', 'as_late_as_possible'}:
            _scheduling += [ALAPSchedule(instruction_durations)]
        elif scheduling_method in {'asap', 'as_soon_as_possible'}:
            _scheduling += [ASAPSchedule(instruction_durations)]
        else:
            raise TranspilerError("Invalid scheduling method %s." %
                                  scheduling_method)

    # Build pass manager
    pm3 = PassManager()
    pm3.append(_unroll3q)
    pm3.append(_reset + _meas)
    if coupling_map or initial_layout:
        pm3.append(_given_layout)
        pm3.append(_choose_layout_1, condition=_choose_layout_condition)
        pm3.append(_choose_layout_2, condition=_choose_layout_condition)
        pm3.append(_embed)
        pm3.append(_swap_check)
        pm3.append(_swap, condition=_swap_condition)
    pm3.append(_unroll)
    pm3.append(_depth_check + _opt + _unroll, do_while=_opt_control)
    if coupling_map and not coupling_map.is_symmetric:
        pm3.append(_direction_check)
        pm3.append(_direction, condition=_direction_condition)
    pm3.append(_reset)
    if scheduling_method:
        pm3.append(_scheduling)

    return pm3
예제 #28
0
def noise_pass_manager(basis_gates=None,
                       initial_layout=None,
                       coupling_map=None,
                       layout_method=None,
                       translation_method=None,
                       seed_transpiler=None,
                       backend=None,
                       routing_method=None,
                       backend_properties=None,
                       transform=False,
                       readout=True,
                       alpha=0.5,
                       next_gates=5,
                       front=True) -> PassManager:
    """Level 3 pass manager: heavy optimization by noise adaptive qubit mapping and
    gate cancellation using commutativity rules and unitary synthesis.

    This pass manager applies the user-given initial layout. If none is given, a search
    for a perfect layout (i.e. one that satisfies all 2-qubit interactions) is conducted.
    If no such layout is found, and device calibration information is available, the
    circuit is mapped to the qubits with best readouts and to CX gates with highest fidelity.

    The pass manager then transforms the circuit to match the coupling constraints.
    It is then unrolled to the basis, and any flipped cx directions are fixed.
    Finally, optimizations in the form of commutative gate cancellation, resynthesis
    of two-qubit unitary blocks, and redundant reset removal are performed.

    Note:
        In simulators where ``coupling_map=None``, only the unrolling and
        optimization stages are done.

    Args:
        backend (BaseBackend)

    Returns:
        a level 3 pass manager.

    Raises:
        TranspilerError: if the passmanager config is invalid.
    """
    if basis_gates is None:
        if getattr(backend, 'configuration', None):
            basis_gates = getattr(backend.configuration(), 'basis_gates', None)
        # basis_gates could be None, or a list of basis, e.g. ['u3', 'cx']
    if isinstance(basis_gates, list) and all(
            isinstance(i, str) for i in basis_gates):
        basis_gates = basis_gates
    if basis_gates is None:
        basis_gates = ['u3', 'cx', 'id']
    # basis_gates = ['u3', 'cx', 'id']
    backend = backend
    if backend is None or backend.configuration().simulator:
        if backend_properties is None or coupling_map is None:
            raise QiskitError(
                "Backend is simulator or not specified, provide backend properties and coupling map."
            )
        coupling_map = coupling_map
        backend_properties = backend_properties
    else:
        if backend_properties is not None or coupling_map is not None:
            warnings.warn(
                "A backend was provide, ignoring backend properties and coupling map",
                UserWarning)
        coupling_map = backend.configuration().coupling_map
        backend_properties = backend.properties()

    if isinstance(coupling_map, list):
        coupling_map = CouplingMap(couplinglist=coupling_map)

    initial_layout = initial_layout
    layout_method = layout_method or 'dense'
    routing_method = routing_method or 'stochastic'
    translation_method = translation_method or 'translator'
    seed_transpiler = seed_transpiler

    # 1. Unroll to 1q or 2q gates
    _unroll3q = Unroll3qOrMore()

    # 2. Layout on good qubits if calibration info available, otherwise on dense links
    _given_layout = SetLayout(initial_layout)

    def _choose_layout_condition(property_set):
        return not property_set['layout']

    _choose_layout_1 = CSPLayout(coupling_map, call_limit=10000, time_limit=60)
    if layout_method == 'trivial':
        _choose_layout_2 = TrivialLayout(coupling_map)
    elif layout_method == 'dense':
        _choose_layout_2 = DenseLayout(coupling_map, backend_properties)
    elif layout_method == 'noise_adaptive':
        _choose_layout_2 = NoiseAdaptiveLayout(backend_properties)
    elif layout_method == 'sabre':
        _choose_layout_2 = SabreLayout(coupling_map,
                                       max_iterations=4,
                                       seed=seed_transpiler)
    elif layout_method == 'chain':
        _choose_layout_2 = ChainLayout(coupling_map,
                                       backend_properties,
                                       readout=readout)
    else:
        raise TranspilerError("Invalid layout method %s." % layout_method)

    # 3. Extend dag/layout with ancillas using the full coupling map
    _embed = [
        FullAncillaAllocation(coupling_map),
        EnlargeWithAncilla(),
        ApplyLayout()
    ]

    # 4. Swap to fit the coupling map
    _swap_check = CheckMap(coupling_map)

    def _swap_condition(property_set):
        return not property_set['is_swap_mapped']

    _swap = [BarrierBeforeFinalMeasurements()]
    if routing_method == 'basic':
        _swap += [BasicSwap(coupling_map)]
    elif routing_method == 'stochastic':
        _swap += [
            StochasticSwap(coupling_map, trials=200, seed=seed_transpiler)
        ]
    elif routing_method == 'lookahead':
        _swap += [LookaheadSwap(coupling_map, search_depth=5, search_width=6)]
    elif routing_method == 'sabre':
        _swap += [
            SabreSwap(coupling_map, heuristic='decay', seed=seed_transpiler)
        ]
    elif routing_method == 'noise_adaptive':
        _swap += [
            NoiseAdaptiveSwap(coupling_map,
                              backend_properties,
                              invert_score=invert_score,
                              swap_score=swap_score,
                              readout=readout,
                              alpha=alpha,
                              next_gates=next_gates,
                              front=front)
        ]
    else:
        raise TranspilerError("Invalid routing method %s." % routing_method)

    # 5. Unroll to the basis
    if translation_method == 'unroller':
        _unroll = [Unroller(basis_gates)]
    elif translation_method == 'translator':
        from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel
        _unroll = [
            UnrollCustomDefinitions(sel, basis_gates),
            BasisTranslator(sel, basis_gates)
        ]
    elif translation_method == 'synthesis':
        _unroll = [
            Unroll3qOrMore(),
            Collect2qBlocks(),
            ConsolidateBlocks(basis_gates=basis_gates),
            UnitarySynthesis(basis_gates),
        ]
    else:
        raise TranspilerError("Invalid translation method %s." %
                              translation_method)

    # 6. Fix any CX direction mismatch
    _direction_check = [CheckCXDirection(coupling_map)]

    def _direction_condition(property_set):
        return not property_set['is_direction_mapped']

    _direction = [CXDirection(coupling_map)]

    # 8. Optimize iteratively until no more change in depth. Removes useless gates
    # after reset and before measure, commutes gates and optimizes continguous blocks.
    _depth_check = [Depth(), FixedPoint('depth')]

    def _opt_control(property_set):
        return not property_set['depth_fixed_point']

    _reset = [RemoveResetInZeroState()]

    _meas = [OptimizeSwapBeforeMeasure(), RemoveDiagonalGatesBeforeMeasure()]

    _opt = [
        Collect2qBlocks(),
        ConsolidateBlocks(basis_gates=basis_gates),
        UnitarySynthesis(basis_gates),
        Optimize1qGates(basis_gates),
        CommutativeCancellation(),
    ]

    # Build pass manager
    pm3 = PassManager()
    pm3.append(_unroll3q)
    if transform:
        _transform = TransformCxCascade()
        pm3.append(_transform)
    pm3.append(_reset + _meas)
    if coupling_map:
        pm3.append(_given_layout)
        pm3.append(_choose_layout_1, condition=_choose_layout_condition)
        pm3.append(_choose_layout_2, condition=_choose_layout_condition)
        pm3.append(_embed)
        pm3.append(_swap_check)
        pm3.append(_swap, condition=_swap_condition)
    pm3.append(_unroll)
    pm3.append(_depth_check + _opt + _unroll, do_while=_opt_control)
    if coupling_map and not coupling_map.is_symmetric:
        pm3.append(_direction_check)
        pm3.append(_direction, condition=_direction_condition)
    pm3.append(_reset)

    return pm3
예제 #29
0
def level_1_pass_manager(
        pass_manager_config: PassManagerConfig) -> PassManager:
    """Level 1 pass manager: light optimization by simple adjacent gate collapsing.

    This pass manager applies the user-given initial layout. If none is given,
    and a trivial layout (i-th virtual -> i-th physical) makes the circuit fit
    the coupling map, that is used.
    Otherwise, the circuit is mapped to the most densely connected coupling subgraph,
    and swaps are inserted to map. Any unused physical qubit is allocated as ancilla space.
    The pass manager then unrolls the circuit to the desired basis, and transforms the
    circuit to match the coupling map. Finally, optimizations in the form of adjacent
    gate collapse and redundant reset removal are performed.

    Note:
        In simulators where ``coupling_map=None``, only the unrolling and
        optimization stages are done.

    Args:
        pass_manager_config: configuration of the pass manager.

    Returns:
        a level 1 pass manager.

    Raises:
        TranspilerError: if the passmanager config is invalid.
    """
    basis_gates = pass_manager_config.basis_gates
    coupling_map = pass_manager_config.coupling_map
    initial_layout = pass_manager_config.initial_layout
    layout_method = pass_manager_config.layout_method or 'dense'
    routing_method = pass_manager_config.routing_method or 'stochastic'
    seed_transpiler = pass_manager_config.seed_transpiler
    backend_properties = pass_manager_config.backend_properties

    # 1. Use trivial layout if no layout given
    _given_layout = SetLayout(initial_layout)

    _choose_layout_and_score = [
        TrivialLayout(coupling_map),
        Layout2qDistance(coupling_map, property_name='trivial_layout_score')
    ]

    def _choose_layout_condition(property_set):
        return not property_set['layout']

    # 2. Use a better layout on densely connected qubits, if circuit needs swaps
    if layout_method == 'trivial':
        _improve_layout = TrivialLayout(coupling_map)
    elif layout_method == 'dense':
        _improve_layout = DenseLayout(coupling_map, backend_properties)
    elif layout_method == 'noise_adaptive':
        _improve_layout = NoiseAdaptiveLayout(backend_properties)
    else:
        raise TranspilerError("Invalid layout method %s." % layout_method)

    def _not_perfect_yet(property_set):
        return property_set['trivial_layout_score'] is not None and \
               property_set['trivial_layout_score'] != 0

    # 3. Extend dag/layout with ancillas using the full coupling map
    _embed = [
        FullAncillaAllocation(coupling_map),
        EnlargeWithAncilla(),
        ApplyLayout()
    ]

    # 4. Decompose so only 1-qubit and 2-qubit gates remain
    _unroll3q = Unroll3qOrMore()

    # 5. Swap to fit the coupling map
    _swap_check = CheckMap(coupling_map)

    def _swap_condition(property_set):
        return not property_set['is_swap_mapped']

    _swap = [BarrierBeforeFinalMeasurements()]
    if routing_method == 'basic':
        _swap += [BasicSwap(coupling_map)]
    elif routing_method == 'stochastic':
        _swap += [
            StochasticSwap(coupling_map, trials=20, seed=seed_transpiler)
        ]
    elif routing_method == 'lookahead':
        _swap += [LookaheadSwap(coupling_map, search_depth=4, search_width=4)]
    else:
        raise TranspilerError("Invalid routing method %s." % routing_method)

    # 6. Unroll to the basis
    _unroll = Unroller(basis_gates)

    # 7. Fix any bad CX directions
    _direction_check = [CheckCXDirection(coupling_map)]

    def _direction_condition(property_set):
        return not property_set['is_direction_mapped']

    _direction = [CXDirection(coupling_map)]

    # 8. Remove zero-state reset
    _reset = RemoveResetInZeroState()

    # 9. Merge 1q rotations and cancel CNOT gates iteratively until no more change in depth
    _depth_check = [Depth(), FixedPoint('depth')]

    def _opt_control(property_set):
        return not property_set['depth_fixed_point']

    _opt = [Optimize1qGates(basis_gates), CXCancellation()]

    # Build pass manager
    pm1 = PassManager()
    if coupling_map:
        pm1.append(_given_layout)
        pm1.append(_choose_layout_and_score,
                   condition=_choose_layout_condition)
        pm1.append(_improve_layout, condition=_not_perfect_yet)
        pm1.append(_embed)
        pm1.append(_unroll3q)
        pm1.append(_swap_check)
        pm1.append(_swap, condition=_swap_condition)
    pm1.append(_unroll)
    if coupling_map and not coupling_map.is_symmetric:
        pm1.append(_direction_check)
        pm1.append(_direction, condition=_direction_condition)
    pm1.append(_reset)
    pm1.append(_depth_check + _opt, do_while=_opt_control)

    return pm1
예제 #30
0
class TestTranspile(QiskitTestCase):
    """Test transpile function."""

    barrier_pass = BarrierBeforeFinalMeasurements()

    def test_pass_manager_none(self):
        """Test passing the default (None) pass manager to the transpiler.

        It should perform the default qiskit flow:
        unroll, swap_mapper, cx_direction, cx_cancellation, optimize_1q_gates
        and should be equivalent to using tools.compile
        """
        qr = QuantumRegister(2, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.h(qr[0])
        circuit.h(qr[0])
        circuit.cx(qr[0], qr[1])
        circuit.cx(qr[1], qr[0])
        circuit.cx(qr[0], qr[1])
        circuit.cx(qr[1], qr[0])

        coupling_map = [[1, 0]]
        basis_gates = ['u1', 'u2', 'u3', 'cx', 'id']

        backend = BasicAer.get_backend('qasm_simulator')
        circuit2 = transpile(circuit, backend=backend, coupling_map=coupling_map,
                             basis_gates=basis_gates, pass_manager=None)

        circuit3 = transpile(circuit, backend=backend, coupling_map=coupling_map,
                             basis_gates=basis_gates)
        self.assertEqual(circuit2, circuit3)

    def test_transpile_basis_gates_no_backend_no_coupling_map(self):
        """Verify transpile() works with no coupling_map or backend."""
        qr = QuantumRegister(2, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.h(qr[0])
        circuit.h(qr[0])
        circuit.cx(qr[0], qr[1])
        circuit.cx(qr[0], qr[1])
        circuit.cx(qr[0], qr[1])
        circuit.cx(qr[0], qr[1])

        basis_gates = ['u1', 'u2', 'u3', 'cx', 'id']
        circuit2 = transpile(circuit, basis_gates=basis_gates)
        dag_circuit = circuit_to_dag(circuit2)
        resources_after = dag_circuit.count_ops()
        self.assertEqual({'u2': 2, 'cx': 4}, resources_after)

    def test_transpile_non_adjacent_layout(self):
        """Transpile pipeline can handle manual layout on non-adjacent qubits.

        circuit:
        qr0:-[H]--.------------  -> 1
                  |
        qr1:-----(+)--.--------  -> 2
                      |
        qr2:---------(+)--.----  -> 3
                          |
        qr3:-------------(+)---  -> 5

        device:
        0  -  1  -  2  -  3  -  4  -  5  -  6

              |     |     |     |     |     |

              13 -  12  - 11 -  10 -  9  -  8  -   7
        """
        qr = QuantumRegister(4, 'qr')
        circuit = QuantumCircuit(qr)
        circuit.h(qr[0])
        circuit.cx(qr[0], qr[1])
        circuit.cx(qr[1], qr[2])
        circuit.cx(qr[2], qr[3])

        coupling_map = FakeMelbourne().configuration().coupling_map
        basis_gates = FakeMelbourne().configuration().basis_gates
        initial_layout = [None, qr[0], qr[1], qr[2], None, qr[3]]

        new_circuit = transpile(circuit,
                                basis_gates=basis_gates,
                                coupling_map=coupling_map,
                                initial_layout=initial_layout)

        for gate, qargs, _ in new_circuit.data:
            if isinstance(gate, CnotGate):
                self.assertIn([x[1] for x in qargs], coupling_map)

    def test_transpile_qft_grid(self):
        """Transpile pipeline can handle 8-qubit QFT on 14-qubit grid.
        """
        qr = QuantumRegister(8)
        circuit = QuantumCircuit(qr)
        for i, _ in enumerate(qr):
            for j in range(i):
                circuit.cu1(math.pi / float(2 ** (i - j)), qr[i], qr[j])
            circuit.h(qr[i])

        coupling_map = FakeMelbourne().configuration().coupling_map
        basis_gates = FakeMelbourne().configuration().basis_gates
        new_circuit = transpile(circuit,
                                basis_gates=basis_gates,
                                coupling_map=coupling_map)

        for gate, qargs, _ in new_circuit.data:
            if isinstance(gate, CnotGate):
                self.assertIn([x[1] for x in qargs], coupling_map)

    def test_already_mapped_1(self):
        """Circuit not remapped if matches topology.

        See: https://github.com/Qiskit/qiskit-terra/issues/342
        """
        backend = FakeRueschlikon()
        coupling_map = backend.configuration().coupling_map
        basis_gates = backend.configuration().basis_gates

        qr = QuantumRegister(16, 'qr')
        cr = ClassicalRegister(16, 'cr')
        qc = QuantumCircuit(qr, cr)
        qc.cx(qr[3], qr[14])
        qc.cx(qr[5], qr[4])
        qc.h(qr[9])
        qc.cx(qr[9], qr[8])
        qc.x(qr[11])
        qc.cx(qr[3], qr[4])
        qc.cx(qr[12], qr[11])
        qc.cx(qr[13], qr[4])
        qc.measure(qr, cr)

        new_qc = transpile(qc, coupling_map=coupling_map, basis_gates=basis_gates)
        cx_qubits = [qargs for (gate, qargs, _) in new_qc.data
                     if gate.name == "cx"]
        cx_qubits_physical = [[ctrl[1], tgt[1]] for [ctrl, tgt] in cx_qubits]
        self.assertEqual(sorted(cx_qubits_physical),
                         [[3, 4], [3, 14], [5, 4], [9, 8], [12, 11], [13, 4]])

    def test_already_mapped_via_layout(self):
        """Test that a manual layout that satisfies a coupling map does not get altered.

        See: https://github.com/Qiskit/qiskit-terra/issues/2036
        """
        basis_gates = ['u1', 'u2', 'u3', 'cx', 'id']
        coupling_map = [[0, 1], [0, 5], [1, 0], [1, 2], [2, 1], [2, 3],
                        [3, 2], [3, 4], [4, 3], [4, 9], [5, 0], [5, 6],
                        [5, 10], [6, 5], [6, 7], [7, 6], [7, 8], [7, 12],
                        [8, 7], [8, 9], [9, 4], [9, 8], [9, 14], [10, 5],
                        [10, 11], [10, 15], [11, 10], [11, 12], [12, 7],
                        [12, 11], [12, 13], [13, 12], [13, 14], [14, 9],
                        [14, 13], [14, 19], [15, 10], [15, 16], [16, 15],
                        [16, 17], [17, 16], [17, 18], [18, 17], [18, 19],
                        [19, 14], [19, 18]]

        q = QuantumRegister(6, name='qn')
        c = ClassicalRegister(2, name='cn')
        qc = QuantumCircuit(q, c)
        qc.h(q[0])
        qc.h(q[5])
        qc.cx(q[0], q[5])
        qc.u1(2, q[5])
        qc.cx(q[0], q[5])
        qc.h(q[0])
        qc.h(q[5])
        qc.barrier(q)
        qc.measure(q[0], c[0])
        qc.measure(q[5], c[1])

        initial_layout = [q[3], q[4], None, None, q[5], q[2], q[1], None, None, q[0],
                          None, None, None, None, None, None, None, None, None, None]

        new_qc = transpile(qc, coupling_map=coupling_map,
                           basis_gates=basis_gates, initial_layout=initial_layout)
        cx_qubits = [qargs for (gate, qargs, _) in new_qc.data
                     if gate.name == "cx"]
        cx_qubits_physical = [[ctrl[1], tgt[1]] for [ctrl, tgt] in cx_qubits]
        self.assertEqual(sorted(cx_qubits_physical),
                         [[9, 4], [9, 4]])

    def test_transpile_bell(self):
        """Test Transpile Bell.

        If all correct some should exists.
        """
        backend = BasicAer.get_backend('qasm_simulator')

        qubit_reg = QuantumRegister(2, name='q')
        clbit_reg = ClassicalRegister(2, name='c')
        qc = QuantumCircuit(qubit_reg, clbit_reg, name="bell")
        qc.h(qubit_reg[0])
        qc.cx(qubit_reg[0], qubit_reg[1])
        qc.measure(qubit_reg, clbit_reg)

        circuits = transpile(qc, backend)
        self.assertIsInstance(circuits, QuantumCircuit)

    def test_transpile_two(self):
        """Test transpile to circuits.

        If all correct some should exists.
        """
        backend = BasicAer.get_backend('qasm_simulator')

        qubit_reg = QuantumRegister(2)
        clbit_reg = ClassicalRegister(2)
        qubit_reg2 = QuantumRegister(2)
        clbit_reg2 = ClassicalRegister(2)
        qc = QuantumCircuit(qubit_reg, clbit_reg, name="bell")
        qc.h(qubit_reg[0])
        qc.cx(qubit_reg[0], qubit_reg[1])
        qc.measure(qubit_reg, clbit_reg)
        qc_extra = QuantumCircuit(qubit_reg, qubit_reg2, clbit_reg, clbit_reg2, name="extra")
        qc_extra.measure(qubit_reg, clbit_reg)
        circuits = transpile([qc, qc_extra], backend)
        self.assertIsInstance(circuits[0], QuantumCircuit)
        self.assertIsInstance(circuits[1], QuantumCircuit)

    def test_mapping_correction(self):
        """Test mapping works in previous failed case.
        """
        backend = FakeRueschlikon()
        qr = QuantumRegister(name='qr', size=11)
        cr = ClassicalRegister(name='qc', size=11)
        circuit = QuantumCircuit(qr, cr)
        circuit.u3(1.564784764685993, -1.2378965763410095, 2.9746763177861713, qr[3])
        circuit.u3(1.2269835563676523, 1.1932982847014162, -1.5597357740824318, qr[5])
        circuit.cx(qr[5], qr[3])
        circuit.u1(0.856768317675967, qr[3])
        circuit.u3(-3.3911273825190915, 0.0, 0.0, qr[5])
        circuit.cx(qr[3], qr[5])
        circuit.u3(2.159209321625547, 0.0, 0.0, qr[5])
        circuit.cx(qr[5], qr[3])
        circuit.u3(0.30949966910232335, 1.1706201763833217, 1.738408691990081, qr[3])
        circuit.u3(1.9630571407274755, -0.6818742967975088, 1.8336534616728195, qr[5])
        circuit.u3(1.330181833806101, 0.6003162754946363, -3.181264980452862, qr[7])
        circuit.u3(0.4885914820775024, 3.133297443244865, -2.794457469189904, qr[8])
        circuit.cx(qr[8], qr[7])
        circuit.u1(2.2196187596178616, qr[7])
        circuit.u3(-3.152367609631023, 0.0, 0.0, qr[8])
        circuit.cx(qr[7], qr[8])
        circuit.u3(1.2646005789809263, 0.0, 0.0, qr[8])
        circuit.cx(qr[8], qr[7])
        circuit.u3(0.7517780502091939, 1.2828514296564781, 1.6781179605443775, qr[7])
        circuit.u3(0.9267400575390405, 2.0526277839695153, 2.034202361069533, qr[8])
        circuit.u3(2.550304293455634, 3.8250017126569698, -2.1351609599720054, qr[1])
        circuit.u3(0.9566260876600556, -1.1147561503064538, 2.0571590492298797, qr[4])
        circuit.cx(qr[4], qr[1])
        circuit.u1(2.1899329069137394, qr[1])
        circuit.u3(-1.8371715243173294, 0.0, 0.0, qr[4])
        circuit.cx(qr[1], qr[4])
        circuit.u3(0.4717053496327104, 0.0, 0.0, qr[4])
        circuit.cx(qr[4], qr[1])
        circuit.u3(2.3167620677708145, -1.2337330260253256, -0.5671322899563955, qr[1])
        circuit.u3(1.0468499525240678, 0.8680750644809365, -1.4083720073192485, qr[4])
        circuit.u3(2.4204244021892807, -2.211701932616922, 3.8297006565735883, qr[10])
        circuit.u3(0.36660280497727255, 3.273119149343493, -1.8003362351299388, qr[6])
        circuit.cx(qr[6], qr[10])
        circuit.u1(1.067395863586385, qr[10])
        circuit.u3(-0.7044917541291232, 0.0, 0.0, qr[6])
        circuit.cx(qr[10], qr[6])
        circuit.u3(2.1830003849921527, 0.0, 0.0, qr[6])
        circuit.cx(qr[6], qr[10])
        circuit.u3(2.1538343756723917, 2.2653381826084606, -3.550087952059485, qr[10])
        circuit.u3(1.307627685019188, -0.44686656993522567, -2.3238098554327418, qr[6])
        circuit.u3(2.2046797998462906, 0.9732961754855436, 1.8527865921467421, qr[9])
        circuit.u3(2.1665254613904126, -1.281337664694577, -1.2424905413631209, qr[0])
        circuit.cx(qr[0], qr[9])
        circuit.u1(2.6209599970201007, qr[9])
        circuit.u3(0.04680566321901303, 0.0, 0.0, qr[0])
        circuit.cx(qr[9], qr[0])
        circuit.u3(1.7728411151289603, 0.0, 0.0, qr[0])
        circuit.cx(qr[0], qr[9])
        circuit.u3(2.4866395967434443, 0.48684511243566697, -3.0069186877854728, qr[9])
        circuit.u3(1.7369112924273789, -4.239660866163805, 1.0623389015296005, qr[0])
        circuit.barrier(qr)
        circuit.measure(qr, cr)

        circuits = transpile(circuit, backend)

        self.assertIsInstance(circuits, QuantumCircuit)

    def test_transpiler_layout_from_intlist(self):
        """A list of ints gives layout to correctly map circuit.
        virtual  physical
         q1_0  -  4   ---[H]---
         q2_0  -  5
         q2_1  -  6   ---[H]---
         q3_0  -  8
         q3_1  -  9
         q3_2  -  10  ---[H]---

        """
        qr1 = QuantumRegister(1, 'qr1')
        qr2 = QuantumRegister(2, 'qr2')
        qr3 = QuantumRegister(3, 'qr3')
        qc = QuantumCircuit(qr1, qr2, qr3)
        qc.h(qr1[0])
        qc.h(qr2[1])
        qc.h(qr3[2])
        layout = [4, 5, 6, 8, 9, 10]

        cmap = [[1, 0], [1, 2], [2, 3], [4, 3], [4, 10],
                [5, 4], [5, 6], [5, 9], [6, 8], [7, 8],
                [9, 8], [9, 10], [11, 3], [11, 10],
                [11, 12], [12, 2], [13, 1], [13, 12]]

        new_circ = transpile(qc, backend=None,
                             coupling_map=cmap,
                             basis_gates=['u2'],
                             initial_layout=layout)
        mapped_qubits = []
        for _, qargs, _ in new_circ.data:
            mapped_qubits.append(qargs[0][1])

        self.assertEqual(mapped_qubits, [4, 6, 10])

    def test_mapping_multi_qreg(self):
        """Test mapping works for multiple qregs.
        """
        backend = FakeRueschlikon()
        qr = QuantumRegister(3, name='qr')
        qr2 = QuantumRegister(1, name='qr2')
        qr3 = QuantumRegister(4, name='qr3')
        cr = ClassicalRegister(3, name='cr')
        qc = QuantumCircuit(qr, qr2, qr3, cr)
        qc.h(qr[0])
        qc.cx(qr[0], qr2[0])
        qc.cx(qr[1], qr3[2])
        qc.measure(qr, cr)

        circuits = transpile(qc, backend)

        self.assertIsInstance(circuits, QuantumCircuit)

    def test_transpile_circuits_diff_registers(self):
        """Transpile list of circuits with different qreg names.
        """
        backend = FakeRueschlikon()
        circuits = []
        for _ in range(2):
            qr = QuantumRegister(2)
            cr = ClassicalRegister(2)
            circuit = QuantumCircuit(qr, cr)
            circuit.h(qr[0])
            circuit.cx(qr[0], qr[1])
            circuit.measure(qr, cr)
            circuits.append(circuit)

        circuits = transpile(circuits, backend)
        self.assertIsInstance(circuits[0], QuantumCircuit)

    def test_wrong_initial_layout(self):
        """Test transpile with a bad initial layout.
        """
        backend = FakeMelbourne()

        qubit_reg = QuantumRegister(2, name='q')
        clbit_reg = ClassicalRegister(2, name='c')
        qc = QuantumCircuit(qubit_reg, clbit_reg, name="bell")
        qc.h(qubit_reg[0])
        qc.cx(qubit_reg[0], qubit_reg[1])
        qc.measure(qubit_reg, clbit_reg)

        bad_initial_layout = [(QuantumRegister(3, 'q'), 0),
                              (QuantumRegister(3, 'q'), 1),
                              (QuantumRegister(3, 'q'), 2)]

        self.assertRaises(KeyError, transpile,
                          qc, backend, initial_layout=bad_initial_layout)

    def test_parameterized_circuit_for_simulator(self):
        """Verify that a parameterized circuit can be transpiled for a simulator backend."""
        qr = QuantumRegister(2, name='qr')
        qc = QuantumCircuit(qr)

        theta = Parameter('theta')
        qc.rz(theta, qr[0])

        transpiled_qc = transpile(qc, backend=BasicAer.get_backend('qasm_simulator'))

        expected_qc = QuantumCircuit(qr)
        expected_qc.u1(theta, qr[0])

        self.assertEqual(expected_qc, transpiled_qc)

    def test_parameterized_circuit_for_device(self):
        """Verify that a parameterized circuit can be transpiled for a device backend."""
        qr = QuantumRegister(2, name='qr')
        qc = QuantumCircuit(qr)

        theta = Parameter('theta')
        qc.rz(theta, qr[0])

        transpiled_qc = transpile(qc, backend=FakeMelbourne())

        qr = QuantumRegister(14, 'q')
        expected_qc = QuantumCircuit(qr)
        expected_qc.u1(theta, qr[0])

        self.assertEqual(expected_qc, transpiled_qc)

    @unittest.mock.patch.object(BarrierBeforeFinalMeasurements, 'run', wraps=barrier_pass.run)
    def test_final_measurement_barrier_for_devices(self, mock_pass):
        """Verify BarrierBeforeFinalMeasurements pass is called in default pipeline for devices."""

        circ = QuantumCircuit.from_qasm_file(self._get_resource_path('example.qasm', Path.QASMS))
        layout = Layout.generate_trivial_layout(*circ.qregs)
        transpile(circ, coupling_map=FakeRueschlikon().configuration().coupling_map,
                  initial_layout=layout)

        self.assertTrue(mock_pass.called)

    def test_do_not_run_cxdirection_with_symmetric_cm(self):
        """When the coupling map is symmetric, do not run CXDirection."""

        circ = QuantumCircuit.from_qasm_file(self._get_resource_path('example.qasm', Path.QASMS))
        layout = Layout.generate_trivial_layout(*circ.qregs)
        coupling_map = []
        for node1, node2 in FakeRueschlikon().configuration().coupling_map:
            coupling_map.append([node1, node2])
            coupling_map.append([node2, node1])

        cxdir_pass = CXDirection(CouplingMap(coupling_map))
        with unittest.mock.patch.object(CXDirection, 'run', wraps=cxdir_pass.run) as mock_pass:
            transpile(circ, coupling_map=coupling_map, initial_layout=layout)
            self.assertFalse(mock_pass.called)

    def test_optimize_to_nothing(self):
        """ Optimize gates up to fixed point in the default pipeline
        See https://github.com/Qiskit/qiskit-terra/issues/2035 """
        qr = QuantumRegister(2)
        circ = QuantumCircuit(qr)
        circ.h(qr[0])
        circ.cx(qr[0], qr[1])
        circ.x(qr[0])
        circ.y(qr[0])
        circ.z(qr[0])
        circ.cx(qr[0], qr[1])
        circ.h(qr[0])
        circ.cx(qr[0], qr[1])
        circ.cx(qr[0], qr[1])

        after = transpile(circ, coupling_map=[[0, 1], [1, 0]],
                          basis_gates=['u3', 'cx'])

        expected = QuantumCircuit(QuantumRegister(2, 'q'))
        self.assertEqual(after, expected)

    def test_pass_manager_empty(self):
        """Test passing an empty PassManager() to the transpiler.

        It should perform no transformations on the circuit.
        """
        qr = QuantumRegister(2)
        circuit = QuantumCircuit(qr)
        circuit.h(qr[0])
        circuit.h(qr[0])
        circuit.cx(qr[0], qr[1])
        circuit.cx(qr[0], qr[1])
        circuit.cx(qr[0], qr[1])
        circuit.cx(qr[0], qr[1])
        resources_before = circuit.count_ops()

        pass_manager = PassManager()
        out_circuit = transpile(circuit, pass_manager=pass_manager)
        resources_after = out_circuit.count_ops()

        self.assertDictEqual(resources_before, resources_after)

    def test_move_measurements(self):
        """Measurements applied AFTER swap mapping.
        """
        backend = FakeRueschlikon()
        cmap = backend.configuration().coupling_map
        circ = QuantumCircuit.from_qasm_file(
            self._get_resource_path('move_measurements.qasm', Path.QASMS))

        lay = [0, 1, 15, 2, 14, 3, 13, 4, 12, 5, 11, 6]
        out = transpile(circ, initial_layout=lay, coupling_map=cmap)
        out_dag = circuit_to_dag(out)
        meas_nodes = out_dag.named_nodes('measure')
        for meas_node in meas_nodes:
            is_last_measure = all([after_measure.type == 'out'
                                   for after_measure in out_dag.quantum_successors(meas_node)])
            self.assertTrue(is_last_measure)

    def test_initialize_reset_should_be_removed(self):
        """The reset in front of initializer should be removed when zero state"""
        qr = QuantumRegister(1, "qr")
        qc = QuantumCircuit(qr)
        qc.initialize([1.0 / math.sqrt(2), 1.0 / math.sqrt(2)], [qr[0]])
        qc.initialize([1.0 / math.sqrt(2), -1.0 / math.sqrt(2)], [qr[0]])

        expected = QuantumCircuit(qr)
        expected.u_base(1.5708, 0, 0, qr[0])
        expected.u_base(0, 0, 0, qr[0])
        expected.reset(qr[0])
        expected.u_base(1.5708, 0, 0, qr[0])
        expected.u_base(0, 0, 3.1416, qr[0])

        after = transpile(qc, basis_gates=['reset', 'U'])

        self.assertEqual(after, expected)

    def test_initialize_FakeMelbourne(self):
        """Test that the zero-state resets are remove in a device not supporting them.
        """
        desired_vector = [1 / math.sqrt(2), 0, 0, 0, 0, 0, 0, 1 / math.sqrt(2)]
        qr = QuantumRegister(3, "qr")
        qc = QuantumCircuit(qr)
        qc.initialize(desired_vector, [qr[0], qr[1], qr[2]])

        out = transpile(qc, backend=FakeMelbourne())
        out_dag = circuit_to_dag(out)
        reset_nodes = out_dag.named_nodes('reset')

        self.assertEqual(reset_nodes, [])

    def test_non_standard_basis(self):
        """Test a transpilation with a non-standard basis"""
        qr1 = QuantumRegister(1, 'q1')
        qr2 = QuantumRegister(2, 'q2')
        qr3 = QuantumRegister(3, 'q3')
        qc = QuantumCircuit(qr1, qr2, qr3)
        qc.h(qr1[0])
        qc.h(qr2[1])
        qc.h(qr3[2])
        layout = [4, 5, 6, 8, 9, 10]

        cmap = [[1, 0], [1, 2], [2, 3], [4, 3], [4, 10], [5, 4], [5, 6], [5, 9],
                [6, 8], [7, 8], [9, 8], [9, 10], [11, 3], [11, 10], [11, 12], [12, 2], [13, 1],
                [13, 12]]

        circuit = transpile(qc, backend=None, coupling_map=cmap,
                            basis_gates=['h'], initial_layout=layout)

        dag_circuit = circuit_to_dag(circuit)
        resources_after = dag_circuit.count_ops()
        self.assertEqual({'h': 3}, resources_after)

    @unittest.skip('skipping due to MacOS specific failure, unrolling to u2')
    def test_basis_subset(self):
        """Test a transpilation with a basis subset of the standard basis"""
        qr = QuantumRegister(1, 'q1')
        qc = QuantumCircuit(qr)
        qc.h(qr[0])
        qc.x(qr[0])
        qc.t(qr[0])

        layout = [4, 5, 6, 8, 9, 10]

        cmap = [[1, 0], [1, 2], [2, 3], [4, 3], [4, 10], [5, 4], [5, 6], [5, 9],
                [6, 8], [7, 8], [9, 8], [9, 10], [11, 3], [11, 10], [11, 12], [12, 2], [13, 1],
                [13, 12]]

        circuit = transpile(qc, backend=None, coupling_map=cmap,
                            basis_gates=['u3'], initial_layout=layout)

        dag_circuit = circuit_to_dag(circuit)
        resources_after = dag_circuit.count_ops()
        self.assertEqual({'u3': 1}, resources_after)