예제 #1
0
def main():
    g = Digraph(13)
    with open("../resources/tinyDAG.txt", ) as f:
        for line in f.readlines():
            vertices = " ".join(line.splitlines()).split(' ')
            if len(vertices) < 2:
                continue
            else:
                v1, v2 = int(vertices[0]), int(vertices[1])
                g.add_edge(v1, v2)
    print(g)
    dfs = DepthFirstOrder(g)
    print(dfs)
    print("v    pre   post")
    print("--------------------")
    for v in range(g.get_V()):
        print(f'{v}     {dfs.pre(v)}     {dfs.post(v)}\n')

    print('Pre-order')
    for v in dfs.preorder_vertices():
        print(f'{v} ', end="")
    print()
    print('Post-order')
    for v in dfs.postorder_vertices():
        print(f'{v} ', end="")
    print()
    print(dfs.postorder_vertices())
    print('Reverse Post-order')
    q1 = dfs.reverse_post()
    for v in q1:
        print(f'{v} ', end="")
def main():
    file_name = '../resources/digraph1.txt'
    with open(file_name) as f:
        ints = list()
        for line in f.read().split('\n'):
            ints.append(line)
        vertices, edges = int(ints[0]), int(ints[1])

    graph = Digraph(vertices)
    inp = ints[
        2:]  # skip first 2 lines in tiny.DG.txt i.e. # of vertices and edges

    for i in range(edges):
        v, w = inp[i].split(' ')
        graph.add_edge(int(v), int(w))

    s = 3
    sources = [3, 4, 5]
    # bfs = BreadthFirstDirectedPaths(graph, s)
    bfs = BreadthFirstDirectedPaths(graph, sources=sources)
    print(bfs)
    for v in range(graph.get_V()):
        if bfs.has_path_to(v):
            print(f'{sources} to {v} ({bfs.dist_to(v)})')
            path = bfs.path_to(v)
            while not path.empty():
                x = path.get()
                if x == s or x in sources:
                    print(f'{x}', end="")
                else:
                    print(f'->{x}', end="")
            print()
        else:
            print(f'{s} to {v} (-): not connected.\n')
예제 #3
0
def main():
    file_name = '../resources/tinyDG.txt'
    with open(file_name) as f:
        ints = list()
        for line in f.read().split('\n'):
            ints.append(line)
        vertices, edges = int(ints[0]), int(ints[1])

    graph = Digraph(vertices)
    print(graph)
    inp = ints[
        2:]  # skip first 2 lines in tiny.DG.txt i.e. # of vertices and edges

    for i in range(edges):
        v, w = inp[i].split(' ')
        graph.add_edge(int(v), int(w))
    print(graph)
    s = 2
    dfs = NonrecursiveDirectedDFS(graph, s)
    print(dfs)
    for v in range(graph.get_V()):
        if dfs.marked(v):
            print(f'{s} is connected to {v} ')
        else:
            print(f'{s} not connected to {v}')
예제 #4
0
    def __init__(self, file_name, delimiter=" "):
        self._st = defaultdict(int)

        # First pass builds the index by reading strings to associate
        # distinct strings with an index
        with open(f"../resources/{file_name}.txt", ) as f:
            for line in f.readlines():
                a = " ".join(line.splitlines()).split(delimiter)
                for i in range(len(a)):
                    if a[i] not in self._st:
                        self._st[a[i]] = len(self._st)

        # inverted index to get string keys in an array
        self._keys = ['' for _ in range(len(self._st))]
        for name in self._st.keys():
            self._keys[self._st.get(name)] = name

        # second pass builds the digraph by connecting first vertex on each
        # line to all others
        self._graph = Digraph(len(self._st))
        with open(f"../resources/{file_name}.txt", ) as f:
            for line in f.readlines():
                a = " ".join(line.splitlines()).split(delimiter)
                v = self._st.get(a[0])
                for i in range(1, len(a)):
                    w = self._st.get(a[i])
                    self._graph.add_edge(v, w)
예제 #5
0
    def __init__(self, synsets=None, hypernyms=None):
        self._nouns_dict = defaultdict(Bag)
        self._reverse_nouns_dict = defaultdict(str)
        max_id = 0

        with open(synsets) as f:
            lines = f.readlines()
            for line in lines:
                items = "".join(line.splitlines()).split(',')
                nouns = items[1].split(' ')

                for i in range(len(nouns)):
                    if nouns[i] not in self._nouns_dict:
                        nouns_list = Bag()
                    else:
                        nouns_list = self._nouns_dict.get(nouns[i])
                    nouns_list.add(int(items[0]))
                    self._nouns_dict[nouns[i]] = nouns_list
                self._reverse_nouns_dict[int(items[0])] = items[1]
                max_id = max(max_id, int(items[0]))

        self._dg = Digraph(max_id + 1)

        with open(hypernyms) as f1:
            lines = f1.readlines()
            for line in lines:
                items = "".join(line.splitlines()).split(',')
                v = int(items[0])
                for i in range(1, len(items)):
                    w = int(items[i])
                    self._dg.add_edge(v, w)

        # if not self._is_dag(self._dg):
        #     raise AttributeError('digraph is not acyclic')
        self._sap = SAP(self._dg)
