Exemple #1
0
 def test_basic(self):
     """Test decompose a single H into u2."""
     qr = QuantumRegister(1, "qr")
     circuit = QuantumCircuit(qr)
     circuit.h(qr[0])
     dag = circuit_to_dag(circuit)
     pass_ = Decompose(HGate)
     after_dag = pass_.run(dag)
     op_nodes = after_dag.op_nodes()
     self.assertEqual(len(op_nodes), 1)
     self.assertEqual(op_nodes[0].name, "u2")
 def test_basic(self):
     """Test decompose a single H into u2.
     """
     qr = QuantumRegister(1, 'qr')
     circuit = QuantumCircuit(qr)
     circuit.h(qr[0])
     dag = circuit_to_dag(circuit)
     pass_ = Decompose(HGate(qr[0]))
     after_dag = pass_.run(dag)
     op_nodes = after_dag.get_op_nodes(data=True)
     self.assertEqual(len(op_nodes), 1)
     self.assertEqual(op_nodes[0][1]["op"].name, 'u2')
Exemple #3
0
 def test_decompose_only_h(self):
     """Test to decompose a single H, without the rest"""
     qr = QuantumRegister(2, "qr")
     circuit = QuantumCircuit(qr)
     circuit.h(qr[0])
     circuit.cx(qr[0], qr[1])
     dag = circuit_to_dag(circuit)
     pass_ = Decompose(HGate)
     after_dag = pass_.run(dag)
     op_nodes = after_dag.op_nodes()
     self.assertEqual(len(op_nodes), 2)
     for node in op_nodes:
         self.assertIn(node.name, ["cx", "u2"])
Exemple #4
0
 def test_decompose_none(self):
     """Test decompose a single H into u2."""
     qr = QuantumRegister(1, "qr")
     circuit = QuantumCircuit(qr)
     circuit.h(qr[0])
     dag = circuit_to_dag(circuit)
     pass_ = Decompose(HGate)
     with self.assertWarns(DeprecationWarning):
         pass_.gate = None
     after_dag = pass_.run(dag)
     op_nodes = after_dag.op_nodes()
     self.assertEqual(len(op_nodes), 1)
     self.assertEqual(op_nodes[0].name, "u2")
Exemple #5
0
 def test_decompose_toffoli(self):
     """Test decompose CCX."""
     qr1 = QuantumRegister(2, "qr1")
     qr2 = QuantumRegister(1, "qr2")
     circuit = QuantumCircuit(qr1, qr2)
     circuit.ccx(qr1[0], qr1[1], qr2[0])
     dag = circuit_to_dag(circuit)
     pass_ = Decompose(CCXGate)
     after_dag = pass_.run(dag)
     op_nodes = after_dag.op_nodes()
     self.assertEqual(len(op_nodes), 15)
     for node in op_nodes:
         self.assertIn(node.name, ["h", "t", "tdg", "cx"])
Exemple #6
0
 def test_decompose_toffoli(self):
     """Test decompose CCX.
     """
     qr1 = QuantumRegister(2, 'qr1')
     qr2 = QuantumRegister(1, 'qr2')
     circuit = QuantumCircuit(qr1, qr2)
     circuit.ccx(qr1[0], qr1[1], qr2[0])
     dag = circuit_to_dag(circuit)
     pass_ = Decompose(ToffoliGate)
     after_dag = pass_.run(dag)
     op_nodes = after_dag.op_nodes()
     self.assertEqual(len(op_nodes), 15)
     for node in op_nodes:
         self.assertIn(node.name, ['h', 't', 'tdg', 'cx'])
Exemple #7
0
 def test_decompose_only_h(self):
     """Test to decompose a single H, without the rest
     """
     qr = QuantumRegister(2, 'qr')
     circuit = QuantumCircuit(qr)
     circuit.h(qr[0])
     circuit.cx(qr[0], qr[1])
     dag = circuit_to_dag(circuit)
     pass_ = Decompose(HGate)
     after_dag = pass_.run(dag)
     op_nodes = after_dag.op_nodes(data=True)
     self.assertEqual(len(op_nodes), 2)
     for node in op_nodes:
         op = node[1]["op"]
         self.assertIn(op.name, ['cx', 'u2'])
