Phase1 Report
Phase1 Report
Project Report
Student Names: Student IDs:
Lulwah Alfadhli 2181150182
Amal Alenezi 2182160072
The ability to represent complex relationships and networks through graphical structures is a
cornerstone of modern computational tasks. Graphs, in their various forms, play an
indispensable role in a range of applications, from telecommunications to social sciences.
However, creating such graphs, especially with weighted edges and under specific constraints,
poses its own set of challenges. This report seeks to introduce an innovative Program using
Python tailored for the construction of connected, weighted graphs. By specifying the number
of vertices (v) and edges (e), users can harness this Program to generate a graph, where the
resultant edge weights are randomized between a given range. With an emphasis on the
adjacency list representation, this report promises a deep dive into the Program design, practical
Implementation, and performance metrics.
Graph Class:
The `Graph` class represents a graph using an adjacency list, which is a dictionary where
keys are vertex identifiers and values are lists of adjacent vertices with weights.
add_vertex Method:
This method adds a new vertex to the graph. If the vertex (key) is not already in the adjacency
list, it initializes an empty list for that key, representing no connections initially.
add_edge Method:
This method establishes an undirected edge between two vertices with a certain weight. If
both vertices exist, it checks whether the edge or its reverse (since the graph is
undirected)already exists using the `edge_exists` method ; if not, it appends a new dictionary
representing the edge and its weight to the adjacency lists of both `from_vertex` and
`to_vertex`. This ensures the graph remains undirected because we add the connection for both
vertices.
edge_exists Method:
This method checks whether a specific edge already exists in the graph. It iterates over all
edges in the adjacency list of the `from_vertex`. If it finds an edge with a destination vertex
(`'to_vertex'`) equal to `to_vertex`, it returns `True`, indicating the edge exists. If the loop
completes without finding the specified edge, the method returns `False`, indicating the edge
does not exist.
display_graph Method:
This method prints the adjacency list of the graph. For each vertex, it compiles a list of strings
representing its connections (including the connected vertex and the weight) and prints them
in a readable format.
main Function:
The `main` function handles user inputs for the number of vertices and edges, creates a
`Graph` object, adds vertices and edges to it, and finally displays the graph and the running
time of the algorithm. It ensures the graph is connected by initially connecting each vertex to
the next one.
The function continues to add edges until the desired number is reached, using the `add_edge`
method. It checks for the uniqueness of edges (no self-loops and no duplicate edges) before
insertion.
The function also tracks the time taken for the graph construction and display process,
providing insight into the algorithm's efficiency.
Source code
import time
import random
class Graph:
def __init__(self):
self.adjacency_list = {}
def display_graph(self):
for vertex in self.adjacency_list:
connections = []
for edge in self.adjacency_list[vertex]:
connections.append(f"({edge['to_vertex']}, {edge['weight']})")
print(f"{vertex} -> {' -> '.join(connections) if connections else 'None'}")
def main():
g = Graph()
start_time = time.time()
for i in range(1, num_vertices + 1):
g.add_vertex(str(i))
end_time = time.time()
print(f"\nAlgorithm Running time: ({end_time - start_time:.6f}) seconds")
if __name__ == "__main__":
main()
Output of running 3 examples on this algorithm
Example 1:
Example 2:
Example 3:
Output of running time of this program on graphs of sizes 5, 10, 20, 30, 40,
50, 60, 70, 80, 90, 100.
Program Performance
0.3
0.25
Running Time in seconds
0.2
0.15
0.1
0.05
0
0 20 40 60 80 100 120
Graph Size
Conclusion:
Graphs, in their abstract elegance, mirror the interconnected nature of today's digital world.
Through this exploration, we've showcased a Python Program solution adept at constructing
graphs with precise vertex and edge counts, all the while ensuring they remain connected and
carry randomized edge weights. This nuanced approach not only fulfills the user-defined
parameters but also brings a level of dynamism with its weight randomization. Trialing the
algorithm across three diverse examples has solidified its robustness and versatility. By also
charting the running time, we gain a comprehensive understanding of the algorithm's efficiency
spectrum. In the ever-evolving sphere of computational graph theory, having tools like the one
detailed in this report can pave the way for more streamlined and effective solutions in the
future.