def run_dag_opt(self):
        """
        It runs the substitution algorithm and creates the optimized DAGCircuit().
        """
        self._substitution()

        dag_dep_opt = DAGDependency()

        dag_dep_opt.name = self.circuit_dag_dep.name

        qregs = list(self.circuit_dag_dep.qregs.values())
        cregs = list(self.circuit_dag_dep.cregs.values())

        for register in qregs:
            dag_dep_opt.add_qreg(register)

        for register in cregs:
            dag_dep_opt.add_creg(register)

        already_sub = []

        if self.substitution_list:
            # Loop over the different matches.
            for group in self.substitution_list:

                circuit_sub = group.circuit_config
                template_inverse = group.template_config

                pred = group.pred_block

                qubit = group.qubit_config[0]

                if group.clbit_config:
                    clbit = group.clbit_config[0]
                else:
                    clbit = []

                # First add all the predecessors of the given match.
                for elem in pred:
                    node = self.circuit_dag_dep.get_node(elem)
                    inst = node.op.copy()
                    inst.condition = node.condition
                    dag_dep_opt.add_op_node(inst, node.qargs, node.cargs)
                    already_sub.append(elem)

                already_sub = already_sub + circuit_sub

                # Then add the inverse of the template.
                for index in template_inverse:
                    all_qubits = self.circuit_dag_dep.qubits
                    qarg_t = group.template_dag_dep.get_node(index).qindices
                    qarg_c = [qubit[x] for x in qarg_t]
                    qargs = [all_qubits[x] for x in qarg_c]

                    all_clbits = self.circuit_dag_dep.clbits
                    carg_t = group.template_dag_dep.get_node(index).cindices

                    if all_clbits and clbit:
                        carg_c = [clbit[x] for x in carg_t]
                        cargs = [all_clbits[x] for x in carg_c]
                    else:
                        cargs = []
                    node = group.template_dag_dep.get_node(index)
                    inst = node.op.copy()
                    inst.condition = node.condition

                    dag_dep_opt.add_op_node(inst.inverse(), qargs, cargs)

            # Add the unmatched gates.
            for node_id in self.unmatched_list:
                node = self.circuit_dag_dep.get_node(node_id)
                inst = node.op.copy()
                inst.condition = node.condition
                dag_dep_opt.add_op_node(inst, node.qargs, node.cargs)

            dag_dep_opt._add_successors()
        # If there is no valid match, it returns the original dag.
        else:
            dag_dep_opt = self.circuit_dag_dep

        self.dag_dep_optimized = dag_dep_opt
        self.dag_optimized = dagdependency_to_dag(dag_dep_opt)
    def run(self, dag):
        """
        Args:
            dag(DAGCircuit): DAG circuit.
        Returns:
            DAGCircuit: optimized DAG circuit.
        Raises:
            TranspilerError: If the template has not the right form or
             if the output circuit acts differently as the input circuit.
        """
        circuit_dag = dag
        circuit_dag_dep = dag_to_dagdependency(circuit_dag)
        circuit = dagdependency_to_circuit(circuit_dag_dep)
        operator_ini = Operator(circuit)

        for template in self.template_list:
            if not isinstance(template, QuantumCircuit):
                raise TranspilerError('A template is a Quantumciruit().')

            identity = np.identity(2**template.num_qubits, dtype=complex)
            comparison = np.allclose(Operator(template).data, identity)

            if not comparison:
                raise TranspilerError(
                    'A template is a Quantumciruit() that performs the identity.'
                )

            if template.num_qubits > len(circuit_dag_dep.qubits):
                raise TranspilerError(
                    'A template should have equal or less number of qubit'
                    ' compared to the circuit.')

            template_dag_dep = circuit_to_dagdependency(template)

            template_m = TemplateMatching(circuit_dag_dep, template_dag_dep,
                                          self.heuristics_qubits_param,
                                          self.heuristics_backward_param)

            template_m.run_template_matching()

            matches = template_m.match_list

            if matches:
                maximal = MaximalMatches(matches)
                maximal.run_maximal_matches()
                max_matches = maximal.max_match_list

                substitution = TemplateSubstitution(
                    max_matches, template_m.circuit_dag_dep,
                    template_m.template_dag_dep)
                substitution.run_dag_opt()

                circuit_dag_dep = substitution.dag_dep_optimized

                circuit_intermediate = dagdependency_to_circuit(
                    circuit_dag_dep)
                opertator_intermediate = Operator(circuit_intermediate)

                if operator_ini != opertator_intermediate:
                    raise TranspilerError(
                        'A failure happened during the substitution.')
            else:
                continue
        circuit_dag = dagdependency_to_dag(circuit_dag_dep)
        return circuit_dag