-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtimequeue.py
More file actions
148 lines (121 loc) · 5.39 KB
/
Copy pathtimequeue.py
File metadata and controls
148 lines (121 loc) · 5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"""CSC148 Lab 4: Abstract Data Types
=== CSC148 Winter 2025 ===
Department of Computer Science,
University of Toronto
=== Module Description ===
This module runs timing experiments to determine how the time taken
to enqueue or dequeue grows for different Queue implementations.
"""
from timeit import timeit
from copy import deepcopy
from python_ta import contracts
# Turn off contract checking to minimize its effect on timing experiments
contracts.ENABLE_CONTRACT_CHECKING = False
from myqueue import Queue, QueueOpposite, QueueDeque
###############################################################################
# Task 4: Running timing experiments
#
# In this part of the lab, you will be conducting timing experiments on Queue
# operations.
#
# Make sure you complete the 3 Queue implementations in myqueue.py
###############################################################################
# Experiment Parameters
# Below are our experiment settings: you may want to change these values.
#
# QUEUE_SIZES: This represents the queue sizes we'll be experimenting with.
# i.e. enqueueing and dequeueing from Queues with size 10000,
# 20000, etc.
# NUM_TRIALS: This represents the number of times we will repeat an
# experiment: when we run our timing experiments, we want to get
# use the average time over a number of trials in order to
# minimize the effect of any outliers.
###############################################################################
QUEUE_SIZES = [1000, 2000, 4000, 8000, 100000]
QUEUE_TYPES = [Queue, QueueOpposite, QueueDeque]
NUM_TRIALS = 20
def _set_up_queues(qsize: int, n: int, qtype: object) -> list:
"""Return a list of <n> queues, each with <qsize> elements.
The returned queues should all be of type qtype.
qtype is either Queue, QueueOpposite, or QueueDeque.
>>> my_queues = _set_up_queues(1, 2, Queue)
>>> len(my_queues)
2
>>> type(my_queues[0]) == Queue
True
>>> my_queues[0].is_empty()
False
>>> _ = my_queues[0].dequeue()
>>> my_queues[0].is_empty()
True
"""
# We create a single Queue with the number of elements we want
q = qtype()
for _ in range(qsize):
q.enqueue(1)
# And make a copy of this Queue (using deepcopy, to save time.)
queue_list = []
for _ in range(n):
queue_list.append(deepcopy(q))
return queue_list
def time_enqueue(qtype: object) -> list[float]:
"""Run timing experiments for the Queue with type qtype
"""
# These two lists will hold our timing results.
queue_times = []
# This loop runs the timing experiment for enqueueing one item to
print(f"Running {qtype.__name__}.enqueue experiments...")
for queue_size in QUEUE_SIZES:
# 1. Initialize the sample queues
queues = _set_up_queues(queue_size, NUM_TRIALS, qtype)
# 2. For each queue created, call the function timeit.
# timeit takes three arguments:
# - a *string* representation of a piece of code to run
# - the number of times to run it (just 1 for us)
# - globals is a technical argument that you DON'T need to
# care about
time = 0
for queue in queues:
time += timeit('queue.enqueue(1)', number=1, globals=locals())
# 3. Get the average time in microseconds (μs)
average_time = (time / NUM_TRIALS) * 1e6
# 4. Report the average time taken and add that to our list of
# results.
queue_times.append(average_time)
print(f'Enqueue: Queue size {queue_size:>7}, time (μs): {average_time}')
return queue_times
def plot_experiment() -> None:
"""Run the timing experiment on AddToStartQueue and AddToEndQueue
and plot a graph."""
import matplotlib.pyplot as plt
# Plot the results of our experiments and assign labels to each plot.
# Our call to plt.plot takes 3 arguments:
# - The x-coordinates of the values to plot
# - The y-coordinates of the values to plot
# - The format we want to plot with.
# 'ro' is 'red circle'
# 'bo' is 'blue circle'
# Other formats include 'rx' (red X), 'bx' (blue X) and many more!
# TODO: If you add more types of Queues, add more markers to this list!
enqueue_markers = ['ro', 'bo', 'go']
for i in range(len(QUEUE_TYPES)):
qt = QUEUE_TYPES[i]
times = time_enqueue(qt)
q_plt, = plt.plot(QUEUE_SIZES, times, enqueue_markers[i])
q_plt.set_label(f"{qt.__name__}.enqueue")
# TODO: Using the provided code as a template, you may want to
# run timing experiments for dequeue as well!
# Hint: You'll need to make a function like time_enqueue but for dequeue
# and then plot the returned time similarly to the above code.
# After we finish plotting everything, we can create the legend of
# our graph and label the axes
plt.legend()
plt.xlabel("Queue Size")
plt.ylabel("Average Time (μs)")
# Show our plotted results. This line must be called after
# all of the other setup.
plt.show()
if __name__ == '__main__':
# Uncomment the plot_experiment() line below to see the plotted graph once
# you have time_enqueue() working.
plot_experiment()