complex process synchronization#
In the process synchronization notebook the synchronization using start_events was compared with a sequence of activities. However, the synchronization of two processes e.g. two vessels can not be implemented using sequence, but requires the start_event synchronization.
In this demo two processes each consisting of a sequence of activities representing the processes of two vessels are synchronized, e.g. because they have to make a hand-over of material.
This basic mechanism is also used in the feeder demo that is discussed under the real-world examples.
0. Import libraries#
import datetime, time
import simpy
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#
No sites and vessels defined in this example
3. Create objects#
3.1. Create site object(s)#
No site objects defined in this example
3.2. Create vessel object(s)#
No vessel objects defined in this example
3.3 Create activity/activities#
The activity names of the first sequence all start with A Basic activity. Activity A Basic activity3 is constrained such that it can only be executed after B Basic activity 2 has been completed. Thus, in this demo, two processes controlled by a structural control element are synchronized with each other using start_events.
# initialise registry and keep_resources
registry = {}
keep_resources = {}
# create a reporting activity
reporting_activity = model.BasicActivity(
env=my_env,
name="Reporting activity",
registry=registry,
duration=0,
keep_resources=keep_resources,
)
# create a list of the sub processes
sub_processes_B = [
model.BasicActivity(
env=my_env,
name="B Basic activity1",
registry=registry,
duration=10,
additional_logs=[reporting_activity],
keep_resources=keep_resources,
),
model.BasicActivity(
env=my_env,
name="B Basic activity2",
registry=registry,
duration=500,
additional_logs=[reporting_activity],
keep_resources=keep_resources,
),
model.BasicActivity(
env=my_env,
name="B Basic activity3",
registry=registry,
duration=120,
additional_logs=[reporting_activity],
keep_resources=keep_resources,
),
]
# create a 'sequential activity' that is made up of the 'sub_processes'
sequential_activity_B = model.SequentialActivity(
env=my_env,
name="B Sequential process",
registry=registry,
sub_processes=sub_processes_B,
keep_resources=keep_resources,
)
# create a list of the sub processes
sub_processes_A = [
model.BasicActivity(
env=my_env,
name="A Basic activity1",
registry=registry,
duration=14,
additional_logs=[reporting_activity],
keep_resources=keep_resources,
),
model.BasicActivity(
env=my_env,
name="A Basic activity2",
registry=registry,
duration=10,
additional_logs=[reporting_activity],
keep_resources=keep_resources,
),
model.BasicActivity(
env=my_env,
name="A Basic activity3",
registry=registry,
duration=220,
additional_logs=[reporting_activity],
keep_resources=keep_resources,
start_event=[
{
"name": "B Basic activity2",
"type": "activity",
"state": "done"
}
],
),
]
# create a 'sequential activity' that is made up of the 'sub_processes'
sequential_activity_A = model.SequentialActivity(
env=my_env,
name="A Sequential process",
registry=registry,
sub_processes=sub_processes_A,
keep_resources=keep_resources,
)
4. Register processes and run simpy#
# initate the simpy processes defined in the 'while activity' and run simpy
model.register_processes([sequential_activity_A, sequential_activity_B, reporting_activity])
my_env.run()
5. Inspect results#
5.1 Inspect logs#
display(plot.get_log_dataframe(reporting_activity, [sequential_activity_A, *sub_processes_A, sequential_activity_B, *sub_processes_B, reporting_activity]))
Activity | Timestamp | ActivityState | type | ref | |
---|---|---|---|---|---|
0 | Reporting activity | 1970-01-01 00:00:00 | START | NaN | NaN |
1 | A Basic activity1 | 1970-01-01 00:00:00 | START | additional log | e7313420-d7c4-4550-bcfc-9392bc2fdfae |
2 | B Basic activity1 | 1970-01-01 00:00:00 | START | additional log | d7c361f6-7b3c-4557-a7b7-3755b5940495 |
3 | Reporting activity | 1970-01-01 00:00:00 | STOP | NaN | NaN |
4 | B Basic activity1 | 1970-01-01 00:00:10 | STOP | additional log | d7c361f6-7b3c-4557-a7b7-3755b5940495 |
5 | B Basic activity2 | 1970-01-01 00:00:10 | START | additional log | ca1011ac-8c6a-4b9c-bab7-db24dd363c96 |
6 | A Basic activity1 | 1970-01-01 00:00:14 | STOP | additional log | e7313420-d7c4-4550-bcfc-9392bc2fdfae |
7 | A Basic activity2 | 1970-01-01 00:00:14 | START | additional log | 66989b96-c7e2-486e-9352-2160ef5dfd01 |
8 | A Basic activity2 | 1970-01-01 00:00:24 | STOP | additional log | 66989b96-c7e2-486e-9352-2160ef5dfd01 |
11 | A Basic activity3 | 1970-01-01 00:00:24 | WAIT_START | additional log | 730be5db-a1b9-4923-b11f-dbca919b56ef |
9 | B Basic activity2 | 1970-01-01 00:08:30 | STOP | additional log | ca1011ac-8c6a-4b9c-bab7-db24dd363c96 |
10 | B Basic activity3 | 1970-01-01 00:08:30 | START | additional log | 92689d91-090a-45b3-bd27-288a8ed3a036 |
12 | A Basic activity3 | 1970-01-01 00:08:30 | WAIT_STOP | additional log | 730be5db-a1b9-4923-b11f-dbca919b56ef |
13 | A Basic activity3 | 1970-01-01 00:08:30 | START | additional log | 730be5db-a1b9-4923-b11f-dbca919b56ef |
14 | B Basic activity3 | 1970-01-01 00:10:30 | STOP | additional log | 92689d91-090a-45b3-bd27-288a8ed3a036 |
15 | A Basic activity3 | 1970-01-01 00:12:10 | STOP | additional log | 730be5db-a1b9-4923-b11f-dbca919b56ef |
5.2 Visualise gantt charts#
plot.get_gantt_chart([*model.get_subprocesses(sequential_activity_A), *model.get_subprocesses(sequential_activity_B)])
Both processes start at the same time. A Basic activity3 enters waiting state since A Basic activity2 has not been completed yet.
Hint: Having a start_event based on the last activity of a sequence is currently not working. If the constraint is made based on the end of the parent sequence, then the intended synchronization can be accomplished.
When changing the duration of A Basic activity2 to 1000 then there will be no waiting since the A Basic activity2 completes after B Basic activity2 has been completed.
5.3 Visualise container volume developments#
Since there are no objects with containers, in this example, there is nothing to visualise.