# Buggy code
def substitute_node_with_dag(self, node, input_dag, wires=None):
    """Replace one node with dag.

    Args:
        node (DAGNode): node to substitute
        input_dag (DAGCircuit): circuit that will substitute the node
        wires (list[Bit]): gives an order for (qu)bits
            in the input circuit. This order gets matched to the node wires
            by qargs first, then cargs, then conditions.

    Raises:
        DAGCircuitError: if met with unexpected predecessor/successors
    """
    condition = node.condition
    # the dag must be amended if used in a
    # conditional context. delete the op nodes and replay
    # them with the condition.
    if condition:
        input_dag.add_creg(condition[0])
        to_replay = []
        for sorted_node in input_dag.topological_nodes():
            if sorted_node.type == "op":
                sorted_node.op.condition = condition
                to_replay.append(sorted_node)
        for input_node in input_dag.op_nodes():
            input_dag.remove_op_node(input_node)
        for replay_node in to_replay:
            input_dag.apply_operation_back(
                replay_node.op, replay_node.qargs, replay_node.cargs
            )

    if wires is None:
        wires = input_dag.wires

    self._check_wires_list(wires, node)

    # Create a proxy wire_map to identify fragments and duplicates
    # and determine what registers need to be added to self
    proxy_map = {w: QuantumRegister(1, "proxy") for w in wires}
    add_qregs = self._check_edgemap_registers(proxy_map, input_dag.qregs, {}, False)
    for qreg in add_qregs:
        self.add_qreg(qreg)

    add_cregs = self._check_edgemap_registers(proxy_map, input_dag.cregs, {}, False)
    for creg in add_cregs:
        self.add_creg(creg)

    # Replace the node by iterating through the input_circuit.
    # Constructing and checking the validity of the wire_map.
    # If a gate is conditioned, we expect the replacement subcircuit
    # to depend on those condition bits as well.
    if node.type != "op":
        raise DAGCircuitError('expected node type "op", got %s' % node.type)

    condition_bit_list = self._bits_in_condition(node.condition)

    wire_map = dict(
        zip(wires, list(node.qargs) + list(node.cargs) + list(condition_bit_list))
    )
    self._check_wiremap_validity(wire_map, wires, self.input_map)
    pred_map, succ_map = self._make_pred_succ_maps(node)
    full_pred_map, full_succ_map = self._full_pred_succ_maps(
        pred_map, succ_map, input_dag, wire_map
    )

    if condition_bit_list:
        # If we are replacing a conditional node, map input dag through
        # wire_map to verify that it will not modify any of the conditioning
        # bits.
        condition_bits = set(condition_bit_list)

        for op_node in input_dag.op_nodes():
            mapped_cargs = {wire_map[carg] for carg in op_node.cargs}

            if condition_bits & mapped_cargs:
                raise DAGCircuitError(
                    "Mapped DAG would alter clbits on which it would be conditioned."
                )

    # Now that we know the connections, delete node
    self._multi_graph.remove_node(node._node_id)

    # Iterate over nodes of input_circuit
    for sorted_node in input_dag.topological_op_nodes():
        # Insert a new node
        condition = self._map_condition(wire_map, sorted_node.condition)
        m_qargs = list(map(lambda x: wire_map.get(x, x), sorted_node.qargs))
        m_cargs = list(map(lambda x: wire_map.get(x, x), sorted_node.cargs))
        node_index = self._add_op_node(sorted_node.op, m_qargs, m_cargs)

        # Add edges from predecessor nodes to new node
        # and update predecessor nodes that change
        all_cbits = self._bits_in_condition(condition)
        all_cbits.extend(m_cargs)
        al = [m_qargs, all_cbits]
        for q in itertools.chain(*al):
            self._multi_graph.add_edge(
                full_pred_map[q],
                node_index,
                dict(name="%s[%s]" % (q.register.name, q.index), wire=q),
            )
            full_pred_map[q] = node_index

    # Connect all predecessors and successors, and remove
    # residual edges between input and output nodes
    for w in full_pred_map:
        self._multi_graph.add_edge(
            full_pred_map[w],
            full_succ_map[w],
            dict(name="%s[%s]" % (w.register.name, w.index), wire=w),
        )
        o_pred = self._multi_graph.predecessors(self.output_map[w]._node_id)
        if len(o_pred) > 1:
            if len(o_pred) != 2:
                raise DAGCircuitError("expected 2 predecessors here")

            p = [x for x in o_pred if x != full_pred_map[w]]
            if len(p) != 1:
                raise DAGCircuitError("expected 1 predecessor to pass filter")

            self._multi_graph.remove_edge(p[0], self.output_map[w])