Exemple #8
0
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
Exemple #9
0
    def test_decompose_conditional(self):
        """Test decompose a 1-qubit gates with a conditional."""
        qr = QuantumRegister(1, "qr")
        cr = ClassicalRegister(1, "cr")
        circuit = QuantumCircuit(qr, cr)
        circuit.h(qr).c_if(cr, 1)
        circuit.x(qr).c_if(cr, 1)
        dag = circuit_to_dag(circuit)
        pass_ = Decompose(HGate)
        after_dag = pass_.run(dag)

        ref_circuit = QuantumCircuit(qr, cr)
        ref_circuit.append(U2Gate(0, pi), [qr[0]]).c_if(cr, 1)
        ref_circuit.x(qr).c_if(cr, 1)
        ref_dag = circuit_to_dag(ref_circuit)

        self.assertEqual(after_dag, ref_dag)
Exemple #10
0
def my_pass_manager(coupling_map, initial_layout):

    _given_layout = SetLayout(initial_layout)
    pm = PassManager([
        Unroller(['u1', 'u2', 'u3', 'cx']), _given_layout,
        BasicSwap(coupling_map),
        Decompose(SwapGate)
    ])
    return pm
Exemple #11
0
    def run(self, quantum_circuit):

        dag_circuit = circuit_to_dag(quantum_circuit)

        init_time = time.time()
        self.parameters["TIME_START"] = init_time

        initial_mapping = []
        if self.parameters["initial_map"] == K7MInitialMapping.RANDOM:
            # Only the first positions which correspond to the circuit qubits
            initial_mapping = numpy.random.permutation(
                self.parameters["nisq_qubits"])
            initial_mapping = initial_mapping[:dag_circuit.num_qubits()]
        elif self.parameters["initial_map"] == K7MInitialMapping.LINEAR:
            initial_mapping = list(range(dag_circuit.num_qubits()))
        elif self.parameters["initial_map"] == K7MInitialMapping.HEURISTIC:
            initial_mapping = cuthill_order(dag_circuit, self.coupling_obj,
                                            self.parameters)

        init_time = time.time() - init_time

        if initial_mapping is None:
            return None, init_time, None

        # print(initial_mapping)
        #
        # return quantum_circuit
        print("                       .......")

        original_pm = PassManager()
        optimal_layout = Layout()
        for c_idx, p_idx in enumerate(initial_mapping):
            optimal_layout.add(quantum_circuit.qregs[0][c_idx], p_idx)

        original_pm.append([
            SetLayout(optimal_layout),
            ApplyLayout(),
            StochasticSwap(self.coupling_obj.coupling, seed=0),
            Decompose(gate=qiskit.extensions.SwapGate)
        ])

        return original_pm.run(quantum_circuit), init_time, initial_mapping
Exemple #12
0
def level_1_pass_manager(pass_manager_config):
    """
    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 (PassManagerConfig)

    Returns:
        PassManager: a level 1 pass manager.
    """
    basis_gates = pass_manager_config.basis_gates
    coupling_map = pass_manager_config.coupling_map
    initial_layout = pass_manager_config.initial_layout
    seed_transpiler = pass_manager_config.seed_transpiler
    backend_properties = pass_manager_config.backend_properties

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

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

    # 2. Use a better layout on densely connected qubits, if circuit needs swaps
    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. Unroll to the basis
    _unroll = Unroller(basis_gates)

    # 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(),
        Unroll3qOrMore(),
        StochasticSwap(coupling_map, trials=20, seed=seed_transpiler),
        Decompose(SwapGate)
    ]

    # 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. 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(), CXCancellation()]

    pm1 = PassManager()
    if coupling_map:
        pm1.append(_set_initial_layout)
        pm1.append([
            TrivialLayout(coupling_map),
            Layout2qDistance(coupling_map,
                             property_name='trivial_layout_score')
        ],
                   condition=_choose_layout_condition)
        pm1.append(DenseLayout(coupling_map, backend_properties),
                   condition=_not_perfect_yet)
        pm1.append(_embed)
    pm1.append(_unroll)
    if coupling_map:
        pm1.append(_swap_check)
        pm1.append(_swap, condition=_swap_condition)
        if 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
Exemple #13
0
    ChainLayout(coupling_map=coupling_map, backend_prop=properties),
    FullAncillaAllocation(coupling_map),
    EnlargeWithAncilla(),
    ApplyLayout()
])


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


pass_manager.append([
    BarrierBeforeFinalMeasurements(),
    Unroll3qOrMore(),
    NoiseAdaptiveSwap(coupling_map=coupling_map, backend_prop=properties),
    Decompose(SwapGate)
])


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


