mirror of
https://github.com/Rushilwiz/AI.git
synced 2025-04-09 22:10:17 -04:00
139 lines
3.7 KiB
Python
139 lines
3.7 KiB
Python
# Name: Rushil Umaretiya
|
|
# Date: 09/18/2020
|
|
|
|
# Each Vertex object will have attributes to store its own name and its list of its neighboring vertices.
|
|
class Vertex:
|
|
def __init__(self, name, vertices):
|
|
self.name = name
|
|
self.vertices = vertices
|
|
|
|
def __str__(self):
|
|
return f'{self.name} {self.vertices}'
|
|
|
|
def __repr__(self):
|
|
return str(self.name)
|
|
|
|
|
|
# If the file exists, read all edges and build a graph. It returns a list of Vertexes.
|
|
def build_graph(filename):
|
|
try:
|
|
file = open(filename, 'r')
|
|
except:
|
|
return []
|
|
|
|
lines = file.read().strip().splitlines()
|
|
vertices = []
|
|
|
|
# Sorry about this solution Ms. Kim, it's not very efficient, but it makes sense.
|
|
|
|
# Create all the source verticies
|
|
for line in lines:
|
|
line = line.strip().split()
|
|
for vertex in vertices:
|
|
if vertex.name == line[0]:
|
|
break
|
|
else:
|
|
vertices.append(Vertex(line[0], []))
|
|
|
|
# Create all the ending verticies
|
|
for line in lines:
|
|
line = line.strip().split()
|
|
for vertex in vertices:
|
|
if vertex.name == line[1]:
|
|
break
|
|
else:
|
|
vertices.append(Vertex(line[1], []))
|
|
|
|
# Link them!
|
|
for line in lines:
|
|
line = line.strip().split()
|
|
source, end = None, None
|
|
for vertex in vertices:
|
|
if vertex.name == line[0]:
|
|
source = vertex
|
|
if vertex.name == line[1]:
|
|
end = vertex
|
|
if source != None and end != None:
|
|
break
|
|
|
|
source.vertices.append(end)
|
|
|
|
return vertices
|
|
|
|
# prints all vertices and adjacent lists of the given graph.
|
|
def display_graph(graph):
|
|
for vertex in graph:
|
|
print (vertex)
|
|
|
|
# checks if two Vertexes are reachable or not.
|
|
def is_reachable(fromV, toV, graph):
|
|
visited = []
|
|
Q = [fromV]
|
|
|
|
while len(Q) > 0:
|
|
state = Q.pop(0)
|
|
|
|
if state not in visited:
|
|
if state == toV:
|
|
return True
|
|
|
|
visited.append(state)
|
|
neighbours = state.vertices
|
|
|
|
for neighbour in neighbours:
|
|
Q.append(neighbour)
|
|
|
|
return False
|
|
|
|
# returns the length of the path from a Vertex to the other Vertex.
|
|
# If the other Vertex is not reachable, return -1. (Ex) Path cost of A to B to C is 2.
|
|
def path_cost(fromV, toV, graph):
|
|
if fromV == toV:
|
|
return 0
|
|
|
|
if not is_reachable(fromV, toV, graph):
|
|
return -1
|
|
|
|
visited = []
|
|
Q = [fromV]
|
|
|
|
while len(Q) > 0:
|
|
state = Q.pop(0)
|
|
if state not in visited:
|
|
if state == toV:
|
|
return len(visited)
|
|
|
|
visited.append(state)
|
|
neighbours = state.vertices
|
|
|
|
for neighbour in neighbours:
|
|
Q.append(neighbour)
|
|
|
|
# Test cases
|
|
g = build_graph(input("filename: ")) # build a graph
|
|
|
|
# To check if you build the graph with object correctly
|
|
for v in g:
|
|
print (v, v.vertices)
|
|
|
|
display_graph(g) # display the graph (edge list)
|
|
fromV, toV = None, None
|
|
print ("If you want to stop checking, type -1 for vertex values")
|
|
fromV_val, toV_val = input("From vertex value: "), input("To vertex value: ") # Get vertex values from user
|
|
|
|
while fromV_val != '-1':
|
|
# Find from and to Vertexes at graph
|
|
for v in g:
|
|
if v.name == fromV_val: fromV = v
|
|
if v.name == toV_val: toV = v
|
|
|
|
if fromV is None or toV is None:
|
|
print ("One or more vertex value does not exist.")
|
|
else:
|
|
print ("From {} to {} is reachable?".format(fromV_val, toV_val), is_reachable(fromV, toV, g))
|
|
print ("Path cost from {} to {} is".format(fromV_val, toV_val), path_cost(fromV, toV, g))
|
|
|
|
# Reset to test another case
|
|
fromV_val, toV_val = input("\nFrom vertex value: "), input("To vertex value: ")
|
|
fromV, toV = None, None
|