# shk-simulation **Repository Path**: yunxia/shk-simulation ## Basic Information - **Project Name**: shk-simulation - **Description**: 一个中观的、可扩展的、基于离散事件的仿真系统脚手架,以及基于它的共享汽车等仿真实现。 系统的核心模块ShkSimulation与共享汽车仿真完全解耦,不涉及任何共享汽车内容,因此支持各种离散事件仿真,只要是离散事件仿真,都可以用ShkSimulation方便实现 - **Primary Language**: C# - **License**: EPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2022-08-30 - **Last Updated**: 2022-08-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ShkSimulation 个人主页:[http://pklue.club](http://pklue.club) 可以 **辅助/帮助编写** 离散事件仿真、排队论仿真、实现可视化等等。 要查看论文中的各种可视化功能,可以编译运行ShkSimulationDesktop模块,演示请看末尾。 不会的话可以直接运行编译好的"..\shk-simulation-master\ShkSimulationDesktop\bin\Debug\net5.0-windows\ShkSimulationDesktop.exe",记得在运行的窗口设置数据文件路径等,在ShkSimulationDesktop/data目录下有很多示例输入数据 #### 介绍 这是一个中观的、可扩展的、基于离散事件的仿真系统脚手架,以及基于它的共享汽车等仿真实现。 系统的核心模块ShkSimulation与共享汽车仿真完全解耦,不涉及任何共享汽车内容,因此支持各种离散事件仿真,只要是离散事件仿真,都能用用到ShkSimulation的内部服务台、顾客服务链、服务机构工厂、需求管理、数据统计等功能或特性 在ShkSimulationImpl中则有进行共享汽车仿真和高速公路仿真的示例代码,模块具体的说明后文模块说明 #### 软件架构 系统包括五个功能模块(现在来看,模块边界也不是很清晰),分别是仿真核心、输入输出、数据统计、仿真工集、仿真优化模块 ![输入图片说明](images/image.png) #### 特性说明 使用的时候主要参考ShkSimulationImpl就好,里面有以上示例代码,impl文件夹下是系统默认实现,使用了更多特性,可当作参考 1. 仿真系统详情 - 仿真运行流程 ![仿真运行流程](images/SimulationProgress.png) 这个流程有点小修改,后续将共享汽车从核心模块解耦后,创建站台工厂和创建道路工厂合并为创建服务机构工厂,工厂创建道路和工厂创建站台合并为创建服务机构。 也就是工厂创建不再单独区分站台、道路工厂,而是通过循环统一创建, 相应地,服务机构创建也不再单独区分站台和道路。 - 服务机构 ![服务机构](images/Agency.png) - 内部服务台 ![](images/InternalAgency.png) - 服务机构工厂 ![](images/AgecncyFactory.png) - 需求管理器 ![](images/DemandManager.png) - 顾客服务机构链 ![](images/AgencyChain.png) 2. 数据统计原理 ![](images/Statistic.png) 3. 仿真优化原理 ![](images/Optimization.png) 4. 模块 - ShkSimulation 是系统核心模块,定义了,是不包含共享汽车内容 - ShkSimulationImpl 是使用核心模块进行共享汽车、高速公路等离散事件仿真的实现 - ShkSimulationDesktop 是用于共享汽车仿真,基于ShkSimulationImpl.carsharing.impl中的各种实现类进行可视化运行的模块 - ShkSimulationApplication 类似于ShkSimulationDesktop,是用于控制台运行的模块,包含的文件只有一个Program.cs,其就是调用ShkSimulationImpl/carsharing/impl/SimulationApplication.cs完成仿真 - ShkSimulationTest 是测试模块,修改后一定要运行保证修改的正确 5. 其他的多线程支持、工具集等自己看哦,论文里也有更详细的说明。 #### 使用示例 在ShkSimulationImpl模块中有4套示例代码: - carsharing目录下是共享汽车仿真相关代码,目录下定义了CarsharingStation等共享汽车仿真共有类,同时有三套不同的代码:impl、demo、efficiency 1. impl 包含了最多功能的实现,使用了更多特性,也是ShkSimulationDesktop中使用的代码。 2. demo 是较为简单的使用方式,定义了一个5个车站,20条道路的路网仿真 3. efficiency 是用来进行性能对比测试的一套代码 - highway目录是高速公路排队仿真,考虑了拥堵传播,仿真的设置是:一条高速公路,被划分为多个路段,每个路段为一个服务机构,第一个路段接收车辆到达,并在路段中服务、转移,最后离开这条高速公路,下游路段会影响上游路段。 可以在ShkSimulationApplication、ShkSimulationDesktop、ShkSimulationTest中查看到示例的运行,比如ShkSimulationTest/QuickBuildTest.cs等 一般的功能参考ShkSimulationImpl下的代码就好啦,对以下部分补充介绍一下。 1. 仿真输入 在创建NetworkInputData(默认实现是NetworkEnvironment)时,需要传入InputConfig实例,可以在其中设置资源路径信息和一般配置信息。 其中的资源信息,通过设置的ResourceLoader(默认Excel)记载后会保存在Network的NetworkInput中,可以通过资源的Key获取到加载的Resource。 例如: ``` 1、设置资源信息 InputConfig config = new InputConfig(); // 设置资源key和路径信息 config.SetResourceValue("roadSectionResource", "C:/Users/PK/Desktop/road-section.xlsx"); NetworkEnvironment inputData = new NetworkEnvironment(config, new ExcelResourceLoader()); 2、根据ResourceKey使用加载好的资源 // 使用对应资源创建工厂/服务机构,资源名和InputConfig中设置的资源Key要一样,不然创建时传入的Resource就是null AgencyFactory factory = FactoryProvider.CreateFactory(RoadSectionCreateFunction, "roadSectionResource"); private static Dictionary RoadSectionCreateFunction(Resource resource) { Dictionary result = new Dictionary(); foreach (RoadSectionConfig roadSectionConfig in HighwayRunConfig.RoadSectionConfigs) { BaseAgencyParams agencyParams = BaseAgencyParams.Create(roadSectionConfig.UniqueId); RoadSection road = new RoadSection(agencyParams); road.Order = roadSectionConfig.Order; road.ServiceRateHelper = new StableServiceRateHelper(TimeSpan.FromHours(1 / roadSectionConfig.RoadSectionServiceRate)); result.Add(agencyParams.UniqueId, road); } return result; } ``` 2. 仿真输出 - 任何有数据统计需求的类都可以实现DataReporter类,而后在实现的接口方法中返回需要的数据,所有的Agency都默认继承了该接口。 示例: ``` public override DataReportInfo GetReportInfo() { return DataReportInfo.Create(UniqueId.ToString(), ClockTime, null, new Dictionary(){ {"ArriveCount", ArriveCount} }); } ``` - 在运行Network.Init()之前可以对数据采集进行设置,系统默认会将不同种类的Agency分别设置为数据汇报集合,可以通过对network.ResultCollector.DataReporterGenerator更改或替换进行自定义 例如: 1. ```Network.ResultCollector.DataReporterGenerator = new DataReporterGenerator(CreateDataReporters);``` 2. ```Network.ResultCollector.DataReporterGenerator.DataReporterGenerateAction += SimulationApplication.AddDataReporters;``` - 可以通过StatisticOptionProvider对统计选项进行设置,统计选项详见数据统计原理或论文。 例如: ``` 注册时间统计特性 RegisterTimeStatisticFunction(DefaultTimeAvgValue, _ => _.AverageCount); 注册集合数据统计值,默认注册最终值的 总和 和 平均值 RegisterNumberStatisticFunction(DefaultSumValue, _ => _.Values.Sum()); RegisterNumberStatisticFunction(DefaultAvgValue, _ => _.Values.Average()); ``` 3. Agency内的Internal[Serve|Arrive|Depart]与继承实现的[Serve|Arrive|Depart] Agency内使用Internal[Serve|Arrive|Depart]来进入内部服务台,因此在自己的代码中尽量使用Internal[Serve|Arrive|Depart]而不是[Serve|Arrive|Depart] #### 万丈高楼平地起 有一定的面向对象基础来使用比较好,把继承、重载、接口、抽象类、访问修饰符、父类子类、实例变量和静态变量等概念理解清楚之后,使用和阅读就很轻松了。 微软教程:[C#教程-Microsoft](https://docs.microsoft.com/zh-cn/dotnet/csharp/) 菜鸟教程:[C#教程-菜鸟教程](https://www.runoob.com/csharp/csharp-tutorial.html) 另外还可以了解一下:面向对象设计的六大设计原则、测试驱动开发概念 可以在这个网站查看C#源代码: [C#源码参考手册](https://referencesource.microsoft.com/) 其他技术文档可以查看Microsoft的网站: [Microsoft技术文档](https://docs.microsoft.com/zh-cn/documentation/) 另外还有基础的数据结构,包括栈、队列、链表等,可以在这个网站可视化查看: [数据结构可视化](https://www.cs.usfca.edu/~galles/visualization/Algorithms.html) 源码的学习可以先阅读O2DES的源代码(主要就是Sandbox.cs): [O2DES](http://www.o2des.net/) ,在本系统中对原来的O2DES进行了改进,在Sandbox.cs中,论文中叙述了改进的思路 #### 部分ShkSimulationDesktop演示 ![输入图片说明](images/%E4%BB%BF%E7%9C%9F.mp4_20220720_205515.109.jpg) ![输入图片说明](images/%E7%BC%96%E8%BE%91.jpg) ![输入图片说明](images/%E8%B7%AF%E7%BD%91.jpg) ![输入图片说明](images/%E4%BB%BF%E7%9C%9F.mp4_20220720_205742.007.jpg) ![输入图片说明](images/%E4%BB%BF%E7%9C%9F.mp4_20220720_205646.742.jpg) #### 参与贡献 有问题或意见,可以直接邮件联系pklue@foxmail.com 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request