![f5b35bce659682d4ebae5f8417b4db02.png](https://i-blog.csdnimg.cn/blog_migrate/e48de30176f0a8d6c7d643302a1d3986.jpeg)
模型还是出自姜启源老师翻译的第三版《数学建模》,章节是第五章“模拟方法建模”。这本书年代比较老了,很多建模方法过于基础,但是仍旧不失为经典的建模教材。
之前我们做过简单差分方程组的探索:
忘荃的趣味编程:简单差分方程组模型的可视化-使用Processingzhuanlan.zhihu.com那么今天我们就进一步探讨更复杂的模型:事件模拟模型。这类模型之间的特点是,各个事件是强耦合的,也就是彼此制约的关系很大。不像是以前的差分方程组描述的各个事件是孤立的,这里的事件因为要排队占用一些资源,或者因为彼此之间的合作关系,所以常常会出现“你等我来我等你”的紧张有序的局面。
这个时候学习过“操作系统”的同学,肯定就会发现,这不就是我们常说的各种多进程同步算法(信号量,PV操作)吗?还真是。使用Simpy来进行这种仿真的最大优势是,能让你专注于描述自己的事件模型,而不必操心整个仿真系统在编程中应该如何实现。使用Simpy做出来的仿真,都自然是高效易懂可扩展的。
虽然现在Simpy文档有中文版翻译了,但是翻译质量真的不敢恭维,所以还是建议拿起翻译工具去看英文文档。
问题场景
![3aeb864570ff91108e9c4ff3b722ec34.png](https://i-blog.csdnimg.cn/blog_migrate/718e879e1693a0e1b0b23b2be5ca505b.jpeg)
仿真代码:
"""
那么先来看看一次仿真的具体情况(将my_print中的注释取消就行了):
到达时间
这里用到了一个小技巧,就是通过在船名SHIPXX 前面加对应个数的空格,大大增加了输出结果的可读性。从这个结果中,大致可以看到,SHIP00,SHIP01和SHIP02都没有等待,而SHIP03和SHIP04则都是到港后等了一会才进港的。而书中则也提供了一次仿真的结果展示:
![22d5910a470a15c38f9b088d426d9f4e.png](https://i-blog.csdnimg.cn/blog_migrate/90e87ed3fca8f119dbfed8b3b2dcf4d1.jpeg)
可以看出我们的这次仿真和书中的仿真结果是有相似之处的。
而书中也提到了,100艘船的仿真结果中的数字指标:
![6dc68570532b7aa88d597bc4c2d4acf1.png](https://i-blog.csdnimg.cn/blog_migrate/9e58a6db4da9bf290c6228eb664ebc00.jpeg)
可以看出其中的平均等待时间的波动还是比较大的,那么我们直接在自己的程序中将总船数设置为5000,看看更精确的平均等待时间究竟是多少呢?
是45.05。
可以看出,这个数字和书中的数据100船平均等待时间相比是偏大的,那么我们大胆地提出一个猜测:模拟的时间越久,就越可能会有卸货很慢很慢的船到来,而这种船会造成严重的拥堵,从而让大家都陷入苦苦等待的情况。而卸货快的船对于平均等待时间的减少则效果不太明显,这就是“一个老鼠屎,坏了一锅粥”的道理吧。
但是,我们做这个仿真模型的意义不止于此,首先我们可以探索各个模型参数对于结果的影响,其次再加上限制条件,目标函数和优化方法,我们就可以做出一个漂亮的模型优化方案了。比如说问题是这样的:“现在给你多少的钱来提升港口效率,增加一个码头要花a元钱,增加一个卸货工人要花b元钱”,那么如何花这笔钱才能最大地提升港口效率呢?