234 lines
7.7 KiB
Python
234 lines
7.7 KiB
Python
import math
|
|
|
|
class Vertex():
|
|
|
|
def __init__(self, vertexID):
|
|
self.ID = vertexID
|
|
|
|
class VertexPair():
|
|
|
|
def __init__(self, first_vertex: Vertex, second_vertex: Vertex):
|
|
|
|
self.first_vertex = first_vertex
|
|
self.second_vertex = second_vertex
|
|
|
|
class Edge():
|
|
|
|
def __init__(self, first_vertex: Vertex, second_vertex: Vertex):
|
|
self.vertex_pair = VertexPair(first_vertex, second_vertex)
|
|
|
|
class Graph():
|
|
|
|
def __init__(self, vertex_size: int, is_digraph=False, adjacency_flag=1):
|
|
|
|
self.graph = self.__init_graph(vertex_size)
|
|
self.is_digraph = is_digraph
|
|
self.vertex_size = vertex_size
|
|
self.adjacency_flag = adjacency_flag
|
|
|
|
def __vertex_in_graph(self, vertexID: int):
|
|
return vertexID in range(0, self.vertex_size)
|
|
|
|
def set_adjacency(self, edge: Edge, adjacency_flag=-1):
|
|
|
|
if adjacency_flag == -1:
|
|
adjacency_flag = self.adjacency_flag
|
|
|
|
first_vertexID = int(edge.vertex_pair.first_vertex.ID)
|
|
second_vertexID = int(edge.vertex_pair.second_vertex.ID)
|
|
|
|
if self.__vertex_in_graph(first_vertexID) and self.__vertex_in_graph(second_vertexID):
|
|
|
|
self.graph[first_vertexID][second_vertexID] = adjacency_flag
|
|
|
|
if not self.is_digraph:
|
|
self.graph[second_vertexID][first_vertexID] = adjacency_flag
|
|
else:
|
|
raise Exception('Vertex out of bounds')
|
|
|
|
def __init_graph(self, vertex_size: int, inital_val=0):
|
|
|
|
return [[inital_val]*vertex_size for _ in range(vertex_size)]
|
|
|
|
def __mark_as_visited(self,visited, element, graph):
|
|
for i in range(0, len(graph)):
|
|
if graph[i][element] == self.adjacency_flag:
|
|
graph[i][element] = visited
|
|
return graph
|
|
|
|
def clear(self, inital_val=0):
|
|
self.graph = self.__init_graph(self.vertex_size, inital_val)
|
|
|
|
def bfs(self, source_vertex: Vertex):
|
|
|
|
|
|
assert self.is_digraph and self.__vertex_in_graph(int(source_vertex.ID))
|
|
|
|
visited = self.adjacency_flag+1
|
|
graph = self.graph.copy()
|
|
queque = [source_vertex.ID]
|
|
|
|
while len(queque) > 0:
|
|
|
|
element = queque[0]
|
|
queque = queque[1:]
|
|
|
|
print(f"Current vertex {element}")
|
|
graph = self.__mark_as_visited(visited, element, graph)
|
|
|
|
for i in range(0, len(graph[element])):
|
|
if graph[element][i] == self.adjacency_flag:
|
|
print(f" ({element}) -> ({i})")
|
|
graph = self.__mark_as_visited(visited, i, graph)
|
|
queque.append(i)
|
|
elif graph[element][i] == visited:
|
|
print(f" ({element}) -> ({i}) - Already visited")
|
|
|
|
def get_parents(self, source_vertex, graph):
|
|
assert self.__vertex_in_graph(source_vertex)
|
|
parents = []
|
|
|
|
for i in range(0, len(graph[source_vertex])):
|
|
if self.graph[source_vertex][i] != 0:
|
|
parents.append(i)
|
|
return parents
|
|
|
|
def dfs(self, source_vertex):
|
|
|
|
graph = self.graph
|
|
visited = self.adjacency_flag+1
|
|
|
|
parents_from_source = self.get_parents(source_vertex, graph)
|
|
|
|
if len(parents_from_source) != 0:
|
|
|
|
graph = self.__mark_as_visited(visited, source_vertex, graph)
|
|
|
|
for i in range(0, len(parents_from_source)):
|
|
|
|
if graph[source_vertex][i] != visited:
|
|
print(f" ({source_vertex}) -> ({parents_from_source[i]})")
|
|
self.dfs(parents_from_source[i])
|
|
graph = self.__mark_as_visited(visited, i, graph)
|
|
else:
|
|
print(f" ({source_vertex}) -> ({parents_from_source[i]})")
|
|
|
|
|
|
def dijkstra(self, source_vertex):
|
|
assert self.is_digraph and self.__vertex_in_graph(int(source_vertex.ID))
|
|
|
|
visited = math.inf
|
|
graph = self.graph.copy()
|
|
queque = [source_vertex.ID]
|
|
visited = []
|
|
weight = [math.inf]*self.vertex_size
|
|
|
|
weight[source_vertex.ID] = 0
|
|
|
|
while len(queque) > 0:
|
|
|
|
element = queque[0]
|
|
queque = queque[1:]
|
|
|
|
print(f"Current vertex {element}")
|
|
|
|
visited.append(element)
|
|
|
|
for i in range(0, self.vertex_size):
|
|
|
|
if graph[element][i] != -1 and i not in visited:
|
|
|
|
if weight[i] > (weight[element]+graph[element][i]):
|
|
|
|
print(f" ({element}) -> ({i}) <-> Weight {(weight[element]+graph[element][i])}")
|
|
weight[i] = (weight[element]+graph[element][i])
|
|
|
|
visited.append(i)
|
|
queque.append(i)
|
|
|
|
elif graph[element][i] != -1 and i in visited:
|
|
|
|
print(f" ({element}) -> ({i}) - Already visited", end=" <-> ")
|
|
|
|
if weight[i] > (weight[element]+graph[element][i]):
|
|
print(f"New Weight {(weight[element]+graph[element][i])}")
|
|
weight[i] = (weight[element]+graph[element][i])
|
|
|
|
return weight
|
|
|
|
def show_matrix(self):
|
|
for i in range(0, self.vertex_size):
|
|
for j in range(0, self.vertex_size):
|
|
print(f'{self.graph[i][j]}', end='')
|
|
print('')
|
|
if __name__ == '__main__':
|
|
|
|
vertex_size = 6
|
|
|
|
graph = Graph(vertex_size, True)
|
|
|
|
print('================================= BFS ====================================')
|
|
graph.set_adjacency(Edge(Vertex(0),Vertex(2)))
|
|
graph.set_adjacency(Edge(Vertex(0),Vertex(4)))
|
|
graph.set_adjacency(Edge(Vertex(0),Vertex(3)))
|
|
|
|
graph.set_adjacency(Edge(Vertex(1),Vertex(2)))
|
|
graph.set_adjacency(Edge(Vertex(1),Vertex(4)))
|
|
|
|
graph.set_adjacency(Edge(Vertex(2),Vertex(4)))
|
|
|
|
graph.set_adjacency(Edge(Vertex(3),Vertex(4)))
|
|
graph.set_adjacency(Edge(Vertex(3),Vertex(5)))
|
|
|
|
graph.set_adjacency(Edge(Vertex(4),Vertex(5)))
|
|
|
|
graph.set_adjacency(Edge(Vertex(5),Vertex(1)))
|
|
graph.bfs(Vertex(0))
|
|
|
|
print('==========================================================================')
|
|
print('================================= DFS ====================================')
|
|
graph.clear()
|
|
|
|
graph.set_adjacency(Edge(Vertex(0),Vertex(2)))
|
|
graph.set_adjacency(Edge(Vertex(0),Vertex(4)))
|
|
graph.set_adjacency(Edge(Vertex(0),Vertex(3)))
|
|
|
|
graph.set_adjacency(Edge(Vertex(2),Vertex(1)))
|
|
graph.set_adjacency(Edge(Vertex(2),Vertex(4)))
|
|
|
|
graph.set_adjacency(Edge(Vertex(3),Vertex(4)))
|
|
graph.set_adjacency(Edge(Vertex(3),Vertex(5)))
|
|
|
|
|
|
graph.set_adjacency(Edge(Vertex(4),Vertex(1)))
|
|
graph.set_adjacency(Edge(Vertex(4),Vertex(5)))
|
|
|
|
graph.set_adjacency(Edge(Vertex(5),Vertex(1)))
|
|
|
|
graph.dfs(Vertex(0).ID)
|
|
|
|
print('==========================================================================')
|
|
print('============================== DIJKSTRA ==================================')
|
|
|
|
graph.clear(inital_val=-1)
|
|
|
|
graph.set_adjacency(Edge(Vertex(0),Vertex(2)), 7)
|
|
graph.set_adjacency(Edge(Vertex(0),Vertex(4)), 4)
|
|
graph.set_adjacency(Edge(Vertex(0),Vertex(3)), 2)
|
|
|
|
graph.set_adjacency(Edge(Vertex(1),Vertex(2)), 0)
|
|
|
|
graph.set_adjacency(Edge(Vertex(2),Vertex(4)), 1)
|
|
|
|
graph.set_adjacency(Edge(Vertex(3),Vertex(4)), 1)
|
|
graph.set_adjacency(Edge(Vertex(3),Vertex(5)), 3)
|
|
|
|
graph.set_adjacency(Edge(Vertex(4),Vertex(1)), 4)
|
|
graph.set_adjacency(Edge(Vertex(4),Vertex(5)), 1)
|
|
|
|
graph.set_adjacency(Edge(Vertex(5),Vertex(1)), 2)
|
|
|
|
print(graph.dijkstra(Vertex(0)))
|
|
|
|
print('==========================================================================')
|