Exemplo n.º 1
0
 def topological_path(self,graph,startVertex,endVertex):
     path = graph.topologicalSort()
     dist, parent = ht.HashTable(),ht.HashTable()
     dist[startVertex] = 0
     parent[startVertex] = None
     startVertexFound = False
     for vertex in path:
         if(vertex == startVertex): startVertexFound = True
         if(not startVertexFound):  continue
         if(dist[vertex] == None): continue
         for neig,weight in graph.__neighbourNode__(vertex):
             if(dist[neig] == None or dist[neig] > dist[vertex] + weight):
                 dist[neig] = dist[vertex] + weight
                 parent[neig] = vertex
     l=[]
     startVertexFound = False
     curr = endVertex
     wt = 0
     while(curr !=None):
         l.append(curr)
         end = curr
         curr = parent[curr]
         if(curr!=None): wt += graph.getValueOf((curr,end))
         if(curr == startVertex):
             startVertexFound = True
             l.append(startVertex)
             break
     l.reverse()
     if(startVertexFound):
         return l,wt
     else:
         return None
Exemplo n.º 2
0
 def shortestPathWeighted(self,graph,startVertex,endVertex):
     record, parent = ht.HashTable(), ht.HashTable()
     record[startVertex] = 0
     parent[startVertex] = None
     recursionTrace,rescueRepetition = ht.HashTable(), ht.HashTable()
     self.__shortestPathWeighted__(graph,startVertex,parent,record,recursionTrace,rescueRepetition)
     l=[endVertex]
     while(endVertex!=None):
         endVertex=parent[endVertex]
         l.append(endVertex)
     l.pop()
     l.reverse()
     return l
Exemplo n.º 3
0
 def __init__(self, vertices = None, edges = None, isUndirectedGraph = True, dtype=str):
     self._hashTable_ = ht.HashTable()
     self._reverse_hashTable_ = ht.HashTable()
     self.noVertices = 0
     self.noEdges = 0
     self.dtype = dtype
     self._isNegativeEdges_ = False
     self._isWeighted_ = False
     self.isUndirectedGraph = isUndirectedGraph
     if(vertices!=None):
         self.initializeVertices(vertices)
     if(edges!=None):
         self.initializeEdge(edges)
Exemplo n.º 4
0
 def __shortestPathWeighted__(self,graph,startVertex,parent,record,recursionTrace,rescueRepetition):
     for neig in graph[startVertex]:
         if(neig not in recursionTrace):
             weight = graph._hashTable_[startVertex][neig]
             if(record[neig] == None):
                 record[neig] = weight + record[startVertex]
                 parent[neig] = startVertex
             elif(record[neig] > weight + record[startVertex]):
                 record[neig] = weight + record[startVertex]
                 parent[neig] = startVertex
             elif(record[neig] <= weight + record[startVertex]):     # Here we are recording the that has weight > current weight
                 if(startVertex not in rescueRepetition):            # In recursive call we will make sure that these edges should not be taken into consideraton
                     rescueRepetition[startVertex] = ht.HashTable()
                     rescueRepetition[startVertex][neig] = None
                 else:
                     rescueRepetition[startVertex][neig] = None
     for neig in graph[startVertex]:
         if(neig not in recursionTrace):# and neig not in rescueRepetition):
             if(startVertex in rescueRepetition and neig in rescueRepetition[startVertex]):
                 pass
             else:
                 recursionTrace[neig] = startVertex
                 self.__shortestPathWeighted__(graph,neig,parent,record,recursionTrace,rescueRepetition)
                 del recursionTrace[neig]
             if(startVertex in rescueRepetition and neig in rescueRepetition[startVertex]):
                 del rescueRepetition[startVertex][neig]
Exemplo n.º 5
0
 def isCycleExist(
         self):  # Time complexity O(|V| + |E|), Space complexity O(|V|)
     parent = ht.HashTable(
     )  # parent is a HashTable of visited vertices Space Complexity: O(|V|)
     for vertex in self.vertices(
     ):  # Time complexity O(|V|), Space complexity O(|V|)
         l = [
             vertex
         ]  # l is a list of vertices reachable from vertex Space Complexity: O(|V|)
         if vertex not in parent:  # parent is a HashTable so Time complexity O(1)
             parent[vertex] = None
             for next_vert in self.__cycleDFSHelper__(
                     vertex, parent,
                     l):  # Space Complexity: O(1), Time Complexity: O(|V|)
                 for i in range(
                         len(l)
                 ):  # in case of unDirected we dont check for last vertex in l
                     if (self.isUndirectedGraph == True
                             and i == len(l) - 2):
                         continue
                     startVert, endVert = next_vert, l[i]
                     table = self._hashTable_[startVert]
                     if (endVert in table):
                         return True  # table  is a HashTable so Time complexity O(1)
     return False
