def test_iter_graph(): G1 = nx.DiGraph() G1 = add_node_after(G1, 1) G1 = add_node_after(G1, 2, 1) G1 = add_node_after(G1, 3, 2) G1 = add_node_after(G1, 4) G1 = add_node_after(G1, 5, 4) G1 = add_node_after(G1, 6, 5, 3) G2 = graph_from_edges((1, 2), (3, 4)) for G in (G1, G2): done = set() for n in iter_graph(G): for p in G.predecessors(n): assert p in done assert n not in done done.add(n) assert done == set(G.nodes) G3 = nx.DiGraph() G3.add_node(1) G3.add_node(2) # 2 un-connexted nodes assert list(iter_graph(G3)) in ([1, 2], [2, 1])
def _find_first_composition_node(Graph): """ retrieve the 'first' composition node of a Graph, it no composition node, return None """ for node in gh.iter_graph(Graph): if StepCategories.is_composition_step(node[0]): return node return None
def _find_first_composition_node(Graph, composition_already_done=None): """ retrieve the 'first' composition node of a Graph, it will ignore composition node already in 'composition_already_done' it no composition node, return None """ if composition_already_done is None: composition_already_done = set() for node in gh.iter_graph(Graph): if StepCategories.is_composition_step( node[0]) and node not in composition_already_done: return node return None
def simplify_none_node(Graph): """ Remove the node where model_name is None from a Graph, those node are 'Passtrought' by convention """ simplified_Graph = Graph.copy() while True: has_none_node = False for step_node, step_name in gh.iter_graph(simplified_Graph): if step_name[0] is None: has_none_node = True break if has_none_node: simplified_Graph = gh.remove_node_keep_connections( simplified_Graph, (step_node, step_name)) else: break return simplified_Graph
def create_graph(self): """ create the graphical structure """ self.complete_graph = graph_from_edges(*self._edges) self._verif_graph_structure() self._terminal_node = get_terminal_nodes(self.complete_graph)[0] self._nodes_order = list(iter_graph(self.complete_graph))
def _rec_convert_graph_to_code_OLD(G, all_params): """ recursive function to convert a graph into a json representation """ if len(G.nodes) == 0: return {} ### 1) Find First composition node has_composition = False for node in gh.iter_graph(G): if StepCategories.is_composition_step(node[0]): has_composition = True break return_gpipe = not has_composition if has_composition: ### If there is a composition node, I need to split between what is above and what is bellow predecessors = gh.get_all_predecessors(G, node) successors = gh.get_all_successors(G, node) if not gh.is_it_a_partition(list(G.nodes), [predecessors, [node], successors]): raise ValueError("Incorrect graph, wrong split around node %s" % str(node)) if len(successors) == 0: # If nothing bellow, I'll be able to return something return_gpipe = True if return_gpipe: if len(G.nodes) > 1: ### I'll create a GraphPipeline object edges = gh.edges_from_graph(G) model_name_mapping = _create_name_mapping(list(G.nodes)) # each node in graph will be mapped to a name within the GraphPipeline models = {model_name_mapping[n]: all_params[n] for n in G.nodes} edges = [ tuple((model_name_mapping[e] for e in edge)) for edge in edges ] return (SpecialModels.GraphPipeline, { "models": models, "edges": edges }) else: ### Otherwise it is just the model_name with its parameters return node[1][1], all_params[list(G.nodes)[0]] G_above = G.subgraph(predecessors + [node]) G_bellow = G.subgraph(successors) connected_Gbellow = gh.get_connected_graphs(G_bellow) if len(connected_Gbellow) == 1: # what is bellow is a 'connected graph' : it means that the composition need should be applied to One model all_params[node] = _rec_convert_graph_to_code_OLD(G_bellow, all_params) else: # otherwise, the composition will be applied to a list of models all_params[node] = [ _rec_convert_graph_to_code_OLD(g, all_params) for g in connected_Gbellow ] return _rec_convert_graph_to_code_OLD(G_above, all_params)
def register_new_class(self, category, klass, hyper=None, default_hyper=None, is_allowed=None, depends_on=None, **kwargs): if not isinstance(klass, type): raise TypeError("klass should be klass") key = category, klass.__name__ if key in self.all_registered: raise ValueError("%s has already been registered" % str(key)) self.all_registered.append(key) self.init_parameters[key] = get_init_parameters(klass) if hyper is not None: self.hyper_parameters[key] = hyper if default_hyper is not None: self.default_hyper_parameters[key] = default_hyper if is_allowed is not None: self.is_allowed[key] = is_allowed if kwargs: self.informations[key] = {k: v for k, v in kwargs.items()} if klass.__name__ not in DICO_NAME_KLASS._mapping: raise ValueError( "You should also register that klass : %s within the 'simple register' file" % klass.__name__) self.step_dependencies.add_node(category) if depends_on is not None: if not isinstance(depends_on, (list, tuple, set)): depends_on = (depends_on, ) for depending_step in depends_on: if depending_step not in StepCategories.alls: raise ValueError(f"{depending_step} is not a know step") self.step_dependencies.add_edge(depending_step, category) if has_cycle(self.step_dependencies): raise ValueError( f"adding this dependency {depending_step} -> {category} create a cycle" ) self._drawing_order = { step: n for n, step in enumerate(iter_graph( self.step_dependencies)) } return self