Skip to content

Commit 2f5f159

Browse files
Added Gantt chart visualization to SJF (Shortest Job First) scheduler
1 parent 5e58b2c commit 2f5f159

File tree

1 file changed

+78
-82
lines changed

1 file changed

+78
-82
lines changed

scheduling/shortest_job_first.py

Lines changed: 78 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,34 @@
11
"""
2-
Shortest job remaining first
3-
Please note arrival time and burst
4-
Please use spaces to separate times entered.
2+
Shortest Job Remaining First (Preemptive SJF)
3+
---------------------------------------------
4+
Please note arrival time and burst time.
5+
Use spaces to separate times entered.
56
"""
67

78
from __future__ import annotations
8-
99
import pandas as pd
10+
import matplotlib.pyplot as plt
1011

1112

1213
def calculate_waitingtime(
1314
arrival_time: list[int], burst_time: list[int], no_of_processes: int
14-
) -> list[int]:
15+
) -> tuple[list[int], list[tuple[int, int, int]]]:
1516
"""
16-
Calculate the waiting time of each processes
17-
Return: List of waiting times.
18-
>>> calculate_waitingtime([1,2,3,4],[3,3,5,1],4)
19-
[0, 3, 5, 0]
20-
>>> calculate_waitingtime([1,2,3],[2,5,1],3)
21-
[0, 2, 0]
22-
>>> calculate_waitingtime([2,3],[5,1],2)
23-
[1, 0]
17+
Calculate the waiting time for each process and record execution timeline for Gantt Chart.
18+
Returns: (waiting_time, timeline)
19+
timeline -> list of tuples: (start_time, end_time, process_id)
2420
"""
25-
remaining_time = [0] * no_of_processes
21+
remaining_time = burst_time.copy()
2622
waiting_time = [0] * no_of_processes
27-
# Copy the burst time into remaining_time[]
28-
for i in range(no_of_processes):
29-
remaining_time[i] = burst_time[i]
30-
3123
complete = 0
3224
increment_time = 0
33-
minm = 999999999
25+
minm = float("inf")
3426
short = 0
3527
check = False
3628

