예제 #1
0
    def _dfs(self, G, v):
        self._marked[v] = True

        for w in G.adj(v):
            # short circuit if odd-length cycle found
            if self._cycle is not None: return

            # found uncolored vertex, so recur
            if not self._marked[w]:
                self._edge_to[w] = v
                self._color[w] = not self._color[v]
                self._dfs(G, w)

            # if v-w create an odd-length cycle, find it
            elif self._color[w] == self._color[v]:
                self._is_bipartite = False
                self._cycle = Stack()
                self._cycle.push(
                    w
                )  # don't need this unless you want to include start vertex twice
                x = v
                while x != w:
                    self._cycle.push(x)
                    x = self._edge_to[x]

                self._cycle.push(w)
    def _dfs(self, G, v):
        self._onStack[v] = True
        self._marked[v] = True
        for e in G.adj(v):
            w = e.to_vertex()

            # short circuit if directed cycle found
            if self._cycle is not None:
                return

            # found new vertex, so recur
            elif not self._marked[w]:
                self._edgeTo[w] = e
                self._dfs(G, w)

            # trace back directed cycle
            elif self._onStack[w]:
                self._cycle = Stack()
                f = e
                while f.from_vertex() != w:
                    self._cycle.push(f)
                    f = self._edgeTo[f.from_vertex()]

                self._cycle.push(f)
                return
        self._onStack[v] = False
예제 #3
0
 def reverse_post(self):
     """
     Returns the vertices in reverse postorder.
     
     :return: the vertices in reverse postorder, as an iterable of vertices
     """
     reverse = Stack()
     for v in self._postorder:
         reverse.push(v)
     return reverse
예제 #4
0
 def path_to(self, v):
     self._validate_vertex(v)
     if self.has_negative_cycle():
         raise UnsupportedOperationException("Negative cost cycle exists")
     if not self.has_path_to(v): return None
     path = Stack()
     e = self._edgeTo[v]
     while e is not None:
         path.push(e)
         e = self._edgeTo[e.from_vertex()]
     return path
예제 #5
0
 def _has_self_loop(self, G):
     # does this graph have a self loop?
     # side effect: initialize cycle to be self loop
     for v in range(G.V()):
         for w in G.adj(v):
             if v == w:
                 self._cycle = Stack()
                 self._cycle.push(v)
                 self._cycle.push(w)
                 return True
     return False
예제 #6
0
 def from_graph(G):
     """
     Initializes a new edge-weighted graph that is a deep copy of G.
     :param G: the edge-weighted graph to copy
     :return: the copy of the graph edge-weighted graph G
     :rtype: EdgeWeightedGraph
     """
     g = EdgeWeightedGraph(G.V())
     g._E = G.E()
     for v in range(G.V()):
         reverse = Stack()
         for e in G.adj(v):
             reverse.push(e)
         for e in reverse:
             g._adj[v].add(e)
     return g
예제 #7
0
    def from_graph(G):
        """
        Initializes a new graph that is a deep copy of G

        :param G: the graph to copy
        :returns: copy of G 
        """
        g = Graph(G.V())
        g._E = G.E()
        for v in range(G.V()):
            # reverse so that adjacency list is in same order as original
            reverse = Stack()
            for w in G._adj[v]:
                reverse.push(w)
            for w in reverse:
                g._adj[v].add(w)
예제 #8
0
 def path_to(self, v):
     """
     Returns a longest path from the source vertex s to vertex v.
     
     :param: the destination vertex
     :returns: a longest path from the source vertex s to vertex v as an iterable of edges, and None if no such path
     """
     self._validate_vertex(v)
     if not self.has_path_to(v):
         return None
     path = Stack()
     edge = self._edge_to[v]
     while not edge is None:
         path.push(edge)
         edge = self._edge_to[edge.from_vertex()]
     return path
예제 #9
0
 def path_to(self, v):
     """
     Returns a shortest path from the source vertex s to vertex v.
     :param v: the destination vertex
     :returns: a shortest path from the source vertex s to vertex v
             as an iterable of edges, and None if no such path
     :raises ValueError: unless 0 <= v < V
     """
     self._validate_vertex(v)
     if not self.has_path_to(v): return None
     path = Stack()
     e = self._edge_to[v]
     while e is not None:
         path.push(e)
         e = self._edge_to[e.from_vertex()]
     return path
