def _test_revuz_minimize(g: IncidenceAutomaton, e_expected: set): before_html = graph_to_html(g) if in_ipynb() else None revuz_minimize(g) if in_ipynb(): after_html = graph_to_html(g) html(beside(before_html, after_html, "Minimization", "Before", "After")) check_graph(g, e_expected)
def test_thompson_compile_nfa_alternation(): (nfa, q0, f) = thompson_compile_nfa("a*|b") if in_ipynb(): ipynb_display_graph(nfa) assert not accepts("bbbbb", nfa) assert accepts("b", nfa) assert accepts("aaaaaa", nfa)
def test_trie_trie(): t1 = make_t1() t2 = make_t2() t1.insert(t2) if in_ipynb(): html(graph_to_html(t1)) assert num_vertices(t1) == 26 assert num_vertices(t2) == 12
def test_graph_to_html_with_weird_chars(): from pybgl.automaton import Automaton, add_edge g = Automaton(2) add_edge(0, 1, WEIRD_CHARS, g) graph_to_html(g) if in_ipynb(): ipynb_display_graph(g)
def test_max_suffix_tree_g(): t = make_suffix_trie("ananas") if in_ipynb(): html(graph_to_html(t)) assert num_vertices(t) == 16 for q in vertices(t): assert is_final(q, t) assert not is_final(BOTTOM, t)
def test_dijkstra_shortest_path(links: list = None): if links is None: links = LINKS # Prepare graph map_eweight = defaultdict(int) pmap_eweight = make_assoc_property_map(map_eweight) g = make_graph(links, pmap_eweight, build_reverse_edge=False) # Dijkstra, stopped when vertex 9 is reached map_vpreds = defaultdict(set) map_vdist = defaultdict(int) s = 0 t = 8 path = dijkstra_shortest_path(g, s, t, pmap_eweight, make_assoc_property_map(map_vpreds), make_assoc_property_map(map_vdist)) if in_ipynb(): ipynb_display_graph(g, dpe={ "color": make_func_property_map( lambda e: "green" if e in path else "red"), "label": pmap_eweight }) assert [(source(e, g), target(e, g)) for e in path] == [(0, 5), (5, 6), (6, 8)]
def run_tests(tests): """ Run a list of tests. Args: tests: A list of pair (f, args) where: f: A test_* function, which raise exceptions in case of problem. args: A tuple corresponding to the parameters passed to f. Returns: 0 in case of success, 1 otherwise. """ ret = 0 try: # Call each tests #for name, f in tests.items(): for f, args in tests: s = "Running test: %s%s" % (f.__name__, args) if in_ipynb(): from pybgl.html import html html("<b>%s</b>" % s) else: print(s) f(*args) except Exception as e: print(e) print(traceback.format_exc()) ret = 1 return ret
def check_deterministic_inclusion( g1 :Automaton, g2 :Automaton, expected :int, show_g1 :bool = True, show_g2 :bool = True ): obtained = deterministic_inclusion(g1, g2) if in_ipynb(): from pybgl.graphviz import graph_to_html from pybgl.html import html l = list() if show_g1: l += ["<b>A</b>", TEMPLATE_HTML % graph_to_html(g1)] if show_g2: l += ["<b>A'</b>", TEMPLATE_HTML % graph_to_html(g2)] result = "A c A'" if obtained == 1 else \ "A = A'" if obtained == 0 else \ "A' c A" if obtained == -1 else \ "A ! A'" if obtained is None else \ "??????" l.append(result) html("<br/>".join(l)) assert obtained == expected, "obtained = %s expected = %s" % (obtained, expected)
def test_graph_to_html_with_html_sequences(): from collections import defaultdict from pybgl.property_map import make_assoc_property_map g = DirectedGraph(2) (e, _) = add_edge(0, 1, g) pmap_vlabel = make_assoc_property_map(defaultdict(str)) pmap_elabel = make_assoc_property_map(defaultdict(str)) gdp = GraphDp(g, dpv={"label": pmap_vlabel}, dpe={"label": pmap_elabel}) for label in [ "<b>foo</b>", "<foo>", "<", ">", "<b>foo</b><bar>", "<bar><b>foo</b>", "<font color='red'><b>foo</b></font>", # NB: foo.png must exists + graphviz imposes <img/> not <img> #"<table><tr><td><img src='foo.png'/></td></tr></table>", ]: print(f"{label} --> {graphviz_escape_html(label)}") pmap_vlabel[0] = pmap_vlabel[1] = pmap_elabel[e] = label shtml = graph_to_html(gdp) if in_ipynb(): html(shtml) ipynb_display_graph(gdp)
def test_thompson_compile_nfa_repetition(): (nfa, q0, f) = thompson_compile_nfa("((ab){3})*") if in_ipynb(): ipynb_display_graph(nfa) for i in range(7): assert accepts("ab" * i, nfa) == (i % 3 == 0), f"w = {'ab' * i}, i = {i}"
def test_thompson_compile_nfa_one_or_more(): (nfa, q0, f) = thompson_compile_nfa("(ab+)+") if in_ipynb(): ipynb_display_graph(nfa) assert not accepts("", nfa) assert not accepts("b", nfa) assert accepts("abbbbb", nfa) assert accepts("abbbbbabbbbbabbbbb", nfa)
def test_thompson_compile_nfa_concatenation(): (nfa, q0, f) = thompson_compile_nfa("a+b+") if in_ipynb(): ipynb_display_graph(nfa) assert not accepts("abab", nfa) assert not accepts("aaa", nfa) assert not accepts("bbb", nfa) assert accepts("ab", nfa) assert accepts("aaaaaabbbbbb", nfa)
def test_graph_extract_small(threshold :int = 50): g = DirectedGraph(5) (e01, _) = add_edge(0, 1, g) (e02, _) = add_edge(0, 2, g) (e04, _) = add_edge(0, 4, g) (e12, _) = add_edge(1, 2, g) (e23, _) = add_edge(2, 3, g) (e24, _) = add_edge(2, 4, g) (e40, _) = add_edge(4, 0, g) (e44, _) = add_edge(4, 4, g) pmap_eweight = make_assoc_property_map({ e01 : 83, e02 : 3, e04 : 78, e12 : 92, e23 : 7, e24 : 18, e40 : 51, e44 : 84, }) extracted_edges = set() pmap_erelevant = make_func_property_map(lambda e: pmap_eweight[e] >= threshold) graph_extract( 0, g, pmap_erelevant = pmap_erelevant, callback_edge_extract = lambda e, g: extracted_edges.add(e) ) if in_ipynb(): pmap_extracted = make_func_property_map(lambda e: e in extracted_edges) html(dotstr_to_html(GraphDp( g, dpe = { "color" : make_func_property_map(lambda e : "darkgreen" if pmap_extracted[e] else "lightgrey"), "style" : make_func_property_map(lambda e : "solid" if pmap_extracted[e] else "dashed"), "label" : pmap_eweight, } ).to_dot()) ) expected_edges = None if threshold == 0: expected_edges = {e for e in edges(g)} elif threshold == 50: expected_edges = {e12, e40, e44, e04, e01} elif threshold > 100: expected_edges = set() if expected_edges is not None: assert (extracted_edges == expected_edges), """Invalid edges: For threshold = %s: extracted: %s expected: %s """ % (threshold, sorted(extracted_edges), sorted(expected_edges))
def test_thompson_compile_nfa_zero_or_one(): (nfa, q0, f) = thompson_compile_nfa("(ab?)*") if in_ipynb(): ipynb_display_graph(nfa) assert accepts("", nfa) assert not accepts("b", nfa) assert accepts("a", nfa) assert accepts("ab", nfa) assert accepts("aba", nfa) assert not accepts("abb", nfa)
def test_thompson_compile_nfa_bracket_repetitions(): (nfa, q0, f) = thompson_compile_nfa("[x-z]{1,3}") if in_ipynb(): ipynb_display_graph(nfa) for w in ["x", "y", "xx", "xy", "zy", "xxx", "yyy", "zzz", "xyz", "zyx"]: assert accepts(w, nfa) is True for w in ["", "xxxx", "aaa"]: assert accepts(w, nfa) is False (nfa, q0, f) = thompson_compile_nfa("x{3}") assert accepts("xxx", nfa)
def test_moore_determination(): nfa = make_nfa() w = "babbbababcccccd" assert accepts(w, nfa) for complete in [True, False]: dfa = moore_determination(nfa, complete=complete) if in_ipynb(): ipynb_display_graph(dfa) assert accepts(w, dfa), f"accepts({w}, dfa) = {accepts(w, dfa)}" nfa = make_second_nfa() w = "" assert accepts(w, nfa) for complete in [True, False]: dfa = moore_determination(nfa, complete=complete) if in_ipynb(): ipynb_display_graph(dfa) assert accepts(w, dfa), f"accepts({w}, dfa) = {accepts(w, dfa)}"
def display_graph(g: Graph, pmap_eweight: ReadPropertyMap = None, map_vpreds: dict = None): if in_ipynb(): dpe = dict() if pmap_eweight: dpe["label"] = pmap_eweight if map_vpreds: shortest_path_dag = {e for es in map_vpreds.values() for e in es} dpe["color"] = make_func_property_map( lambda e: "red" if e in shortest_path_dag else None) ipynb_display_graph(g, dpe=dpe)
def test_read_graphviz_simple(): g = DirectedGraph() dot = """digraph G { 0; 1; 2; 0->1; }""" read_graphviz(dot.splitlines(), g) if in_ipynb(): ipynb_display_graph(g) assert num_vertices(g) == 3 assert num_edges(g) == 1
def demo_minimal_cover(g: DirectedGraph, min_fds: set): if not in_ipynb(): return s_dot = GraphDp( g, dg_default={ "rankdir": "LR" }, dpe={ "color": make_func_property_map(lambda e: "darkgreen" if edge_to_pair( e, g) in min_fds else "red"), "style": make_func_property_map(lambda e: "solid" if edge_to_pair(e, g) in min_fds else "dashed"), }).to_dot() html(dotstr_to_html(s_dot))
def test_deterministic_union(show_g1: bool = True, show_g2: bool = True, show_g12: bool = True): g1 = make_dafsa1() g2 = make_dafsa2() g12 = deterministic_union(g1, g2) if in_ipynb(): from pybgl.graphviz import graph_to_html from pybgl.html import html l = list() if show_g1: l += ["<b>A</b>", graph_to_html(g1)] if show_g2: l += ["<b>A'</b>", graph_to_html(g2)] if show_g12: l += ["<b>A ∪ A'</b><br/>", graph_to_html(g12)] html("<br/>".join(l)) assert num_vertices(g12) == 12 assert num_edges(g12) == 11
def test_revuz_height(): g = make_incidence_node_automaton([(0, 1), (0, 2), (1, 2), (1, 3), (2, 4), (3, 4)], make_assoc_property_map( defaultdict(lambda: None, { 1: "a", 2: "b", 3: "a", 4: "c" }))) map_vheight = defaultdict() pmap_vheight = make_assoc_property_map(map_vheight) pmap_vlabel = make_func_property_map(lambda u: "%s<br/>height: %s" % (u, pmap_vheight[u])) max_height = revuz_height(g, pmap_vheight) if in_ipynb(): html(graph_to_html(g)) assert map_vheight == {0: 3, 1: 2, 2: 1, 3: 1, 4: 0} assert max_height == 3, f"Expected max_height = 3, got {max_height}"
def test_matching_tries(): both = {"an", "banana"} only1 = {"ananas", "x", "y", "z"} only2 = {"bananas", "bank", "t"} corpus1 = both | only1 corpus2 = both | only2 t1 = Trie() for w in corpus1: t1.insert(w) t2 = Trie() for w in corpus2: t2.insert(w) if in_ipynb(): html(graph_to_html(t1)) html(graph_to_html(t2)) l = trie_matching(t1, t2) assert l[1] == len(only1) assert l[2] == len(only2) assert l[3] == len(both)
def test_read_graphviz_custom(): from collections import defaultdict from pybgl.property_map import ReadWritePropertyMap, make_assoc_property_map from pybgl.graphviz import ReadGraphvizVisitor class MyReadGraphvizVisitor(ReadGraphvizVisitor): def __init__(self, g: Graph, pmap_vlabel: ReadWritePropertyMap, pmap_elabel: ReadWritePropertyMap): super().__init__(g) self.pmap_vlabel = pmap_vlabel self.pmap_elabel = pmap_elabel def on_install_vertex_property(self, u, g, key, value): if key == "label": self.pmap_vlabel[u] = value def on_install_edge_property(self, e, g, key, value): if key == "label": self.pmap_elabel[e] = value map_vlabel = defaultdict(str) map_elabel = defaultdict(str) g = DirectedGraph() dot = """digraph G { 0 [fontsize=8 label='red']; 1 [label='green']; 2 [label='blue' fontsize=10]; 0->1 [label='my_label']; }""" vis = MyReadGraphvizVisitor(g, make_assoc_property_map(map_vlabel), make_assoc_property_map(map_elabel)) read_graphviz(dot.splitlines(), g, vis) if in_ipynb(): ipynb_display_graph(g) assert map_vlabel == {0: "red", 1: "green", 2: "blue"}, map_vlabel e_01 = next(iter(edges(g))) assert map_elabel == {e_01: "my_label"}, map_vlabel
def test_strong_components(): # Create the graph g = DirectedGraph(7) add_edge(0, 1, g) add_edge(1, 2, g) add_edge(2, 3, g) add_edge(3, 1, g) add_edge(3, 4, g) add_edge(4, 5, g) add_edge(5, 6, g) add_edge(6, 4, g) # Find strong connected components map_component = {u : None for u in vertices(g)} pmap_component = make_assoc_property_map(map_component) strong_components(g, pmap_component) # Rendering pmap_color = make_assoc_property_map({ 0 : "red", 1 : "blue", 2 : "green", 3 : "purple" }) assert map_component == { 0 : 2, 1 : 1, 2 : 1, 3 : 1, 4 : 0, 5 : 0, 6 : 0, } if in_ipynb(): html(strong_components_to_html(g, pmap_color, pmap_component).replace("\\n", ""))
def test_graph_copy_small(threshold :int = 50): g = DirectedGraph(5) (e01, _) = add_edge(0, 1, g) (e02, _) = add_edge(0, 2, g) (e04, _) = add_edge(0, 4, g) (e12, _) = add_edge(1, 2, g) (e23, _) = add_edge(2, 3, g) (e24, _) = add_edge(2, 4, g) (e40, _) = add_edge(4, 0, g) (e44, _) = add_edge(4, 4, g) map_eweight = { e01 : 83, e02 : 3, e04 : 78, e12 : 92, e23 : 7, e24 : 18, e40 : 51, e44 : 84, } pmap_eweight = make_assoc_property_map(map_eweight) pmap_erelevant = make_func_property_map(lambda e: pmap_eweight[e] >= threshold) g_dup = DirectedGraph(0) # Edge duplicate map_eweight_dup = dict() pmap_eweight_dup = make_assoc_property_map(map_eweight_dup) def callback_dup_edge(e, g, e_dup, g_dup): pmap_eweight_dup[e_dup] = pmap_eweight[e] # Vertex mapping map_vertices = dict() pmap_vertices = make_assoc_property_map(map_vertices) map_edges = dict() pmap_edges = make_assoc_property_map(map_edges) graph_copy( 0, g, g_dup, pmap_erelevant = pmap_erelevant, pmap_vertices = pmap_vertices, pmap_edges = pmap_edges, callback_dup_edge = callback_dup_edge ) if in_ipynb(): ori_html = dotstr_to_html( GraphDp( g, dpv = { "label" : make_func_property_map(lambda u: "%s<br/>(becomes %s)" % (u, pmap_vertices[u])) }, dpe = { "color" : make_func_property_map(lambda e : "darkgreen" if pmap_erelevant[e] else "lightgrey"), "style" : make_func_property_map(lambda e : "solid" if pmap_erelevant[e] else "dashed"), "label" : pmap_eweight, } ).to_dot() ) dup_html = dotstr_to_html( GraphDp( g_dup, dpe = { "label" : pmap_eweight_dup, } ).to_dot() ) html( """ <table> <tr> <th>Original</th> <th>Extracted</th> </tr><tr> <td>%s</td> <td>%s</td> </tr> </table> """ % (ori_html, dup_html) ) if threshold == 50: expected_num_edges = 5 assert map_vertices == { 0 : 0, 1 : 1, 2 : 2, 4 : 3 } for e, e_dup in map_edges.items(): u = source(e, g) v = target(e, g) u_dup = source(e_dup, g_dup) v_dup = target(e_dup, g_dup) assert u_dup == pmap_vertices[u], "u_dup = %s ; pmap_vertices[%s] = %s" % (u_dup, u, pmap_vertices[u]) assert v_dup == pmap_vertices[v], "v_dup = %s ; pmap_vertices[%s] = %s" % (v_dup, v, pmap_vertices[v]) assert pmap_eweight[e] == pmap_eweight_dup[e_dup] elif threshold < min([w for w in map_eweight.values()]): expected_num_edges = num_edges(g) elif threshold > max([w for w in map_eweight.values()]): expected_num_edges = 0 assert expected_num_edges == num_edges(g_dup), \ """ Invalid edge number: Expected: %s Obtained: %s """ % (expected_num_edges, num_edges(g_dup))
def test_in_ipynb(): assert in_ipynb() is True
def test_in_ipynb(): assert in_ipynb() is False
#!/usr/bin/env pytest-3 # -*- coding: utf-8 -*- __author__ = "Marc-Olivier Buob" __maintainer__ = "Marc-Olivier Buob" __email__ = "*****@*****.**" __copyright__ = "Copyright (C) 2020, Nokia" __license__ = "BSD-3" from pybgl.ipynb import in_ipynb, ipynb_get_background_color, ipynb_get_foreground_color if not in_ipynb(): def test_in_ipynb(): assert in_ipynb() is False def test_ipynb_get_background_color(): assert ipynb_get_background_color() is None def test_ipynb_get_foreground_color(): assert ipynb_get_background_color() is None else: def test_in_ipynb(): assert in_ipynb() is True def test_ipynb_get_background_color(): assert isinstance(ipynb_get_background_color(), str) def test_ipynb_get_foreground_color(): assert isinstance(ipynb_get_background_color(), str)
def test_thompson_compile_nfa_escaped_operators(): regexp = r"\|\.\*\+\(\)\{\}\[\]aa" (nfa, q0, f) = thompson_compile_nfa(regexp) accepts(regexp.replace("\\", ""), nfa) if in_ipynb(): ipynb_display_graph(nfa)
def test_thompson_compile_nfa(): (nfa, q0, f) = thompson_compile_nfa("(a?b)*?c+d") if in_ipynb(): ipynb_display_graph(nfa) assert accepts("babbbababcccccd", nfa)