Initial commit: Heapsort and Priority Queue Implementation

- Implemented complete Heapsort algorithm with max-heap operations
- Implemented binary heap-based Priority Queue with all core operations
- Created Task class for task scheduling applications
- Implemented Task Scheduler simulation using priority queue
- Added comprehensive test suite (70+ tests, all passing)
- Implemented sorting algorithm comparison utilities (Heapsort vs Quicksort vs Merge Sort)
- Added detailed README with comprehensive analysis and documentation
- Included demonstration scripts for all features
- Generated performance comparison plots
- Modular, well-documented code following academic standards

Author: Carlos Gutierrez
Email: cgutierrez44833@ucumberlands.edu
This commit is contained in:
Carlos Gutierrez
2025-11-09 21:54:13 -05:00
commit c1b0fd3aaf
26 changed files with 3552 additions and 0 deletions

12
examples/__init__.py Normal file
View File

@@ -0,0 +1,12 @@
"""
Example Scripts for MSCS532 Assignment 4
This package contains demonstration scripts for:
- Heapsort implementation
- Priority Queue usage
- Sorting algorithm comparisons
Author: Carlos Gutierrez
Email: cgutierrez44833@ucumberlands.edu
"""

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""
Sorting Algorithm Comparison Demonstration
This script demonstrates the empirical comparison of Heapsort,
Quicksort, and Merge Sort on different input sizes and distributions.
Author: Carlos Gutierrez
Email: cgutierrez44833@ucumberlands.edu
"""
import sys
import os
# Add parent directory to path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from src.comparison import run_comparison
def main():
"""Run sorting algorithm comparison."""
print("\n" + "=" * 80)
print("SORTING ALGORITHM COMPARISON DEMONSTRATION")
print("Author: Carlos Gutierrez")
print("Email: cgutierrez44833@ucumberlands.edu")
print("=" * 80)
# Run comparison with different sizes
# Note: Large sizes may take significant time
sizes = [100, 1000, 10000]
print(f"\nComparing Heapsort, Quicksort, and Merge Sort")
print(f"Input sizes: {sizes}")
print(f"\nNote: This may take a few moments...\n")
results = run_comparison(sizes=sizes)
print("\n" + "=" * 80)
print("COMPARISON COMPLETE")
print("=" * 80)
print("\nKey Observations:")
print("1. Heapsort: Consistent O(n log n) performance across all input types")
print("2. Quicksort: Fastest on average, but degrades on sorted inputs")
print("3. Merge Sort: Consistent performance, requires O(n) extra space")
print("\nSee README.md for detailed analysis.\n")
if __name__ == "__main__":
main()

155
examples/generate_plots.py Normal file
View File

@@ -0,0 +1,155 @@
#!/usr/bin/env python3
"""
Generate Performance Comparison Plots
This script generates visualization plots comparing Heapsort, Quicksort,
and Merge Sort performance on different input sizes and distributions.
Author: Carlos Gutierrez
Email: cgutierrez44833@ucumberlands.edu
"""
import sys
import os
import matplotlib.pyplot as plt
import numpy as np
# Add parent directory to path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from src.comparison import compare_sorting_algorithms
def generate_performance_plots():
"""Generate performance comparison plots."""
print("Generating performance comparison plots...")
# Test sizes - using smaller sizes for faster generation
sizes = [100, 500, 1000, 5000, 10000]
print("Running performance comparisons...")
results = compare_sorting_algorithms(sizes)
# Create output directory if it doesn't exist
output_dir = os.path.join(os.path.dirname(__file__), '..', 'docs')
os.makedirs(output_dir, exist_ok=True)
# Extract data for plotting
algorithms = ['heapsort', 'quicksort', 'merge_sort']
distributions = ['sorted', 'reverse_sorted', 'random']
# Create figure with subplots
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
fig.suptitle('Sorting Algorithm Performance Comparison', fontsize=16, fontweight='bold')
colors = {
'heapsort': '#2E86AB',
'quicksort': '#A23B72',
'merge_sort': '#F18F01'
}
markers = {
'heapsort': 'o',
'quicksort': 's',
'merge_sort': '^'
}
for idx, dist in enumerate(distributions):
ax = axes[idx]
for algo in algorithms:
times = results[algo][dist]
ax.plot(sizes, times,
marker=markers[algo],
color=colors[algo],
linewidth=2,
markersize=8,
label=algo.replace('_', ' ').title())
ax.set_xlabel('Input Size (n)', fontsize=12)
ax.set_ylabel('Time (seconds)', fontsize=12)
ax.set_title(f'{dist.replace("_", " ").title()} Input', fontsize=13, fontweight='bold')
ax.grid(True, alpha=0.3)
ax.legend(fontsize=10)
ax.set_xscale('log')
ax.set_yscale('log')
plt.tight_layout()
plot_path = os.path.join(output_dir, 'sorting_comparison.png')
plt.savefig(plot_path, dpi=300, bbox_inches='tight')
print(f"Saved plot to: {plot_path}")
plt.close()
# Create a combined comparison plot
fig, ax = plt.subplots(figsize=(12, 8))
x = np.arange(len(sizes))
width = 0.25
for i, algo in enumerate(algorithms):
# Use random distribution for comparison
times = results[algo]['random']
ax.bar(x + i * width, times, width,
label=algo.replace('_', ' ').title(),
color=colors[algo],
alpha=0.8)
ax.set_xlabel('Input Size (n)', fontsize=12, fontweight='bold')
ax.set_ylabel('Time (seconds)', fontsize=12, fontweight='bold')
ax.set_title('Sorting Algorithm Performance on Random Input', fontsize=14, fontweight='bold')
ax.set_xticks(x + width)
ax.set_xticklabels([str(s) for s in sizes])
ax.legend(fontsize=11)
ax.grid(True, alpha=0.3, axis='y')
plt.tight_layout()
bar_plot_path = os.path.join(output_dir, 'sorting_comparison_bar.png')
plt.savefig(bar_plot_path, dpi=300, bbox_inches='tight')
print(f"Saved bar chart to: {bar_plot_path}")
plt.close()
# Create a line plot showing all distributions for each algorithm
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
fig.suptitle('Algorithm Performance Across Different Input Distributions', fontsize=16, fontweight='bold')
for idx, algo in enumerate(algorithms):
ax = axes[idx]
for dist in distributions:
times = results[algo][dist]
ax.plot(sizes, times,
marker='o',
linewidth=2,
markersize=6,
label=dist.replace('_', ' ').title())
ax.set_xlabel('Input Size (n)', fontsize=12)
ax.set_ylabel('Time (seconds)', fontsize=12)
ax.set_title(f'{algo.replace("_", " ").title()} Performance', fontsize=13, fontweight='bold')
ax.grid(True, alpha=0.3)
ax.legend(fontsize=10)
ax.set_xscale('log')
ax.set_yscale('log')
plt.tight_layout()
algo_dist_plot_path = os.path.join(output_dir, 'algorithm_distributions.png')
plt.savefig(algo_dist_plot_path, dpi=300, bbox_inches='tight')
print(f"Saved algorithm distribution plot to: {algo_dist_plot_path}")
plt.close()
print("\nAll plots generated successfully!")
return {
'comparison': plot_path,
'bar_chart': bar_plot_path,
'distributions': algo_dist_plot_path
}
if __name__ == "__main__":
try:
generate_performance_plots()
except ImportError:
print("Error: matplotlib is required for generating plots.")
print("Install it with: pip install matplotlib")
sys.exit(1)

167
examples/heapsort_demo.py Normal file
View File

@@ -0,0 +1,167 @@
#!/usr/bin/env python3
"""
Heapsort Demonstration Script
This script demonstrates the usage of the heapsort implementation
with various examples and use cases.
Author: Carlos Gutierrez
Email: cgutierrez44833@ucumberlands.edu
"""
import sys
import os
# Add parent directory to path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from src.heapsort import heapsort, heap_extract_max, heap_insert, _build_max_heap
def demo_basic_sorting():
"""Demonstrate basic heapsort functionality."""
print("=" * 80)
print("BASIC HEAPSORT DEMONSTRATION")
print("=" * 80)
# Example 1: Simple array
print("\n1. Sorting a simple array:")
arr = [12, 11, 13, 5, 6, 7]
print(f" Original: {arr}")
sorted_arr = heapsort(arr.copy(), inplace=False)
print(f" Sorted: {sorted_arr}")
# Example 2: Already sorted array
print("\n2. Sorting an already sorted array:")
arr = [1, 2, 3, 4, 5]
print(f" Original: {arr}")
sorted_arr = heapsort(arr.copy(), inplace=False)
print(f" Sorted: {sorted_arr}")
# Example 3: Reverse sorted array
print("\n3. Sorting a reverse-sorted array:")
arr = [5, 4, 3, 2, 1]
print(f" Original: {arr}")
sorted_arr = heapsort(arr.copy(), inplace=False)
print(f" Sorted: {sorted_arr}")
# Example 4: Array with duplicates
print("\n4. Sorting an array with duplicate elements:")
arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
print(f" Original: {arr}")
sorted_arr = heapsort(arr.copy(), inplace=False)
print(f" Sorted: {sorted_arr}")
# Example 5: In-place sorting
print("\n5. In-place sorting:")
arr = [64, 34, 25, 12, 22, 11, 90]
print(f" Before: {arr}")
heapsort(arr, inplace=True)
print(f" After: {arr}")
def demo_heap_operations():
"""Demonstrate heap utility operations."""
print("\n" + "=" * 80)
print("HEAP OPERATIONS DEMONSTRATION")
print("=" * 80)
# Build max-heap
print("\n1. Building a max-heap:")
arr = [4, 10, 3, 5, 1]
print(f" Original array: {arr}")
_build_max_heap(arr)
print(f" Max-heap: {arr}")
print(f" Root (max): {arr[0]}")
# Extract maximum
print("\n2. Extracting maximum from heap:")
heap = [10, 5, 3, 4, 1]
_build_max_heap(heap)
print(f" Heap before: {heap}")
max_val = heap_extract_max(heap)
print(f" Extracted: {max_val}")
print(f" Heap after: {heap}")
# Insert into heap
print("\n3. Inserting into heap:")
heap = [10, 5, 3, 4, 1]
_build_max_heap(heap)
print(f" Heap before: {heap}")
heap_insert(heap, 15)
print(f" Inserted 15")
print(f" Heap after: {heap}")
print(f" New root: {heap[0]}")
def demo_custom_key():
"""Demonstrate sorting with custom key function."""
print("\n" + "=" * 80)
print("CUSTOM KEY FUNCTION DEMONSTRATION")
print("=" * 80)
# Sort dictionaries by value
print("\n1. Sorting dictionaries by 'value' key:")
arr = [
{'name': 'Alice', 'value': 30},
{'name': 'Bob', 'value': 20},
{'name': 'Charlie', 'value': 40},
{'name': 'David', 'value': 10}
]
print(f" Original: {[d['name'] for d in arr]}")
sorted_arr = heapsort(arr.copy(), key=lambda x: x['value'], inplace=False)
print(f" Sorted by value: {[d['name'] for d in sorted_arr]}")
# Sort tuples by second element
print("\n2. Sorting tuples by second element:")
arr = [(1, 5), (2, 3), (3, 8), (4, 1)]
print(f" Original: {arr}")
sorted_arr = heapsort(arr.copy(), key=lambda x: x[1], inplace=False)
print(f" Sorted: {sorted_arr}")
def demo_performance():
"""Demonstrate performance on different input sizes."""
print("\n" + "=" * 80)
print("PERFORMANCE DEMONSTRATION")
print("=" * 80)
import time
import random
sizes = [100, 1000, 10000]
print("\nSorting random arrays of different sizes:")
print(f"{'Size':<10} {'Time (seconds)':<20} {'Sorted':<10}")
print("-" * 40)
for size in sizes:
arr = [random.randint(1, size * 10) for _ in range(size)]
start = time.perf_counter()
sorted_arr = heapsort(arr.copy(), inplace=False)
end = time.perf_counter()
is_sorted = sorted_arr == sorted(arr)
print(f"{size:<10} {end - start:<20.6f} {str(is_sorted):<10}")
def main():
"""Run all demonstrations."""
print("\n" + "=" * 80)
print("HEAPSORT IMPLEMENTATION DEMONSTRATION")
print("Author: Carlos Gutierrez")
print("Email: cgutierrez44833@ucumberlands.edu")
print("=" * 80)
demo_basic_sorting()
demo_heap_operations()
demo_custom_key()
demo_performance()
print("\n" + "=" * 80)
print("DEMONSTRATION COMPLETE")
print("=" * 80 + "\n")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,233 @@
#!/usr/bin/env python3
"""
Priority Queue Demonstration Script
This script demonstrates the usage of the priority queue implementation
with various examples and use cases.
Author: Carlos Gutierrez
Email: cgutierrez44833@ucumberlands.edu
"""
import sys
import os
# Add parent directory to path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from src.priority_queue import PriorityQueue
from src.task import Task
def demo_basic_operations():
"""Demonstrate basic priority queue operations."""
print("=" * 80)
print("BASIC PRIORITY QUEUE OPERATIONS")
print("=" * 80)
# Create a max-heap priority queue
pq = PriorityQueue(is_max_heap=True)
print("\n1. Creating and inserting tasks:")
tasks = [
Task("T1", priority=10, arrival_time=0.0, description="Task 1"),
Task("T2", priority=5, arrival_time=1.0, description="Task 2"),
Task("T3", priority=15, arrival_time=2.0, description="Task 3"),
Task("T4", priority=20, arrival_time=3.0, description="Task 4"),
Task("T5", priority=8, arrival_time=4.0, description="Task 5")
]
for task in tasks:
pq.insert(task)
print(f" Inserted: {task.task_id} (priority: {task.priority})")
print(f"\n Queue size: {pq.size()}")
print(f" Is empty: {pq.is_empty()}")
# Peek at highest priority
print("\n2. Peeking at highest priority task:")
top_task = pq.peek()
print(f" Top task: {top_task.task_id} (priority: {top_task.priority})")
print(f" Queue size after peek: {pq.size()} (unchanged)")
# Extract tasks in priority order
print("\n3. Extracting tasks in priority order:")
while not pq.is_empty():
task = pq.extract_max()
print(f" Extracted: {task.task_id} (priority: {task.priority})")
print(f"\n Queue size: {pq.size()}")
print(f" Is empty: {pq.is_empty()}")
def demo_min_heap():
"""Demonstrate min-heap priority queue."""
print("\n" + "=" * 80)
print("MIN-HEAP PRIORITY QUEUE")
print("=" * 80)
pq = PriorityQueue(is_max_heap=False)
print("\nInserting tasks into min-heap:")
tasks = [
Task("T1", priority=10, arrival_time=0.0),
Task("T2", priority=5, arrival_time=1.0),
Task("T3", priority=15, arrival_time=2.0),
Task("T4", priority=20, arrival_time=3.0),
Task("T5", priority=8, arrival_time=4.0)
]
for task in tasks:
pq.insert(task)
print(f" Inserted: {task.task_id} (priority: {task.priority})")
print("\nExtracting tasks (lowest priority first):")
while not pq.is_empty():
task = pq.extract_min()
print(f" Extracted: {task.task_id} (priority: {task.priority})")
def demo_key_operations():
"""Demonstrate priority key update operations."""
print("\n" + "=" * 80)
print("PRIORITY KEY UPDATE OPERATIONS")
print("=" * 80)
pq = PriorityQueue(is_max_heap=True)
# Insert tasks
task1 = Task("T1", priority=10, arrival_time=0.0)
task2 = Task("T2", priority=20, arrival_time=1.0)
task3 = Task("T3", priority=15, arrival_time=2.0)
pq.insert(task1)
pq.insert(task2)
pq.insert(task3)
print("\nInitial state:")
print(f" Top task: {pq.peek().task_id} (priority: {pq.peek().priority})")
# Increase priority
print("\n1. Increasing T1's priority from 10 to 25:")
success = pq.increase_key(task1, 25)
print(f" Update successful: {success}")
print(f" New priority: {task1.priority}")
print(f" Top task: {pq.peek().task_id} (priority: {pq.peek().priority})")
# Decrease priority
print("\n2. Decreasing T1's priority from 25 to 12:")
success = pq.decrease_key(task1, 12)
print(f" Update successful: {success}")
print(f" New priority: {task1.priority}")
print(f" Top task: {pq.peek().task_id} (priority: {pq.peek().priority})")
def demo_task_scheduling():
"""Demonstrate task scheduling simulation."""
print("\n" + "=" * 80)
print("TASK SCHEDULING SIMULATION")
print("=" * 80)
pq = PriorityQueue(is_max_heap=True)
# Create tasks with deadlines
tasks = [
Task("T1", priority=10, arrival_time=0.0, deadline=100.0, execution_time=5.0),
Task("T2", priority=15, arrival_time=1.0, deadline=50.0, execution_time=3.0),
Task("T3", priority=8, arrival_time=2.0, deadline=200.0, execution_time=10.0),
Task("T4", priority=20, arrival_time=3.0, deadline=30.0, execution_time=2.0),
Task("T5", priority=12, arrival_time=4.0, deadline=150.0, execution_time=7.0)
]
print("\nTasks to schedule:")
for task in tasks:
print(f" {task.task_id}: priority={task.priority}, deadline={task.deadline}, "
f"execution_time={task.execution_time}")
# Insert all tasks
for task in tasks:
pq.insert(task)
print("\nScheduling order (by priority):")
current_time = 0.0
while not pq.is_empty():
task = pq.extract_max()
print(f"\n Executing: {task.task_id}")
print(f" Priority: {task.priority}")
print(f" Start time: {current_time}")
print(f" Execution time: {task.execution_time}")
print(f" Deadline: {task.deadline}")
# Check if task will meet deadline
completion_time = current_time + task.execution_time
if task.deadline and completion_time > task.deadline:
print(f" ⚠️ WARNING: Will miss deadline!")
else:
print(f" ✓ Will meet deadline")
current_time = completion_time
print(f"\n Total completion time: {current_time}")
def demo_large_queue():
"""Demonstrate performance with large queue."""
print("\n" + "=" * 80)
print("LARGE QUEUE PERFORMANCE")
print("=" * 80)
import time
pq = PriorityQueue(is_max_heap=True)
num_tasks = 10000
print(f"\nInserting {num_tasks} tasks...")
start = time.perf_counter()
for i in range(num_tasks):
priority = (i * 7) % 100 # Vary priorities
task = Task(f"T{i}", priority=priority, arrival_time=float(i))
pq.insert(task)
insert_time = time.perf_counter() - start
print(f" Insert time: {insert_time:.6f} seconds")
print(f" Queue size: {pq.size()}")
print(f"\nExtracting all tasks...")
start = time.perf_counter()
count = 0
prev_priority = float('inf')
while not pq.is_empty():
task = pq.extract_max()
# Verify ordering
assert task.priority <= prev_priority, "Ordering violated!"
prev_priority = task.priority
count += 1
extract_time = time.perf_counter() - start
print(f" Extract time: {extract_time:.6f} seconds")
print(f" Tasks extracted: {count}")
print(f" Ordering verified: ✓")
def main():
"""Run all demonstrations."""
print("\n" + "=" * 80)
print("PRIORITY QUEUE IMPLEMENTATION DEMONSTRATION")
print("Author: Carlos Gutierrez")
print("Email: cgutierrez44833@ucumberlands.edu")
print("=" * 80)
demo_basic_operations()
demo_min_heap()
demo_key_operations()
demo_task_scheduling()
demo_large_queue()
print("\n" + "=" * 80)
print("DEMONSTRATION COMPLETE")
print("=" * 80 + "\n")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,163 @@
#!/usr/bin/env python3
"""
Task Scheduler Simulation Demonstration
This script demonstrates the task scheduler implementation using the priority queue.
It shows various scheduling scenarios and analyzes the results.
Author: Carlos Gutierrez
Email: cgutierrez44833@ucumberlands.edu
"""
import sys
import os
# Add parent directory to path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from src.scheduler import TaskScheduler, simulate_scheduler
from src.task import Task
def demo_basic_scheduling():
"""Demonstrate basic priority-based scheduling."""
print("=" * 80)
print("BASIC PRIORITY-BASED SCHEDULING")
print("=" * 80)
scheduler = TaskScheduler()
# Create tasks with different priorities
tasks = [
Task("T1", priority=10, arrival_time=0.0, execution_time=5.0, description="Low priority task"),
Task("T2", priority=30, arrival_time=0.0, execution_time=3.0, description="High priority task"),
Task("T3", priority=20, arrival_time=0.0, execution_time=4.0, description="Medium priority task"),
Task("T4", priority=15, arrival_time=0.0, execution_time=2.0, description="Medium-low priority task"),
]
print("\nTasks to schedule (in priority order):")
for task in sorted(tasks, key=lambda t: t.priority, reverse=True):
print(f" {task.task_id}: priority={task.priority}, execution_time={task.execution_time}")
results = scheduler.schedule_tasks(tasks)
scheduler.print_schedule(results)
def demo_deadline_scheduling():
"""Demonstrate scheduling with deadlines."""
print("\n" + "=" * 80)
print("SCHEDULING WITH DEADLINES")
print("=" * 80)
scheduler = TaskScheduler()
# Create tasks with deadlines
tasks = [
Task("T1", priority=10, arrival_time=0.0, deadline=100.0, execution_time=5.0),
Task("T2", priority=20, arrival_time=0.0, deadline=30.0, execution_time=3.0),
Task("T3", priority=15, arrival_time=0.0, deadline=50.0, execution_time=10.0),
Task("T4", priority=25, arrival_time=0.0, deadline=20.0, execution_time=2.0),
Task("T5", priority=12, arrival_time=0.0, deadline=150.0, execution_time=7.0),
]
print("\nTasks with deadlines:")
for task in tasks:
print(f" {task.task_id}: priority={task.priority}, deadline={task.deadline}, "
f"execution_time={task.execution_time}")
results = scheduler.schedule_tasks(tasks)
scheduler.print_schedule(results)
def demo_large_workload():
"""Demonstrate scheduling a large number of tasks."""
print("\n" + "=" * 80)
print("LARGE WORKLOAD SCHEDULING")
print("=" * 80)
import random
# Generate random tasks
num_tasks = 50
tasks = []
random.seed(42) # For reproducibility
for i in range(num_tasks):
priority = random.randint(1, 100)
execution_time = random.uniform(0.5, 10.0)
deadline = random.uniform(10.0, 200.0)
tasks.append(
Task(f"T{i+1}", priority=priority, arrival_time=0.0,
deadline=deadline, execution_time=execution_time)
)
print(f"\nScheduling {num_tasks} tasks...")
stats = simulate_scheduler(tasks, verbose=False)
print(f"\nScheduling Statistics:")
print(f" Total tasks: {stats.total_tasks}")
print(f" Completed: {stats.completed_tasks}")
print(f" Deadline met: {stats.deadline_met} ({stats.deadline_met/stats.total_tasks*100:.1f}%)")
print(f" Deadline missed: {stats.deadline_missed} ({stats.deadline_missed/stats.total_tasks*100:.1f}%)")
print(f" Total execution time: {stats.total_execution_time:.2f}")
print(f" Average wait time: {stats.average_wait_time:.2f}")
print(f" Throughput: {stats.throughput:.2f} tasks/time unit")
def demo_priority_vs_deadline():
"""Compare priority-based vs deadline-based scheduling."""
print("\n" + "=" * 80)
print("PRIORITY-BASED vs DEADLINE-AWARE SCHEDULING")
print("=" * 80)
# Create tasks where high priority tasks have tight deadlines
tasks = [
Task("T1", priority=30, arrival_time=0.0, deadline=15.0, execution_time=10.0),
Task("T2", priority=20, arrival_time=0.0, deadline=50.0, execution_time=5.0),
Task("T3", priority=10, arrival_time=0.0, deadline=100.0, execution_time=3.0),
]
print("\nScenario: High priority task (T1) has tight deadline")
print("Tasks:")
for task in tasks:
print(f" {task.task_id}: priority={task.priority}, deadline={task.deadline}, "
f"execution_time={task.execution_time}")
# Priority-based scheduling
scheduler = TaskScheduler()
results = scheduler.schedule_tasks(tasks)
print("\nPriority-based scheduling (highest priority first):")
scheduler.print_schedule(results)
# Note: This demonstrates that pure priority scheduling may miss deadlines
# A more sophisticated scheduler could use deadline-aware priority adjustment
def main():
"""Run all scheduler demonstrations."""
print("\n" + "=" * 80)
print("TASK SCHEDULER SIMULATION DEMONSTRATION")
print("Author: Carlos Gutierrez")
print("Email: cgutierrez44833@ucumberlands.edu")
print("=" * 80)
demo_basic_scheduling()
demo_deadline_scheduling()
demo_large_workload()
demo_priority_vs_deadline()
print("\n" + "=" * 80)
print("DEMONSTRATION COMPLETE")
print("=" * 80)
print("\nKey Observations:")
print("1. Priority-based scheduling ensures high-priority tasks execute first")
print("2. Pure priority scheduling may miss deadlines for lower-priority tasks")
print("3. The scheduler efficiently handles large workloads using O(n log n) algorithm")
print("4. Statistics provide insights into scheduling performance")
print("=" * 80 + "\n")
if __name__ == "__main__":
main()