예제 #10
0
 def _dfs(self, G, u, v):
     self._marked[v] = True
     for w in G.adj(v):
         # short circuit if cycle already found
         if self._cycle is not None: return
         if not self._marked[w]:
             self._edgeTo[w] = v
             self._dfs(G, v, w)
         elif w != u:
             self._cycle = Stack()
             x = v
             while x != w:
                 self._cycle.push(x)
                 x = self._edgeTo[x]
             self._cycle.push(w)
             self._cycle.push(v)
예제 #11
0
 def path_to(self, v):
     """
     Returns a shortest path from the source vertex s to vertex v.
     :param v: the destination vertex
     :return: a shortest path from the source vertex s to vertex v
     :rtype: collections.iterable[DirectedEdge]
     :raises IllegalArgumentException: unless 0 <= v < V
     """
     self._validate_vertex(v)
     if not self.has_path_to(v):
         return None
     path = Stack()
     e = self._edge_to[v]
     while e is not None:
         path.push(e)
         e = self._edge_to[e.from_vertex()]
     return path
예제 #12
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
예제 #13
0
    def _has_parallel_edges(self, G):
        # does this graph have two parallel edges?
        # side effect: initialize cycle to be two parallel edges
        self._marked = [False] * G.V()
        for v in range(G.V()):
            # check for parallel edges incident to v
            for w in G.adj(v):
                if self._marked[w]:
                    self._cycle = Stack()
                    self._cycle.push(v)
                    self._cycle.push(w)
                    self._cycle.push(v)
                    return True
                self._marked[w] = True

            for w in G.adj(v):
                self._marked[w] = False
        return False
 def path_to(self, v):
     """
     Returns a shortest path between the source vertex s and vertex v.
     :param v: the destination vertex
     :return: a shortest path between the source vertex s and vertex v.
     None if no such path
     :rtype: collections.iterable[Edge]
     :raises IllegalArgumentException: unless 0 <= v < V
     """
     self._validate_vertex(v)
     if not self.has_path_to(v):
         return None
     path = Stack()
     x = v
     e = self._edge_to[v]
     while e is not None:
         edge = self._edge_to[x]
         path.push(edge)
         x = e.other(x)
         e = self._edge_to[x]
     return path
예제 #15
0
    def _dfs(self, digraph, v):
        self._on_stack[v] = True
        self._marked[v] = True
        for w in digraph.adj(v):
            # short circuit if directed cycle found
            if self.has_cycle():
                return
            # found new vertex, so recur
            elif not self._marked[w]:
                self._edge_to[w] = v
                self._dfs(digraph, w)
            # trace back directed cycle
            elif self._on_stack[w]:
                self._cycle = Stack()
                x = v
                while x != w:
                    self._cycle.push(x)
                    x = self._edge_to[x]
                self._cycle.push(w)
                self._cycle.push(v)

        self._on_stack[v] = False
예제 #16
0
    def _dfs(self, graph, v):
        self._on_stack[v] = True
        self._marked[v] = True
        for edge in graph.adj(v):
            w = edge.to_vertex()

            # short circuit if directed cycle found
            if self.has_cycle():
                return
            # found new vertex, so recur
            elif not self._marked[w]:
                self._edge_to[w] = edge
                self._dfs(graph, w)
            # trace back directed cycle
            elif self._on_stack[w]:
                self._cycle = Stack()
                f = edge
                while f.from_vertex() != w:
                    self._cycle.push(f)
                    f = self._edge_to[f.from_vertex()]
                self._cycle.push(f)

        self._on_stack[v] = False
예제 #17
0
 def path_to(self, v):
     if not self.has_path_to(v): return None
     path = Stack()
     x = v
     while x != self._s:
         path.push(x)
         x = self._edgeTo[x]
     path.push(self._s)
     return path
예제 #18
0
    def path_to(self, v):
        """
        Returns a shortest path between the source vertex s (or sources)
        and v, or null if no such path.

        :param v: the vertex
        :returns: the sequence of vertices on a shortest path, as an Iterable
        :raises ValueError: unless 0 <= v < V
        """
        if not self.has_path_to(v): return None
        path = Stack()
        x = v
        while self._dist_to[x] != 0:
            path.push(x)
            x = self._edgeTo[x]
        path.push(x)
        return path
