In August, as the event co-organizer of Singapore .NET Developers Community, I’m proud to have Professor Li from National University of Singapore to join us as a speaker. He was sharing with us about the O2DES.NET which is used for simulation modelling.
For personal learning and knowledge sharing purposes, I decide to note down what I have tried out with O2DES.NET so far.
What is O2DES?
O2DES.NET is a simulation framework. It is a project started in 2014 by the team and later is used for simulation modelling of mega container port in 2016. Now the team is still actively working on this open-source framework.
O2 stands for Object Oriented and DES stands for Discrete-Event Simulation. I think most of you should have already known about object oriented programming, so I won’t talk about it here.
DES is a simulation that models the operation of a system as a discrete sequence of events in time. Each event occurs at a particular instant in time and marks a change of state in the system. Between the consecutive events, there will be no change in the system. Opposite of DES is Continuous Simulation which events complete smoothly without any time delay.
In the real world, a queue in a restaurant can be modelled for DES. Both the customer queue and the staff can be the system entities. The system events can then be CustomerArrival, FoodOrder, and CustomerDeparture. The random variables characterised to model this system are food ordering time and the customer inter-arrival time.
This actually brings up another interesting point is that, in order to find out the best time to finish the food ordering for the restaurant, we need to use simulation instead of AI.
Modelling and Simulation
So how do we exactly define modelling and simulation?
Modelling is the process of creating a model which represents a system including its properties. Since model is made similar to a real system, it helps the analysts to predict the effect of changes to a system.
Simulation of a system is the process of using the model to analyse the performance of the system.
Hence with these two techniques, we can easily understand how the system actually operates. From there, we can then can test and diagnose problems in the system.
Getting Started: Our Basic Model
As a quick start, what we will do is to create a console demo app. Here, we will be using .NET Core 3.0.
dotnet new console
After that, we will install the O2DES.NET Nuget package.
dotnet add package O2DESNet --version 3.4.9
Now we can proceed with our Hello World model which is extended from the abstract class Sandbox from the O2DES.NET library. The following screenshot shows how we do it.
Here we have only one event which is called MyEvent. When this event happens, it will print a line to the console. After that it will schedule next MyEvent in one minute later.
In the simulator constructor, we will schedule our first event which will be executed immediately without any delay.
What is ClockTime? ClockTime is a DateTime variable in Sandbox and its initiate value is DateTime.MinValue. With the Schedule function defined in Sandbox class, the ClockTime will increase by the number of minute based on what we have input.
Here, our sample code says TimeSpan.FromMinutes(1), so the console will print the following.
There are 10 lines above. So does that mean we need to wait 10 minutes to get all of the lines printed? Nope. Since the Sandbox is stimulating time by doing the time ticking, so the time is not our real time. Hence, if we change to print DateTime.Now instead of ClockTime, we will see multiple lines of the same time.
So, why there are only 10 lines printed? It is not because we put in 10 in the MyEvent method. That one is the initial integer for the counter. We need to move on to see how we actually run the model.
We can control the number of events by inputing the event count into the Run method. So, when we do simulation.Run(10), the event will only happen 10 times and thus only 10 lines are printed.
So from this sample code, what we can know is that events can be declared with any number of input parameters because it’s just a normal C# method. However, the return type of the events must always be void. Hence, a void member method of the model class is indifferent from an event.
Also, Professor Li pointed out that all events have to be declared in a model class which it belongs to.
In addition, with multiple events in a model, one event can also trigger an immediate execution of another event just simply by invoking it as a method.
Running the model above will have the following results.
What we have seen so far are events in atomic model, i.e. all the events are in a single class. However, what if we have a more complicated system with multiple sub-systems? Luckily, O2DES.NET supports modularisation as well.
For example, we can add the “public” access specifier to the event method, so it can be called from outside of the module.
We can also further introduce publisher-subscriber pattern into our model so that we can invite subscribers to subscribe our events.
With the event keyword, it means the OnMyOutputEvent can only be triggered from inside the module, which is through Invoke().
We also added Dispose() method to remove subscribers from the event so that there will be no memory leak.
Now, as an Action type, the event can be subscribed by any external parties which can handle the same parameters.
As we can see in our sample, we have two types of scheduling. First is we call schedule without any parameter, as shown below.
Schedule(() => MyEvent(10, 50));
This means the event will be triggered immediately at the current clock time.
We have also scheduled the event to be called in one minute later by specifying a timespan of one minute.
In addition, we can also schedule an event to be invoked at the specified clock-time by passing in a DateTime value as following.
Schedule(() => MyEvent(10, 50), ClockTime.AddMinutes(15));
The first line will thus print “01/01/0001 00:15:00” instead of “01/01/0001 00:00:00”.
Interestingly, the O2DES.NET library also offers methods to generate random time delay based on various statistical distribution. For example, we can have the following.
If we look into the codes of O2DESNet.Distributions, we will realise that it is based on Math.Net Numerics, a library which offers methods and algorithms for numerical computations in science, engineering, and every day use.
Another interesting stuff to take note is the DefaultRS which stands for default random stream. For those who are familiar with MATLAB, random stream should sound familiar to you. The streams can be thought of as a list of pseudo-random numbers that are generated. A stream of random numbers is used to generate samples from the various distributions defined in our model. We are allowed to initiate it with various seed in O2DES.NET.
So running the program above which now has random time delay, we will get something quite similar to the following outcome.
That’s all what I have learned so far. The half-an-hour talk delivered by Profession Li is indeed very interesting and what I have covered here is only the O2DES.NET library part. If you are interested to know more, please refer to the links in References below for more details about this open-source project.