if not coupling_map.is_symmetric:
    pass_manager.append(CheckCXDirection(coupling_map))
    pass_manager.append(CXDirection(coupling_map),
                        condition=direction_condition)

depth_check = [Depth(), FixedPoint('depth')]

Exemple #14
0
def level_2_pass_manager(pass_manager_config: PassManagerConfig) -> PassManager:
    """Level 2 pass manager: medium optimization by noise adaptive qubit mapping and
    gate cancellation using commutativity rules.

    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 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.
    """
    basis_gates = pass_manager_config.basis_gates
    coupling_map = pass_manager_config.coupling_map
    initial_layout = pass_manager_config.initial_layout
    seed_transpiler = pass_manager_config.seed_transpiler
    backend_properties = pass_manager_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, 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)]

    # 5. 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)]

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

    # 7. 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(), CommutativeCancellation()]

    pm2 = PassManager()
    pm2.append(_unroll)
    if coupling_map:
        pm2.append(_given_layout)
        pm2.append(CSPLayout(coupling_map, call_limit=1000, time_limit=10),
                   condition=_choose_layout_condition)
        pm2.append(_choose_layout, condition=_choose_layout_condition)
        pm2.append(_embed)
        pm2.append(_swap_check)
        pm2.append(_swap, condition=_swap_condition)
        if 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)

    return pm2
Exemple #15
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
print("coupling map: ", coupling_map)

pm = PassManager()

# Use the trivial layout
pm.append(TrivialLayout(coupling_map))

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

# Swap mapper
pm.append(LookaheadSwap(coupling_map))

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

# Simplify CXs
pm.append(CXDirection(coupling_map))

# unroll to single qubit gates
pm.append(Unroller(['u1', 'u2', 'u3', 'id', 'cx']))
qc1_new = pm.run(qc1)
qc2_new = pm.run(qc2)

print("Bell circuit before passes:")
print(qc1)
print("Bell circuit after passes:")
print(qc1_new)
print("Superposition circuit before passes:")
print(qc2)
Exemple #17
0
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
Exemple #18
0
    def run(self, quantum_circuit):

        dag_circuit = circuit_to_dag(quantum_circuit)

        init_time = time.time()

        initial_mapping = []
        if self.parameters["initial_map"] == K7MInitialMapping.RANDOM:
            # Only the first positions which correspond to the circuit qubits
            initial_mapping = numpy.random.permutation(
                self.parameters["nisq_qubits"])
            initial_mapping = initial_mapping[:dag_circuit.num_qubits()]
        elif self.parameters["initial_map"] == K7MInitialMapping.LINEAR:
            initial_mapping = list(range(dag_circuit.num_qubits()))
        elif self.parameters["initial_map"] == K7MInitialMapping.HEURISTIC:
            initial_mapping = cuthill_order(dag_circuit, self.coupling_obj,
                                            self.parameters)

        init_time = time.time() - init_time

        # print(initial_mapping)
        #
        # return quantum_circuit
        print("                       .......")

        original_pm = PassManager()
        optimal_layout = Layout()
        for c_idx, p_idx in enumerate(initial_mapping):
            optimal_layout.add(quantum_circuit.qregs[0][c_idx], p_idx)

        original_pm.append([
            SetLayout(optimal_layout),
            ApplyLayout(),
            StochasticSwap(self.coupling_obj.coupling),
            Decompose(gate=qiskit.extensions.SwapGate)
        ])

        return original_pm.run(quantum_circuit), init_time, initial_mapping
        """
            NAIVE ROUTING
        """
        # if self.positions_obj == None:
        #     self.positions_obj = K7MPositions(dag_circuit,
        #                                       self.parameters,
        #                                       initial_mapping)
        # '''
        #     Start with an initial configuration
        # '''
        # compiled_dag, back_stack = self.find_solution(dag_circuit, self.parameters["dry_run"])
        #
        # """
        #     Returning here stops backtracking -> A full backtrack is not available,
        #     but the following code, after having iterated through the possible
        #     configurations (code before here):
        #     * counts the most common configuration
        #     * computes for each configuration the cost
        #     * chooses the configuration of minimum cost
        # """
        #
        # # Clean the positions
        # self.positions_obj = None
        #
        # return dag_to_circuit(compiled_dag)
        """