Lab2
Lab2
Lab2:Graphs
Graph Data Structure
Definition
A graph is a non-linear data structure consisting of nodes (vertices) and
edges.
Types:
Graph Representation
1. Adjacency Matrix
A 2D array where adj[i][j] = 1 indicates an edge exists between nodes i and
j.
import numpy as np
Lab2:Graphs 1
# [A, B, C, D, E, F]
graph = np.array([[0,1,0,1,1,0],
[1,0,1,0,0,0],
[0,1,0,0,1,1],
[1,0,0,0,1,0],
[1,0,1,1,0,1],
[0,0,1,0,1,0]])
2. Adjacency List
A dictionary where each key is a node, and its value is a list of adjacent nodes.
# Adjacency List
graph = { 'A': ['B','D','E'],
'B': ['A','C'],
'C': ['B','E','F'],
'D': ['A','E'],
'E': ['A','C','D','F'],
'F': ['C','E']
}
NetworkX Package
Lab2:Graphs 2
import networkx as nx
graph.add_node("A")
graph.add_node("B")
graph.add_node("C")
graph.add_node("D")
graph.add_node("E")
graph.add_node("F")
#{ 'A': ['B','D','E'],
# 'B': ['A','C'],
# 'C': ['B','E','F'],
# 'D': ['A','E'],
# 'E': ['A','C','D','F'],
# 'F': ['C','E']
# }
graph.add_edge("A","B")
graph.add_edge("A","D")
graph.add_edge("A","E")
graph.add_edge("B","A")
graph.add_edge("B","C")
graph.add_edge("C","B")
graph.add_edge("C","E")
graph.add_edge("C","F")
graph.add_edge("D","A")
graph.add_edge("D","E")
graph.add_edge("E","A")
graph.add_edge("E","C")
graph.add_edge("E","D")
Lab2:Graphs 3
graph.add_edge("E","F")
graph.add_edge("F","C")
graph.add_edge("F","E")
Output:
Number of nodes: 6
Number of edges: 8
Nodes: ['A', 'B', 'C', 'D', 'E', 'F']
Edges: [('A', 'B'), ('A', 'D'), ('A', 'E'), ('B', 'C'), ('C',
Neighbors of node A: ['B', 'D', 'E']
Number of edges connented to node A (degree): 3
graph.remove_node("C")
print("Nodes: ", list(graph.nodes))
Output:
Nodes: ['A', 'B', 'D', 'E', 'F']
Lab2:Graphs 4
Output:
Edges: [('A', 'B'), ('A', 'D'), ('A', 'E'), ('D', 'E'), ('E',
graph.remove_edge("A","E")
print("Neighbors of node A: ", list(graph.adj["A"]))
Output:
Neighbors of node A: ['B', 'D']
digraph = nx.DiGraph()
Output:
Number of nodes: 5
Lab2:Graphs 5
Number of edges: 6
Nodes: ['A', 'D', 'C', 'B', 'E']
Edges: [('A', 'D'), ('A', 'C'), ('C', 'B'), ('C', 'D'), ('B',
Neighbors of node A: ['D', 'C']
Number of edges connented to node A (degree): 4
Components:
tree = Tree()
tree.create_node("A", "a")
tree.create_node("B", "b", parent="a")
tree.create_node("C", "c", parent="a")
tree.create_node("D", "d", parent="b")
tree.create_node("E", "e", parent="b")
tree.create_node("H", "h", parent="d")
tree.create_node("I", "i", parent="d")
tree.create_node("F", "f", parent="c")
tree.create_node("G", "g", parent="c")
Lab2:Graphs 6
print(tree)
Output:
Output:
Tree depth: 3
Number of nodes: 9
Tree Root: a
Nodes: [Node(tag=A, identifier=a, data=None), Node(tag=B, ident
Depth of node D: 2
Parent of node D: Node(tag=B, identifier=b, data=None)
Leaves of node D: [Node(tag=H, identifier=h, data=None), Node(t
Lab2:Graphs 7
Children of node D: ['h', 'i']
Siblings of node H: [Node(tag=I, identifier=i, data=None)]
# Show subtree
sub_t = tree.subtree('b')
sub_t.show()
Output:
b'B\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 D\n\xe2\x94\x82 \xe2
# Remove a node
tree.remove_node("b")
tree.show()
# Move a node
tree.move_node('f', 'h')
tree.show()
Lab Solution:
Network Topology and Graph Representation
Problem Description
We need to represent a computer network with 7 devices as a graph. The devices
and their connections with bandwidths are as follows:
Connections:
Lab2:Graphs 8
Router ↔ Switch1: 100 Mbps
import numpy as np
# Adjacency matrix
graph = np.array([
[0, 100, 50, 0, 0, 0, 0], # Router connections
[100, 0, 0, 200, 0, 150, 0], # Switch1 connections
[50, 0, 0, 0, 300, 0, 250], # Switch2 connections
[0, 200, 0, 0, 400, 0, 0], # Server1 connections
[0, 0, 300, 400, 0, 0, 0], # Server2 connections
[0, 150, 0, 0, 0, 0, 100], # PC1 connections
[0, 0, 250, 0, 0, 100, 0], # PC2 connections
])
# Device names
devices = ['Router', 'Switch1', 'Switch2', 'Server1', 'Server2',
Lab2:Graphs 9
# Print header row with formatted spacing
header = f"{'':<10}" + ''.join(f"{device:<10}" for device in dev
print(header)
print('-' * len(header)) # Separator line for clarity
# Print each row with device name and matrix values, formatted f
for i, row in enumerate(graph):
line = f"{devices[i]:<10}" + ''.join(f"{value:<10}" for valu
print(line)
Lab2:Graphs 10
Modify the latency between "Router" and "Switch1" to 15 ms.
class ComputerNetwork:
def __init__(self, network_map):
self.networkMap = network_map # 2D array representing l
self.deviceNames = [] # List of device names
def fillDeviceNames(self):
print("Enter device names (no duplicates):")
for i in range(len(self.networkMap)):
while True:
device = input(f"Enter device name for row {i +
if device not in self.deviceNames:
self.deviceNames.append(device)
break
else:
print("Device name already exists. Try again
Lab2:Graphs 11
print(f"Latency between {a} and {b} updated to {c} m
def printNetworkMap(self):
print("\nNetwork Map:")
header = f"{'':<10}" + ''.join(f"{name:<10}" for name in
print(header)
print('-' * len(header))
for i, row in enumerate(self.networkMap):
line = f"{self.deviceNames[i]:<10}" + ''.join(f"{val
print(line)
# Update latencies
network1.updateLatency("Router", "Switch1", 15)
network1.updateLatency("Router", "Server1", 50)
Lab2:Graphs 12
# Print updated network map
network1.printNetworkMap()
FUNCTION fillDeviceNames():
DISPLAY "Enter device names, ensuring no duplicates:"
FOR each row in networkMap:
WHILE True:
PROMPT "Enter device name for this row:"
IF device name is not already in deviceNames:
ADD device name to deviceNames
BREAK
ELSE:
DISPLAY "Device name already exists. Try again."
Lab2:Graphs 13
tree.create_node("Switch2", "S2", parent="D2")
tree.create_node("Switch3", "S3", parent="D2")
tree.create_node("Workstation", "W1", parent="S1")
print(tree)
Lab2:Graphs 14