Basic Example

This is a step-by-step tutorial on how to develop a basic discrete event simulation model using pydsol-model. Example can be found at ./examples/basic_example.py.

Step-by-Step Tutorial

We want to create a basic discrete event simulation model with one source, one server, one sink with entities passing through the model, using links with distance of 1. See conceptualization of the simulation model in the figure below.

alternate text

Start with creating a new DSOLModel class for this basic example.

from pydsol.core.model import DSOLModel

class BasicExampleModel(DSOLModel):
    def __init__(self, simulator):
        super().__init__(simulator)

    def construct_model(self):
       # add model objects

Then, add the model objects that we want in our simulation model as following:

from pydsol.core.model import DSOLModel

from pydsol.model.source import Source
from pydsol.model.server import Server
from pydsol.model.sink import Sink
from pydsol.model.link import Link

class BasicExampleModel(DSOLModel):
    def __init__(self, simulator):
        super().__init__(simulator)

    def construct_model(self):
        # Create model
        source = Source(self.simulator)
        server = Server(self.simulator)
        sink = Sink(self.simulator)

        link_1 = Link(self.simulator, source, server, 1)
        link_2 = Link(self.simulator, server, sink, 1)

For all the model objects, the default values are used. Note that Source creates entities of type Entity by default.

Next, the structure of the model components needs to be set - so how are the entities flowing through the model? This is done using the attribute next. This attribute defines what the next model object is. A next needs to be defined for each model object expect for the Sink.

from pydsol.core.model import DSOLModel

from pydsol.model.source import Source
from pydsol.model.server import Server
from pydsol.model.sink import Sink
from pydsol.model.link import Link

class BasicExampleModel(DSOLModel):
    def __init__(self, simulator):
        super().__init__(simulator)

    def construct_model(self):
        # Create model
        source = Source(self.simulator)
        server = Server(self.simulator)
        sink = Sink(self.simulator)

        link_1 = Link(self.simulator, source, server, 1)
        link_2 = Link(self.simulator, server, sink, 1)

        # Set structure
        source.next = link_1
        link_1.next = server
        server.next = link_2
        link_2.next = sink

The simulation model is now finished and ready to run. For running, pydsol-core is used. Running the model for one replication with a start time of 0, no warm-up time, and a run time of 100. This results in the following code:

from pydsol.core.experiment import SingleReplication
from pydsol.core.model import DSOLModel
from pydsol.core.simulator import DEVSSimulatorFloat

from pydsol.model.source import Source
from pydsol.model.server import Server
from pydsol.model.sink import Sink
from pydsol.model.link import Link


class BasicExampleModel(DSOLModel):
    def __init__(self, simulator):
        super().__init__(simulator)

    def construct_model(self):
        print("\nReplication starts...")
        # Create model
        source = Source(self.simulator)
        server = Server(self.simulator)
        sink = Sink(self.simulator)

        link_1 = Link(self.simulator, source, server, 1)
        link_2 = Link(self.simulator, server, sink, 1)

        # Set structure
        source.next = link_1
        link_1.next = server
        server.next = link_2
        link_2.next = sink

if __name__ == "__main__":
    simulator = DEVSSimulatorFloat("sim")
    model = BasicExampleModel(simulator)
    replication = SingleReplication("rep1", 0.0, 0.0, 100)
    simulator.initialize(model, replication)
    simulator.start()

Extensions

An example for extending or modifying a basic discrete event simulation models (in def construct_model) is to give your own input to the interarrival times, processing times, and distribution to each model station. For example:

def construct_model(self):
    print("\nReplication starts...")
    # Create model
    source = Source(self.simulator, interarrival_time=0.5)
    server = Server(self.simulator, processing_time=1, distribution=None)
    sink = Sink(self.simulator)

    link_1 = Link(self.simulator, source, server, 1)
    link_2 = Link(self.simulator, server, sink, 1)

    # Set structure
    source.next = link_1
    link_1.next = server
    server.next = link_2
    link_2.next = sink

Also, you can customize the names of each model objects. For example, naming the links:

def construct_model(self):
    print("\nReplication starts...")
    # Create model
    source = Source(self.simulator, interarrival_time=0.5)
    server = Server(self.simulator, processing_time=1, distribution=None)
    sink = Sink(self.simulator)

    link_1 = Link(self.simulator, source, server, 1, name="Link 1.0")
    link_2 = Link(self.simulator, server, sink, 1, name="Link 2.0")

    # Set structure
    source.next = link_1
    link_1.next = server
    server.next = link_2
    link_2.next = sink

If entities should be carried by a Vehicle from, for example, the source to the server, add the vehicle type to the Source object. Also, to make sure that the Source actually uses Entity as entity type, we add this attribute to the Source object like:

from pydsol.model.entities import Entity, Vehicle

            def construct_model(self):
                print("\nReplication starts...")
                # Create model
                source = Source(self.simulator, interarrival_time=0.5, vehicle_type=Vehicle,
                                entity_type = Entity)
                server = Server(self.simulator, processing_time=1, distribution=None)
                sink = Sink(self.simulator)

                link_1 = Link(self.simulator, source, server, 1, name="Link 1.0")
                link_2 = Link(self.simulator, server, sink, 1, name="Link 2.0")

                # Set structure
                source.next = link_1
                link_1.next = server
                server.next = link_2
                link_2.next = sink

Another example to extend the basic simulation model is to add another link from the source to the server. This is combined with all the other customizations and extensions, and gives the code as below. This code is also available at ./examples/basic_example_extended.py.

from pydsol.core.experiment import SingleReplication
from pydsol.core.model import DSOLModel
from pydsol.core.simulator import DEVSSimulatorFloat

from pydsol.model.entities import Entity, Vehicle
from pydsol.model.source import Source
from pydsol.model.server import Server
from pydsol.model.sink import Sink
from pydsol.model.link import Link


class BasicExampleModel(DSOLModel):
    def __init__(self, simulator):
        super().__init__(simulator)

    def construct_model(self):
        print("\nReplication starts...")
        # Create model
        source = Source(self.simulator, 0.5, entity_type=Entity, vehicle_type=Vehicle)
        server = Server(self.simulator, processing_time=1, distribution=None)
        sink = Sink(self.simulator)

        link_1 = Link(self.simulator, source, server, 1, name="Link 1.0")
        link_11 = Link(self.simulator, source, server, 1, name="Link 1.1")
        link_2 = Link(self.simulator, server, sink, 1, name="Link 2.0")

        # Set structure
        source.next = [link_1, link_11]
        link_1.next = link_11.next = server

        server.next = link_2
        link_2.next = sink


if __name__ == "__main__":
    simulator = DEVSSimulatorFloat("sim")
    model = BasicExampleModel(simulator)
    replication = SingleReplication("rep1", 0.0, 0.0, 100)
    simulator.initialize(model, replication)
    simulator.start()