SingleRun + HasDelayPlugin#

This example notebook shows how you can integrate percentual delays in your simulation. We demonstrate how you can use the HasDelayPlugin, and how you can give it a certain delay percentage.

0. Import libraries#

import datetime, time
import simpy

import shapely.geometry
import pandas as pd

import openclsim.core as core
import openclsim.model as model
import openclsim.plot as plot
import openclsim.plugins as plugins

1. Initialise simpy environment#

# setup environment (simulation time needs to match the available weather data)
simulation_start = 0
my_env = simpy.Environment(initial_time=simulation_start)

2. Define object classes#

# create a Site object based on desired mixin classes
Site = type(
    "Site",
    (
        core.Identifiable,
        core.Log,
        core.Locatable,
        core.HasContainer,
        core.HasResource,
    ),
    {},
)

# create a TransportProcessingResource object based on desired mixin classes
TransportProcessingResource = type(
    "TransportProcessingResource",
    (
        core.ContainerDependentMovable,
        core.Processor,
        core.HasResource,
        core.LoadingFunction,
        core.UnloadingFunction,
        core.Identifiable,
        core.Log,
    ),
    {},
)

3. Create objects#

3.1. Create site object(s)#

# prepare input data for from_site
location_from_site = shapely.geometry.Point(4.18055556, 52.18664444)
data_from_site = {"env": my_env,
                  "name": "from_site",
                  "geometry": location_from_site,
                  "capacity": 12,
                  "level": 12
                 }
# instantiate from_site 
from_site = Site(**data_from_site)

# prepare input data for to_site
location_to_site = shapely.geometry.Point(4.25222222, 52.11428333)
data_to_site = {"env": my_env,
                "name": "to_site",
                "geometry": location_to_site,
                "capacity": 12,
                "level": 0
               }
# instantiate to_site 
to_site = Site(**data_to_site)

3.2. Create vessel object(s)#

# prepare input data for vessel_01
data_vessel01 = {"env": my_env,
                 "name": "vessel01",
                 "geometry": location_from_site, 
                 "loading_rate": 1,
                 "unloading_rate": 1,
                 "capacity": 4,
                 "compute_v": lambda x: 10
               }
# instantiate vessel_01 
vessel01 = TransportProcessingResource(**data_vessel01)

3.3 Create activity/activities#

# initialise registry
registry = {}
keep_resources = {}
# create delay sequence activities
DelaySequenceActivity =  type(
    "TestShiftActivity",
    (
        plugins.HasDelayPlugin,
        model.SequentialActivity,  # the order is critical!
    ),
    {},
)

DelayWhileActivity =  type(
    "TestShiftActivity",
    (
        plugins.HasDelayPlugin,
        model.WhileActivity,  # the order is critical!
    ),
    {},
)

DelayMoveActivity =  type(
    "TestMoveActivity",
    (
        plugins.HasDelayPlugin,
        model.MoveActivity,  # the order is critical!
    ),
    {},
)

DelayShiftActivity =  type(
    "TestShiftActivity",
    (
        plugins.HasDelayPlugin,
        model.ShiftAmountActivity,  # the order is critical!
    ),
    {},
)

DelayBasicActivity =  type(
    "TestShiftActivity",
    (
        plugins.HasDelayPlugin,
        model.BasicActivity,  # the order is critical!
    ),
    {},
)
# create a list of the sub processes
sub_processes = [
    DelayMoveActivity(
        env=my_env,
        name="sailing empty",
        registry=registry,
        mover=vessel01,
        destination=from_site,
        delay_percentage=10,
    ),
    DelayShiftActivity(
        env=my_env,
        name="load cargo",
        registry=registry,
        processor=vessel01,
        origin=from_site,
        destination=vessel01,
        amount=4,
        duration=10,
        delay_percentage=10,
    ),
    DelayMoveActivity(
        env=my_env,
        name="sailing full",
        registry=registry,
        mover=vessel01,
        destination=to_site,
        delay_percentage=10,
    ),
    DelayShiftActivity(
        env=my_env,
        name="unload cargo",
        registry=registry,
        processor=vessel01,
        origin=vessel01,
        destination=to_site,
        amount=4,
        duration=10,
        delay_percentage=10,
    ),
    DelayBasicActivity(
        env=my_env,
        name="Basic activity",
        registry=registry,
        duration=0,
        additional_logs=[vessel01],
        delay_percentage=10,
    ),
]

# create a 'sequential activity' that is made up of the 'sub_processes'
sequential_activity = DelaySequenceActivity(
    env=my_env,
    name="Single run process",
    registry=registry,
    sub_processes=sub_processes,
    delay_percentage=10,
)

# create a while activity that executes the 'sequential activity' while a stop condition is not met 
while_activity = DelayWhileActivity(
    env=my_env,
    name="While activity",
    registry=registry,
    sub_processes=[sequential_activity],
    condition_event=[{"type": "container", "concept": to_site, "state": "full"}],
    delay_percentage=10,
)

4. Register processes and run simpy#

model.register_processes([while_activity])
my_env.run()

5. Inspect results#

5.1 Inspect logs#