예제 #6
0
def main():
    file_name = '../resources/tinyDG.txt'
    with open(file_name) as f:
        ints = list()
        for line in f.read().split('\n'):
            ints.append(line)
        vertices, edges = int(ints[0]), int(ints[1])

    graph = Digraph(vertices)
    print(graph)
    inp = ints[
        2:]  # skip first 2 lines in tiny.DG.txt i.e. # of vertices and edges

    for i in range(edges):
        v, w = inp[i].split(' ')
        graph.add_edge(int(v), int(w))
    print(graph)

    scc = KosarajuSharirSCC(graph)
    m = scc.count()
    print(f'{m} strong components')
    components = [Queue() for _ in range(m)]
    for v in range(graph.get_V()):
        components[scc.id(v)].put(v)
    for i in range(m):
        for v in components[i].queue:
            print(f'{v} ', end="")
        print()
예제 #7
0
class SymbolDigraph:
    def __init__(self, file_name, delimiter=" "):
        self._st = defaultdict(int)

        # First pass builds the index by reading strings to associate
        # distinct strings with an index
        with open(f"../resources/{file_name}.txt", ) as f:
            for line in f.readlines():
                a = " ".join(line.splitlines()).split(delimiter)
                for i in range(len(a)):
                    if a[i] not in self._st:
                        self._st[a[i]] = len(self._st)

        # inverted index to get string keys in an array
        self._keys = ['' for _ in range(len(self._st))]
        for name in self._st.keys():
            self._keys[self._st.get(name)] = name

        # second pass builds the digraph by connecting first vertex on each
        # line to all others
        self._graph = Digraph(len(self._st))
        with open(f"../resources/{file_name}.txt", ) as f:
            for line in f.readlines():
                a = " ".join(line.splitlines()).split(delimiter)
                v = self._st.get(a[0])
                for i in range(1, len(a)):
                    w = self._st.get(a[i])
                    self._graph.add_edge(v, w)

    def contains(self, s):
        return s in self._st

    def index_of(self, s):
        return self._st.get(s)

    def name_of(self, v):
        self.__validate_vertex(v)
        if isinstance(v, int):
            return self._keys[v]
        else:
            return self._keys[v.item]

    def digraph(self):
        return self._graph

    def __validate_vertex(self, v):
        n = self._graph.get_V()
        if isinstance(v, int):
            if v < 0 or v >= n:
                raise ValueError(f'vertex {v} is not between 0 and {n - 1}')
        else:
            if v.item < 0 or v.item >= n:
                raise ValueError(f'vertex {v} is not between 0 and {n - 1}')

    def __repr__(self):
        return f'<{self.__class__.__name__}(_st={self._st}, _graph={self._graph}, _keys={self._keys})>'
예제 #8
0
def main():
    with open("../resources/digraph1.txt") as f:
        values = "".join(f.readlines()).split('\n')
        V, E = int(values[0]), int(values[1])
        g = Digraph(V)
        sap = SAP(g)
        for line in values:
            vertices = "".join(line).split(' ')
            if len(vertices) < 2:
                continue
            else:
                v, w = int(vertices[0]), int(vertices[1])
                g.add_edge(v, w)
                length = sap.length(v, w)
                ancestor = sap.ancestor(v, w)
                print(f'length = {length}, ancestor={ancestor}')
    # sap = SAP(g)
    print(g)
    print(sap)
예제 #9
0
def read_graph_file(filename: str) -> (Graph, [Vertex], [tuple]):
    """
        Read a graph file from the class specified format.

        Args:
        * filename - Read in the file specified by filename

        Returns:
            A tuple that contains a graph object and two lists
    """
    graph = Graph()
    verts = []
    edges = []
    is_weighted = None

    # Open up the file and parse the graph from text
    with open(filename, "r") as file:
        counter = 0

        # Iterate through the file
        for line in file:

            # Obtain the type of graph
            if counter == 0:
                graph_type = line.strip()
                if graph_type == "G":
                    graph = Graph()
                elif graph_type == "D":
                    graph = Digraph()
                else:
                    raise ValueError("Graph type not properly specified")

            # Obtain the verticies for the graph.
            elif counter == 1:
                for key in line.strip().split(","):
                    verts.append(Vertex(key))

            # Obtain all the edges.
            elif counter > 1:
                edge = line.strip("()\n").split(",")
                if is_weighted is None:
                    is_weighted = bool(len(edge) == 3)
                elif is_weighted and len(edge) < 3:
                    raise ValueError(
                        "You specified an edge with weights and one without. You should only do one or the other."
                    )

                if len(edge) != 3 and len(edge) != 2:
                    raise ValueError(
                        f"You specified an incorrect amount of args for the edge: {line}"
                    )
                edges.append(edge)
            counter += 1

    return graph, verts, edges
