Exemplo n.º 1
0
    def __init__(self, regex):
        """Initializes the NFA from the specified regular expression.

        :param regex: the regular expression

        """
        self.regex = regex
        m = len(regex)
        self.m = m
        ops = Stack()
        graph = Digraph(m + 1)
        for i in range(0, m):
            lp = i
            if regex[i] == "(" or regex[i] == "|":
                ops.push(i)
            elif regex[i] == ")":
                or_ = ops.pop()

                # 2-way or operator
                if regex[or_] == "|":
                    lp = ops.pop()
                    graph.add_edge(lp, or_ + 1)
                    graph.add_edge(or_, i)
                elif regex[or_] == "(":
                    lp = or_
                else:
                    assert False
            if i < m - 1 and regex[i + 1] == "*":
                graph.add_edge(lp, i + 1)
                graph.add_edge(i + 1, lp)
            if regex[i] == "(" or regex[i] == "*" or regex[i] == ")":
                graph.add_edge(i, i + 1)
        if ops.size() != 0:
            raise ValueError("Invalid regular expression")
        self.graph = graph
Exemplo n.º 2
0
class SymbolDigraph:
    """
    The SymbolDigraph class representsclass represents a digraph, where the
    vertex names are arbitrary strings.
    By providing mappings between vertex names and integers,
    it serves as a wrapper around the Digraph data type, which assumes the 
    vertex names are integers between 0 and V - 1.
    It also supports initializing a symbol digraph from a file.
    
    This implementation uses an ST to map from strings to integers,
    an array to map from integers to strings, and a Digraph to store
    the underlying graph.
    The index_of and contains operations take time 
    proportional to log V, where V is the number of vertices.
    The name_of operation takes constant time.
    """
    def __init__(self, filename, delimiter):
        """
        Initializes a digraph from a file using the specified delimiter.
        Each line in the file contains
        the name of a vertex, followed by a list of the names
        of the vertices adjacent to that vertex, separated by the delimiter.

        :param filename: the name of the file
        :param delimiter: the delimiter between fields
        """
        self._st = BinarySearchST()  # string -> index

        # First pass builds the index by reading strings to associate
        # distinct strings with an index
        stream = InStream(filename)
        while not stream.isEmpty():
            a = stream.readLine().split(delimiter)
            for i in range(len(a)):
                if not self._st.contains(a[i]):
                    self._st.put(a[i], self._st.size())

        stdio.writef("Done reading %s\n", filename)

        # inverted index to get keys in an array
        self._keys = [None] * self._st.size()  # index  -> string
        for name in self._st.keys():
            self._keys[self._st.get(name)] = name

        # second pass builds the graph by connecting first vertex on each
        # line to all others
        self._graph = Digraph(self._st.size())  # the underlying graph
        stream = InStream(filename)
        while stream.hasNextLine():
            a = stream.readLine().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):
        """
        Does the graph contain the vertex named s?

        :param s: the name of a vertex
        :return:s true if s is the name of a vertex, and false otherwise        
        """
        return self._st.contains(s)

    def index_of(self, s):
        """
        Returns the integer associated with the vertex named s.
        :param s: the name of a vertex
        :returns: the integer (between 0 and V - 1) associated with the vertex named s
        """
        return self._st.get(s)

    def name_of(self, v):
        """
        Returns the name of the vertex associated with the integer v.
        @param  v the integer corresponding to a vertex (between 0 and V - 1) 
        @throws IllegalArgumentException unless 0 <= v < V
        @return the name of the vertex associated with the integer v
        """
        self._validateVertex(v)
        return self._keys[v]

    def digraph(self):
        return self._graph

    def _validateVertex(self, v):
        # throw an IllegalArgumentException unless 0 <= v < V
        V = self._graph.V()
        if v < 0 or v >= V:
            raise ValueError("vertex {} is not between 0 and {}".format(
                v, V - 1))
            i = 0
            for v in self._order:
                self._rank[v] = i
                i += 1

    def has_order(self):
        return self._order is not None

    def order(self):
        return self._order

    def rank(self, v):
        if self.has_order():
            return self._rank[v]
        else:
            return -1


if __name__ == '__main__':
    graph = Digraph(5)
    graph.add_edge(0, 1)
    graph.add_edge(0, 3)
    graph.add_edge(2, 3)
    graph.add_edge(4, 0)
    graph.add_edge(2, 4)

    # cycles = DirectedCycle(graph)
    topo = Topological(graph)
    print(topo.has_order())
    print(topo.order())