pd.concat([plot.get_log_dataframe(act, [while_activity, sequential_activity, *sub_processes]) for act in sub_processes]).sort_values(by='Timestamp')
Activity Timestamp ActivityState type ref
0 sailing empty 1970-01-01 00:00:00.000000 START NaN NaN
1 sailing empty 1970-01-01 00:00:00.000000 STOP NaN NaN
2 sailing empty 1970-01-01 00:00:00.000000 WAIT_START plugin delay
3 sailing empty 1970-01-01 00:00:00.000000 WAIT_STOP plugin delay
0 load cargo 1970-01-01 00:00:00.000000 START NaN NaN
1 load cargo 1970-01-01 00:00:10.000000 STOP NaN NaN
2 load cargo 1970-01-01 00:00:10.000000 WAIT_START plugin delay
3 load cargo 1970-01-01 00:00:11.000000 WAIT_STOP plugin delay
0 sailing full 1970-01-01 00:00:11.000000 START NaN NaN
2 sailing full 1970-01-01 00:15:53.824591 WAIT_START plugin delay
1 sailing full 1970-01-01 00:15:53.824591 STOP NaN NaN
3 sailing full 1970-01-01 00:17:28.107050 WAIT_STOP plugin delay
0 unload cargo 1970-01-01 00:17:28.107050 START NaN NaN
2 unload cargo 1970-01-01 00:17:38.107050 WAIT_START plugin delay
1 unload cargo 1970-01-01 00:17:38.107050 STOP NaN NaN
2 Basic activity 1970-01-01 00:17:39.107050 WAIT_START plugin delay
1 Basic activity 1970-01-01 00:17:39.107050 STOP NaN NaN
0 Basic activity 1970-01-01 00:17:39.107050 START NaN NaN
3 unload cargo 1970-01-01 00:17:39.107050 WAIT_STOP plugin delay
3 Basic activity 1970-01-01 00:17:39.107050 WAIT_STOP plugin delay
4 sailing empty 1970-01-01 00:19:25.017755 START NaN NaN
5 sailing empty 1970-01-01 00:35:07.842347 STOP NaN NaN
6 sailing empty 1970-01-01 00:35:07.842347 WAIT_START plugin delay
4 load cargo 1970-01-01 00:36:42.124806 START NaN NaN
7 sailing empty 1970-01-01 00:36:42.124806 WAIT_STOP plugin delay
6 load cargo 1970-01-01 00:36:52.124806 WAIT_START plugin delay
5 load cargo 1970-01-01 00:36:52.124806 STOP NaN NaN
4 sailing full 1970-01-01 00:36:53.124806 START NaN NaN
7 load cargo 1970-01-01 00:36:53.124806 WAIT_STOP plugin delay
6 sailing full 1970-01-01 00:52:35.949397 WAIT_START plugin delay
5 sailing full 1970-01-01 00:52:35.949397 STOP NaN NaN
7 sailing full 1970-01-01 00:54:10.231856 WAIT_STOP plugin delay
4 unload cargo 1970-01-01 00:54:10.231856 START NaN NaN
6 unload cargo 1970-01-01 00:54:20.231856 WAIT_START plugin delay
5 unload cargo 1970-01-01 00:54:20.231856 STOP NaN NaN
7 unload cargo 1970-01-01 00:54:21.231856 WAIT_STOP plugin delay
5 Basic activity 1970-01-01 00:54:21.231856 STOP NaN NaN
6 Basic activity 1970-01-01 00:54:21.231856 WAIT_START plugin delay
7 Basic activity 1970-01-01 00:54:21.231856 WAIT_STOP plugin delay
4 Basic activity 1970-01-01 00:54:21.231856 START NaN NaN
8 sailing empty 1970-01-01 00:57:50.853266 START NaN NaN
10 sailing empty 1970-01-01 01:13:33.677858 WAIT_START plugin delay
9 sailing empty 1970-01-01 01:13:33.677858 STOP NaN NaN
11 sailing empty 1970-01-01 01:15:07.960317 WAIT_STOP plugin delay
8 load cargo 1970-01-01 01:15:07.960317 START NaN NaN
9 load cargo 1970-01-01 01:15:17.960317 STOP NaN NaN
10 load cargo 1970-01-01 01:15:17.960317 WAIT_START plugin delay
8 sailing full 1970-01-01 01:15:18.960317 START NaN NaN
11 load cargo 1970-01-01 01:15:18.960317 WAIT_STOP plugin delay
9 sailing full 1970-01-01 01:31:01.784908 STOP NaN NaN
10 sailing full 1970-01-01 01:31:01.784908 WAIT_START plugin delay
8 unload cargo 1970-01-01 01:32:36.067367 START NaN NaN
11 sailing full 1970-01-01 01:32:36.067367 WAIT_STOP plugin delay
9 unload cargo 1970-01-01 01:32:46.067367 STOP NaN NaN
10 unload cargo 1970-01-01 01:32:46.067367 WAIT_START plugin delay
10 Basic activity 1970-01-01 01:32:47.067367 WAIT_START plugin delay
8 Basic activity 1970-01-01 01:32:47.067367 START NaN NaN
9 Basic activity 1970-01-01 01:32:47.067367 STOP NaN NaN
11 unload cargo 1970-01-01 01:32:47.067367 WAIT_STOP plugin delay
11 Basic activity 1970-01-01 01:32:47.067367 WAIT_STOP plugin delay

5.2 Visualise gantt charts#

objects = [while_activity, sequential_activity, vessel01, from_site, to_site]
objects.extend(sub_processes)
plot.get_gantt_chart(objects)