Returns the sub-dispatcher induced by the workflow from outputs.

        :param outputs:
            Ending data nodes.
        :type outputs: list[str], iterable, optional

        :param bfs_graphs:
            A dictionary with directed graphs where evaluate the
            breadth-first-search.
        :type bfs_graphs: dict[str | Token, networkx.DiGraph | dict], optional

        :return:
            A sub-dispatcher
        :rtype: Dispatcher

def _get_dsp_from_bfs(self, outputs, bfs_graphs=None):
        """
        Returns the sub-dispatcher induced by the workflow from outputs.

        :param outputs:
            Ending data nodes.
        :type outputs: list[str], iterable, optional

        :param bfs_graphs:
            A dictionary with directed graphs where evaluate the
            breadth-first-search.
        :type bfs_graphs: dict[str | Token, networkx.DiGraph | dict], optional

        :return:
            A sub-dispatcher
        :rtype: Dispatcher
        """

        bfs = bfs_graphs[NONE] if bfs_graphs is not None else self.dmap

        # Get sub dispatcher breadth-first-search graph.
        dsp = self.get_sub_dsp_from_workflow(
            sources=outputs, graph=bfs, reverse=True, _update_links=False
        )

        # Namespace shortcuts.
        succ, nodes, pred = dsp.dmap.succ, dsp.nodes, dsp.dmap.pred
        rm_edges, nds = dsp.dmap.remove_edges_from, dsp.data_nodes
        from .utils.alg import _nodes, _get_sub_out, _update_io

        for n in dsp.sub_dsp_nodes:
            a = nodes[n] = nodes[n].copy()
            bfs = bfs_graphs[n] if bfs_graphs is not None else None

            out = _get_sub_out(a, succ[n])
            if 'input_domain' in a:
                out.update(_nodes(a['inputs'].values()))

            a['function'] = a['function']._get_dsp_from_bfs(out, bfs)

            i, o = _update_io(a, pred[n], succ[n])  # Unreachable nodes.
            rm_edges({(u, n) for u in i}.union(((n, u) for u in o)))

        return dsp