def from_base_graph(cls, bgraph: BaseGraph): "Obtain finite graph from base graph" nodes = set(bgraph.V) edges = set(bgraph.E) data = bgraph.data() gid = bgraph.id() return Graph(gid=gid, nodes=nodes, edges=edges, data=data)
def setUp(self): self.n1 = Node("n1", {}) self.n2 = Node("n2", {}) self.n3 = Node("n3", {}) self.n4 = Node("n4", {}) self.n5 = Node("n5", {}) self.e1 = Edge.undirected("e1", start_node=self.n1, end_node=self.n2) self.e2 = Edge.undirected("e2", start_node=self.n2, end_node=self.n3) self.e3 = Edge.undirected("e3", start_node=self.n3, end_node=self.n4) self.e4 = Edge.undirected("e4", start_node=self.n1, end_node=self.n4) self.graph = BaseGraph( "g1", data={ "my": "graph", "data": "is", "very": "awesome" }, nodes=set([self.n1, self.n2, self.n3, self.n4]), edges=set([self.e1, self.e2]), ) # intialize profiler self.prof = cProfile.Profile() self.prof.enable() self.verbose = False
def test_has_self_loop(self): """""" n1 = Node("n1", {}) n2 = Node("n2", {}) e1 = Edge("e1", start_node=n1, end_node=n2, edge_type=EdgeType.UNDIRECTED) e2 = Edge("e2", start_node=n1, end_node=n1, edge_type=EdgeType.UNDIRECTED) g1 = BaseGraph("graph", nodes=set([n1, n2]), edges=set([e1, e2])) g2 = BaseGraph("graph", nodes=set([n1, n2]), edges=set([e1])) self.assertTrue(BaseGraphAnalyzer.has_self_loop(g1)) self.assertFalse(BaseGraphAnalyzer.has_self_loop(g2))
def to_base_graph(self): """! Transform Graph object to BaseGraph object """ return BaseGraph( gid=self.id(), nodes=set(self.V.values()), edges=set(self.E.values()), data=self.data(), )
class BaseGraphTest(unittest.TestCase): def setUp(self): self.n1 = Node("n1", {}) self.n2 = Node("n2", {}) self.n3 = Node("n3", {}) self.n4 = Node("n4", {}) self.n5 = Node("n5", {}) self.e1 = Edge.undirected("e1", start_node=self.n1, end_node=self.n2) self.e2 = Edge.undirected("e2", start_node=self.n2, end_node=self.n3) self.e3 = Edge.undirected("e3", start_node=self.n3, end_node=self.n4) self.e4 = Edge.undirected("e4", start_node=self.n1, end_node=self.n4) self.graph = BaseGraph( "g1", data={ "my": "graph", "data": "is", "very": "awesome" }, nodes=set([self.n1, self.n2, self.n3, self.n4]), edges=set([self.e1, self.e2]), ) # intialize profiler self.prof = cProfile.Profile() self.prof.enable() self.verbose = False def tearDown(self): """ """ p = Stats(self.prof) p.sort_stats("cumtime") if self.verbose is True: p.dump_stats("profiles/test_basegraph.py.prof") p.strip_dirs() def test_id(self): return self.assertEqual(self.graph.id(), "g1") def test_V(self): """""" V = {v.id(): v for v in self.graph.V} nodes = {"n1": self.n1, "n2": self.n2, "n3": self.n3, "n4": self.n4} for nid, node in nodes.copy().items(): self.assertEqual(nid in V, nid in nodes) self.assertEqual(V[nid], nodes[nid]) def test_E(self): """""" E = {e.id(): e for e in self.graph.E} edges = {"e1": self.e1, "e2": self.e2} for eid, edge in edges.copy().items(): self.assertEqual(eid in E, eid in edges) self.assertEqual(E[eid], edges[eid])
def test_is_trivial_2(self): """""" n = Node("n646", {}) e = Edge("e8", start_node=n, end_node=n, edge_type=EdgeType.UNDIRECTED) check = False try: BaseGraph(gid="temp", data={}, nodes=set([n]), edges=set([e])) except ValueError: check = True self.assertTrue(check)
def test_contains_g(self): """""" es = set([self.e1]) g = BaseGraph( gid="temp", data={}, nodes=set([self.n1, self.n2, self.n3]), edges=es, ) contains = BaseGraphSetOps.contains(g, es) self.assertTrue(contains)
def test_edges_by_end(self): """""" n1 = Node("n1", {}) n2 = Node("n2", {}) e1 = Edge( "e1", start_node=n1, end_node=n2, edge_type=EdgeType.UNDIRECTED ) e2 = Edge( "e2", start_node=n1, end_node=n1, edge_type=EdgeType.UNDIRECTED ) g = BaseGraph("g", nodes=set([n1, n2]), edges=set([e1, e2])) self.assertEqual(BaseGraphOps.edges_by_end(g, n2), set([e1]))
def test_add_graph(self): n = Node("n646", {}) n1 = Node("n647", {}) n2 = Node("n648", {}) e = Edge( "e8", start_node=self.n1, end_node=n, edge_type=EdgeType.UNDIRECTED ) gg = BaseGraph( gid="temp", data={}, nodes=set([n, n1, n2]), edges=set([e]) ) g = BaseGraphAlgOps.add(self.graph, gg) self.assertEqual( BaseGraphOps.nodes(g), set([self.n1, self.n2, self.n3, self.n4, n, n1, n2]), ) self.assertEqual(BaseGraphOps.edges(g), set([e, self.e1, self.e2]))
def set_op( g: AbstractGraph, obj: Union[Set[AbstractNode], Set[AbstractEdge], AbstractGraph, AbstractNode, AbstractEdge, ], op: Callable[[Union[Set[AbstractNode], Set[AbstractEdge]]], Union[Set[AbstractNode], Set[AbstractEdge], AbstractGraph], ], ) -> Optional[Union[Set[AbstractNode], Set[AbstractEdge], bool]]: """! \brief generic set operation for graph \param obj the hooked object to operation. We deduce its corresponding argument from its type. \param op operation that is going to be applied to obj and its corresponding object. The idea is to give a single interface for generic set operation functions. For example if object is a set of nodes we provide the target for the operation as the nodes of this graph, if it is an edge we provide a set of edges of this graph """ is_node = isinstance(obj, AbstractNode) if is_node: return BaseGraphSetOps.set_op_node_edge(g=g, obj=set([obj]), op=op) is_edge = isinstance(obj, AbstractEdge) if is_edge: return BaseGraphSetOps.set_op_node_edge(g=g, obj=set([obj]), op=op) is_set = isinstance(obj, (set, frozenset)) if is_set: return BaseGraphSetOps.set_op_node_edge(g=g, obj=obj, op=op) is_graph = isinstance(obj, AbstractGraph) if is_graph: oeset = BaseGraphOps.edges(obj) onset = BaseGraphOps.nodes(obj) oedge_set = BaseGraphSetOps.set_op(g, obj=oeset, op=op) onode_set = BaseGraphSetOps.set_op(g, obj=onset, op=op) gdata = g.data() gdata.update(obj.data()) return BaseGraph(gid=str(uuid4()), nodes=onode_set, edges=oedge_set, data=gdata) else: raise TypeError("argument type is not supported: " + type(obj).__name__)
def plus_minus_node_edge( g: AbstractGraph, el: Union[Set[AbstractNode], Set[AbstractEdge], AbstractGraph], is_plus=False, ) -> BaseGraph: """! \brief subtraction of elements for G - v cases, see Diestel p. 4 """ if isinstance(el, AbstractGraph): if is_plus is False: elnodes = set(el.V) nodes = {n for n in g.V if n not in elnodes} bg = BaseGraph.based_on_node_set(edges=set(g.E), nodes=nodes) bg.update_data(g.data()) return bg else: nodes = set(g.V).union(el.V) edges = set(g.E).union(el.E) bg = BaseGraph.from_edge_node_set(edges=edges, nodes=nodes) bg.update_data(g.data()) return bg nset = all(isinstance(e, AbstractNode) for e in el) if nset: if is_plus is False: nodes = {n for n in g.V if n not in el} edges = set(g.E) bg = BaseGraph.based_on_node_set(edges=edges, nodes=nodes) bg.update_data(g.data()) return bg else: nodes = set(g.V).union(el) edges = set(g.E) bg = BaseGraph.based_on_node_set(edges=edges, nodes=nodes) bg.update_data(g.data()) return bg eset = all(isinstance(e, AbstractEdge) for e in el) if eset: if is_plus is False: edges = {e for e in g.E if e not in el} bg = BaseGraph.from_edge_node_set(edges=edges, nodes=set(g.V)) bg.update_data(g.data()) return bg else: edges = set(g.E).union(el) bg = BaseGraph.from_edge_node_set(edges=edges, nodes=set(g.V)) bg.update_data(g.data()) return bg
class BaseGraphSearcherTests(unittest.TestCase): """""" def setUp(self): self.verbose = False # # Alan Gibbons, Algorithmic graph theory 1985, p. 22, fig. 1.16 # depth first undirected graph # nodes self.n1 = Node("n1", data={}) self.n2 = Node("n2", data={}) self.n3 = Node("n3", data={}) self.n4 = Node("n4", data={}) self.n5 = Node("n5", data={}) self.n6 = Node("n6", data={}) self.n7 = Node("n7", data={}) self.n8 = Node("n8", data={}) self.n9 = Node("n9", data={}) self.n10 = Node("n10", data={}) self.n11 = Node("n11", data={}) self.n12 = Node("n12", data={}) self.n13 = Node("n13", data={}) # edges self.e1u = Edge.undirected( "n1n4", start_node=self.n1, end_node=self.n4, data={} ) self.e2u = Edge.undirected( "n1n3", start_node=self.n1, end_node=self.n3, data={} ) self.e3u = Edge.undirected( "n1n2", start_node=self.n1, end_node=self.n2, data={} ) self.e4u = Edge.undirected( "n1n5", start_node=self.n1, end_node=self.n5, data={} ) self.e5u = Edge.undirected( "n1n6", start_node=self.n1, end_node=self.n6, data={} ) self.e6u = Edge.undirected( "n1n7", start_node=self.n1, end_node=self.n7, data={} ) self.e7u = Edge.undirected( "n1n8", start_node=self.n1, end_node=self.n8, data={} ) self.e8u = Edge.undirected( "n8n2", start_node=self.n8, end_node=self.n2, data={} ) self.e9u = Edge.undirected( "n9n10", start_node=self.n9, end_node=self.n10, data={} ) self.e10u = Edge.undirected( "n9n13", start_node=self.n9, end_node=self.n13, data={} ) self.e11u = Edge.undirected( "n10n11", start_node=self.n10, end_node=self.n11, data={} ) self.e12u = Edge.undirected( "n10n12", start_node=self.n10, end_node=self.n12, data={} ) self.ugraph = BaseGraph( "ugraph", nodes=set( [ self.n1, self.n2, self.n3, self.n4, self.n5, self.n6, self.n7, self.n8, self.n9, self.n10, self.n11, self.n12, self.n13, ] ), edges=set( [ self.e1u, self.e2u, self.e3u, self.e4u, self.e5u, self.e6u, self.e7u, self.e8u, self.e9u, self.e10u, self.e11u, self.e12u, ] ), data={}, ) # tree self.a = Node("a") self.b = Node("b") self.c = Node("c") self.d = Node("d") self.e = Node("e") self.f = Node("f") self.g = Node("g") self.h = Node("h") self.j = Node("j") self.k = Node("k") self.m = Node("m") # # +--a --+ # | | # b c # | \ # +--+--+ g # | | | | # d e f h -- j # | # +--+---+ # | | # k m # # self.ab = Edge(edge_id="ab", start_node=self.a, end_node=self.b) self.ac = Edge(edge_id="ac", start_node=self.a, end_node=self.c) self.bd = Edge(edge_id="bd", start_node=self.b, end_node=self.d) self.be = Edge(edge_id="be", start_node=self.b, end_node=self.e) self.bf = Edge(edge_id="bf", start_node=self.b, end_node=self.f) self.fk = Edge(edge_id="fk", start_node=self.f, end_node=self.k) self.fm = Edge(edge_id="fm", start_node=self.f, end_node=self.m) self.cg = Edge(edge_id="cg", start_node=self.c, end_node=self.g) self.gh = Edge(edge_id="gh", start_node=self.g, end_node=self.h) self.hj = Edge(edge_id="hj", start_node=self.h, end_node=self.j) self.gtree = BaseGraph.from_edgeset( edges=set( [ self.ab, self.ac, self.bd, self.be, self.bf, self.fk, self.fm, self.cg, self.gh, self.hj, ] ), ) # initialize profiler self.prof = cProfile.Profile() self.prof.enable() # print("\n<<<<--------") def tearDown(self): """ """ p = Stats(self.prof) p.sort_stats("cumtime") if self.verbose is True: p.dump_stats("profiles/test_graphsearcher.py.prof") p.print_stats() p.strip_dirs() # p.print_stats() # print("\n--------->>>") def test_id(self): return self.assertEqual(self.ugraph.id(), "ugraph") @unittest.skip("Implementation is not finished yet") def test_depth_first_search(self): "" def egen(node): return BaseGraphOps.edges_of(self.ugraph, node) result = BaseGraphSearcher.depth_first_search( g=self.ugraph, edge_generator=egen ) self.assertEqual(2, result["nb-component"]) # test leaves preds = result["dfs-trees"] comps = [] for root, c in preds.items(): cd = {} for key, val in c.items(): if val is not None: cd[key] = val comps.append(cd) # print(comps) first = comps.pop(0) def test_uniform_cost_search(self): """""" start_node = self.b goal_node = self.m problem_set = self.gtree.E elist, solution = BaseGraphSearcher.uniform_cost_search( g=self.gtree, goal=goal_node, start=start_node, problem_set=problem_set ) edges = [solution["edge"]] while solution["parent"] is not None: solution = solution["parent"] edges.append(solution["edge"]) edges.pop() # last element edge is None self.assertEqual(list(reversed(edges)), [self.bf, self.fm])
def setUp(self): self.n1 = Node("n1", {}) self.n2 = Node("n2", {}) self.n3 = Node("n3", {}) self.n4 = Node("n4", {}) self.n5 = Node("n5", {}) self.e1 = Edge( "e1", start_node=self.n1, end_node=self.n2, edge_type=EdgeType.UNDIRECTED, ) self.e2 = Edge( "e2", start_node=self.n2, end_node=self.n3, edge_type=EdgeType.UNDIRECTED, ) self.e3 = Edge( "e3", start_node=self.n3, end_node=self.n4, edge_type=EdgeType.UNDIRECTED, ) self.e4 = Edge( "e4", start_node=self.n1, end_node=self.n4, edge_type=EdgeType.UNDIRECTED, ) self.graph = BaseGraph( "g1", data={"my": "graph", "data": "is", "very": "awesome"}, nodes=set([self.n1, self.n2, self.n3, self.n4]), edges=set([self.e1, self.e2]), ) self.graph_2 = BaseGraph( "g2", data={"my": "graph", "data": "is", "very": "awesome"}, nodes=set([self.n1, self.n2, self.n3, self.n4]), edges=set([self.e1, self.e2, self.e3]), ) # self.a = Node("a", {}) # b self.b = Node("b", {}) # c self.f = Node("f", {}) # d self.e = Node("e", {}) # e self.ae = Edge( "ae", start_node=self.a, end_node=self.e, edge_type=EdgeType.UNDIRECTED, ) self.ab = Edge( "ab", start_node=self.a, end_node=self.b, edge_type=EdgeType.UNDIRECTED, ) self.af = Edge( "af", start_node=self.a, end_node=self.f, edge_type=EdgeType.UNDIRECTED, ) self.be = Edge( "be", start_node=self.b, end_node=self.e, edge_type=EdgeType.UNDIRECTED, ) self.ef = Edge( "ef", start_node=self.e, end_node=self.f, edge_type=EdgeType.UNDIRECTED, ) # undirected graph self.ugraph2 = BaseGraph( "ug2", data={"my": "graph", "data": "is", "very": "awesome"}, nodes=set([self.a, self.b, self.e, self.f]), edges=set( [ self.ae, self.ab, self.af, self.be, self.ef, ] ), ) # ugraph2 : # +-----+ # / \ # a -- b -- e # \ / # +-----f self.ugraph3 = BaseGraph( "ug3", data={"my": "graph", "data": "is", "very": "awesome"}, nodes=set([self.a, self.b, self.e, self.f]), edges=set( [ self.ab, # self.af, self.be, ] ), ) # ugraph3 : # # # a -- b -- e # \ # +-----f self.ugraph4 = BaseGraph( "ug4", data={"my": "graph", "data": "is", "very": "awesome"}, nodes=set(BaseGraphOps.nodes(self.ugraph2)).union( BaseGraphOps.nodes(self.graph_2) ), edges=BaseGraphOps.edges(self.ugraph2).union( BaseGraphOps.edges(self.graph_2) ), ) # ugraph 4 # +-----+ n1 -- n2 -- n3 -- n4 # / \ \ / # a -- b -- e +--------------+ # \ / # +-----f # make some directed edges self.bb = Node("bb", {}) self.cc = Node("cc", {}) self.dd = Node("dd", {}) self.ee = Node("ee", {}) self.bb_cc = Edge( "bb_cc", start_node=self.bb, end_node=self.cc, edge_type=EdgeType.DIRECTED, ) self.cc_dd = Edge( "cc_dd", start_node=self.cc, end_node=self.dd, edge_type=EdgeType.DIRECTED, ) self.dd_ee = Edge( "dd_ee", start_node=self.dd, end_node=self.ee, edge_type=EdgeType.DIRECTED, ) self.ee_bb = Edge( "ee_bb", start_node=self.ee, end_node=self.bb, edge_type=EdgeType.DIRECTED, ) self.bb_dd = Edge( "bb_dd", start_node=self.bb, end_node=self.dd, edge_type=EdgeType.DIRECTED, )
def setUp(self): self.verbose = False # # Alan Gibbons, Algorithmic graph theory 1985, p. 22, fig. 1.16 # depth first undirected graph # nodes self.n1 = Node("n1", data={}) self.n2 = Node("n2", data={}) self.n3 = Node("n3", data={}) self.n4 = Node("n4", data={}) self.n5 = Node("n5", data={}) self.n6 = Node("n6", data={}) self.n7 = Node("n7", data={}) self.n8 = Node("n8", data={}) self.n9 = Node("n9", data={}) self.n10 = Node("n10", data={}) self.n11 = Node("n11", data={}) self.n12 = Node("n12", data={}) self.n13 = Node("n13", data={}) # edges self.e1u = Edge.undirected( "n1n4", start_node=self.n1, end_node=self.n4, data={} ) self.e2u = Edge.undirected( "n1n3", start_node=self.n1, end_node=self.n3, data={} ) self.e3u = Edge.undirected( "n1n2", start_node=self.n1, end_node=self.n2, data={} ) self.e4u = Edge.undirected( "n1n5", start_node=self.n1, end_node=self.n5, data={} ) self.e5u = Edge.undirected( "n1n6", start_node=self.n1, end_node=self.n6, data={} ) self.e6u = Edge.undirected( "n1n7", start_node=self.n1, end_node=self.n7, data={} ) self.e7u = Edge.undirected( "n1n8", start_node=self.n1, end_node=self.n8, data={} ) self.e8u = Edge.undirected( "n8n2", start_node=self.n8, end_node=self.n2, data={} ) self.e9u = Edge.undirected( "n9n10", start_node=self.n9, end_node=self.n10, data={} ) self.e10u = Edge.undirected( "n9n13", start_node=self.n9, end_node=self.n13, data={} ) self.e11u = Edge.undirected( "n10n11", start_node=self.n10, end_node=self.n11, data={} ) self.e12u = Edge.undirected( "n10n12", start_node=self.n10, end_node=self.n12, data={} ) self.ugraph = BaseGraph( "ugraph", nodes=set( [ self.n1, self.n2, self.n3, self.n4, self.n5, self.n6, self.n7, self.n8, self.n9, self.n10, self.n11, self.n12, self.n13, ] ), edges=set( [ self.e1u, self.e2u, self.e3u, self.e4u, self.e5u, self.e6u, self.e7u, self.e8u, self.e9u, self.e10u, self.e11u, self.e12u, ] ), data={}, ) # tree self.a = Node("a") self.b = Node("b") self.c = Node("c") self.d = Node("d") self.e = Node("e") self.f = Node("f") self.g = Node("g") self.h = Node("h") self.j = Node("j") self.k = Node("k") self.m = Node("m") # # +--a --+ # | | # b c # | \ # +--+--+ g # | | | | # d e f h -- j # | # +--+---+ # | | # k m # # self.ab = Edge(edge_id="ab", start_node=self.a, end_node=self.b) self.ac = Edge(edge_id="ac", start_node=self.a, end_node=self.c) self.bd = Edge(edge_id="bd", start_node=self.b, end_node=self.d) self.be = Edge(edge_id="be", start_node=self.b, end_node=self.e) self.bf = Edge(edge_id="bf", start_node=self.b, end_node=self.f) self.fk = Edge(edge_id="fk", start_node=self.f, end_node=self.k) self.fm = Edge(edge_id="fm", start_node=self.f, end_node=self.m) self.cg = Edge(edge_id="cg", start_node=self.c, end_node=self.g) self.gh = Edge(edge_id="gh", start_node=self.g, end_node=self.h) self.hj = Edge(edge_id="hj", start_node=self.h, end_node=self.j) self.gtree = BaseGraph.from_edgeset( edges=set( [ self.ab, self.ac, self.bd, self.be, self.bf, self.fk, self.fm, self.cg, self.gh, self.hj, ] ), ) # initialize profiler self.prof = cProfile.Profile() self.prof.enable()
def from_abstract_graph(cls, g_): """""" g = BaseGraph.from_abstract_graph(g_) return cls.from_base_graph(g)
def from_edge_node_set(cls, edges: Set[Edge], nodes: Set[Node]): g = BaseGraph.from_edge_node_set(edges=edges, nodes=nodes) return cls.from_base_graph(g)
def from_edgeset(cls, edges: Set[Edge]): g = BaseGraph.from_edgeset(edges) return cls.from_base_graph(g)