# Traceback (DAGCircuitError)
import qiskit as qk
qc = qk.QuantumCircuit(2,1)
qc.cx(0,1).c_if(qc.cregs[0], 1)
qc.cx(1,0)
print(qc)
┌───┐
q_0: ───■───┤ X ├
┌─┴─┐ └─┬─┘
q_1: ─┤ X ├───■──
└─┬─┘
┌──┴──┐
c: 1/╡ = 1 ╞═════
└─────┘
qk.transpile(qc, basis_gates=['u3', 'cz'])

---------------------------------------------------------------------------
DAGCircuitError                           Traceback (most recent call last)
<ipython-input-2-ee46705662ef> in <module>
4
5
----> 6 qk.transpile(qc, basis_gates=['u3', 'cz']).draw()

~/q/qiskit-terra/qiskit/compiler/transpile.py in transpile(circuits, backend, basis_gates, coupling_map, backend_properties, initial_layout, layout_method, routing_method, translation_method, seed_transpiler, optimization_level, pass_manager, callback, output_name)
217     # Transpile circuits in parallel
218     circuits = parallel_map(_transpile_circuit, list(zip(circuits, transpile_args)),
--> 219                             task_args=(faulty_qubits_map, backend))
220
221     if len(circuits) == 1:

~/q/qiskit-terra/qiskit/tools/parallel.py in parallel_map(task, values, task_args, task_kwargs, num_processes)
106         return []
107     if len(values) == 1:
--> 108         return [task(values[0], *task_args, **task_kwargs)]
109
110     Publisher().publish("terra.parallel.start", len(values))

~/q/qiskit-terra/qiskit/compiler/transpile.py in _transpile_circuit(circuit_config_tuple, faulty_qubits_map, backend)
320
321     result = pass_manager.run(circuit, callback=transpile_config['callback'],
--> 322                               output_name=transpile_config['output_name'])
323
324     if faulty_qubits_map:

