Sdeslib.Simulation 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Sdeslib.Simulation --version 1.0.0
NuGet\Install-Package Sdeslib.Simulation -Version 1.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Sdeslib.Simulation" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Sdeslib.Simulation --version 1.0.0
#r "nuget: Sdeslib.Simulation, 1.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Sdeslib.Simulation as a Cake Addin
#addin nuget:?package=Sdeslib.Simulation&version=1.0.0

// Install Sdeslib.Simulation as a Cake Tool
#tool nuget:?package=Sdeslib.Simulation&version=1.0.0

Discrete Event Simulation

A very simple impletantation of a discrete event simulation library.

This library allows to simulate discrete sequence of events in time. For more informations related to the Discreve Event Simulation, please refer to https://en.wikipedia.org/wiki/

Getting started

  1. Create a new console .Net project and install nuget package using this command: Install-Package Sdeslib.Simulation

  2. Copy the the HelloWorld class to the project

using System; using System.Collections.Generic; using Sdeslib.Simulation;

namespace HelloWorld { class HelloWorldSimulation { Simulation des = new Simulation();

    public void Run()
    {
        des.InsertEvent(des.NewEvent(0, HelloWorld));
        des.Run();
    }

    private IEnumerable<Event> HelloWorld()
    {
        Console.WriteLine("Hello, World!");
        yield break;
    }

    static void Main(string[] args)
    {
        HelloWorldSimulation program = new HelloWorldSimulation();
        program.Run();
    }
}

}

Events

In this library, an event is represented by a method. The method must contain a (1) set of commands (may change the simulation status) and a sequence of new events to be inserted to the not precessed events queeue.

    public IEnumerable<Event> AnEvent1(string client)
    {
    	int time = sim.now;
    	Do some action;
    	Do some action;
    	....
        yield return sim.NewEvent(time+5, AnEvent2 );
        yield return sim.NewEvent(time+10, AnEvent3 ); // Events must be generated in chronological order.         
    }

    public IEnumerable<Event> AnEvent2(string client)
    {
    	
    	Do some action;
    	Do some action;
    	....            
        yield return sim.NewEvent(sim.now+5, AnEvent3 );            
    }


    public IEnumerable<Event> AnEvent3(string client)
    {
    	
    	Do some action;
    	Do some action;
    	....            
        yield break; //this event does not generate new events
    }

Simulation Core

In each step of simulation, the core algoritm does: 1) get the next event in the not precessed events queeue. 2) run the commands that change the state of simulation until the first "yield return" is met. 3) add the new events stream generated by the current event. 4) go to step 1).

The list of new generated events is traversed lazily. That means, the core algoritm goes reading the not processed list as it is needed. The core algoritm is able to handle infinity list, as in the following example:

    public IEnumerable<Event> GenerateCustomers()
    {
        var now = sim.Now;

        while (true)
        {
            now += FactoryRandom.GetPoisson(averageCustomerArrivalTime);
            yield return sim.NewEvent(now, () => ArriveClient($"client {count++}"));
        }
    }

Stop Condition

The simulation ends when there are no more events to be processed. It also allow finish early a simulation by other four other criterios:

  • Max number of iterations;
  • Max time execution;
  • Max size of pending event list;
  • Custom user stop;

Exemple

The example above simulate a M/M/1 queue. https://en.wikipedia.org/wiki/M/M/1_queue

public class QueeueSimulation
{
    
    Simulation sim = new Simulation(); //creates an instance of the core simulator.
    private double averageCustomerArrivalTime = 10;
    private double averageCustomerServiceTime = 10;


    //state of simulation:
    private Queue<string> clientQueue { get; set; } = new Queue<string>();
    public bool InAttendance { get; set; }

    public class Item
    {
        public string Client { get; set; }
        public long? Arrival { get; set; }
        public long? Start { get; set; }
        public long? Finish { get; set; }
        public long? WaitTime => Start - Arrival;
    }

    public Dictionary<string, Item> Attendance = new Dictionary<string, Item>();

    //Events:

    public IEnumerable<Event> AddAttendanceQueue(string client)
    {
        Console.WriteLine($"{sim.Now,-10} AddAttendanceQueue {client}");
        var now = sim.Now;
        clientQueue.Enqueue(client);
        yield break;
    }

    public IEnumerable<Event> StartService(string client)
    {
        Attendance[client].Start = sim.Now;
        Console.WriteLine($"{sim.Now,-10} StartService {client}");
        var now = sim.Now;

        yield return sim.NewEvent(now + FactoryRandom.GetPoisson(averageCustomerServiceTime), () => EndService(client));
    }

    public IEnumerable<Event> EndService(string client)
    {
        Attendance[client].Finish = sim.Now;
        Console.WriteLine($"{sim.Now,-10} EndService {client}");
        InAttendance = false;

        if (clientQueue.Any())
        {
            var c = clientQueue.Dequeue();

            yield return sim.NewEvent(sim.Now, () => StartService(c));
        }
    }

    public IEnumerable<Event> ArriveClient(string client)
    {
        Attendance.Add(client, new Item {Arrival = sim.Now});
        Console.WriteLine($"{sim.Now,-10} ArriveClient {client} ");
        var now = sim.Now;

        if (!InAttendance && !clientQueue.Any())
        {
            InAttendance = true;

            yield return sim.NewEvent(sim.Now, () => StartService(client));
        }
        else
        {
            yield return sim.NewEvent(sim.Now, () => AddAttendanceQueue(client));
        }
    }

    private int count = 0;

    public IEnumerable<Event> GenerateCustomers()
    {
        var now = sim.Now;

        while (true)
        {
            now += FactoryRandom.GetPoisson(averageCustomerArrivalTime);

            yield return sim.NewEvent(now, () => ArriveClient($"client {count++}"));
        }
    }


    public void Run()
    {
    	//add initial events to the simulation
    	//this method must be used before stat simulation
    	//Inside an event method, new events are created with yield return. sim.InsertEvent will not be used anymore!     	
        sim.InsertEvent(sim.NewEvent(FactoryRandom.GetPoisson(averageCustomerArrivalTime), () => GenerateCustomers()));



        //stop simulation after time 30000 in the simulation clock
        sim.UserStop += time => time >= 30000;            
        sim.Run();
        //get simulation statistics
        var averateWaitingTime = Attendance.Where(x => x.Value.Start.HasValue).Average(x => x.Value.WaitTime);
        Console.WriteLine($"Average waiting time: {averateWaitingTime}");
        Console.WriteLine(sw.Elapsed);
    }
}
Product Compatible and additional computed target framework versions.
.NET Framework net461 is compatible.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
4.0.0 597 2/22/2019
3.0.0 493 2/22/2019
2.0.0 493 2/22/2019
1.0.0 523 2/22/2019

None