Module dsa.graph

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

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

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
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
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
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
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
def bf_traverse(self, start_label: str)

Perform breadth first traversal in an adjacency matrix

Args

start_label
starting vertex label
def df_traverse(self, start_label: str)

Perform depth first traversal in an adjacency matrix

Args

start_label
starting vertex label
def print_graph(self)

Print the contents of the graph

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
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
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
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
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
def print_graph(self)

Print the contents of the graph.

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
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
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
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
def bf_traverse(self)

Perform breadth first traversal.

def bfs(self, end)

Recursive breadth first search.

Args

end
vertex to search for

Returns: Vertex in the graph None if not found.

def df_traverse(self)

Perform depth first traversal.

def dfs(self, end)

Recursive depth first search.

Args

end
vertex to search for

Returns: Vertex in the graph None if not found.

def dfs_rec(self, current, end, visited=None)

helper depth first search recursive function

Returns: Vertex in the graph None if not found.

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
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
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
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
def bf_traverse(self, vertex: type[WeightedVertex])

breadth first traversal

Args

vertex
starting vertex
def bfs(self, vertex: type[WeightedVertex], target)

breadth first search

Args

vertex
startering vertex
target
target value to search for
def df_traverse(self, vertex: type[WeightedVertex], visited={})

depth first traversal

Args

vertex
starting vertex
visited
dictionary of visited vertices
def dfs(self, target: type[WeightedVertex])

depth first search

Args

target
target value to search for