37-
# Process until all processes are completed
29+
timeline = [] # To store execution sequence for Gantt chart
30+
last_process = -1
31+
3832
while complete != no_of_processes:
3933
for j in range(no_of_processes):
4034
if (
@@ -49,43 +43,41 @@ def calculate_waitingtime(
4943
if not check:
5044
increment_time += 1
5145
continue
52-
remaining_time[short] -= 1
5346

47+
# Record when process switches (for Gantt chart)
48+
if short != last_process:
49+
if timeline and timeline[-1][2] == last_process:
50+
timeline[-1] = (timeline[-1][0], increment_time, last_process)
51+
if short != -1:
52+
timeline.append((increment_time, None, short))
53+
last_process = short
54+
55+
remaining_time[short] -= 1
5456
minm = remaining_time[short]
5557
if minm == 0:
56-
minm = 999999999
58+
minm = float("inf")
5759

5860
if remaining_time[short] == 0:
5961
complete += 1
6062
check = False
61-
62-
# Find finish time of current process
6363
finish_time = increment_time + 1
64-
65-
# Calculate waiting time
6664
finar = finish_time - arrival_time[short]
6765
waiting_time[short] = finar - burst_time[short]
68-
6966
waiting_time[short] = max(waiting_time[short], 0)
7067

71-
# Increment time
7268
increment_time += 1
73-
return waiting_time
69+
70+
# Close last ongoing process in timeline
71+
if timeline and timeline[-1][1] is None:
72+
timeline[-1] = (timeline[-1][0], increment_time, last_process)
73+
74+
return waiting_time, timeline
7475

7576

7677
def calculate_turnaroundtime(
7778
burst_time: list[int], no_of_processes: int, waiting_time: list[int]
7879
) -> list[int]:
79-
"""
80-
Calculate the turn around time of each Processes
81-
Return: list of turn around times.
82-
>>> calculate_turnaroundtime([3,3,5,1], 4, [0,3,5,0])
83-
[3, 6, 10, 1]
84-
>>> calculate_turnaroundtime([3,3], 2, [0,3])
85-
[3, 6]
86-
>>> calculate_turnaroundtime([8,10,1], 3, [1,0,3])
87-
[9, 10, 4]
88-
"""
80+
"""Calculate the turn around time for each process."""
8981
turn_around_time = [0] * no_of_processes
9082
for i in range(no_of_processes):
9183
turn_around_time[i] = burst_time[i] + waiting_time[i]
@@ -94,60 +86,64 @@ def calculate_turnaroundtime(
9486

9587
def calculate_average_times(
9688
waiting_time: list[int], turn_around_time: list[int], no_of_processes: int
97-
) -> None:
98-
"""
99-
This function calculates the average of the waiting & turnaround times
100-
Prints: Average Waiting time & Average Turn Around Time
101-
>>> calculate_average_times([0,3,5,0],[3,6,10,1],4)
102-
Average waiting time = 2.00000
103-
Average turn around time = 5.0
104-
>>> calculate_average_times([2,3],[3,6],2)
105-
Average waiting time = 2.50000
106-
Average turn around time = 4.5
107-
>>> calculate_average_times([10,4,3],[2,7,6],3)
108-
Average waiting time = 5.66667
109-
Average turn around time = 5.0
110-
"""
111-
total_waiting_time = 0
112-
total_turn_around_time = 0
113-
for i in range(no_of_processes):
114-
total_waiting_time = total_waiting_time + waiting_time[i]
115-
total_turn_around_time = total_turn_around_time + turn_around_time[i]
116-
print(f"Average waiting time = {total_waiting_time / no_of_processes:.5f}")
117-
print("Average turn around time =", total_turn_around_time / no_of_processes)
89+
) -> tuple[float, float]:
90+
"""Calculate and return average waiting and turnaround times."""
91+
avg_wait = sum(waiting_time) / no_of_processes
92+
avg_turn = sum(turn_around_time) / no_of_processes
93+
print(f"Average waiting time = {avg_wait:.5f}")
94+
print(f"Average turn around time = {avg_turn:.5f}")
95+
return avg_wait, avg_turn
96+
97+
98+
def plot_gantt_chart(timeline: list[tuple[int, int, int]], processes: list[int]) -> None:
99+
"""Plot a Gantt chart for process execution."""
100+
fig, ax = plt.subplots(figsize=(10, 2))
101+
colors = plt.cm.tab10.colors # Nice color set
102+
for start, end, pid in timeline:
103+
ax.barh(
104+
0,
105+
end - start,
106+
left=start,
107+
color=colors[pid % len(colors)],
108+
edgecolor="black",
109+
label=f"P{processes[pid]}",
110+
)
111+
ax.text((start + end) / 2, 0, f"P{processes[pid]}", ha="center", va="center", color="white", fontsize=9)
112+
113+
ax.set_xlabel("Time")
114+
ax.set_yticks([])
115+
ax.set_title("Gantt Chart - Shortest Job Remaining First (SJF Preemptive)")
116+
handles, labels = plt.gca().get_legend_handles_labels()
117+
by_label = dict(zip(labels, handles))
118+
ax.legend(by_label.values(), by_label.keys(), bbox_to_anchor=(1.05, 1), loc="upper left")
119+
plt.tight_layout()
120+
plt.show()
118121

119122

120123
if __name__ == "__main__":
121-
print("Enter how many process you want to analyze")
122-
no_of_processes = int(input())
124+
print("Enter how many processes you want to analyze:")
125+
no_of_processes = int(input().strip())
126+
123127
burst_time = [0] * no_of_processes
124128
arrival_time = [0] * no_of_processes
125129
processes = list(range(1, no_of_processes + 1))
126130

127131
for i in range(no_of_processes):
128-
print("Enter the arrival time and burst time for process:--" + str(i + 1))
132+
print(f"Enter the arrival time and burst time for process {i + 1}:")
129133
arrival_time[i], burst_time[i] = map(int, input().split())
130134

131-
waiting_time = calculate_waitingtime(arrival_time, burst_time, no_of_processes)
132-
133-
bt = burst_time
134-
n = no_of_processes
135-
wt = waiting_time
136-
turn_around_time = calculate_turnaroundtime(bt, n, wt)
137-
135+
waiting_time, timeline = calculate_waitingtime(arrival_time, burst_time, no_of_processes)
136+
turn_around_time = calculate_turnaroundtime(burst_time, no_of_processes, waiting_time)
138137
calculate_average_times(waiting_time, turn_around_time, no_of_processes)
139138

140-
fcfs = pd.DataFrame(
141-
list(zip(processes, burst_time, arrival_time, waiting_time, turn_around_time)),
142-
columns=[
143-
"Process",
144-
"BurstTime",
145-
"ArrivalTime",
146-
"WaitingTime",
147-
"TurnAroundTime",
148-
],
139+
# Display results table
140+
df = pd.DataFrame(
141+
list(zip(processes, arrival_time, burst_time, waiting_time, turn_around_time)),
142+
columns=["Process", "ArrivalTime", "BurstTime", "WaitingTime", "TurnAroundTime"],
149143
)
144+
pd.set_option("display.max_rows", df.shape[0] + 1)
145+
print("\n--- Process Table ---")
146+
print(df)
150147

151-
# Printing the dataFrame
152-
pd.set_option("display.max_rows", fcfs.shape[0] + 1)
153-
print(fcfs)
148+
# Plot Gantt chart
149+
plot_gantt_chart(timeline, processes)

0 commit comments

Comments
 (0)