55
66我们可以通过建立一个模拟实验来决定。我们将需要为学生,打印任务和打印机构建表现表示(Figure 4)。当学生提交打印任务时,我们将把他们添加到等待列表中,一个打印任务的队列。 当打印机完成任务时,它将检查队列,以检查是否有剩余的任务要处理。我们感兴趣的是学生等待他们的论文打印的平均时间。这等于任务在队列中等待的平均时间量。
77![ 3.14.模拟:打印机.figure4] ( assets/3.14.%E6%A8%A1%E6%8B%9F%EF%BC%9A%E6%89%93%E5%8D%B0%E6%9C%BA.figure4.png )
8+
9+
810* Figure 4*
911
10- 为了建模这种情况 ,我们需要使用一些概率。例如,学生可以打印长度从1到20页的纸张。如果从1到20的每个长度同样可能,则可以通过使用1和20之间的随机数来模拟打印任务的实际长度。这意味着出现从1到20的任何长度的机会是平等的 。
12+ 为了为这种情况建模 ,我们需要使用一些概率。例如,学生可以打印长度从 1 到 20 页的纸张。如果从 1 到 20 的每个长度有同样的可能性,则可以通过使用 1 和 20 之间的随机数来模拟打印任务的实际长度。这意味着出现从 1 到 20 的任何长度的机会是平等的 。
1113
12- 如果实验室中有10个学生 ,每人打印两次,则平均每小时有20个打印任务 。 在任何给定的秒,打印任务将被创建的机会是什么? 回答这个问题的方法是考虑任务与时间的比率。 每小时20个任务意味着平均每180秒将有一个任务 :
14+ 如果实验室中有 10 个学生 ,每人打印两次,则平均每小时有 20 个打印任务 。 在任何给定的秒,打印任务将被创建的机会是什么? 回答这个问题的方法是考虑任务与时间的比率。每小时 20 个任务意味着平均每 180 秒将有一个任务 :
1315
1416![ 3.14.模拟:打印机.figure1] ( assets/3.14.%E6%A8%A1%E6%8B%9F%EF%BC%9A%E6%89%93%E5%8D%B0%E6%9C%BA.figure1.png )
1517
16- 对于每一秒,我们可以通过生成1到180之间的随机数来模拟打印任务发生的机会。如果数字是180 ,我们说一个任务已经创建。请注意,可能会在一下子创建许多任务,或者需要等待一段时间才有任务。这就是模拟的本质。你想模拟真实的情况就需要尽可能接近一般参数。
18+ 对于每一秒,我们可以通过生成 1 到 180 之间的随机数来模拟打印任务发生的机会。如果数字是 180 ,我们说一个任务已经创建。请注意,可能会在一下子创建许多任务,或者需要等待一段时间才有任务。这就是模拟的本质。你想模拟真实的情况就需要尽可能接近一般参数。
1719
1820### 3.14.1.主要模拟步骤
19211 . 创建打印任务的队列,每个任务都有个时间戳。队列启动的时候为空。
20222 . 每秒(currentSecond):
2123
22- * 是否创建新的打印任务?如果是,将 currentSecond 作为时间戳添加到队列。
24+ * 是否创建新的打印任务?如果是,将 ` currentSecond ` 作为时间戳添加到队列。
2325 * 如果打印机不忙并且有任务在等待
2426 * 从打印机队列中删除一个任务并将其分配给打印机
25- * 从 currentSecond 中减去时间戳,以计算该任务的等待时间。
27+ * 从 ` currentSecond ` 中减去时间戳,以计算该任务的等待时间。
2628 * 将该任务的等待时间附件到列表中稍后处理。
2729 * 根据打印任务的页数,确定需要多少时间。
2830 * 打印机需要一秒打印,所以得从该任务的所需的等待时间减去一秒。
3133
3234
3335### 3.14.2 Python 实现
34- 为了设计此模拟,我们将为上述三个真实世界对象创建类:Printer, Task, PrintQueue
36+ 为了设计此模拟,我们将为上述三个真实世界对象创建类:` Printer ` , ` Task ` , ` PrintQueue `
3537
36- Printer 类(Listing 2)需要跟踪它当前是否有任务。如果有,则它处于忙碌状态(13-17 行),并且可以从任务的页数计算所需的时间。构造函数允许初始化每分钟页面的配置,tick 方法将内部定时器递减直到打印机设置为空闲(11 行)
38+ ` Printer ` 类(Listing 2)需要跟踪它当前是否有任务。如果有,则它处于忙碌状态(13-17 行),并且可以从任务的页数计算所需的时间。构造函数允许初始化每分钟页面的配置,` tick ` 方法将内部定时器递减直到打印机设置为空闲(11 行)
3739
3840```` python
3941class Printer :
@@ -60,7 +62,7 @@ class Printer:
6062````
6163* Listing 2*
6264
63- Task 类(Listing 3)表示单个打印任务。创建任务时,随机数生成器将提供 1 到 20 页的长度。我们选择使用随机模块中的 randrange 函数。
65+ ` Task ` 类(Listing 3)表示单个打印任务。创建任务时,随机数生成器将提供 1 到 20 页的长度。我们选择使用随机模块中的 ` randrange ` 函数。
6466
6567````
6668>>> import random
@@ -70,7 +72,7 @@ Task 类(Listing 3)表示单个打印任务。创建任务时,随机数生
70728
7173>>>
7274````
73- 每个任务还需要保存一个时间戳用于计算等待时间。此时间戳将表示任务被创建并放置到打印机队列中的时间。可以使用 waitTime 方法来检索在打印开始之前队列中花费的时间。
75+ 每个任务还需要保存一个时间戳用于计算等待时间。此时间戳将表示任务被创建并放置到打印机队列中的时间。可以使用 ` waitTime ` 方法来检索在打印开始之前队列中花费的时间。
7476
7577```` python
7678import random
@@ -91,7 +93,7 @@ class Task:
9193````
9294* Listing 3*
9395
94- Listing 4 实现了上述算法。PrintQueue 对象是我们现有队列 ADT 的一个实例。newPrintTask 决定是否创建一个新的打印任务。我们再次选择使用随机模块的 randrange 函数返回 1 到 180 之间的随机整数。打印任务每 180 秒到达一次。通过从随机整数(32 行)的范围中任意选择,我们可以模拟这个随机事件。模拟功能允许我们设置打印机的总时间和每分钟的页数。
96+ Listing 4 实现了上述算法。` PrintQueue ` 对象是我们现有队列 ADT 的一个实例。` newPrintTask ` 决定是否创建一个新的打印任务。我们再次选择使用随机模块的 ` randrange ` 函数返回 1 到 180 之间的随机整数。打印任务每 180 秒到达一次。通过从随机整数(32 行)的范围中任意选择,我们可以模拟这个随机事件。模拟功能允许我们设置打印机的总时间和每分钟的页数。
9597
9698````
9799from pythonds.basic.queue import Queue
@@ -134,7 +136,7 @@ for i in range(10):
134136
135137当我们运行模拟时,我们不应该担心每次的结果不同。这是由于随机数的概率性质决定的。 因为模拟的参数可以被调整,我们对调整后可能发生的趋势感兴趣。 这里有一些结果。
136138
137- 首先,我们将使用每分钟五页的页面速率运行模拟60分钟 (3,600秒)。 此外,我们将进行10次独立试验 。记住,因为模拟使用随机数,每次运行将返回不同的结果。
139+ 首先,我们将使用每分钟五页的页面速率运行模拟 60 分钟 (3,600秒)。 此外,我们将进行 10 次独立试验 。记住,因为模拟使用随机数,每次运行将返回不同的结果。
138140
139141````
140142>>>for i in range(10):
@@ -151,9 +153,9 @@ Average Wait 48.33 secs 0 tasks remaining.
151153Average Wait 39.31 secs 3 tasks remaining.
152154Average Wait 376.05 secs 1 tasks remaining.
153155````
154- 在运行 10 次实验后,我们可以看到,平均等待时间为 122.09 秒。 还可以看到平均等待时间有很大的变化,最小值为17.27秒,最大值为376.05秒 。 你也可能注意到,只有两种情况所有任务都完成。
156+ 在运行 10 次实验后,我们可以看到,平均等待时间为 122.09 秒。 还可以看到平均等待时间有很大的变化,最小值为 17.27 秒,最大值为 376.05 秒 。 你也可能注意到,只有两种情况所有任务都完成。
155157
156- 现在,我们将页面速率调整为每分钟10页,再次运行10次测试 ,页面速度更快,我们希望在一小时内完成更多的任务。
158+ 现在,我们将页面速率调整为每分钟 10 页,再次运行 10 次测试 ,页面速度更快,我们希望在一小时内完成更多的任务。
157159
158160````
159161>>>for i in range(10):
@@ -175,15 +177,15 @@ Average Wait 18.17 secs 0 tasks remaining.
175177
176178我们试图回答一个问题,即当前打印机是否可以处理任务负载,如果它设置为打印更好的质量,较慢的页面速率。我们采用的方法是编写一个模拟打印任务作为各种页数和到达时间的随机事件的模拟。
177179
178- 上面的输出显示,每分钟打印5页,平均等待时间从低的17秒到高的376秒(约6分钟 )。使用更快的打印速率,低值为1秒,高值仅为28 。此外,在 10 次运行中的8次,每分钟5页 ,打印任务在结束时仍在队列中等待。
180+ 上面的输出显示,每分钟打印 5 页,平均等待时间从低的 17 秒到高的 376 秒(约 6 分钟 )。使用更快的打印速率,低值为 1 秒,高值仅为 28 。此外,在 10 次运行中的 8 次,每分钟 5 页 ,打印任务在结束时仍在队列中等待。
179181
180182因此,我们说减慢打印机的速度以获得更好的质量可能不是一个好主意。学生们不能等待他们的论文打印完,特别是当他们需要到下一个班级。六分钟的等待时间太长了。
181183
182184这种类型的模拟分析允许我们回答许多问题,通常被称为“如果”的问题。我们需要做的是改变模拟使用的参数,我们可以模拟任何数量。例如
183- * 如果入学人数增加,平均学生人数增加 20人 该怎么办?
185+ * 如果入学人数增加,平均学生人数增加 20 人 该怎么办?
184186 * 如果是星期六,学生不需要上课怎么办?他们能负担得了吗?
185- * 如果平均打印任务的大小减少了,由于 Python是一个强大的语言 ,程序往往要短得多?
187+ * 如果平均打印任务的大小减少了,由于 Python 是一个强大的语言 ,程序往往要短得多?
186188
187- 这些问题都可以通过修改上述模拟来回答。然而,重要的是要记住,模拟有效取决于构建它的假设是没问题的。关于每小时打印任务的数量和每小时的学生数量的真实数据对于构建鲁棒的模拟是必要的 。
189+ 这些问题都可以通过修改上述模拟来回答。然而,重要的是要记住,模拟有效取决于构建它的假设是没问题的。关于每小时打印任务的数量和每小时的学生数量的真实数据对于构建鲁棒性的模拟是必要的 。
188190
189191
0 commit comments