예제 #10
0
def main():
    g = Digraph(13)
    with open("../resources/tinyDG.txt", ) as f:
        for line in f.readlines():
            vertices = " ".join(line.splitlines()).split(' ')
            if len(vertices) < 2:
                continue
            else:
                v1, v2 = int(vertices[0]), int(vertices[1])
                g.add_edge(v1, v2)

    finder = DirectedCycleX(g)
    print(finder)
    if finder.has_cycle():
        print('Directed cycle')
        for v in finder.get_cycle():
            print(f'{v} ', end="")
        print()
    else:
        print('No directed cycle')
def main():
    g = Digraph(13)
    with open("../resources/tinyDG.txt", ) as f:
        for line in f.readlines():
            vertices = " ".join(line.splitlines()).split(' ')
            if len(vertices) < 2:
                continue
            else:
                v1, v2 = int(vertices[0]), int(vertices[1])
                g.add_edge(v1, v2)
    print(g)
    euler = DirectedEulerianCycle(g)
    print(euler)
    print("Eulerian cycle: ")
    if euler.has_eulerian_cycle():
        for v in euler.cycle():
            print(v + " ")
        print()
    else:
        print("none")

    print()
예제 #12
0
    def __init__(self, regex):
        m = len(regex)
        graph = Digraph(m + 1)
        ops = LifoQueue()  # stack of states

        for i in range(m):
            lp = i
            # for left parentheses add Epsilon transition to next state, and push state index to stack
            if regex[i] == '(' or regex[i] == '|':  # '|' is operator for or
                # if the regex has left parentheses '(' or the '|' meta-characters,
                # push the *state index [i]* of the meta-character on the stack
                ops.put(i)

            # if we encounter a right parentheses, pop the corresponding left parentheses and/or '|'
            elif regex[i] == ')':
                _or = ops.get()
                # 2-way or operator
                if regex[_or] == '|':
                    lp = ops.get()
                    graph.add_edge(lp, _or + 1)
                    graph.add_edge(_or, i)

                else:
                    lp = _or
                # else:
                #     assert False

            # closure operator * (uses 1-character lookahead)
            if i < m - 1 and regex[i + 1] == '*':
                graph.add_edge(lp, i + 1)
                graph.add_edge(i + 1, lp)
            if regex[i] in ("(", "*", ")"):
                graph.add_edge(i, i + 1)
        if ops.qsize() != 0:
            raise ValueError('Invalid regular expression')
        self._m = m
        self._graph = graph
        self._regex = regex
예제 #13
0
def main():

    file_name = '../resources/tinyDG.txt'
    with open(file_name) as f:
        ints = list()
        for line in f.read().split('\n'):
            ints.append(line)
        vertices, edges = int(ints[0]), int(ints[1])

    graph = Digraph(vertices)
    # print(graph)
    inp = ints[
        2:]  # skip first 2 lines in tiny.DG.txt i.e. # of vertices and edges
    sources = Bag()
    sources.add(1)
    sources.add(5)
    sources.add(10)

    for i in range(edges):
        v, w = inp[i].split(' ')
        graph.add_edge(int(v), int(w))

    # print(graph)

    # s = 6
    # reachable from single source vertex, s
    # dfs = DirectedDFS(graph, int(s))
    # print(dfs)

    # reachable from many source vertices, sources
    dfs = DirectedDFS(graph, sources)
    # print(dfs)

    for v in range(graph.get_V()):
        if dfs.marked(v):
            print(f'{v} ')
예제 #14
0
def main(args: argparse.Namespace):
    """
        Check if a path exists between two vertices.

        Args:
        * args - The parsed argument namespace from argparse
    """
    # Input checks
    if not args.folder:
        raise ValueError("There was no npm folder path specified!")

    vertices, edges = traverse_npm_folder(args.folder.rstrip("/"))
    graph = Digraph()
    # Obtain the graph properties and then fill out the graph.
    fill_graph(graph, vertices, edges)

    hist = dict()
    root = args.folder.rstrip("/").split("/")[-1]
    print("#### START EVALUATION ####\n")
    print(f"\tExamining the directory: {root}")
    highest = 0
    dependency = ""
    for key, vertex in graph.graph.items():
        if len(vertex.neighbors) > highest:
            highest = len(vertex.neighbors)
            dependency = key

    print(
        f"\tMost depended on package: {dependency} with {highest} dependants")
    path_len, package = graph.find_longest_path()
    print(
        f"\tThe longest shortest path was: {path_len} edges and to the package: {package}"
    )
    is_acyclic = graph.prove_acyclic(args.folder.strip("/").split("/")[-1])
    print(f"\tThe graph is acyclic: {is_acyclic}")
    print("\n#### END EVALUATION ####")