Exemplo n.º 6
0
 def __DFS_List__(self,vertices):
     #vertex = self.dtype(vertex)
     parent = ht.HashTable()
     for vertex in vertices:
         if vertex not in parent:
             l=[vertex]
             parent[vertex] = None
             for v in self.__DFS_Vertex__(vertex,parent): l.append(v)
             yield l
Exemplo n.º 7
0
 def DFS(self,v):
     if(type(v) == list):
         yield from self.__DFS_List__(v)
     else:
         vertex = self.dtype(v)
         parent = ht.HashTable()
         parent[vertex] = None
         yield vertex
         yield from self.__DFS_Vertex__(vertex,parent)
Exemplo n.º 8
0
 def BFS(self,vertex):
     vertex = self.dtype(vertex)
     # Here we require to index by our vertices but its not sure that our vertices are represented by numbers
     # thats why we use hashTable otherwise there is a simpler implementation of same code using list,numpy array insted of hashtable :)
     # so we use hashTable insted
     level,parent = ht.HashTable(),ht.HashTable()
     i = 1
     level[vertex], parent[vertex] = 0, None
     frontier = [vertex]
     while(frontier):
         next = []
         for u in frontier:
             for v_key in self[u]:
                 if v_key not in level:
                     level[v_key] = i
                     parent[v_key] = u
                     next.append(v_key)
         frontier = next
         i += 1
     return level, parent
Exemplo n.º 9
0
 def topologicalSort(self):
     if(self.isUndirectedGraph): return
     if(self.isCycleExist()): return
     parent = ht.HashTable()
     l = []
     for vert in self.vertices():
         if(vert not in parent):
             parent[vert] = None
             self.__topologicalSort__(vert,parent,l)
             l.append(vert)
     l.reverse()
     return l
Exemplo n.º 10
0
    def bellman_ford(self,graph,startVertex,endVertex):
        def relax(u,v,w,dist,parent):
            if(dist[u] == None): return
            if(dist[v] == None or dist[v] > dist[u] + w):
                dist[v] = dist[u] + w
                parent[v] = u

        # Initialization
        parent = ht.HashTable()
        dist = ht.HashTable()
        for vert in graph.vertices():
            parent[vert],dist[vert] = None,None
        dist[startVertex] = 0
        
        # Bellman-Ford Algo
        for _ in range(graph.noOfVertices()):
            for u,v,w in graph.edges():
                relax(u,v,w,dist,parent)
        # Check  if there is any -ve cycle in path of startVertex
        for u,v,w in graph.edges():
            if(dist[u] == None):continue
            if(dist[v] > dist[u] + w):  return None
        return self.__htable_to_list__(parent,dist,endVertex)
Exemplo n.º 11
0
 def dijkstraV1(self,graph,startVertex,endVertex):
     if(startVertex == endVertex): return [startVertex,endVertex], 0
     if(graph._isNegativeEdges_): return
     def extract_min(dist,Q):    # O(|V|)
         minimum, ret_vert = None, None
         for vert, dump in Q:
             weight = dist[vert]
             if(weight == None): continue
             if(minimum == None):
                 minimum = weight
                 ret_vert = vert
             else:
                 if(weight < minimum):
                     minimum = weight
                     ret_vert = vert
         return minimum,ret_vert
     # Initialization
     V = graph.getVertices()
     Q = ht.HashTable()
     for vert in V:  Q[vert] = None
     parent = ht.HashTable()
     for vert in V:  parent[vert] = None
     dist = ht.HashTable()
     for vert in V:  dist[vert] = None
     dist[startVertex] = 0
     
     # Dijkstra Algorithm
     while(len(Q) != 0):
         minimum, vert = extract_min(dist,Q)
         if(vert == None): break
         del Q[vert]
         for vertex,weight in graph.__neighbourNode__(vert):
             if(dist[vertex] == None or dist[vertex] >  dist[vert] + weight):
                 dist[vertex] = dist[vert] + weight
                 parent[vertex] = vert
     return self.__htable_to_list__(parent,dist,endVertex)