예제 #19
0
    def path_to(self, v):
        """
        Returns a path between the source vertex s and vertex v, or
        None if no such path.
        :param v: the vertex
        :returns: the sequence of vertices on a path between the source vertex
                   s and vertex v, as an Iterable
        :raises ValueError: unless 0 <= v < V
        """
        self._validateVertex(v)
        if not self.has_path_to(v): return None
        path = Stack()
        w = v
        while w != self._s:
            path.push(w)
            w = self._edgeTo[w]
        path.push(self._s)

        return path
예제 #20
0
class DirectedCycle:
    """
    The DirectedCycle class represents a data type for determining whether a 
    digraph has a directed cycle. The hasCycle operation determines whether the 
    digraph has a directed cycle and, and of so, the cycle operation returns one.

    This implementation uses depth-first search. The constructor takes time proportional 
    to V + E (in the worst case), where V is the number of vertices and E is the 
    number of edges. Afterwards, the hasCycle operation takes constant time; the 
    cycle operation takes time proportional to the length of the cycle.

    See Topological to compute a topological order if the digraph is acyclic.

    For additional documentation, see Section 4.2 of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
    """
    def __init__(self, digraph):
        """
        Determines whether the digraph has a directed cycle and, if so,
        finds such a cycle.
        
        :digraph: the digraph
        """
        self._cycle = None
        self._on_stack = [False] * digraph.V()
        self._edge_to = [0] * digraph.V()
        self._marked = [False] * digraph.V()
        for v in range(digraph.V()):
            if not self._marked[v]:
                self._dfs(digraph, v)

    # check that algorithm computes either the topological order or finds a directed cycle
    def _dfs(self, digraph, v):
        self._on_stack[v] = True
        self._marked[v] = True
        for w in digraph.adj(v):
            # short circuit if directed cycle found
            if self.has_cycle():
                return
            # found new vertex, so recur
            elif not self._marked[w]:
                self._edge_to[w] = v
                self._dfs(digraph, w)
            # trace back directed cycle
            elif self._on_stack[w]:
                self._cycle = Stack()
                x = v
                while x != w:
                    self._cycle.push(x)
                    x = self._edge_to[x]
                self._cycle.push(w)
                self._cycle.push(v)

        self._on_stack[v] = False

    def has_cycle(self):
        """
        Does the digraph have a directed cycle?
        
        :returns: true if there is a cycle, false otherwise
        """
        return self._cycle != None

    def cycle(self):
        """
        Returns a directed cycle if the digraph has a directed cycle, and null otherwise.
        
        :returns: a directed cycle (as an iterable) if the digraph has a directed cycle, and null otherwise
        """
        return self._cycle
예제 #21
0
class Cycle:
    """
    The Cycle class represents a data type for 
    determining whether an undirected graph has a cycle.
    The hasCycle operation determines whether the graph has
    a cycle and, if so, the cycle operation returns one.

    This implementation uses depth-first search.
    The constructor takes time proportional to V + E
    (in the worst case),
    where V is the number of vertices and E is the number of edges.
    Afterwards, the hasCycle operation takes constant time
    the cycle operation takes time proportional
    to the length of the cycle.
    """
    def __init__(self, G):
        """
        Determines whether the undirected graph G has a cycle and,
        if so, finds such a cycle.
     
        :param G: the undirected graph
        """
        if self._has_self_loop(G): return
        if self._has_parallel_edges(G): return
        self._marked = [False] * G.V()
        self._edgeTo = [0] * G.V()
        self._cycle = None
        for v in range(G.V()):
            if not self._marked[v]:
                self._dfs(G, -1, v)

    def _has_self_loop(self, G):
        # does this graph have a self loop?
        # side effect: initialize cycle to be self loop
        for v in range(G.V()):
            for w in G.adj(v):
                if v == w:
                    self._cycle = Stack()
                    self._cycle.push(v)
                    self._cycle.push(w)
                    return True
        return False

    def _has_parallel_edges(self, G):
        # does this graph have two parallel edges?
        # side effect: initialize cycle to be two parallel edges
        self._marked = [False] * G.V()
        for v in range(G.V()):
            # check for parallel edges incident to v
            for w in G.adj(v):
                if self._marked[w]:
                    self._cycle = Stack()
                    self._cycle.push(v)
                    self._cycle.push(w)
                    self._cycle.push(v)
                    return True
                self._marked[w] = True

            for w in G.adj(v):
                self._marked[w] = False
        return False

    def has_cycle(self):
        """
        Returns true if the graph G has a cycle.

        :returns: true if the graph has a cycle false otherwise
        """
        return self._cycle is not None

    def cycle(self):
        """
        Returns a cycle in the graph G.
        
        :returns: a cycle if the graph G has a cycle,
            and null otherwise
        """
        return self._cycle

    def _dfs(self, G, u, v):
        self._marked[v] = True
        for w in G.adj(v):
            # short circuit if cycle already found
            if self._cycle is not None: return
            if not self._marked[w]:
                self._edgeTo[w] = v
                self._dfs(G, v, w)
            elif w != u:
                self._cycle = Stack()
                x = v
                while x != w:
                    self._cycle.push(x)
                    x = self._edgeTo[x]
                self._cycle.push(w)
                self._cycle.push(v)
