def test_get_components(self): """""" comps = self.ugraph4.get_components() cs = list(comps) cs0ns = BaseGraphOps.nodes(cs[0]) cs0es = BaseGraphOps.edges(cs[0]) # cs1ns = BaseGraphOps.nodes(cs[1]) cs1es = BaseGraphOps.edges(cs[1]) # # compare graphs # first component u2nodes = set([self.a, self.b, self.e, self.f]) u2edges = set([self.ab, self.af, self.ae, self.be, self.ef]) # second component g2node = set([self.n1, self.n2, self.n3, self.n4]) g2edge = set([self.e1, self.e2, self.e3, self.e4]) # cond1 = u2nodes == cs0ns or u2nodes == cs1ns # cond2 = g2node == cs0ns or g2node == cs1ns # cond3 = u2edges == cs0es or u2edges == cs1es cond4 = g2edge == cs0es or g2edge == cs1es self.assertTrue(cond1) self.assertTrue(cond2) self.assertTrue(cond3) self.assertTrue(cond4)
def is_proper_subgraph(g1: AbstractGraph, g2: AbstractGraph) -> bool: "check if g2 is subgraph of g1" ns = BaseGraphOps.nodes(g2) es = BaseGraphOps.edges(g2) contains_nodes = BaseGraphOps.contains(g1, ns) contains_edges = BaseGraphOps.contains(g1, es) return contains_edges and contains_nodes
def nodes_per_level(self, level: int) -> Set[Node]: """! extract nodes of certain level in tree """ return set([ n for n in BaseGraphOps.nodes(self) if self.height_of(n) == level ])
def test__sub__n(self): """""" n = Node("n646", {}) g = self.graph - n self.assertEqual( BaseGraphOps.nodes(g), set([self.n1, self.n2, self.n3, self.n4]) )
def is_induced_subgraph(g1: AbstractGraph, g2: AbstractGraph) -> bool: """ check if g2 is induced subgraph of g1 induced subgraph: g2 \sub g1 ^ xy \in Edge[g1] with x,y Vertex[g2] """ is_subgraph = BaseGraphAnalyzer.is_subgraph(g1, g2) if not is_subgraph: return False g2_vertices = BaseGraphOps.nodes(g2) g1_edges = BaseGraphOps.edges(g1) for g1_edge in g1_edges: has_node_id1 = False has_node_id2 = False edge_node_ids = g1_edge.node_ids() edge_node_id1 = edge_node_ids[0] edge_node_id2 = edge_node_ids[1] for g2_vertex in g2_vertices: vertex_id = g2_vertex.id() if vertex_id == edge_node_id1: has_node_id1 = True if vertex_id == edge_node_id2: has_node_id2 = True # if not has_node_id1 and not has_node_id2: return False return True
def from_digraph(cls, dig: DiGraph, fs: Optional[Set[Factor]]): """! \brief Construct a BayesianNetwork from a directed graph We assume that edges encode an independence structure of the system. Hence we deduce factors from them. If there is any evidence associated with a random variable, we apply them to reduce factors. \param dig A Directed Graph whose nodes are random variables \return BayesianNetwork \code{.py} >>> myDiGraph = DiGraph() \endcode """ if fs is None: fs = cls.deduce_factors_from_digraph(dig) # return BayesianNetwork( gid=str(uuid4()), nodes=BaseGraphOps.nodes(dig), edges=BaseGraphOps.edges(dig), factors=fs, )
def test_from_edgeset(self): """""" eset = set([self.e1, self.e2, self.e3, self.e4]) g = Graph.from_edgeset(eset) self.assertEqual( BaseGraphOps.nodes(g), set([self.n1, self.n2, self.n3, self.n4]) ) self.assertEqual(BaseGraphOps.edges(g), eset)
def find_maximal_cliques(self): """! find maximal cliques in graph using Bron Kerbosch algorithm as per arxiv.org/1006.5440 """ P: Set[Node] = BaseGraphOps.nodes(self) X: Set[Node] = set() R: Set[Node] = set() Cs: List[Set[Node]] = [] self.bron_kerbosch(P, R, X, Cs) return Cs
def cond_prod_by_variable_elimination( self, queries: Set[NumCatRVariable], evidences: Set[Tuple[str, NumericValue]], ordering_fn=min_unmarked_neighbours, ): """! Compute conditional probabilities with variable elimination from Koller and Friedman 2009, p. 304 """ if queries.issubset(BaseGraphOps.nodes(self)) is False: raise ValueError( "Query variables must be a subset of vertices of graph") queries = self.reduce_queries_with_evidence(queries, evidences) factors, E = self.reduce_factors_with_evidence(evidences) Zs = set() for z in BaseGraphOps.nodes(self): if z not in E and z not in queries: Zs.add(z) return self.conditional_prod_by_variable_elimination( queries=queries, Zs=Zs, factors=factors, ordering_fn=ordering_fn)
def test__add__g(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 = Graph(gid="temp", data={}, nodes=set([n, n1, n2]), edges=set([e])) g = 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 test_subtract_g(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, self.e1]), ) g = BaseGraphAlgOps.subtract(self.graph, gg) self.assertEqual(BaseGraphOps.edges(g), set([])) self.assertEqual(BaseGraphOps.nodes(g), set([self.n3, self.n4]))
def from_graph(cls, g: Graph): """! \brief Construct an undirected graph from given graph. \throws ValueError if the graph contains a directed edge. \param g source graph """ for e in BaseGraphOps.edges(g): if e.type() == EdgeType.DIRECTED: raise ValueError("Graph contains directed edges") return UndiGraph( gid=str(uuid4()), data=g.data(), nodes=BaseGraphOps.nodes(g), edges=BaseGraphOps.edges(g), )
def is_stable(g: AbstractGraph, ns: FrozenSet[AbstractNode]) -> bool: """! \brief check if given node set is stable We ensure that no nodes in the given node set is a neighbour of one another as per the definition of Diestel 2017, p. 3. \throws ValueError if argument node set is not a subset of vertices of the graph \code{.py} >>> n1 = Node("n1", {}) >>> n2 = Node("n2", {}) >>> n3 = Node("n3", {}) >>> n4 = Node("n4", {}) >>> n5 = Node("n5", {}) >>> e1 = Edge( >>> "e1", start_node=n1, end_node=n2, edge_type=EdgeType.UNDIRECTED >>> ) >>> e2 = Edge( >>> "e2", start_node=n2, end_node=n3, edge_type=EdgeType.UNDIRECTED >>> ) >>> e3 = Edge( >>> "e3", start_node=n3, end_node=n4, edge_type=EdgeType.UNDIRECTED >>> ) >>> graph_2 = Graph( >>> "g2", >>> data={"my": "graph", "data": "is", "very": "awesome"}, >>> nodes=set([n1, n2, n3, n4, n5]), >>> edges=set([e1, e2, e3]), >>> ) >>> graph_2.is_stable(set([n1, n3, n5])) >>> True \endcode """ if ns.issubset(BaseGraphOps.nodes(g)) is False: raise ValueError("node set is not contained in graph") node_list = list(ns) while node_list: n1 = node_list.pop() for n2 in node_list: if g.is_neighbour_of(n1=n1, n2=n2): return False return True
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 set_op_node_edge( g: AbstractGraph, obj: Union[Set[AbstractNode], Set[AbstractEdge]], op: Callable[[Union[Set[AbstractNode], Set[AbstractEdge]]], Union[Set[AbstractNode], Set[AbstractEdge]], ], ): """!""" is_eset = all(isinstance(o, AbstractEdge) for o in obj) if is_eset: edges = BaseGraphOps.edges(g) return op(edges, obj) is_nset = all(isinstance(o, AbstractNode) for o in obj) if is_nset is False: raise TypeError("argument type is not supported: " + type(obj).__name__) # nodes = BaseGraphOps.nodes(g) return op(nodes, obj)
def max_product_ve(self, evidences: Set[Tuple[str, NumericValue]]): """! Compute most probable assignments given evidences """ factors, E = self.reduce_factors_with_evidence(evidences) Zs = set() for z in BaseGraphOps.nodes(self): if z not in E: Zs.add(z) cardinality = self.order_by_greedy_metric(nodes=Zs, s=min_unmarked_neighbours) V = {v.id(): v for v in self.V} ordering = [ V[n[0]] for n in sorted(list(cardinality.items()), key=lambda x: x[1]) ] assignments, factors, z_phi = self.max_product_eliminate_vars( factors=factors, Zs=ordering) return assignments, factors, z_phi
def find_articulation_points( self, graph_maker: Callable[[Node], GraphObject]) -> Set[Node]: """! \brief find articulation points of graph. Find the articulation points of a graph. An articulation point, also called cut vertex is defined as the vertex that separates two other vertices of the same component. The algorithm we implement here is the naive version see, Erciyes 2018, p. 228. For the definition of the cut vertex, see Diestel 2017, p. 11 """ nb_component = self.nb_components() points: Set[Node] = set() for node in BaseGraphOps.nodes(self): graph = graph_maker(node) if graph.nb_components() > nb_component: points.add(node) return points
def is_disjoint(g1: AbstractGraph, g2: AbstractGraph) -> bool: "check if g2 is disjoint to g1" ns = BaseGraphOps.nodes(g1) ns_ = g2.vertex_intersection(ns) return len(ns_) == 0
def is_spanning_subgraph(g1: AbstractGraph, g2: AbstractGraph) -> bool: "check if g2 is spanning subgraph of g1" if not BaseGraphAnalyzer.is_subgraph(g1, g2): return False return BaseGraphOps.nodes(g1) == BaseGraphOps.nodes(g2)
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_2 = UndiGraph( "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.c = Node("c", {}) self.d = Node("d", {}) self.f = Node("f", {}) # d self.e = Node("e", {}) # e self.g = Node("g", {}) self.h = Node("h", {}) 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, data={"w": 1}, edge_type=EdgeType.UNDIRECTED, ) self.af = Edge( "af", start_node=self.a, end_node=self.f, edge_type=EdgeType.UNDIRECTED, ) self.ah = Edge( "ah", start_node=self.a, end_node=self.h, edge_type=EdgeType.UNDIRECTED, ) self.bh = Edge( "bh", start_node=self.b, end_node=self.h, edge_type=EdgeType.UNDIRECTED, ) self.be = Edge( "be", start_node=self.b, end_node=self.e, edge_type=EdgeType.UNDIRECTED, ) self.ef = Edge( "ef", data={"w": 5}, start_node=self.e, end_node=self.f, edge_type=EdgeType.UNDIRECTED, ) self.de = Edge( "de", data={"w": 4}, start_node=self.d, end_node=self.e, edge_type=EdgeType.UNDIRECTED, ) self.df = Edge( "df", data={"w": 8}, start_node=self.d, end_node=self.f, edge_type=EdgeType.UNDIRECTED, ) self.cd = Edge( "cd", data={"w": 3}, start_node=self.c, end_node=self.d, edge_type=EdgeType.UNDIRECTED, ) self.cg = Edge( "cg", start_node=self.c, end_node=self.g, edge_type=EdgeType.UNDIRECTED, ) self.gd = Edge( "gd", data={"w": 7}, start_node=self.g, end_node=self.d, edge_type=EdgeType.UNDIRECTED, ) self.bg = Edge( "bg", data={"w": 6}, start_node=self.b, end_node=self.g, edge_type=EdgeType.UNDIRECTED, ) self.fg = Edge( "fg", start_node=self.f, end_node=self.g, edge_type=EdgeType.UNDIRECTED, ) self.bc = Edge( "bc", start_node=self.b, end_node=self.c, data={"w": 2}, edge_type=EdgeType.UNDIRECTED, ) # undirected graph self.ugraph1 = UndiGraph( "ug1", 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, ]), ) # ugraph1: # +-----+ # / \ # a b e # \ / # +-----f self.ugraph2 = UndiGraph( "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 = UndiGraph( "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 = UndiGraph( "ug4", data={ "my": "graph", "data": "is", "very": "awesome" }, nodes=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 self.ugraph5 = UndiGraph( "ug5", data={ "my": "graph", "data": "is", "very": "awesome" }, nodes=set([self.a, self.b, self.c, self.d, self.e, self.f, self.g]), edges=set([ self.ab, self.bc, self.bg, self.cd, self.gd, self.df, self.de, self.ef, ]), ) # ugraph 5 # +----c---+ +--e # / 2 3 \ / 4 | # a --- b d | 5 # 1 \ 6 7 / \ 8 | # +---g---+ +--f self.ugraph6 = UndiGraph( "ug6", data={ "my": "graph", "data": "is", "very": "awesome" }, nodes=set([ self.a, self.b, self.c, self.d, self.e, self.f, self.g, self.h, ]), edges=set([ self.ab, self.ah, self.bc, self.bh, self.cd, self.de, self.df, self.cg, self.fg, ]), ) # ugraph 6 # a--+ e----d # | \ / \ # | b----c f # | / \ / # h--+ g self.ad = Edge( "ad", start_node=self.a, end_node=self.d, edge_type=EdgeType.UNDIRECTED, ) # self.ugraph7 = UndiGraph( "ug7", nodes=set([self.a, self.b, self.c, self.d]), edges=set([self.ab, self.bc, self.cd, self.ad]), )
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.directed("e1", start_node=self.n1, end_node=self.n2) self.e2 = Edge.directed("e2", start_node=self.n2, end_node=self.n3) self.e3 = Edge.directed("e3", start_node=self.n3, end_node=self.n4) self.e4 = Edge.directed("e4", start_node=self.n1, end_node=self.n4) self.graph_2 = DiGraph( "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.e4]), ) # # n1 → n2 → n3 → n4 # | ↑ # +--------------+ self.a = Node("a", {}) # b self.b = Node("b", {}) # c self.c = Node("c", {}) self.d = Node("d", {}) self.f = Node("f", {}) # d self.e = Node("e", {}) # e self.g = Node("g", {}) self.h = Node("h", {}) self.ae = Edge.directed("ae", start_node=self.a, end_node=self.e) self.ab = Edge.directed("ab", start_node=self.a, end_node=self.b) self.af = Edge.directed("af", start_node=self.a, end_node=self.f) self.ah = Edge.directed("ah", start_node=self.a, end_node=self.h) self.bh = Edge.directed("bh", start_node=self.b, end_node=self.h) self.be = Edge.directed("be", start_node=self.b, end_node=self.e) self.ef = Edge.directed("ef", start_node=self.e, end_node=self.f) self.de = Edge.directed("de", start_node=self.d, end_node=self.e) self.df = Edge.directed("df", start_node=self.d, end_node=self.f) self.cd = Edge.directed("cd", start_node=self.c, end_node=self.d) self.cg = Edge.directed("cg", start_node=self.c, end_node=self.g) self.gd = Edge.directed("gd", start_node=self.g, end_node=self.d) self.bg = Edge.directed("bg", start_node=self.b, end_node=self.g) self.fg = Edge.directed("fg", start_node=self.f, end_node=self.g) self.bc = Edge.directed("bc", start_node=self.b, end_node=self.c) # directed graph self.dgraph1 = DiGraph( "dg1", 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, ]), ) # dgraph1: # # # a --------> e b # | | # +---> f <---+ # self.dgraph2 = DiGraph( "dg2", 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, ]), ) # dgraph2 : # # a -> b -> e -> f # | ↑ ↑ # +---------+----+ self.dgraph3 = DiGraph( "dg3", 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, ]), ) # dgraph3 : # # a -> b -> e # \ # +---> f self.dgraph4 = DiGraph( "dg4", data={ "my": "graph", "data": "is", "very": "awesome" }, nodes=BaseGraphOps.nodes(self.dgraph2).union( BaseGraphOps.nodes(self.graph_2)), edges=BaseGraphOps.edges(self.dgraph2).union( BaseGraphOps.edges(self.graph_2)), ) # dgraph 4 # # a -> b -> e -> f n1 -> n2 -> n3 -> n4 # | ↑ ↑ | ↑ # +---------+----+ +------------------+ self.e_n = Edge.directed("en", start_node=self.e, end_node=self.n1) self.dgraph5 = DiGraph( "dg5", data={ "my": "graph", "data": "is", "very": "awesome" }, nodes=set([self.a, self.b, self.c, self.d, self.e, self.f, self.g]), edges=set([ self.ab, self.bc, self.bg, self.cd, self.gd, self.df, self.de, self.ef, ]), ) # dgraph 5 # +--> c +---> e # / \ / | # a -> b +--> d | # \ / \ v # +--> g +---> f self.dgraph6 = DiGraph( "dg6", data={ "my": "graph", "data": "is", "very": "awesome" }, nodes=set([ self.a, self.b, self.c, self.d, self.e, self.f, self.g, self.h, ]), edges=set([ self.ab, self.ah, self.bc, self.bh, self.cd, self.de, self.df, self.cg, self.fg, ]), )
def is_set_of(self, n: Node, fn: Callable[[Node, Node], bool]) -> Set[Node]: nodes = BaseGraphOps.nodes(self) nset = set([y for y in nodes if fn(n, y) is True]) return nset
def test_add_node(self): n = Node("n646", {}) g = BaseGraphAlgOps.add(self.graph, n) self.assertEqual( BaseGraphOps.nodes(g), set([self.n1, self.n2, self.n3, self.n4, n]) )
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, )