Module dsa.graph
Expand source code
class AdjacencyMatrixGraph:
"""
An unweighted adjacency matrix graph implementation in Python
(allows either directed or undirected representation)
"""
def __init__(self, labels: list[str]):
"""
Args:
labels: list of labels for each vertex
"""
self.labels = labels
self.label_index = { label: index for index, label in enumerate(labels) }
node_count = len(self.labels)
self.array = [[None for i in range(node_count)] for j in range(node_count)]
def add_edge(self, a_label: str, b_label: str):
"""
Add an undirected edge between one vertex to another (same as add_edge())
Args:
a_label: starting vertex label
b_label: ending vertex label
"""
self.add_adjacent_vertex(a_label, b_label)
def add_adjacent_vertex(self, a_label: str, b_label: str):
"""
Add an undirected edge between one vertex to another (same as add_adjacent_vertex())
Args:
a_label: starting vertex label
b_label: ending vertex label
"""
a = self.label_index[a_label]
b = self.label_index[b_label]
self.array[a][b] = True
self.array[a][a] = True
self.array[b][a] = True
self.array[b][b] = True
def add_directed_edge(self, a_label: str, b_label: str):
"""
Add a directed edge between one vertex to another (same as add_directed_adjacent_vertex() and add_adjacent_directed_vertex())
Args:
a_label: starting vertex label
b_label: ending vertex label
"""
self.add_adjacent_directed_vertex(a_label, b_label)
def add_directed_adjacent_vertex(self, a_label: str, b_label: str):
"""
Add a directed edge between one vertex to another (same as add_adjacent_directed_vertex() and add_directed_edge())
Args:
a_label: starting vertex label
b_label: ending vertex label
"""
self.add_adjacent_directed_vertex(a_label, b_label)
def add_adjacent_directed_vertex(self, a_label: str, b_label: str):
"""
Add a directed edge between one vertex to another (same as add_directed_adjacent_vertex() and add_directed_edge())
Args:
a_label: starting vertex label
b_label: ending vertex label
"""
a = self.label_index[a_label]
b = self.label_index[b_label]
self.array[a][b] = True
self.array[a][a] = True
self.array[b][b] = True
def df_traverse(self, start_label: str):
"""
Perform depth first traversal in an adjacency matrix
Args:
start_label: starting vertex label
"""
return self._df_rec_traverse(start_label, dict())
def _df_rec_traverse(self, start_label: str, visited):
"""
Helper method for depth first recursive traversal
"""
start_index = self.label_index[start_label]
visited[start_index] = True
print(self.labels[start_index])
for i in range(len(self.array)):
if i not in visited and self.array[start_index][i]:
self.df_rec_traverse(self.labels[i], visited)
def bf_traverse(self, start_label: str):
"""
Perform breadth first traversal in an adjacency matrix
Args:
start_label: starting vertex label
"""
q = []
visited={}
start_index = self.label_index[start_label]
q.append(start_index)
while len(q) > 0:
current = q.pop(0) # equivalent of dequeue
if current not in visited:
visited[current] = True
print(self.labels[current])
for i in range(len(self.array)):
if self.array[current][i]:
q.append(i)
def print_graph(self):
"""
Print the contents of the graph
"""
print(" |", end="")
for label in self.labels:
print(f"{label:^3}", end=" ")
print()
print("----" * (len(self.array) + 1))
for r, row in enumerate(self.array):
label = self.labels[r]
print(f"{label:^3}|", end="");
for col in row:
b = " T " if col else " "
print(b, end=" ")
print()
class AdjacencyMatrixWeightedGraph:
"""
A weighted adjacency matrix graph implementation in Python
(allows either directed or undirected representation)
"""
def __init__(self, labels):
"""
Args:
labels: list of labels for each vertex
"""
self.labels = labels
self.label_index = { label: index for index, label in enumerate(labels) }
node_count = len(self.labels)
self.array = [[None for i in range(node_count)] for j in range(node_count)]
def add_edge(self, a_label: str, b_label: str, weight):
"""
Add an undirected edge between one vertex to another (same as add_edge())
Args:
a_label: starting vertex label
b_label: ending vertex label
weight: weight of the vertex
"""
self.add_adjacent_vertex(a_label, b_label, weight)
def add_adjacent_vertex(self, a_label: str, b_label: str, weight):
"""
Add an undirected edge between one vertex to another (same as add_edge())
Args:
a_label: starting vertex label
b_label: ending vertex label
weight: weight of the vertex
"""
a = self.label_index[a_label]
b = self.label_index[b_label]
self.array[a][b] = weight
self.array[a][a] = 0
self.array[b][a] = weight
self.array[b][b] = 0
def add_directed_edge(self, a_label: str, b_label: str, weight):
"""
Add a weighted directed edge between one vertex to another (same as add_adjacent_directed_vertex(), add_directed_adjacent_vertex())
Args:
a_label: starting vertex label
b_label: ending vertex label
weight: weight of the vertex
"""
self.add_adjacent_directed_vertex(a_label, b_label, weight)
def add_directed_adjacent_vertex(self, a_label: str, b_label: str, weight):
"""
Add a weighted directed edge between one vertex to another (same as add_directed_edge(), add_adjacent_directed_vertex())
Args:
a_label: starting vertex label
b_label: ending vertex label
weight: weight of the vertex
"""
self.add_adjacent_directed_vertex(a_label, b_label, weight)
def add_adjacent_directed_vertex(self, a_label: str, b_label: str, weight):
"""
Add a weighted directed edge between one vertex to another (same as add_directed_edge(), add_directed_adjacent_vertex())
Args:
a_label: starting vertex label
b_label: ending vertex label
weight: weight of the vertex
"""
a = self.label_index[a_label]
b = self.label_index[b_label]
self.array[a][b] = weight
self.array[a][a] = 0
self.array[b][b] = 0
def print_graph(self):
"""
Print the contents of the graph.
"""
print(" |", end="")
for label in self.labels:
print(f"{label:>3}", end=" ")
print()
print("----" * (len(self.array) + 1))
for r, row in enumerate(self.array):
label = self.labels[r]
print(f"{label:^3}|", end="");
for col in row:
w = f"{col:3}" if col is not None else " "
print(w, end=" ")
print()
class Vertex:
pass
class Vertex:
"""
A unweighted adjacency list vertex implementation in Python
(allows either directed or undirected representation)
"""
def __init__(self, value):
"""
Args:
value: value of the vertex
"""
#: value of the vertex
self.value = value
#: list of adjacent vertices
self.adjacents = []
def add_adjacent_vertex(self, vertex: type[Vertex]):
"""
Add an undirected vertex to the adjacency list (same as add_edge()).
Args:
vertex: vertex to add
"""
if vertex not in self.adjacents:
self.adjacents.append(vertex)
if self not in vertex.adjacents:
vertex.add_adjacent_vertex(self)
def add_edge(self, vertex: type[Vertex]):
"""
Add an undirected vertex to the adjacency list (same as add_adjacent_vertex()).
Args:
vertex: vertex to add
"""
self.add_adjacent_vertex(vertex)
def add_directed_edge(self, vertex: type[Vertex]):
"""
Add a directed vertex to the adjacency list (same as add_directed_adjacent_vertex()).
Args:
vertex: vertex to add
"""
self.add_directed_adjacent_vertex(vertex)
def add_directed_adjacent_vertex(self, vertex: type[Vertex]):
"""
Add a directed vertex to the adjacency list (same as add_directed_edge()).
Args:
vertex: vertex to add
"""
if vertex not in self.adjacents:
self.adjacents.append(vertex)
def df_traverse(self):
"""
Perform depth first traversal.
"""
self._df_traverse_rec(self, dict())
def _df_traverse_rec(self, vertex: type[Vertex], visited={}):
"""
helper depth first traversal recursive function
"""
visited[vertex] = True
print(vertex.value)
for v in vertex.adjacents:
if not visited.get(v, False):
v._df_traverse_rec(v, visited)
def bf_traverse(self):
"""
Perform breadth first traversal.
"""
start = self
visited = {}
queue = []
queue.append(start)
while len(queue) > 0:
current = queue[0]
del queue[0]
if not visited.get(current, False):
visited[current] = True
print(current.value)
for v in current.adjacents:
queue.append(v)
def dfs(self, end):
"""
Recursive depth first search.
Args:
end: vertex to search for
Returns:
Vertex in the graph
None if not found.
"""
return self.dfs_rec(self, end, dict())
def dfs_rec(self, current, end, visited=None):
"""
helper depth first search recursive function
Returns:
Vertex in the graph
None if not found.
"""
if current.value == end.value:
print("Found: ", end.value)
return current
visited[current] = True
print(current.value)
for v in current.adjacents:
if not visited.get(v, False):
return v.dfs_rec(v, end, visited)
return None
def bfs(self, end):
"""
Recursive breadth first search.
Args:
end: vertex to search for
Returns:
Vertex in the graph
None if not found.
"""
visited = {}
queue = []
start = self
visited[start] = True
queue.append(start)
while len(queue) > 0:
current = queue[0]
del queue[0]
print(current.value)
# print("Visited: ", visited)
# print("Queue: ", queue)
if current.value == end.value:
return current
for v in current.adjacents:
if not visited.get(v, False):
visited[v] = True
queue.append(v)
return None
def __repr__(self):
return self.value
class WeightedVertex:
pass
class WeightedVertex:
"""
A weighted adjacency list vertex implementation in Python
(allows either directed or undirected representation)
"""
def __init__(self, value):
"""
Args:
value: value of the vertex
"""
self.value = value
self.adjacents = {}
# same as add_adjacent_vertex
def add_edge(self, vertex: type[WeightedVertex], weight):
"""
Add a weighted directed edge to the adjacency list (same as add_adjacent_vertex()).
Args:
vertex: vertex to add
weight: weight of the vertex
"""
self.add_adjacent_vertex(vertex, weight)
# same as add_directed_adjacent_vertex
def add_directed_edge(self, vertex: type[WeightedVertex], weight):
"""
Add a weighted directed edge to the adjacency list (same as add_directed_adjacent_vertex()).
Args:
vertex: vertex to add
weight: weight of the vertex
"""
self.add_directed_adjacent_vertex(vertex, weight)
def add_directed_adjacent_vertex(self, vertex: type[WeightedVertex], weight):
"""
Add a weighted directed edge to the adjacency list (same as add_directed_edge()).
Args:
vertex: vertex to add
weight: weight of the vertex
"""
if vertex not in self.adjacents:
self.adjacents[vertex] = weight
def add_adjacent_vertex(self, vertex: type[WeightedVertex], weight):
"""
Add a weighted edge to the adjacency list (same as add_directed_edge()).
Args:
vertex: vertex to add
weight: weight of the vertex
"""
if vertex not in self.adjacents:
self.adjacents[vertex] = weight
if self not in vertex.adjacents:
vertex.adjacents[self] = weight
def df_traverse(self, vertex: type[WeightedVertex], visited={}):
"""
depth first traversal
Args:
vertex: starting vertex
visited: dictionary of visited vertices
"""
visited[vertex] = True
print(vertex.value)
for v in vertex.adjacents:
if not visited.get(v, False):
v.df_traverse(v, visited)
def bf_traverse(self, vertex: type[WeightedVertex]):
"""
breadth first traversal
Args:
vertex: starting vertex
"""
visited = {}
queue = []
queue.append(vertex)
while len(queue) > 0:
current = queue[0]
del queue[0]
if not visited.get(current, False):
visited[current] = True
print(current.value)
for v in current.adjacents:
queue.append(v)
def dfs(self, target: type[WeightedVertex]):
"""
depth first search
Args:
target: target value to search for
"""
return self._dfs_rec(self, target, dict())
def _dfs_rec(self, current, end, visited={}):
"""
recursive depth first search healper function
Args:
current: starting vertex
end: target vertex to search for
visited: dictionary of visited values
"""
print(current.value, visited.keys())
if current.value == end.value:
return current
visited[current] = True
print("Current: ", current.value)
for v in current.adjacents:
if not visited.get(v, False):
v.dfs_rec(v, end, visited)
return None
def bfs(self, vertex: type[WeightedVertex], target):
"""
breadth first search
Args:
vertex: startering vertex
target: target value to search for
"""
visited = {}
queue = []
queue.append(vertex)
while len(queue) > 0:
current = queue[0]
del queue[0]
if current.value == target:
return current
if not visited.get(current, False):
visited[current] = True
print(current.value)
for v in current.adjacents:
queue.append(v)
return None
def __repr__(self):
return self.value
def __lt__(self, vertex):
return self.value < vertex.value
#### Dijkstra's Algorithm Functions
def shortest_path(start, end, debug=False):
"""
Helper function that returns a weight table and a previous vertex table using Dijkstra's Algorithm.
Args:
start: starting vertex
end: ending vertex
debug: if True, display weight table as it is being built
Returns:
a tuple of a weight table dictionary and a previous path dictionary
"""
weight_table = {}
previous = {}
visited = {}
queue = [] # ideally, a min heap
current = start
queue.append(current)
weight_table[current.value] = 0
previous[current.value] = current
while len(queue) > 0:
current_weight = weight_table.get(current.value, float('inf'))
visited[current.value] = True
# for non-weighted version, use:
# for adjacent in current.adjacents:
# weight = 1
for adjacent, weight in current.adjacents.items():
if not visited.get(adjacent.value, False):
queue.append(adjacent)
wt = weight_table.get(adjacent.value, float('inf'))
if wt > weight + current_weight:
weight_table[adjacent.value] = weight + current_weight
previous[adjacent.value] = current
if debug:
print(weight_table)
current = queue[0]
del queue[0]
return weight_table, previous
def find_path(start, end, debug=False):
"""
Return the shortest path of two vertices using Dijkstra's Algorithm.
Args:
start: starting vertex
end: ending vertex
debug: if True, display the weight table
Returns:
A list of vertices that form a shortest path
"""
weight_table, previous = shortest_path(start, end, debug)
path = []
current = end
path.append(current.value)
while current != start:
current = previous[current.value]
path.append(current.value)
path.reverse()
if debug:
print("previous table")
print(previous)
print("weight table")
print(weight_table)
print("price ", weight_table[end.value])
return path
Functions
def find_path(start, end, debug=False)
-
Return the shortest path of two vertices using Dijkstra's Algorithm.
Args
start
- starting vertex
end
- ending vertex
debug
- if True, display the weight table
Returns: A list of vertices that form a shortest path
Expand source code
def find_path(start, end, debug=False): """ Return the shortest path of two vertices using Dijkstra's Algorithm. Args: start: starting vertex end: ending vertex debug: if True, display the weight table Returns: A list of vertices that form a shortest path """ weight_table, previous = shortest_path(start, end, debug) path = [] current = end path.append(current.value) while current != start: current = previous[current.value] path.append(current.value) path.reverse() if debug: print("previous table") print(previous) print("weight table") print(weight_table) print("price ", weight_table[end.value]) return path
def shortest_path(start, end, debug=False)
-
Helper function that returns a weight table and a previous vertex table using Dijkstra's Algorithm.
Args
start
- starting vertex
end
- ending vertex
debug
- if True, display weight table as it is being built
Returns: a tuple of a weight table dictionary and a previous path dictionary
Expand source code
def shortest_path(start, end, debug=False): """ Helper function that returns a weight table and a previous vertex table using Dijkstra's Algorithm. Args: start: starting vertex end: ending vertex debug: if True, display weight table as it is being built Returns: a tuple of a weight table dictionary and a previous path dictionary """ weight_table = {} previous = {} visited = {} queue = [] # ideally, a min heap current = start queue.append(current) weight_table[current.value] = 0 previous[current.value] = current while len(queue) > 0: current_weight = weight_table.get(current.value, float('inf')) visited[current.value] = True # for non-weighted version, use: # for adjacent in current.adjacents: # weight = 1 for adjacent, weight in current.adjacents.items(): if not visited.get(adjacent.value, False): queue.append(adjacent) wt = weight_table.get(adjacent.value, float('inf')) if wt > weight + current_weight: weight_table[adjacent.value] = weight + current_weight previous[adjacent.value] = current if debug: print(weight_table) current = queue[0] del queue[0] return weight_table, previous
Classes
class AdjacencyMatrixGraph (labels: list[str])
-
An unweighted adjacency matrix graph implementation in Python (allows either directed or undirected representation)
Args
labels
- list of labels for each vertex
Expand source code
class AdjacencyMatrixGraph: """ An unweighted adjacency matrix graph implementation in Python (allows either directed or undirected representation) """ def __init__(self, labels: list[str]): """ Args: labels: list of labels for each vertex """ self.labels = labels self.label_index = { label: index for index, label in enumerate(labels) } node_count = len(self.labels) self.array = [[None for i in range(node_count)] for j in range(node_count)] def add_edge(self, a_label: str, b_label: str): """ Add an undirected edge between one vertex to another (same as add_edge()) Args: a_label: starting vertex label b_label: ending vertex label """ self.add_adjacent_vertex(a_label, b_label) def add_adjacent_vertex(self, a_label: str, b_label: str): """ Add an undirected edge between one vertex to another (same as add_adjacent_vertex()) Args: a_label: starting vertex label b_label: ending vertex label """ a = self.label_index[a_label] b = self.label_index[b_label] self.array[a][b] = True self.array[a][a] = True self.array[b][a] = True self.array[b][b] = True def add_directed_edge(self, a_label: str, b_label: str): """ Add a directed edge between one vertex to another (same as add_directed_adjacent_vertex() and add_adjacent_directed_vertex()) Args: a_label: starting vertex label b_label: ending vertex label """ self.add_adjacent_directed_vertex(a_label, b_label) def add_directed_adjacent_vertex(self, a_label: str, b_label: str): """ Add a directed edge between one vertex to another (same as add_adjacent_directed_vertex() and add_directed_edge()) Args: a_label: starting vertex label b_label: ending vertex label """ self.add_adjacent_directed_vertex(a_label, b_label) def add_adjacent_directed_vertex(self, a_label: str, b_label: str): """ Add a directed edge between one vertex to another (same as add_directed_adjacent_vertex() and add_directed_edge()) Args: a_label: starting vertex label b_label: ending vertex label """ a = self.label_index[a_label] b = self.label_index[b_label] self.array[a][b] = True self.array[a][a] = True self.array[b][b] = True def df_traverse(self, start_label: str): """ Perform depth first traversal in an adjacency matrix Args: start_label: starting vertex label """ return self._df_rec_traverse(start_label, dict()) def _df_rec_traverse(self, start_label: str, visited): """ Helper method for depth first recursive traversal """ start_index = self.label_index[start_label] visited[start_index] = True print(self.labels[start_index]) for i in range(len(self.array)): if i not in visited and self.array[start_index][i]: self.df_rec_traverse(self.labels[i], visited) def bf_traverse(self, start_label: str): """ Perform breadth first traversal in an adjacency matrix Args: start_label: starting vertex label """ q = [] visited={} start_index = self.label_index[start_label] q.append(start_index) while len(q) > 0: current = q.pop(0) # equivalent of dequeue if current not in visited: visited[current] = True print(self.labels[current]) for i in range(len(self.array)): if self.array[current][i]: q.append(i) def print_graph(self): """ Print the contents of the graph """ print(" |", end="") for label in self.labels: print(f"{label:^3}", end=" ") print() print("----" * (len(self.array) + 1)) for r, row in enumerate(self.array): label = self.labels[r] print(f"{label:^3}|", end=""); for col in row: b = " T " if col else " " print(b, end=" ") print()
Methods
def add_adjacent_directed_vertex(self, a_label: str, b_label: str)
-
Add a directed edge between one vertex to another (same as add_directed_adjacent_vertex() and add_directed_edge())
Args
a_label
- starting vertex label
b_label
- ending vertex label
Expand source code
def add_adjacent_directed_vertex(self, a_label: str, b_label: str): """ Add a directed edge between one vertex to another (same as add_directed_adjacent_vertex() and add_directed_edge()) Args: a_label: starting vertex label b_label: ending vertex label """ a = self.label_index[a_label] b = self.label_index[b_label] self.array[a][b] = True self.array[a][a] = True self.array[b][b] = True
def add_adjacent_vertex(self, a_label: str, b_label: str)
-
Add an undirected edge between one vertex to another (same as add_adjacent_vertex())
Args
a_label
- starting vertex label
b_label
- ending vertex label
Expand source code
def add_adjacent_vertex(self, a_label: str, b_label: str): """ Add an undirected edge between one vertex to another (same as add_adjacent_vertex()) Args: a_label: starting vertex label b_label: ending vertex label """ a = self.label_index[a_label] b = self.label_index[b_label] self.array[a][b] = True self.array[a][a] = True self.array[b][a] = True self.array[b][b] = True
def add_directed_adjacent_vertex(self, a_label: str, b_label: str)
-
Add a directed edge between one vertex to another (same as add_adjacent_directed_vertex() and add_directed_edge())
Args
a_label
- starting vertex label
b_label
- ending vertex label
Expand source code
def add_directed_adjacent_vertex(self, a_label: str, b_label: str): """ Add a directed edge between one vertex to another (same as add_adjacent_directed_vertex() and add_directed_edge()) Args: a_label: starting vertex label b_label: ending vertex label """ self.add_adjacent_directed_vertex(a_label, b_label)
def add_directed_edge(self, a_label: str, b_label: str)
-
Add a directed edge between one vertex to another (same as add_directed_adjacent_vertex() and add_adjacent_directed_vertex())
Args
a_label
- starting vertex label
b_label
- ending vertex label
Expand source code
def add_directed_edge(self, a_label: str, b_label: str): """ Add a directed edge between one vertex to another (same as add_directed_adjacent_vertex() and add_adjacent_directed_vertex()) Args: a_label: starting vertex label b_label: ending vertex label """ self.add_adjacent_directed_vertex(a_label, b_label)
def add_edge(self, a_label: str, b_label: str)
-
Add an undirected edge between one vertex to another (same as add_edge())
Args
a_label
- starting vertex label
b_label
- ending vertex label
Expand source code
def add_edge(self, a_label: str, b_label: str): """ Add an undirected edge between one vertex to another (same as add_edge()) Args: a_label: starting vertex label b_label: ending vertex label """ self.add_adjacent_vertex(a_label, b_label)
def bf_traverse(self, start_label: str)
-
Perform breadth first traversal in an adjacency matrix
Args
start_label
- starting vertex label
Expand source code
def bf_traverse(self, start_label: str): """ Perform breadth first traversal in an adjacency matrix Args: start_label: starting vertex label """ q = [] visited={} start_index = self.label_index[start_label] q.append(start_index) while len(q) > 0: current = q.pop(0) # equivalent of dequeue if current not in visited: visited[current] = True print(self.labels[current]) for i in range(len(self.array)): if self.array[current][i]: q.append(i)
def df_traverse(self, start_label: str)
-
Perform depth first traversal in an adjacency matrix
Args
start_label
- starting vertex label
Expand source code
def df_traverse(self, start_label: str): """ Perform depth first traversal in an adjacency matrix Args: start_label: starting vertex label """ return self._df_rec_traverse(start_label, dict())
def print_graph(self)
-
Print the contents of the graph
Expand source code
def print_graph(self): """ Print the contents of the graph """ print(" |", end="") for label in self.labels: print(f"{label:^3}", end=" ") print() print("----" * (len(self.array) + 1)) for r, row in enumerate(self.array): label = self.labels[r] print(f"{label:^3}|", end=""); for col in row: b = " T " if col else " " print(b, end=" ") print()
class AdjacencyMatrixWeightedGraph (labels)
-
A weighted adjacency matrix graph implementation in Python (allows either directed or undirected representation)
Args
labels
- list of labels for each vertex
Expand source code
class AdjacencyMatrixWeightedGraph: """ A weighted adjacency matrix graph implementation in Python (allows either directed or undirected representation) """ def __init__(self, labels): """ Args: labels: list of labels for each vertex """ self.labels = labels self.label_index = { label: index for index, label in enumerate(labels) } node_count = len(self.labels) self.array = [[None for i in range(node_count)] for j in range(node_count)] def add_edge(self, a_label: str, b_label: str, weight): """ Add an undirected edge between one vertex to another (same as add_edge()) Args: a_label: starting vertex label b_label: ending vertex label weight: weight of the vertex """ self.add_adjacent_vertex(a_label, b_label, weight) def add_adjacent_vertex(self, a_label: str, b_label: str, weight): """ Add an undirected edge between one vertex to another (same as add_edge()) Args: a_label: starting vertex label b_label: ending vertex label weight: weight of the vertex """ a = self.label_index[a_label] b = self.label_index[b_label] self.array[a][b] = weight self.array[a][a] = 0 self.array[b][a] = weight self.array[b][b] = 0 def add_directed_edge(self, a_label: str, b_label: str, weight): """ Add a weighted directed edge between one vertex to another (same as add_adjacent_directed_vertex(), add_directed_adjacent_vertex()) Args: a_label: starting vertex label b_label: ending vertex label weight: weight of the vertex """ self.add_adjacent_directed_vertex(a_label, b_label, weight) def add_directed_adjacent_vertex(self, a_label: str, b_label: str, weight): """ Add a weighted directed edge between one vertex to another (same as add_directed_edge(), add_adjacent_directed_vertex()) Args: a_label: starting vertex label b_label: ending vertex label weight: weight of the vertex """ self.add_adjacent_directed_vertex(a_label, b_label, weight) def add_adjacent_directed_vertex(self, a_label: str, b_label: str, weight): """ Add a weighted directed edge between one vertex to another (same as add_directed_edge(), add_directed_adjacent_vertex()) Args: a_label: starting vertex label b_label: ending vertex label weight: weight of the vertex """ a = self.label_index[a_label] b = self.label_index[b_label] self.array[a][b] = weight self.array[a][a] = 0 self.array[b][b] = 0 def print_graph(self): """ Print the contents of the graph. """ print(" |", end="") for label in self.labels: print(f"{label:>3}", end=" ") print() print("----" * (len(self.array) + 1)) for r, row in enumerate(self.array): label = self.labels[r] print(f"{label:^3}|", end=""); for col in row: w = f"{col:3}" if col is not None else " " print(w, end=" ") print()
Methods
def add_adjacent_directed_vertex(self, a_label: str, b_label: str, weight)
-
Add a weighted directed edge between one vertex to another (same as add_directed_edge(), add_directed_adjacent_vertex())
Args
a_label
- starting vertex label
b_label
- ending vertex label
weight
- weight of the vertex
Expand source code
def add_adjacent_directed_vertex(self, a_label: str, b_label: str, weight): """ Add a weighted directed edge between one vertex to another (same as add_directed_edge(), add_directed_adjacent_vertex()) Args: a_label: starting vertex label b_label: ending vertex label weight: weight of the vertex """ a = self.label_index[a_label] b = self.label_index[b_label] self.array[a][b] = weight self.array[a][a] = 0 self.array[b][b] = 0
def add_adjacent_vertex(self, a_label: str, b_label: str, weight)
-
Add an undirected edge between one vertex to another (same as add_edge())
Args
a_label
- starting vertex label
b_label
- ending vertex label
weight
- weight of the vertex
Expand source code
def add_adjacent_vertex(self, a_label: str, b_label: str, weight): """ Add an undirected edge between one vertex to another (same as add_edge()) Args: a_label: starting vertex label b_label: ending vertex label weight: weight of the vertex """ a = self.label_index[a_label] b = self.label_index[b_label] self.array[a][b] = weight self.array[a][a] = 0 self.array[b][a] = weight self.array[b][b] = 0
def add_directed_adjacent_vertex(self, a_label: str, b_label: str, weight)
-
Add a weighted directed edge between one vertex to another (same as add_directed_edge(), add_adjacent_directed_vertex())
Args
a_label
- starting vertex label
b_label
- ending vertex label
weight
- weight of the vertex
Expand source code
def add_directed_adjacent_vertex(self, a_label: str, b_label: str, weight): """ Add a weighted directed edge between one vertex to another (same as add_directed_edge(), add_adjacent_directed_vertex()) Args: a_label: starting vertex label b_label: ending vertex label weight: weight of the vertex """ self.add_adjacent_directed_vertex(a_label, b_label, weight)
def add_directed_edge(self, a_label: str, b_label: str, weight)
-
Add a weighted directed edge between one vertex to another (same as add_adjacent_directed_vertex(), add_directed_adjacent_vertex())
Args
a_label
- starting vertex label
b_label
- ending vertex label
weight
- weight of the vertex
Expand source code
def add_directed_edge(self, a_label: str, b_label: str, weight): """ Add a weighted directed edge between one vertex to another (same as add_adjacent_directed_vertex(), add_directed_adjacent_vertex()) Args: a_label: starting vertex label b_label: ending vertex label weight: weight of the vertex """ self.add_adjacent_directed_vertex(a_label, b_label, weight)
def add_edge(self, a_label: str, b_label: str, weight)
-
Add an undirected edge between one vertex to another (same as add_edge())
Args
a_label
- starting vertex label
b_label
- ending vertex label
weight
- weight of the vertex
Expand source code
def add_edge(self, a_label: str, b_label: str, weight): """ Add an undirected edge between one vertex to another (same as add_edge()) Args: a_label: starting vertex label b_label: ending vertex label weight: weight of the vertex """ self.add_adjacent_vertex(a_label, b_label, weight)
def print_graph(self)
-
Print the contents of the graph.
Expand source code
def print_graph(self): """ Print the contents of the graph. """ print(" |", end="") for label in self.labels: print(f"{label:>3}", end=" ") print() print("----" * (len(self.array) + 1)) for r, row in enumerate(self.array): label = self.labels[r] print(f"{label:^3}|", end=""); for col in row: w = f"{col:3}" if col is not None else " " print(w, end=" ") print()
class Vertex (value)
-
A unweighted adjacency list vertex implementation in Python (allows either directed or undirected representation)
Args
value
- value of the vertex
Expand source code
class Vertex: pass
Methods
def add_adjacent_vertex(self, vertex: type[Vertex])
-
Add an undirected vertex to the adjacency list (same as add_edge()).
Args
vertex
- vertex to add
Expand source code
def add_adjacent_vertex(self, vertex: type[Vertex]): """ Add an undirected vertex to the adjacency list (same as add_edge()). Args: vertex: vertex to add """ if vertex not in self.adjacents: self.adjacents.append(vertex) if self not in vertex.adjacents: vertex.add_adjacent_vertex(self)
def add_directed_adjacent_vertex(self, vertex: type[Vertex])
-
Add a directed vertex to the adjacency list (same as add_directed_edge()).
Args
vertex
- vertex to add
Expand source code
def add_directed_adjacent_vertex(self, vertex: type[Vertex]): """ Add a directed vertex to the adjacency list (same as add_directed_edge()). Args: vertex: vertex to add """ if vertex not in self.adjacents: self.adjacents.append(vertex)
def add_directed_edge(self, vertex: type[Vertex])
-
Add a directed vertex to the adjacency list (same as add_directed_adjacent_vertex()).
Args
vertex
- vertex to add
Expand source code
def add_directed_edge(self, vertex: type[Vertex]): """ Add a directed vertex to the adjacency list (same as add_directed_adjacent_vertex()). Args: vertex: vertex to add """ self.add_directed_adjacent_vertex(vertex)
def add_edge(self, vertex: type[Vertex])
-
Add an undirected vertex to the adjacency list (same as add_adjacent_vertex()).
Args
vertex
- vertex to add
Expand source code
def add_edge(self, vertex: type[Vertex]): """ Add an undirected vertex to the adjacency list (same as add_adjacent_vertex()). Args: vertex: vertex to add """ self.add_adjacent_vertex(vertex)
def bf_traverse(self)
-
Perform breadth first traversal.
Expand source code
def bf_traverse(self): """ Perform breadth first traversal. """ start = self visited = {} queue = [] queue.append(start) while len(queue) > 0: current = queue[0] del queue[0] if not visited.get(current, False): visited[current] = True print(current.value) for v in current.adjacents: queue.append(v)
def bfs(self, end)
-
Recursive breadth first search.
Args
end
- vertex to search for
Returns: Vertex in the graph None if not found.
Expand source code
def bfs(self, end): """ Recursive breadth first search. Args: end: vertex to search for Returns: Vertex in the graph None if not found. """ visited = {} queue = [] start = self visited[start] = True queue.append(start) while len(queue) > 0: current = queue[0] del queue[0] print(current.value) # print("Visited: ", visited) # print("Queue: ", queue) if current.value == end.value: return current for v in current.adjacents: if not visited.get(v, False): visited[v] = True queue.append(v) return None
def df_traverse(self)
-
Perform depth first traversal.
Expand source code
def df_traverse(self): """ Perform depth first traversal. """ self._df_traverse_rec(self, dict())
def dfs(self, end)
-
Recursive depth first search.
Args
end
- vertex to search for
Returns: Vertex in the graph None if not found.
Expand source code
def dfs(self, end): """ Recursive depth first search. Args: end: vertex to search for Returns: Vertex in the graph None if not found. """ return self.dfs_rec(self, end, dict())
def dfs_rec(self, current, end, visited=None)
-
helper depth first search recursive function
Returns: Vertex in the graph None if not found.
Expand source code
def dfs_rec(self, current, end, visited=None): """ helper depth first search recursive function Returns: Vertex in the graph None if not found. """ if current.value == end.value: print("Found: ", end.value) return current visited[current] = True print(current.value) for v in current.adjacents: if not visited.get(v, False): return v.dfs_rec(v, end, visited) return None
class WeightedVertex (value)
-
A weighted adjacency list vertex implementation in Python (allows either directed or undirected representation)
Args
value
- value of the vertex
Expand source code
class WeightedVertex: pass
Methods
def add_adjacent_vertex(self, vertex: type[WeightedVertex], weight)
-
Add a weighted edge to the adjacency list (same as add_directed_edge()).
Args
vertex
- vertex to add
weight
- weight of the vertex
Expand source code
def add_adjacent_vertex(self, vertex: type[WeightedVertex], weight): """ Add a weighted edge to the adjacency list (same as add_directed_edge()). Args: vertex: vertex to add weight: weight of the vertex """ if vertex not in self.adjacents: self.adjacents[vertex] = weight if self not in vertex.adjacents: vertex.adjacents[self] = weight
def add_directed_adjacent_vertex(self, vertex: type[WeightedVertex], weight)
-
Add a weighted directed edge to the adjacency list (same as add_directed_edge()).
Args
vertex
- vertex to add
weight
- weight of the vertex
Expand source code
def add_directed_adjacent_vertex(self, vertex: type[WeightedVertex], weight): """ Add a weighted directed edge to the adjacency list (same as add_directed_edge()). Args: vertex: vertex to add weight: weight of the vertex """ if vertex not in self.adjacents: self.adjacents[vertex] = weight
def add_directed_edge(self, vertex: type[WeightedVertex], weight)
-
Add a weighted directed edge to the adjacency list (same as add_directed_adjacent_vertex()).
Args
vertex
- vertex to add
weight
- weight of the vertex
Expand source code
def add_directed_edge(self, vertex: type[WeightedVertex], weight): """ Add a weighted directed edge to the adjacency list (same as add_directed_adjacent_vertex()). Args: vertex: vertex to add weight: weight of the vertex """ self.add_directed_adjacent_vertex(vertex, weight)
def add_edge(self, vertex: type[WeightedVertex], weight)
-
Add a weighted directed edge to the adjacency list (same as add_adjacent_vertex()).
Args
vertex
- vertex to add
weight
- weight of the vertex
Expand source code
def add_edge(self, vertex: type[WeightedVertex], weight): """ Add a weighted directed edge to the adjacency list (same as add_adjacent_vertex()). Args: vertex: vertex to add weight: weight of the vertex """ self.add_adjacent_vertex(vertex, weight)
def bf_traverse(self, vertex: type[WeightedVertex])
-
breadth first traversal
Args
vertex
- starting vertex
Expand source code
def bf_traverse(self, vertex: type[WeightedVertex]): """ breadth first traversal Args: vertex: starting vertex """ visited = {} queue = [] queue.append(vertex) while len(queue) > 0: current = queue[0] del queue[0] if not visited.get(current, False): visited[current] = True print(current.value) for v in current.adjacents: queue.append(v)
def bfs(self, vertex: type[WeightedVertex], target)
-
breadth first search
Args
vertex
- startering vertex
target
- target value to search for
Expand source code
def bfs(self, vertex: type[WeightedVertex], target): """ breadth first search Args: vertex: startering vertex target: target value to search for """ visited = {} queue = [] queue.append(vertex) while len(queue) > 0: current = queue[0] del queue[0] if current.value == target: return current if not visited.get(current, False): visited[current] = True print(current.value) for v in current.adjacents: queue.append(v) return None
def df_traverse(self, vertex: type[WeightedVertex], visited={})
-
depth first traversal
Args
vertex
- starting vertex
visited
- dictionary of visited vertices
Expand source code
def df_traverse(self, vertex: type[WeightedVertex], visited={}): """ depth first traversal Args: vertex: starting vertex visited: dictionary of visited vertices """ visited[vertex] = True print(vertex.value) for v in vertex.adjacents: if not visited.get(v, False): v.df_traverse(v, visited)
def dfs(self, target: type[WeightedVertex])
-
depth first search
Args
target
- target value to search for
Expand source code
def dfs(self, target: type[WeightedVertex]): """ depth first search Args: target: target value to search for """ return self._dfs_rec(self, target, dict())