예제 #22
0
class Bipartite:
    """
    The Bipartite class represents a data type for 
    determining whether an undirected graph is bipartite or whether
    it has an odd-length cycle.
    The isBipartite operation determines whether the graph is
    bipartite. If so, the color operation determines a
    bipartition if not, the oddCycle operation determines a
    cycle with an odd number of edges.
    
    This implementation uses depth-first search.
    The constructor takes time proportional to V + E
    (in the worst case),
    where V is the number of vertices and E is the number of edges.
    Afterwards, the isBipartite and color operations
    take constant time the oddCycle operation takes time proportional
    to the length of the cycle.
    See BipartiteX for a nonrecursive version that uses breadth-first
    search.
    """
    class UnsupportedOperationException(Exception):
        pass

    def __init__(self, G):
        """
        Determines whether an undirected graph is bipartite and finds either a
        bipartition or an odd-length cycle.

        :param G: the graph
        """
        self._is_bipartite = True  # is the graph bipartite?
        self._color = [
            False
        ] * G.V()  # color[v] gives vertices on one side of bipartition
        self._marked = [
            False
        ] * G.V()  # marked[v] = True if v has been visited in DFS
        self._edge_to = [0] * G.V()  # edgeTo[v] = last edge on path to v
        self._cycle = None  # odd-length cycle

        for v in range(G.V()):
            if not self._marked[v]:
                self._dfs(G, v)

        assert self._check(G)

    def _dfs(self, G, v):
        self._marked[v] = True

        for w in G.adj(v):
            # short circuit if odd-length cycle found
            if self._cycle is not None: return

            # found uncolored vertex, so recur
            if not self._marked[w]:
                self._edge_to[w] = v
                self._color[w] = not self._color[v]
                self._dfs(G, w)

            # if v-w create an odd-length cycle, find it
            elif self._color[w] == self._color[v]:
                self._is_bipartite = False
                self._cycle = Stack()
                self._cycle.push(
                    w
                )  # don't need this unless you want to include start vertex twice
                x = v
                while x != w:
                    self._cycle.push(x)
                    x = self._edge_to[x]

                self._cycle.push(w)

    def is_bipartite(self):
        """
        Returns True if the graph is bipartite.
        
        :returns: True if the graph is bipartite False otherwise
        """
        return self._is_bipartite

    def color(self, v):
        """
        Returns the side of the bipartite that vertex v is on.

        :param v: the vertex
        :returns: the side of the bipartition that vertex v is on two vertices
                are in the same side of the bipartition if and only if they have the
                same color
        :raises IllegalArgumentException: unless 0 <= v < V 
        :raises UnsupportedOperationException: if this method is called when the graph
                is not bipartite
        """
        self._validateVertex(v)
        if not self._is_bipartite:
            raise Bipartite.UnsupportedOperationException(
                "graph is not bipartite")
        return self._color[v]

    def odd_cycle(self):
        """
        Returns an odd-length cycle if the graph is not bipartite, and
        None otherwise.
        
        :returns: an odd-length cycle if the graph is not bipartite
                (and hence has an odd-length cycle), and None otherwise
        """
        return self._cycle

    def _check(self, G):
        # graph is bipartite
        if self._is_bipartite:
            for v in range(G.V()):
                for w in G.adj(v):
                    if self._color[v] == self._color[w]:
                        error = "edge {}-{} with {} and {} in same side of bipartition\n".format(
                            v, w, v, w)
                        print(error, file=sys.stderr)
                        return False
        # graph has an odd-length cycle
        else:
            # verify cycle
            first = -1
            last = -1
            for v in self.odd_cycle():
                if first == -1:
                    first = v
                last = v

            if first != last:
                error = "cycle begins with {} and ends with {}\n".format(
                    first, last)
                print(error, file=sys.stderr)
                return False
        return True

    def _validateVertex(self, v):
        # raise an ValueError unless 0 <= v < V
        V = len(self._marked)
        if v < 0 or v >= V:
            raise ValueError("vertex {} is not between 0 and {}".format(
                v, V - 1))
