def _flatten_graph(flow, flattened): graph = nx.DiGraph(name=_graph_name(flow)) subgraph_map = {} # Flatten all nodes for n in flow.graph.nodes_iter(): subgraph = _flatten(n, flattened) subgraph_map[n] = subgraph graph = gu.merge_graphs([graph, subgraph]) # Reconnect all nodes to there corresponding subgraphs for (u, v) in flow.graph.edges_iter(): # Retain and update the original edge attributes. u_v_attrs = gu.get_edge_attrs(flow.graph, u, v) if not u_v_attrs: u_v_attrs = FLATTEN_EDGE_DATA.copy() else: u_v_attrs.update(FLATTEN_EDGE_DATA) u_no_succ = list(gu.get_no_successors(subgraph_map[u])) # Connect the ones with no predecessors in v to the ones with no # successors in u (thus maintaining the edge dependency). for n in gu.get_no_predecessors(subgraph_map[v]): # NOTE(harlowja): give each edge its own copy so that if its later # modified that the same copy isn't modified. graph.add_edges_from(((n2, n, copy.deepcopy(u_v_attrs)) for n2 in u_no_succ if not graph.has_edge(n2, n))) return graph
def _flatten_unordered(self, flow): """Flattens a unordered flow.""" graph = nx.DiGraph(name=flow.name) for item in flow: # NOTE(harlowja): we do *not* connect the graphs together, this # retains that each item (translated to subgraph) is disconnected # from each other which will result in unordered execution while # running. graph = gu.merge_graphs([graph, self._flatten(item)]) return graph
def _flatten_linear(self, flow): """Flattens a linear flow.""" graph = nx.DiGraph(name=flow.name) previous_nodes = [] for item in flow: subgraph = self._flatten(item) graph = gu.merge_graphs([graph, subgraph]) # Find nodes that have no predecessor, make them have a predecessor # of the previous nodes so that the linearity ordering is # maintained. Find the ones with no successors and use this list # to connect the next subgraph (if any). self._add_new_edges(graph, previous_nodes, list(gu.get_no_predecessors(subgraph))) # There should always be someone without successors, otherwise we # have a cycle A -> B -> A situation, which should not be possible. previous_nodes = list(gu.get_no_successors(subgraph)) return graph
def _flatten_graph(flow, flattened): graph = nx.DiGraph(name=_graph_name(flow)) subgraph_map = {} # Flatten all nodes for n in flow.graph.nodes_iter(): subgraph = _flatten(n, flattened) subgraph_map[n] = subgraph graph = gu.merge_graphs([graph, subgraph]) # Reconnect all nodes to there corresponding subgraphs for (u, v) in flow.graph.edges_iter(): u_no_succ = list(gu.get_no_successors(subgraph_map[u])) # Connect the ones with no predecessors in v to the ones with no # successors in u (thus maintaining the edge dependency). for n in gu.get_no_predecessors(subgraph_map[v]): graph.add_edges_from(((n2, n, FLATTEN_EDGE_DATA) for n2 in u_no_succ if not graph.has_edge(n2, n))) return graph
def _flatten_linear(flow, flattened): graph = nx.DiGraph(name=_graph_name(flow)) previous_nodes = [] for f in flow: subgraph = _flatten(f, flattened) graph = gu.merge_graphs([graph, subgraph]) # Find nodes that have no predecessor, make them have a predecessor of # the previous nodes so that the linearity ordering is maintained. Find # the ones with no successors and use this list to connect the next # subgraph (if any). for n in gu.get_no_predecessors(subgraph): graph.add_edges_from(((n2, n, FLATTEN_EDGE_DATA) for n2 in previous_nodes if not graph.has_edge(n2, n))) # There should always be someone without successors, otherwise we have # a cycle A -> B -> A situation, which should not be possible. previous_nodes = list(gu.get_no_successors(subgraph)) return graph
def _flatten_graph(self, flow): """Flattens a graph flow.""" graph = nx.DiGraph(name=flow.name) # Flatten all nodes into a single subgraph per node. subgraph_map = {} for item in flow: subgraph = self._flatten(item) subgraph_map[item] = subgraph graph = gu.merge_graphs([graph, subgraph]) # Reconnect all node edges to there corresponding subgraphs. for (u, v) in flow.graph.edges_iter(): # Retain and update the original edge attributes. u_v_attrs = gu.get_edge_attrs(flow.graph, u, v) # Connect the ones with no predecessors in v to the ones with no # successors in u (thus maintaining the edge dependency). self._add_new_edges(graph, list(gu.get_no_successors(subgraph_map[u])), list(gu.get_no_predecessors(subgraph_map[v])), edge_attrs=u_v_attrs) return graph
def _flatten_linear(flow, flattened): graph = nx.DiGraph(name=_graph_name(flow)) previous_nodes = [] for f in flow: subgraph = _flatten(f, flattened) graph = gu.merge_graphs([graph, subgraph]) # Find nodes that have no predecessor, make them have a predecessor of # the previous nodes so that the linearity ordering is maintained. Find # the ones with no successors and use this list to connect the next # subgraph (if any). for n in gu.get_no_predecessors(subgraph): # NOTE(harlowja): give each edge its own copy so that if its later # modified that the same copy isn't modified. graph.add_edges_from(((n2, n, FLATTEN_EDGE_DATA.copy()) for n2 in previous_nodes if not graph.has_edge(n2, n))) # There should always be someone without successors, otherwise we have # a cycle A -> B -> A situation, which should not be possible. previous_nodes = list(gu.get_no_successors(subgraph)) return graph
def _flatten_unordered(flow, flattened): graph = nx.DiGraph(name=_graph_name(flow)) for f in flow: graph = gu.merge_graphs([graph, _flatten(f, flattened)]) return graph