def collapse_connections(self):
        src2dests = {}
        dest2src = {}

        g = CollapsedGraph(self)

        conns = list_data_connections(g)
        drvconns = list_driver_connections(g)

        # mark all connected vars for removal since they're being collapsed
        to_remove = set([u for u,v in conns])
        to_remove.update([v for u,v in conns])
        to_remove.update([u for u,v in drvconns if not is_driver_node(g, u)])
        to_remove.update([v for u,v in drvconns if not is_driver_node(g, v)])

        # temporarily rename drivers in driver connections to include
        # the name of the connected var
        for i,(u,v) in enumerate(drvconns):
            if is_driver_node(g, u):
                drvconns[i] = ('%s@%s' % (u,v), v)
                dest2src[v] = drvconns[i][0]
            elif is_driver_node(g, v):
                drvconns[i] = (u, '%s@%s' % (v,u))

        for u,v in drvconns:
            src2dests.setdefault(u, set()).add(v)

        for u,v in conns:
            src2dests.setdefault(u, set()).add(v)
            dest2src[v] = u

        # reroute inputs that are also sources
        while True:
            size = len(src2dests)
            for src, dests in src2dests.items():
                if src in dest2src:
                    truesrc = dest2src[src]
                    src2dests[truesrc].update(dests)
                    for d in dests:
                        if d in dest2src:
                            dest2src[d] = truesrc
                    del src2dests[src]

            # if no nodes re-routed, stop
            if len(src2dests) == size:
                break

        # clean up any driver connections to params that have already been
        # included in a param group node
        dparams = {}
        for src, dests, in src2dests.items():
            if '@' in src:
                drv, var = src.split('@',1)
                dparams.setdefault(drv, set()).update([d for d in dests if d != var])

        for src, dests, in src2dests.items():
            if '@' in src:
                drv, var = src.split('@',1)
                if var in dparams[drv]:
                    del src2dests[src]

        for src, dests in src2dests.items():
            _add_collapsed_node(g, src, dests)

        g.remove_nodes_from(to_remove)

        return g
Enumerate the partitions of a multiset with lb < num(parts)
dataset/ETHPy150Open OpenMDAO/OpenMDAO-Framework/openmdao.main/src/openmdao/main/depgraph.py/DependencyGraph.collapse_connections--crossover with--dataset/ETHPy150Open sympy/sympy/sympy/utilities/enumerative.py/MultisetPartitionTraverser.enum_large