~/q/qiskit-terra/qiskit/transpiler/passmanager.py in run(self, circuits, output_name, callback)
212         """
213         if isinstance(circuits, QuantumCircuit):
--> 214             return self._run_single_circuit(circuits, output_name, callback)
215         elif len(circuits) == 1:
216             return self._run_single_circuit(circuits[0], output_name, callback)

~/q/qiskit-terra/qiskit/transpiler/passmanager.py in _run_single_circuit(self, circuit, output_name, callback)
275         if callback is None and self.callback:  # TODO to remove with __init__(callback)
276             callback = self.callback
--> 277         result = running_passmanager.run(circuit, output_name=output_name, callback=callback)
278         self.property_set = running_passmanager.property_set
279         return result

~/q/qiskit-terra/qiskit/transpiler/runningpassmanager.py in run(***failed resolving arguments***)
113         for passset in self.working_list:
114             for pass_ in passset:
--> 115                 dag = self._do_pass(pass_, dag, passset.options)
116
117         circuit = dag_to_circuit(dag)

~/q/qiskit-terra/qiskit/transpiler/runningpassmanager.py in _do_pass(self, pass_, dag, options)
143         # Run the pass itself, if not already run
144         if pass_ not in self.valid_passes:
--> 145             dag = self._run_this_pass(pass_, dag)
146
147             # update the valid_passes property

~/q/qiskit-terra/qiskit/transpiler/runningpassmanager.py in _run_this_pass(self, pass_, dag)
155             # Measure time if we have a callback or logging set
156             start_time = time()
--> 157             new_dag = pass_.run(dag)
158             end_time = time()
159             run_time = end_time - start_time

~/q/qiskit-terra/qiskit/transpiler/passes/basis/basis_translator.py in run(self, dag)
153                     dag.substitute_node(node, bound_target_dag.op_nodes()[0].op, inplace=True)
154                 else:
--> 155                     dag.substitute_node_with_dag(node, bound_target_dag)
156             else:
157                 raise TranspilerError('BasisTranslator did not map {}.'.format(node.name))

~/q/qiskit-terra/qiskit/dagcircuit/dagcircuit.py in substitute_node_with_dag(self, node, input_dag, wires)
810             wires = input_dag.wires
811
--> 812         self._check_wires_list(wires, node)
813
814         # Create a proxy wire_map to identify fragments and duplicates

~/q/qiskit-terra/qiskit/dagcircuit/dagcircuit.py in _check_wires_list(self, wires, node)
686         if len(wires) != wire_tot:
687             raise DAGCircuitError("expected %d wires, got %d"
--> 688                                   % (wire_tot, len(wires)))
689
690     def _make_pred_succ_maps(self, node):

DAGCircuitError: 'expected 2 wires, got 3'

# Fixed code
def substitute_node_with_dag(self, node, input_dag, wires=None):
    """Replace one node with dag.

    Args:
        node (DAGNode): node to substitute
        input_dag (DAGCircuit): circuit that will substitute the node
        wires (list[Bit]): gives an order for (qu)bits
            in the input circuit. This order gets matched to the node wires
            by qargs first, then cargs, then conditions.

    Raises:
        DAGCircuitError: if met with unexpected predecessor/successors
    """
    in_dag = input_dag
    condition = node.condition
    # the dag must be amended if used in a
    # conditional context. delete the op nodes and replay
    # them with the condition.
    if condition:
        in_dag = copy.deepcopy(input_dag)
        in_dag.add_creg(condition[0])
        to_replay = []
        for sorted_node in in_dag.topological_nodes():
            if sorted_node.type == "op":
                sorted_node.op.condition = condition
                to_replay.append(sorted_node)
        for input_node in in_dag.op_nodes():
            in_dag.remove_op_node(input_node)
        for replay_node in to_replay:
            in_dag.apply_operation_back(
                replay_node.op, replay_node.qargs, replay_node.cargs
            )

    if wires is None:
        wires = in_dag.wires

    self._check_wires_list(wires, node)

    # Create a proxy wire_map to identify fragments and duplicates
    # and determine what registers need to be added to self
    proxy_map = {w: QuantumRegister(1, "proxy") for w in wires}
    add_qregs = self._check_edgemap_registers(proxy_map, in_dag.qregs, {}, False)
    for qreg in add_qregs:
        self.add_qreg(qreg)

    add_cregs = self._check_edgemap_registers(proxy_map, in_dag.cregs, {}, False)
    for creg in add_cregs:
        self.add_creg(creg)

    # Replace the node by iterating through the input_circuit.
    # Constructing and checking the validity of the wire_map.
    # If a gate is conditioned, we expect the replacement subcircuit
    # to depend on those condition bits as well.
    if node.type != "op":
        raise DAGCircuitError('expected node type "op", got %s' % node.type)

    condition_bit_list = self._bits_in_condition(node.condition)

    wire_map = dict(
        zip(wires, list(node.qargs) + list(node.cargs) + list(condition_bit_list))
    )
    self._check_wiremap_validity(wire_map, wires, self.input_map)
    pred_map, succ_map = self._make_pred_succ_maps(node)
    full_pred_map, full_succ_map = self._full_pred_succ_maps(
        pred_map, succ_map, in_dag, wire_map
    )

    if condition_bit_list:
        # If we are replacing a conditional node, map input dag through
        # wire_map to verify that it will not modify any of the conditioning
        # bits.
        condition_bits = set(condition_bit_list)

        for op_node in in_dag.op_nodes():
            mapped_cargs = {wire_map[carg] for carg in op_node.cargs}

            if condition_bits & mapped_cargs:
                raise DAGCircuitError(
                    "Mapped DAG would alter clbits on which it would be conditioned."
                )

    # Now that we know the connections, delete node
    self._multi_graph.remove_node(node._node_id)

    # Iterate over nodes of input_circuit
    for sorted_node in in_dag.topological_op_nodes():
        # Insert a new node
        condition = self._map_condition(wire_map, sorted_node.condition)
        m_qargs = list(map(lambda x: wire_map.get(x, x), sorted_node.qargs))
        m_cargs = list(map(lambda x: wire_map.get(x, x), sorted_node.cargs))
        node_index = self._add_op_node(sorted_node.op, m_qargs, m_cargs)

        # Add edges from predecessor nodes to new node
        # and update predecessor nodes that change
        all_cbits = self._bits_in_condition(condition)
        all_cbits.extend(m_cargs)
        al = [m_qargs, all_cbits]
        for q in itertools.chain(*al):
            self._multi_graph.add_edge(
                full_pred_map[q],
                node_index,
                dict(name="%s[%s]" % (q.register.name, q.index), wire=q),
            )
            full_pred_map[q] = node_index

    # Connect all predecessors and successors, and remove
    # residual edges between input and output nodes
    for w in full_pred_map:
        self._multi_graph.add_edge(
            full_pred_map[w],
            full_succ_map[w],
            dict(name="%s[%s]" % (w.register.name, w.index), wire=w),
        )
        o_pred = self._multi_graph.predecessors(self.output_map[w]._node_id)
        if len(o_pred) > 1:
            if len(o_pred) != 2:
                raise DAGCircuitError("expected 2 predecessors here")

            p = [x for x in o_pred if x != full_pred_map[w]]
            if len(p) != 1:
                raise DAGCircuitError("expected 1 predecessor to pass filter")

            self._multi_graph.remove_edge(p[0], self.output_map[w])