def read_file(text_file):

    graph = Graph()
    verts = []
    edges = []
    is_weighted = None

    with open(text_file, "r") as open_file:
        line_counter = 0
        for line in open_file:
            if line_counter == 0:  # Chooses either a Graph or Digraph
                graph_type = line.strip()
                if graph_type == "G":
                    graph = Graph()
                elif graph_type == "D":
                    graph = Digraph()
                else:
                    raise ValueError(
                        "A Graph type has not been properly specified")
            if line_counter == 1:  # Adds all the Verticies from the txt file
                for key in line.strip().split(","):
                    verts.append(key)
            elif line_counter > 1:  # Add all the edges and checks if its weighted
                edge = line.strip("()\n").split(",")
                if is_weighted is None:
                    is_weighted = bool(len(edge) == 3)
                elif is_weighted and len(edge) < 3:
                    raise ValueError(
                        "All edges must be either unweighted or weighted")

                if len(edge) != 3 and len(edge) != 2:
                    raise ValueError(
                        f"Text file has unusual amount of arguments for edges")
                if len(edge) > 3:
                    raise ValueError("To many arguments for the edges")
                edges.append(edge)
            line_counter += 1  # Traverses through the txt file line by line

        return graph, verts, edges
예제 #16
0
class WordNet:
    def __init__(self, synsets=None, hypernyms=None):
        self._nouns_dict = defaultdict(Bag)
        self._reverse_nouns_dict = defaultdict(str)
        max_id = 0

        with open(synsets) as f:
            lines = f.readlines()
            for line in lines:
                items = "".join(line.splitlines()).split(',')
                nouns = items[1].split(' ')

                for i in range(len(nouns)):
                    if nouns[i] not in self._nouns_dict:
                        nouns_list = Bag()
                    else:
                        nouns_list = self._nouns_dict.get(nouns[i])
                    nouns_list.add(int(items[0]))
                    self._nouns_dict[nouns[i]] = nouns_list
                self._reverse_nouns_dict[int(items[0])] = items[1]
                max_id = max(max_id, int(items[0]))

        self._dg = Digraph(max_id + 1)

        with open(hypernyms) as f1:
            lines = f1.readlines()
            for line in lines:
                items = "".join(line.splitlines()).split(',')
                v = int(items[0])
                for i in range(1, len(items)):
                    w = int(items[i])
                    self._dg.add_edge(v, w)

        # if not self._is_dag(self._dg):
        #     raise AttributeError('digraph is not acyclic')
        self._sap = SAP(self._dg)

    def nouns_dict(self):
        return self._nouns_dict

    def rev_nouns_dict(self):
        return self._reverse_nouns_dict

    def _is_dag(self, dg):
        dc = DirectedCycle(dg)
        return dc.has_cycle()

    def nouns(self):
        # returns all WordNet nouns
        return list(self._nouns_dict.keys())

    def is_noun(self, word):
        # is the word a WordNet noun?
        return True if word in self._nouns_dict else False

    def distance(self, noun_a, noun_b):
        # distance between noun_a and noun_b
        if not self.is_noun(noun_a) or not self.is_noun(noun_b):
            raise AttributeError(f'noun arguments to distance() not found')
        return self._sap.length(
            self._nouns_dict.get(noun_a).first.item,
            self._nouns_dict.get(noun_b).first.item)

    def sap(self, noun_a, noun_b):
        # a synset (second field of synsets.txt) that is the common ancestor of noun_a and noun_b
        # in a shortest ancestral path (defined below)
        if not self.is_noun(noun_a) or not self.is_noun(noun_b):
            raise AttributeError(f'noun arguments to distance() not found')
        _id = self._sap.ancestor(
            self._nouns_dict.get(noun_a).first.item,
            self._nouns_dict.get(noun_b).first.item)
        return self._reverse_nouns_dict.get(_id)

    def __repr__(self):
        return f'<{self.__class__.__name__}(' \
               f'_dg={self._dg})>'
예제 #17
0
 def __init__(self, g: Digraph):
     self._tc = [DirectedDFS(g, v) for v in range(g.get_V())]