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:
12
examples/__init__.py
Normal file
12
examples/__init__.py
Normal 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
|
||||
"""
|
||||
|
||||
51
examples/comparison_demo.py
Normal file
51
examples/comparison_demo.py
Normal 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
155
examples/generate_plots.py
Normal 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
167
examples/heapsort_demo.py
Normal 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()
|
||||
|
||||
233
examples/priority_queue_demo.py
Normal file
233
examples/priority_queue_demo.py
Normal 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()
|
||||
|
||||
163
examples/scheduler_simulation.py
Normal file
163
examples/scheduler_simulation.py
Normal 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()
|
||||
|
||||
Reference in New Issue
Block a user