RepeatActivity + stop condition#

This notebook provides an example of a simulation that takes a number of sub_processes, grouped in a SequentialActivity, that is executed in a WhileActivity while a stop condition is not yet met.

For this example we work with the following sub_processes:

  • sailing empty

  • loading

  • sailing full

  • unloading

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

1. Initialise simpy environment#

# setup environment
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": 100,
                  "level": 100
                 }
# 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": 100,
                "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": 0.0004,
                 "unloading_rate": 0.0004,
                 "capacity": 4,
                 "compute_v": lambda x: 10
               }
# instantiate vessel_01 
vessel01 = TransportProcessingResource(**data_vessel01)

3.3 Create activity/activities#

# initialise registry
registry = {}
# create a list of the sub processes
sub_processes = [
    model.MoveActivity(
        env=my_env,
        name="sailing empty",
        registry=registry,
        mover=vessel01,
        destination=from_site,
    ),
    model.ShiftAmountActivity(
        env=my_env,
        name="loading",
        registry=registry,
        processor=vessel01,
        origin=from_site,
        destination=vessel01,
        amount=4,
        duration=1000,
    ),
    model.MoveActivity(
        env=my_env,
        name="sailing full",
        registry=registry,
        mover=vessel01,
        destination=to_site,
    ),
    model.ShiftAmountActivity(
        env=my_env,
        name="unloading",
        registry=registry,
        processor=vessel01,
        origin=vessel01,
        destination=to_site,
        amount=4,
        duration=1000,
    ),
    model.BasicActivity(
        env=my_env,
        name="basic activity",
        registry=registry,
        duration=0,
        additional_logs=[vessel01],
    ),
]

# create a 'sequential activity' that is made up of the 'sub_processes'
sequential_activity = model.SequentialActivity(
        env=my_env,
        name="sequential",
        registry=registry,
        sub_processes=sub_processes,
    )

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

4. Register processes and run simpy#

# initate the simpy processes defined in the 'while activity' and run simpy
model.register_processes([while_activity])
my_env.run()

5. Inspect results#

5.1 Inspect logs#

plot.get_log_dataframe(vessel01, [while_activity])
Activity Timestamp ActivityState container level geometry type ref
0 sailing empty 1970-01-01 00:00:00.000000 START 0.0 POINT (4.18055556 52.18664444) NaN NaN
1 sailing empty 1970-01-01 00:00:00.000000 STOP 0.0 POINT (4.18055556 52.18664444) NaN NaN
2 loading 1970-01-01 00:00:00.000000 START 0.0 POINT (4.18055556 52.18664444) NaN NaN
3 loading 1970-01-01 00:16:40.000000 STOP 4.0 POINT (4.18055556 52.18664444) NaN NaN
4 sailing full 1970-01-01 00:16:40.000000 START 4.0 POINT (4.18055556 52.18664444) NaN NaN
... ... ... ... ... ... ... ...
245 sailing full 1970-01-02 02:26:38.404972 STOP 4.0 POINT (4.25222222 52.11428333) NaN NaN
246 unloading 1970-01-02 02:26:38.404972 START 4.0 POINT (4.25222222 52.11428333) NaN NaN
247 unloading 1970-01-02 02:43:18.404972 STOP 0.0 POINT (4.25222222 52.11428333) NaN NaN
248 basic activity 1970-01-02 02:43:18.404972 START 0.0 POINT (4.25222222 52.11428333) additional log f3e55f40-2c68-4e38-b86d-e228b9fbd84e
249 basic activity 1970-01-02 02:43:18.404972 STOP 0.0 POINT (4.25222222 52.11428333) additional log f3e55f40-2c68-4e38-b86d-e228b9fbd84e

250 rows × 7 columns

5.2 Visualise gantt charts#

plot.get_gantt_chart([while_activity])
plot.get_gantt_chart([vessel01, from_site, to_site],id_map=[while_activity])

5.3 Visualise container volume developments#

fig = plot.get_step_chart([vessel01, from_site, to_site])
../_images/2bec3873e8128b0d1390488968d4d5cf054ee4b7115c76c6ace0e99daf808b50.png

Sandbox#

pd.DataFrame.from_dict(vessel01.log)
Timestamp ActivityID ActivityState ObjectState ActivityLabel
0 1970-01-01 00:00:00.000000 9d762179-acd5-4700-8587-a4a98ea484a9 START {'container level': 0.0, 'geometry': POINT (4.... {}
1 1970-01-01 00:00:00.000000 9d762179-acd5-4700-8587-a4a98ea484a9 STOP {'container level': 0.0, 'geometry': POINT (4.... {}
2 1970-01-01 00:00:00.000000 15f76a8b-df06-44d7-87cc-f53b655e263a START {'container level': 0.0, 'geometry': POINT (4.... {}
3 1970-01-01 00:16:40.000000 15f76a8b-df06-44d7-87cc-f53b655e263a STOP {'container level': 4.0, 'geometry': POINT (4.... {}
4 1970-01-01 00:16:40.000000 f2fe8407-924a-4d6a-9fd7-89c2f78bf6d5 START {'container level': 4.0, 'geometry': POINT (4.... {}
... ... ... ... ... ...
245 1970-01-02 02:26:38.404972 f2fe8407-924a-4d6a-9fd7-89c2f78bf6d5 STOP {'container level': 4.0, 'geometry': POINT (4.... {}
246 1970-01-02 02:26:38.404972 67fb2e0a-6bfe-4c27-a8f3-99fab2bd054e START {'container level': 4.0, 'geometry': POINT (4.... {}
247 1970-01-02 02:43:18.404972 67fb2e0a-6bfe-4c27-a8f3-99fab2bd054e STOP {'container level': 0.0, 'geometry': POINT (4.... {}
248 1970-01-02 02:43:18.404972 f3e55f40-2c68-4e38-b86d-e228b9fbd84e START {'container level': 0.0, 'geometry': POINT (4.... {'type': 'additional log', 'ref': 'f3e55f40-2c...
249 1970-01-02 02:43:18.404972 f3e55f40-2c68-4e38-b86d-e228b9fbd84e STOP {'container level': 0.0, 'geometry': POINT (4.... {'type': 'additional log', 'ref': 'f3e55f40-2c...

250 rows × 5 columns

list(set(vessel01.log["ActivityID"]))
['9d762179-acd5-4700-8587-a4a98ea484a9',
 '15f76a8b-df06-44d7-87cc-f53b655e263a',
 '67fb2e0a-6bfe-4c27-a8f3-99fab2bd054e',
 'f3e55f40-2c68-4e38-b86d-e228b9fbd84e',
 'f2fe8407-924a-4d6a-9fd7-89c2f78bf6d5']