Exemplo n.º 12
0
 def dijkstraV2(self,graph,startVertex,endVertex):
     # =====================================================================
     def extract_min(q):
         q[-1][3]=0
         q[0],q[-1] = q[-1], q[0]
         ret = q.pop()
         min_heapify(q,len(q),0)
         return ret
     # =====================================================================
     def min_heapify(a,n,i):     # O(lg(V))
         if(2*i + 1 < n):
             if(a[i][0] == None and a[2*i + 1][0] != None):
                 a[i], a[2*i + 1] = a[2*i + 1], a[i]
                 a[i][3], a[2*i + 1][3] = a[2*i + 1][3], a[i][3]
                 min_heapify(a,n,2*i + 1)
             elif(a[i][0]!=None and a[2*i + 1][0] !=None):
                 if(a[i][0] > a[2*i + 1][0]):
                     a[i], a[2*i + 1] = a[2*i + 1], a[i]
                     a[i][3], a[2*i + 1][3] = a[2*i + 1][3], a[i][3]
                     min_heapify(a,n,2*i + 1)
         if(2*i + 2 < n):
             if(a[i][0] == None and a[2*i + 2][0] != None):
                 a[i], a[2*i + 2] = a[2*i + 2], a[i]
                 a[i][3], a[2*i + 2][3] = a[2*i + 2][3], a[i][3]
                 min_heapify(a,n,2*i + 2)
             elif(a[i][0] != None and a[2*i + 2][0] != None):
                 if(a[i][0] > a[2*i + 2][0]):
                     a[i], a[2*i + 2] = a[2*i + 2], a[i]
                     a[i][3], a[2*i + 2][3] = a[2*i + 2][3], a[i][3]
                     min_heapify(a,n,2*i + 2)
     # =====================================================================
     def move_up(Q,H,vertex):    #O(lg(V))
         vertex = vertex[1]
         curr_Q = H[vertex]
         index = curr_Q[3]
         while(index>0):
             parent_index = (index - 1)//2
             if(Q[parent_index][0] == None or Q[parent_index][0] > Q[index][0]):
                 Q[parent_index], Q[index] =  Q[index], Q[parent_index]
                 Q[parent_index][3], Q[index][3] =  Q[index][3], Q[parent_index][3]
             else:
                 break
             index = parent_index
     # =====================================================================
     def relax(u,v,weight,Q,H):    # O(lg(V))
         curr_Q_value_v = H[v]     # it will go to H and return list refrence from Q of vertex v
         curr_Q_value_u = H[u]
         if(curr_Q_value_v[0] == None or curr_Q_value_v[0] > curr_Q_value_u[0] + weight):
             curr_Q_value_v[0] = curr_Q_value_u[0] + weight
             curr_Q_value_v[2] = u
             move_up(Q,H,curr_Q_value_v)
     # =====================================================================
     
     if(graph._isNegativeEdges_):
         return
     # Initialization
     Q = [[0,startVertex,None,0]] # Here Q will record the distance path b/w vertices 1st element: cost, 2nd element: vertex, 3rd element: parent, 4th element: index
     H = ht.HashTable()           # we require this hashTable cause in relax part if we don't use hash table then
                                  # to updating the cost of vertex v in Q we have to scan whole array Q to find v and then update cost
     i = 0                        # H provides us element of Q in O(1) i.e. it will give us Q[v] in O(1)
     H[startVertex] = Q[i] 
     for vertex in graph.vertices():
         if(vertex == startVertex):  continue
         i += 1
         Q.append([None,vertex,None,i])
         H[vertex] = Q[i]
     S = []
     
     # Dijkstra Algorithm
     while(len(Q) != 0):
         u = extract_min(Q)
         S.append(u)
         if(u[0] == None): break
         for vertex,weight in graph.__neighbourNode__(u[1]):
             relax(u[1],vertex,weight,Q,H)
             
     # Finally return the path
     parent = ht.HashTable()
     weig = ht.HashTable()
     for i in range(len(S)):
         parent[S[i][1]] = S[i][2]
         weig[S[i][1]] = S[i][0]
     return self.__htable_to_list__(parent,weig,endVertex)
Exemplo n.º 13
0
 def __getDFSParentHashTable__(self,vertex):
     vertex = self.dtype(vertex)
     parent = ht.HashTable()
     parent[vertex] = None
     [ next_vert for next_vert in self.__DFS_Vertex__(vertex,parent)]
     return parent
Exemplo n.º 14
0
 def addNewVertex(self,vertex):
     vertex = self.dtype(vertex)
     if(self._hashTable_[vertex] == None):
         self.noVertices += 1
     self._hashTable_[vertex] = ht.HashTable()