def condensation( G, components ):
	"""Return the condensation of G with respect to the given components.

	Given components C_1 .. C_k which partition the nodes of G, the
	condensation graph cG has nodes <C_1> .. <C_k> and has edge
	(<C_i>,<C_j>) iff there was an edge in G from a node in C_i to a
	node in C_j.
	
	Note: the given components can be arbitrary, but if they are the
	strongly connected components (in the graph theory sense, not the
	dynamics sense) of G, then cG corresponds to the directed acyclic
	graph between strongly connected components.

	Parameters
	----------
	G : DiGraph

	components : list of lists of component nodes.

	Returns
	-------
	cG : DiGraph
	   The condensed graph.
	"""
	mapping = dict([(n,c) for c in range(len(components)) for n in components[c]])
	cG = DiGraph()
	for u in mapping:
		cG.add_node(mapping[u])
		for _,v in G.graph.edges_iter(u, data=False):
			if v not in components[mapping[u]]:
				cG.add_edge(mapping[u], mapping[v])
	return cG
Esempio n. 2
0
def condensation( G, components, loops=False ):
    """Return the condensation of G with respect to the given components.

    Given components C_1 .. C_k which partition the nodes of G, the
    condensation graph cG has nodes <C_1> .. <C_k> and has edge
    (<C_i>,<C_j>) iff there was an edge in G from a node in C_i to a
    node in C_j.
    
    Note: the given components can be arbitrary, but if they are the
    strongly connected components (in the graph theory sense, not the
    dynamics sense) of G, then cG corresponds to the directed acyclic
    graph between strongly connected components.

    Parameters
    ----------
    G : DiGraph

    components : list of lists of component nodes, or dictionary of
    component label -> component nodes

    loops : whether to allow condensed nodes to have self loops (default: False)

    Returns
    -------
    cG : DiGraph
       The condensed graph.
    """
    # convert list to dict
    if isinstance(components,list):
        components = {c:components[c] for c in range(len(components))}
        
    mapping = {n:c for c in components for n in components[c]}
    cG = DiGraph()
    for u in mapping.keys():
        cG.add_node(mapping[u])
        for v in G.successors(u):
            # if v~u and u,v are in the same component, don't add the loop
            # (unless we allow loops)
            if loops or v not in components[mapping[u]]:
                cG.add_edge(mapping[u], mapping[v])
    return cG