예제 #23
0
def evaluate():
    ops = Stack()
    vals = Stack()

    while not stdio.isEmpty():
        # Read token, push if operator
        s = stdio.readString()
        if s == "(": pass
        elif s == "+": ops.push(s)
        elif s == "-": ops.push(s)
        elif s == "*": ops.push(s)
        elif s == "/": ops.push(s)
        elif s == "sqrt": ops.push(s)
        elif s == ")":
            # Pop, evaluate and push result if token is ")"
            op = ops.pop()
            v = vals.pop()
            if op == "+": v = vals.pop() + v
            elif op == "-": v = vals.pop() - v
            elif op == "*": v = vals.pop() * v
            elif op == "/": v = vals.pop() / v
            elif op == "sqrt": v = math.sqrt(v)
            vals.push(v)
        else:
            vals.push(float(s))
    stdio.writeln(vals.pop())
class EdgeWeightedDirectedCycle:
    """
     Determines whether the edge-weighted digraph G has a directed cycle and,
     if so, finds such a cycle.
     :param G the edge-weighted digraph
    """
    def __init__(self, G):
        self._marked = [False] * G.V()  # marked[v] = has vertex v been marked?
        self._edgeTo = [
            None
        ] * G.V()  # edgeTo[v] = previous DirectedEdge on path to v
        self._onStack = [False] * G.V()  # onStack[v] = is vertex on the stack?
        self._cycle = None  # directed cycle (or None if no such cycle)

        for v in range(G.V()):
            if not self._marked[v]:
                self._dfs(G, v)

        # check that digraph has a cycle
        assert self._check()

    # check that algorithm computes either the topological order or finds a directed cycle
    def _dfs(self, G, v):
        self._onStack[v] = True
        self._marked[v] = True
        for e in G.adj(v):
            w = e.to_vertex()

            # short circuit if directed cycle found
            if self._cycle is not None:
                return

            # found new vertex, so recur
            elif not self._marked[w]:
                self._edgeTo[w] = e
                self._dfs(G, w)

            # trace back directed cycle
            elif self._onStack[w]:
                self._cycle = Stack()
                f = e
                while f.from_vertex() != w:
                    self._cycle.push(f)
                    f = self._edgeTo[f.from_vertex()]

                self._cycle.push(f)
                return
        self._onStack[v] = False

    # Does the edge-weighted digraph have a directed cycle?
    # @return True if the edge-weighted digraph has a directed cycle,
    # False otherwise
    def has_cycle(self):
        return self._cycle is not None

    # Returns a directed cycle if the edge-weighted digraph has a directed cycle,
    # and None otherwise.
    # @return a directed cycle (as an iterable) if the edge-weighted digraph
    #    has a directed cycle, and None otherwise
    def cycle(self):
        return self._cycle

    # certify that digraph is either acyclic or has a directed cycle
    def _check(self):

        # edge-weighted digraph is cyclic
        if self.has_cycle():
            # verify cycle
            first = None
            last = None
            for e in self.cycle():
                if first is None:
                    first = e
                if last is not None:
                    if last.to_vertex() != e.from_vertex():
                        print("cycle edges {} and {} not incident".format(
                            last, e))
                        return False
                last = e

            if last.to_vertex() != first.from_vertex():
                print("cycle edges {} and {} not incident".format(last, first))
                return False

        return True