From b2e1a6d7b0c86311070d0a92e03110704cd59744 Mon Sep 17 00:00:00 2001 From: Girish Mittapalle Date: Sun, 24 Mar 2024 22:24:47 -0400 Subject: [PATCH] Fixed automation bug --- gunfolds/conversions.py | 289 +++++++++--------- sphinx-build/conversions/internal.rst | 10 + sphinx-build/estimation/linear_model.rst | 40 +-- sphinx-build/getting_started.rst | 2 +- sphinx-build/run.py | 31 +- sphinx-build/solvers/imperative/traversal.rst | 60 ++-- .../solvers/imperative/unknownrate.rst | 10 +- sphinx-build/utils/comparison.rst | 20 +- sphinx-build/utils/graphkit.rst | 30 +- 9 files changed, 259 insertions(+), 233 deletions(-) diff --git a/gunfolds/conversions.py b/gunfolds/conversions.py index db34f3c0..b0f9dfc2 100644 --- a/gunfolds/conversions.py +++ b/gunfolds/conversions.py @@ -6,6 +6,22 @@ import igraph import sys +################### Start of Internal Conversions ################### + +def nodenum(edgepairs): + """ + Returns the number of nodes in the graph + + :param edgepairs: list of edge pairs + :type edgepairs: list + + :returns: number of nodes in the graph + :rtype: integer + """ + nodes = 0 + for e in edgepairs: + nodes = np.max([nodes, int(e[0]), int(e[1])]) + return nodes def g2num(g): """ @@ -72,57 +88,6 @@ def bg2num(g): num = num | (1 << (n2 - v * n - w)) return num - -def graph2nx(G): - """ - Convert a ``gunfolds`` graph to NetworkX format ignoring bidirected edges - - :param G: ``gunfolds`` format graph - :type G: dictionary (``gunfolds`` graphs) - - :returns: NetworkX format graph - :rtype: NetworkX graph - """ - g = nx.DiGraph() - for v in G: - edges = [(v, x) for x in G[v] if G[v][x] in (1, 3)] - if edges: - g.add_edges_from(edges) - else: - g.add_node(v) - return g - - -def graph2dot(g, filename): - """ - Save the graph structure of `g` to a graphviz format dot file with the name `filename` - - :param g: ``gunfolds`` graph - :type g: dictionary (``gunfolds`` graphs) - - :param filename: name of the file - :type filename: string - """ - G = graph2nx(g) - nx.drawing.nx_pydot.write_dot(G, filename) - - -def nx2graph(G): - """ - Convert NetworkX format graph to ``gunfolds`` graph ignoring bidirected edges - - :param G: ``gunfolds`` format graph - :type G: dictionary (``gunfolds`` graphs) - - :returns: ``gunfolds`` graph - :rtype: dictionary (``gunfolds`` graphs) - """ - g = {n: {} for n in G} - for n in G: - g[n] = {x: 1 for x in G[n]} - return g - - def num2CG(num, n): """ Converts a number whose binary representaion encodes edge @@ -217,6 +182,21 @@ def ian2g(g): gg[str(w)][str(v)] = c[g[w][v]] return gg +def edgepairs2g(edgepairs): + """ + Converts edge pairs to a ``gunfolds`` graph + + :param edgepairs: list of edge pairs + :type edgepairs: list + + :returns: ``gunfolds`` graph + :rtype: dictionary (``gunfolds`` graph) + """ + n = nodenum(edgepairs) + g = {x+1: {} for x in range(n)} + for e in edgepairs: + g[int(e[0])][int(e[1])] = 1 + return g # Adjacency matrix functions @@ -334,6 +314,54 @@ def vec2g(v, n): A, B = vec2adj(v, n) return adjs2graph(A, B) +def Glag2CG(results): + """Converts lag graph format to gunfolds graph format, + and A and B matrices representing directed and bidirected edges weights. + + Args: + results (dict): A dictionary containing: + - 'graph': A 3D NumPy array of shape [N, N, 2] representing the graph structure. + - 'val_matrix': A NumPy array of shape [N, N, 2] storing edge weights. + + Returns: + tuple: (graph_dict, A_matrix, B_matrix) + """ + + graph_array = results['graph'] + bidirected_edges = np.where(graph_array == 'o-o', 1, 0).astype(int) + directed_edges = np.where(graph_array == '-->', 1, 0).astype(int) + + graph_dict = adjs2graph(np.transpose(directed_edges[:, :, 1]), np.transpose((bidirected_edges[:, :, 0]))) + A_matrix = results['val_matrix'][:, :, 1] + B_matrix = results['val_matrix'][:, :, 0] + + return graph_dict, A_matrix, B_matrix + +def nxbp2graph(G): + """ + Ask + + :param G: ``gunfolds`` format graph + :type G: dictionary (``gunfolds`` graphs) + + :returns: Ask + :rtype: + """ + nodesnum = len(G)//2 + g = {n+1: {} for n in range(nodesnum)} + for n in g: + g[n] = {(x % nodesnum+1): 1 for x in G[n-1]} + return g + + +################### Add new functions to internal conversions above ############# +################### End of Internal Conversions ######################## + +# Dont remove this fake function for automating sphinx build. +def sphinx_automation_fake(): + return + +################### Start of Clingo Conversions ################### def rate(u): """ @@ -633,39 +661,6 @@ def c2edgepairs(clist): return [x.strip(' ')[6:-1].split(',') for x in clist] -def nodenum(edgepairs): - """ - Returns the number of nodes in the graph - - :param edgepairs: list of edge pairs - :type edgepairs: list - - :returns: number of nodes in the graph - :rtype: integer - """ - nodes = 0 - for e in edgepairs: - nodes = np.max([nodes, int(e[0]), int(e[1])]) - return nodes - - -def edgepairs2g(edgepairs): - """ - Converts edge pairs to a ``gunfolds`` graph - - :param edgepairs: list of edge pairs - :type edgepairs: list - - :returns: ``gunfolds`` graph - :rtype: dictionary (``gunfolds`` graph) - """ - n = nodenum(edgepairs) - g = {x+1: {} for x in range(n)} - for e in edgepairs: - g[int(e[0])][int(e[1])] = 1 - return g - - def msl_jclingo2g(output_g): """ Converts the output of ``clingo`` to ``gunfolds`` graph for ``rasl_msl`` @@ -736,42 +731,6 @@ def old_g2clingo(g, file=sys.stdout): print('edgeu('+str(v)+','+str(w)+').', file=file) print('confu('+str(v)+','+str(w)+').', file=file) - -def g2ig(g): - """ - Converts our graph representation to an igraph for plotting - - :param g: ``gunfolds`` graph - :type g: dictionary (``gunfolds`` graphs) - - :returns: igraph representation of ``gunfolds`` graph - :rtype: igraph - """ - t = np.where(graph2adj(g) == 1) - l = zip(t[0], t[1]) - ig = igraph.Graph(l, directed=True) - ig.vs["name"] = np.sort([u for u in g]) - ig.vs["label"] = ig.vs["name"] - return ig - - -def nxbp2graph(G): - """ - Ask - - :param G: ``gunfolds`` format graph - :type G: dictionary (``gunfolds`` graphs) - - :returns: Ask - :rtype: - """ - nodesnum = len(G)//2 - g = {n+1: {} for n in range(nodesnum)} - for n in g: - g[n] = {(x % nodesnum+1): 1 for x in G[n-1]} - return g - - def encode_sccs(g, idx, components=True, SCCS=None): """ Encodes strongly connected components of ``gunfolds`` graph to ``clingo`` predicates @@ -846,25 +805,81 @@ def encode_list_sccs(glist, scc_members=None): s += ':- directed(X,Y,U), scc(X,K), scc(Y,L), K != L, sccsize(L,Z), Z > 1, not dag(K,L,N), u(U,N).' return s -def Glag2CG(results): - """Converts lag graph format to gunfolds graph format, - and A and B matrices representing directed and bidirected edges weights. - Args: - results (dict): A dictionary containing: - - 'graph': A 3D NumPy array of shape [N, N, 2] representing the graph structure. - - 'val_matrix': A NumPy array of shape [N, N, 2] storing edge weights. +################### Add only new functions to clingo conversions above ############# +################### End of Clingo Conversions ######################## - Returns: - tuple: (graph_dict, A_matrix, B_matrix) - """ +# Dont remove this fake function for automating sphinx build. +def sphinx_automation_fake(): + return - graph_array = results['graph'] - bidirected_edges = np.where(graph_array == 'o-o', 1, 0).astype(int) - directed_edges = np.where(graph_array == '-->', 1, 0).astype(int) +################### Start of External Conversions ################### - graph_dict = adjs2graph(np.transpose(directed_edges[:, :, 1]), np.transpose((bidirected_edges[:, :, 0]))) - A_matrix = results['val_matrix'][:, :, 1] - B_matrix = results['val_matrix'][:, :, 0] +def graph2nx(G): + """ + Convert a ``gunfolds`` graph to NetworkX format ignoring bidirected edges + + :param G: ``gunfolds`` format graph + :type G: dictionary (``gunfolds`` graphs) + + :returns: NetworkX format graph + :rtype: NetworkX graph + """ + g = nx.DiGraph() + for v in G: + edges = [(v, x) for x in G[v] if G[v][x] in (1, 3)] + if edges: + g.add_edges_from(edges) + else: + g.add_node(v) + return g + + +def graph2dot(g, filename): + """ + Save the graph structure of `g` to a graphviz format dot file with the name `filename` + + :param g: ``gunfolds`` graph + :type g: dictionary (``gunfolds`` graphs) + + :param filename: name of the file + :type filename: string + """ + G = graph2nx(g) + nx.drawing.nx_pydot.write_dot(G, filename) + + +def nx2graph(G): + """ + Convert NetworkX format graph to ``gunfolds`` graph ignoring bidirected edges + + :param G: ``gunfolds`` format graph + :type G: dictionary (``gunfolds`` graphs) + + :returns: ``gunfolds`` graph + :rtype: dictionary (``gunfolds`` graphs) + """ + g = {n: {} for n in G} + for n in G: + g[n] = {x: 1 for x in G[n]} + return g + +def g2ig(g): + """ + Converts our graph representation to an igraph for plotting + + :param g: ``gunfolds`` graph + :type g: dictionary (``gunfolds`` graphs) + + :returns: igraph representation of ``gunfolds`` graph + :rtype: igraph + """ + t = np.where(graph2adj(g) == 1) + l = zip(t[0], t[1]) + ig = igraph.Graph(l, directed=True) + ig.vs["name"] = np.sort([u for u in g]) + ig.vs["label"] = ig.vs["name"] + return ig - return graph_dict, A_matrix, B_matrix \ No newline at end of file +################### Add only new functions to external conversions above ############# +################### End of External Conversions ######################## \ No newline at end of file diff --git a/sphinx-build/conversions/internal.rst b/sphinx-build/conversions/internal.rst index 1103e6c6..9164c88c 100644 --- a/sphinx-build/conversions/internal.rst +++ b/sphinx-build/conversions/internal.rst @@ -38,6 +38,11 @@ g2vec .. autofunction:: gunfolds.conversions.g2vec +Glag2CG +------- +.. autofunction:: gunfolds.conversions.Glag2CG + + graph2adj --------- .. autofunction:: gunfolds.conversions.graph2adj @@ -63,6 +68,11 @@ num2CG .. autofunction:: gunfolds.conversions.num2CG +nxbp2graph +---------- +.. autofunction:: gunfolds.conversions.nxbp2graph + + ug2num ------ .. autofunction:: gunfolds.conversions.ug2num diff --git a/sphinx-build/estimation/linear_model.rst b/sphinx-build/estimation/linear_model.rst index 7f16f30c..d110b9bf 100644 --- a/sphinx-build/estimation/linear_model.rst +++ b/sphinx-build/estimation/linear_model.rst @@ -8,21 +8,6 @@ AB2intAB .. autofunction:: gunfolds.estimation.linear_model.AB2intAB -G2AH ----- -.. autofunction:: gunfolds.estimation.linear_model.G2AH - - -G2SVAR ------- -.. autofunction:: gunfolds.estimation.linear_model.G2SVAR - - -VARbic ------- -.. autofunction:: gunfolds.estimation.linear_model.VARbic - - amap ---- .. autofunction:: gunfolds.estimation.linear_model.amap @@ -38,16 +23,16 @@ data2AB .. autofunction:: gunfolds.estimation.linear_model.data2AB -data2VARgraph -------------- -.. autofunction:: gunfolds.estimation.linear_model.data2VARgraph - - data2graph ---------- .. autofunction:: gunfolds.estimation.linear_model.data2graph +data2VARgraph +------------- +.. autofunction:: gunfolds.estimation.linear_model.data2VARgraph + + decide\_absences ---------------- .. autofunction:: gunfolds.estimation.linear_model.decide_absences @@ -73,6 +58,16 @@ estimateSVAR .. autofunction:: gunfolds.estimation.linear_model.estimateSVAR +G2AH +---- +.. autofunction:: gunfolds.estimation.linear_model.G2AH + + +G2SVAR +------ +.. autofunction:: gunfolds.estimation.linear_model.G2SVAR + + genData ------- .. autofunction:: gunfolds.estimation.linear_model.genData @@ -178,6 +173,11 @@ transitionMatrix4 .. autofunction:: gunfolds.estimation.linear_model.transitionMatrix4 +VARbic +------ +.. autofunction:: gunfolds.estimation.linear_model.VARbic + + weight\_and\_mask ----------------- .. autofunction:: gunfolds.estimation.linear_model.weight_and_mask diff --git a/sphinx-build/getting_started.rst b/sphinx-build/getting_started.rst index c619afc1..efc2b99a 100644 --- a/sphinx-build/getting_started.rst +++ b/sphinx-build/getting_started.rst @@ -6,4 +6,4 @@ Getting Started getting_started/tutorials getting_started/contributors getting_started/publications - + diff --git a/sphinx-build/run.py b/sphinx-build/run.py index 4b82d569..37e89327 100644 --- a/sphinx-build/run.py +++ b/sphinx-build/run.py @@ -37,7 +37,7 @@ def rst4conv(module, rst_name, names): print(".. currentmodule:: gunfolds." + module, file=rst_file) print("\n", file=rst_file) function_names = names - function_names.sort() + function_names.sort(key = lambda x:x.lower()) for func in function_names: funct = "" for c in func: @@ -64,13 +64,14 @@ def rst4conv(module, rst_name, names): print(" conversions/clingo", file=rst_file) print(" conversions/external", file=rst_file) print(" conversions/internal", file=rst_file) - graph_conv = ["nodenum", "g2num", "ug2num", "bg2num", "num2CG", "dict_format_converter", "g2ian", "ian2g", - "edgepairs2g", "graph2adj", "graph2badj", "adjs2graph", "g2vec", "vec2adj", "vec2g"] - clingo_conv = ["rate", "clingo_preamble", "g2clingo", "numbered_g2clingo", "clingo_wedge", "numbered_g2wclingo", - "g2wclingo", "clingo2num", "rasl_a2edgetuple", "a2edgetuple", "rasl_c2edgepairs", "c2edgepairs", - "msl_jclingo2g", "rasl_jclingo2g", "drasl_jclingo2g", "old_g2clingo", "encode_sccs", - "encode_list_sccs"] - other_conv = ["graph2nx", "graph2dot", "nx2graph", "g2ig"] + function_names = extract_function_names("../gunfolds/conversions.py") + indx = [] + for i in range(len(function_names)): + if function_names[i]=="sphinx_automation_fake": + indx.append(i) + graph_conv = function_names[0:indx[0]] + clingo_conv = function_names[indx[0]+1:indx[1]] + other_conv = function_names[indx[1]+1:] rst4conv(module, "internal", graph_conv) rst4conv(module, "clingo", clingo_conv) rst4conv(module, "external", other_conv) @@ -91,7 +92,7 @@ def rst4estimation(module): print("\n", file=rst_file) file_path = "../../gunfolds/estimation" function_names = extract_function_names(file_path + "/" + module + ".py") - function_names.sort() + function_names.sort(key = lambda x:x.lower()) for func in function_names: funct = "" for c in func: @@ -118,7 +119,7 @@ def rst4estimation(module): print(len(s) * "=", file=rst_file) print(".. toctree::\n", file=rst_file) li = os.listdir("../gunfolds/estimation") - li.sort() + li.sort(key = lambda x:x.lower()) for filename in li: if filename.endswith(".py") and not filename.endswith("__.py"): print(" estimation/" + filename[:-3], file=rst_file) @@ -151,7 +152,7 @@ def rst4solvers(module): print("\n", file=rst_file) file_path = "../../../gunfolds/solvers" function_names = extract_function_names(file_path + "/" + module + ".py") - function_names.sort() + function_names.sort(key = lambda x:x.lower()) for func in function_names: funct = "" for c in func: @@ -215,7 +216,7 @@ def rst4utils(module): print("\n", file=rst_file) file_path = "../../gunfolds/utils" function_names = extract_function_names(file_path + "/" + module + ".py") - function_names.sort() + function_names.sort(key = lambda x:x.lower()) for func in function_names: funct = "" for c in func: @@ -242,7 +243,7 @@ def rst4utils(module): print(len(s) * "=", file=rst_file) print(".. toctree::\n", file=rst_file) li = os.listdir("../gunfolds/utils") - li.sort() + li.sort(key = lambda x:x.lower()) for filename in li: if filename.endswith(".py") and not filename.endswith("__.py"): print(" utils/" + filename[:-3], file=rst_file) @@ -263,7 +264,7 @@ def rst4viz(module): print("\n", file=rst_file) file_path = "../../gunfolds/viz" function_names = extract_function_names(file_path + "/" + module + ".py") - function_names.sort() + function_names.sort(key = lambda x:x.lower()) for func in function_names: funct = "" for c in func: @@ -290,7 +291,7 @@ def rst4viz(module): print(len(s) * "=", file=rst_file) print(".. toctree::\n", file=rst_file) li = os.listdir("../gunfolds/viz") - li.sort() + li.sort(key = lambda x:x.lower()) for filename in li: if filename.endswith(".py") and not filename.endswith("__.py"): print(" viz/" + filename[:-3], file=rst_file) \ No newline at end of file diff --git a/sphinx-build/solvers/imperative/traversal.rst b/sphinx-build/solvers/imperative/traversal.rst index b5b11e58..9a118eb0 100644 --- a/sphinx-build/solvers/imperative/traversal.rst +++ b/sphinx-build/solvers/imperative/traversal.rst @@ -13,11 +13,6 @@ addaAedge .. autofunction:: gunfolds.solvers.traversal.addaAedge -addaVpath ---------- -.. autofunction:: gunfolds.solvers.traversal.addaVpath - - addacedge --------- .. autofunction:: gunfolds.solvers.traversal.addacedge @@ -38,11 +33,21 @@ addavedge .. autofunction:: gunfolds.solvers.traversal.addavedge +addaVpath +--------- +.. autofunction:: gunfolds.solvers.traversal.addaVpath + + check3 ------ .. autofunction:: gunfolds.solvers.traversal.check3 +checkable +--------- +.. autofunction:: gunfolds.solvers.traversal.checkable + + checkAedge ---------- .. autofunction:: gunfolds.solvers.traversal.checkAedge @@ -53,11 +58,6 @@ checkApath .. autofunction:: gunfolds.solvers.traversal.checkApath -checkable ---------- -.. autofunction:: gunfolds.solvers.traversal.checkable - - checkbedges ----------- .. autofunction:: gunfolds.solvers.traversal.checkbedges @@ -98,16 +98,16 @@ chunks .. autofunction:: gunfolds.solvers.traversal.chunks -cleanVedges ------------ -.. autofunction:: gunfolds.solvers.traversal.cleanVedges - - cleanedges ---------- .. autofunction:: gunfolds.solvers.traversal.cleanedges +cleanVedges +----------- +.. autofunction:: gunfolds.solvers.traversal.cleanVedges + + cloneempty ---------- .. autofunction:: gunfolds.solvers.traversal.cloneempty @@ -133,11 +133,6 @@ delaAedge .. autofunction:: gunfolds.solvers.traversal.delaAedge -delaVpath ---------- -.. autofunction:: gunfolds.solvers.traversal.delaVpath - - delacedge --------- .. autofunction:: gunfolds.solvers.traversal.delacedge @@ -158,6 +153,11 @@ delavedge .. autofunction:: gunfolds.solvers.traversal.delavedge +delaVpath +--------- +.. autofunction:: gunfolds.solvers.traversal.delaVpath + + edge\_function\_idx ------------------- .. autofunction:: gunfolds.solvers.traversal.edge_function_idx @@ -293,11 +293,6 @@ maskaCedge .. autofunction:: gunfolds.solvers.traversal.maskaCedge -maskaVpath ----------- -.. autofunction:: gunfolds.solvers.traversal.maskaVpath - - maskanedge ---------- .. autofunction:: gunfolds.solvers.traversal.maskanedge @@ -313,6 +308,11 @@ maskavedge .. autofunction:: gunfolds.solvers.traversal.maskavedge +maskaVpath +---------- +.. autofunction:: gunfolds.solvers.traversal.maskaVpath + + memo\_no\_return ---------------- .. autofunction:: gunfolds.solvers.traversal.memo_no_return @@ -328,11 +328,6 @@ ok2addaAedge .. autofunction:: gunfolds.solvers.traversal.ok2addaAedge -ok2addaVpath ------------- -.. autofunction:: gunfolds.solvers.traversal.ok2addaVpath - - ok2addacedge ------------ .. autofunction:: gunfolds.solvers.traversal.ok2addacedge @@ -363,6 +358,11 @@ ok2addavedge .. autofunction:: gunfolds.solvers.traversal.ok2addavedge +ok2addaVpath +------------ +.. autofunction:: gunfolds.solvers.traversal.ok2addaVpath + + prune\_sort\_CDS ---------------- .. autofunction:: gunfolds.solvers.traversal.prune_sort_CDS diff --git a/sphinx-build/solvers/imperative/unknownrate.rst b/sphinx-build/solvers/imperative/unknownrate.rst index 0f3a5181..be047110 100644 --- a/sphinx-build/solvers/imperative/unknownrate.rst +++ b/sphinx-build/solvers/imperative/unknownrate.rst @@ -53,16 +53,16 @@ confpairs .. autofunction:: gunfolds.solvers.unknownrate.confpairs -delAloop --------- -.. autofunction:: gunfolds.solvers.unknownrate.delAloop - - del\_loop --------- .. autofunction:: gunfolds.solvers.unknownrate.del_loop +delAloop +-------- +.. autofunction:: gunfolds.solvers.unknownrate.delAloop + + e2num ----- .. autofunction:: gunfolds.solvers.unknownrate.e2num diff --git a/sphinx-build/utils/comparison.rst b/sphinx-build/utils/comparison.rst index 768a346f..dd63db80 100644 --- a/sphinx-build/utils/comparison.rst +++ b/sphinx-build/utils/comparison.rst @@ -3,16 +3,6 @@ comparison .. currentmodule:: gunfolds.utils.comparison -SM\_converging --------------- -.. autofunction:: gunfolds.utils.comparison.SM_converging - - -SM\_fixed ---------- -.. autofunction:: gunfolds.utils.comparison.SM_fixed - - compatible\_at\_u ----------------- .. autofunction:: gunfolds.utils.comparison.compatible_at_u @@ -48,3 +38,13 @@ search\_match .. autofunction:: gunfolds.utils.comparison.search_match +SM\_converging +-------------- +.. autofunction:: gunfolds.utils.comparison.SM_converging + + +SM\_fixed +--------- +.. autofunction:: gunfolds.utils.comparison.SM_fixed + + diff --git a/sphinx-build/utils/graphkit.rst b/sphinx-build/utils/graphkit.rst index f90fe68d..2434b5fe 100644 --- a/sphinx-build/utils/graphkit.rst +++ b/sphinx-build/utils/graphkit.rst @@ -3,16 +3,6 @@ graphkit .. currentmodule:: gunfolds.utils.graphkit -OCE ---- -.. autofunction:: gunfolds.utils.graphkit.OCE - - -\_OCE ------ -.. autofunction:: gunfolds.utils.graphkit._OCE - - \_normed\_OCE ------------- .. autofunction:: gunfolds.utils.graphkit._normed_OCE @@ -23,21 +13,26 @@ OCE .. autofunction:: gunfolds.utils.graphkit._normed_undirected_OCE +\_OCE +----- +.. autofunction:: gunfolds.utils.graphkit._OCE + + \_undirected\_OCE ----------------- .. autofunction:: gunfolds.utils.graphkit._undirected_OCE -addAring --------- -.. autofunction:: gunfolds.utils.graphkit.addAring - - addanedge --------- .. autofunction:: gunfolds.utils.graphkit.addanedge +addAring +-------- +.. autofunction:: gunfolds.utils.graphkit.addAring + + addedges -------- .. autofunction:: gunfolds.utils.graphkit.addedges @@ -183,6 +178,11 @@ no\_parents .. autofunction:: gunfolds.utils.graphkit.no_parents +OCE +--- +.. autofunction:: gunfolds.utils.graphkit.OCE + + oerror ------ .. autofunction:: gunfolds.utils.graphkit.oerror