TUDelft-CITG / OpenCLSim

Rule driven scheduling of cyclic activities for in-depth comparison of alternative operating strategies.
https://openclsim.readthedocs.io
MIT License
14 stars 17 forks source link

Start event waits for entire activity to finish #89

Closed Pietervanhalem closed 4 years ago

Pietervanhalem commented 4 years ago

Summary

OpenCLSim version: 1.2.1 Python version: Python 3.7.3 Operating System: Docker (WSL) -> Jupyter Notebook

Description

When I start a simulation with 2 barges and two activities the second barge waits for the first barge to finish when it can start directly with the second activity.

What I Did

import datetime, time
import simpy
import shapely.geometry
import openclsim.core as core
import openclsim.model as model
import openclsim.plot as plot
import numpy as np
my_env = simpy.Environment(initial_time = time.mktime(datetime.datetime.now().timetuple()))
my_env.epoch = time.mktime(datetime.datetime.now().timetuple())
discharge_site_GC = type(
    'Site', 
    (
        core.Identifiable,
        core.Log,
        core.Locatable,
        core.HasContainer,
        core.HasResource
    ),
    {}
)

dredging_site_GC = type(
    'Site', 
    (
        core.Identifiable,
        core.Log,
        core.Locatable,
        core.HasContainer,
        core.HasResource,
        core.UnloadingFunction,
        core.LoadingFunction,
        core.Processor,
    ),
    {}
)

barge_GC = type(
    "Barge",
    (
        core.Identifiable,
        core.Log,
        core.ContainerDependentMovable,
        core.Processor,
        core.HasResource,
        core.UnloadingFunction,
    ),
    {},
)
def compute_v_provider(v_empty, v_full):
    return lambda x: x * (v_full - v_empty) + v_empty

discharge_site_location_1 = shapely.geometry.Point(4.1, 52)
discharge_site_location_2 = shapely.geometry.Point(4.2, 52)
dredging_site_location = shapely.geometry.Point(4, 52.1)

discharge_site_data_1 = {
    "env": my_env,
    "name": "discharge_site_data_1",
    "geometry": discharge_site_location_1,
    "capacity": 50_000,
    "level": 0
}

discharge_site_data_2 = {
    "env": my_env,
    "name": "discharge_site_data_2",
    "geometry": discharge_site_location_2,
    "capacity": 50_000,
    "level": 0
}

dredging_site_data = {
    "env": my_env,
    "name": "dredging_site_data",
    "geometry": dredging_site_location,
    "capacity": 100_000,
    "level": 100_000,
    "unloading_rate": 1,
    "loading_rate": 1,
}

barge_data = {
    "env": my_env,
    "name": "Hopper 01",
    "geometry": discharge_site_location_1,
    "unloading_rate": 1,
    "capacity": 5_000,
    "compute_v": compute_v_provider(5, 4.5),
}
barge_data_2 = {
    "env": my_env,
    "name": "Hopper 02",
    "geometry": discharge_site_location_1,
    "unloading_rate": 1,
    "capacity": 5_000,
    "compute_v": compute_v_provider(5, 4.5),
}

dredging_site = dredging_site_GC(**dredging_site_data)
discharge_site_1 = discharge_site_GC(**discharge_site_data_1)
discharge_site_2 = discharge_site_GC(**discharge_site_data_2)
barge_1 = barge_GC(**barge_data)
barge_2 = barge_GC(**barge_data_2)
act_1 = model.Activity(
    env = my_env,
    name = "Soil movement 1",
    origin = dredging_site,
    destination = discharge_site_1,
    loader = dredging_site,
    mover = barge_1,
    unloader = barge_1,
    start_event = None,
    stop_event = None
)

act_2 =model.Activity(
    env = my_env,
    name = "Soil movement 2",
    origin = dredging_site,
    destination = discharge_site_1,
    loader = dredging_site,
    mover = barge_2,
    unloader = barge_2,
    start_event = None,
    stop_event = None
)

## bugg
# start_event = [act_1.main_process, act_2.main_process] 
## or
start_event = discharge_site_1.container.full_event

act_3 =model.Activity(
    env = my_env,
    name = "Soil movement 3",
    origin = dredging_site,
    destination = discharge_site_2,
    loader = dredging_site,
    mover = barge_1,
    unloader = barge_1,
    start_event = start_event,
    stop_event = None
)

act_4 =model.Activity(
    env = my_env,
    name = "Soil movement 4",
    origin = dredging_site,
    destination = discharge_site_2,
    loader = dredging_site,
    mover = barge_2,
    unloader = barge_2,
    start_event = start_event,
    stop_event = None
)
my_env.run()
objects =[dredging_site, discharge_site_1, barge_1, barge_2]
objects.extend([discharge_site_2])
objects.extend([act_1,act_2,act_3,act_4])

activities = []
for obj in objects:
    L = set(obj.log["Message"])
    for l in L:
        if l[-5:] == 'start' and l[:-6] not in activities:
            activities.append(l[:-6])

C = np.linspace(0,255, len(activities))
colors = {}
for i in range(len(activities)):
    colors[i] = f'rgb({int(C[i]/2)},{int(C[len(C) - 1 - i]/1.5)},{int(C[i])})'

plot.vessel_planning(objects, activities, colors)

image

Pietervanhalem commented 4 years ago

With the following code the new feature is included. Witch overwrites "I think it good to point out that with this PR there is a difference between activity.main_proces and simpy.events.(env, [origin.container.empty_event, destination.container.full_event]) . With activity.main_proces this issue still holds. However, I think that is a good thing."

import datetime, time
import simpy
import shapely.geometry
import openclsim.core as core
import openclsim.model as model
import openclsim.plot as plot
import numpy as np
my_env = simpy.Environment(initial_time = time.mktime(datetime.datetime.now().timetuple()))
my_env.epoch = time.mktime(datetime.datetime.now().timetuple())
discharge_site_GC = type(
    'Site', 
    (
        core.Identifiable,
        core.Log,
        core.Locatable,
        core.HasContainer,
        core.HasResource
    ),
    {}
)

dredging_site_GC = type(
    'Site', 
    (
        core.Identifiable,
        core.Log,
        core.Locatable,
        core.HasContainer,
        core.HasResource,
        core.UnloadingFunction,
        core.LoadingFunction,
        core.Processor,
    ),
    {}
)

barge_GC = type(
    "Barge",
    (
        core.Identifiable,
        core.Log,
        core.ContainerDependentMovable,
        core.Processor,
        core.HasResource,
        core.UnloadingFunction,
    ),
    {},
)
def compute_v_provider(v_empty, v_full):
    return lambda x: x * (v_full - v_empty) + v_empty

discharge_site_location_1 = shapely.geometry.Point(4.1, 52)
discharge_site_location_2 = shapely.geometry.Point(4.2, 52)
dredging_site_location = shapely.geometry.Point(4, 52.1)

discharge_site_data_1 = {
    "env": my_env,
    "name": "discharge_site_data_1",
    "geometry": discharge_site_location_1,
    "capacity": 50_000,
    "level": 0
}

discharge_site_data_2 = {
    "env": my_env,
    "name": "discharge_site_data_2",
    "geometry": discharge_site_location_2,
    "capacity": 50_000,
    "level": 0
}

dredging_site_data = {
    "env": my_env,
    "name": "dredging_site_data",
    "geometry": dredging_site_location,
    "capacity": 100_000,
    "level": 100_000,
    "unloading_rate": 1,
    "loading_rate": 1,
}

barge_data = {
    "env": my_env,
    "name": "Hopper 01",
    "geometry": discharge_site_location_1,
    "unloading_rate": 1,
    "capacity": 5_000,
    "compute_v": compute_v_provider(5, 4.5),
}
barge_data_2 = {
    "env": my_env,
    "name": "Hopper 02",
    "geometry": discharge_site_location_1,
    "unloading_rate": 1,
    "capacity": 5_000,
    "compute_v": compute_v_provider(5, 4.5),
}

dredging_site = dredging_site_GC(**dredging_site_data)
discharge_site_1 = discharge_site_GC(**discharge_site_data_1)
discharge_site_2 = discharge_site_GC(**discharge_site_data_2)
barge_1 = barge_GC(**barge_data)
barge_2 = barge_GC(**barge_data_2)
act_1 = model.Activity(
    env = my_env,
    name = "Soil movement 1",
    origin = dredging_site,
    destination = discharge_site_1,
    loader = dredging_site,
    mover = barge_1,
    unloader = barge_1,
    start_event = None,
    stop_event = None
)

act_2 =model.Activity(
    env = my_env,
    name = "Soil movement 2",
    origin = dredging_site,
    destination = discharge_site_1,
    loader = dredging_site,
    mover = barge_2,
    unloader = barge_2,
    start_event = None,
    stop_event = None
)

def start_event(mover, activities):           
    relevant_activities = [act for act in activities if act.mover == mover]
    activity_main_process = [act.main_process for act in relevant_activities]    
    return activity_main_process

act_3 =model.Activity(
    env = my_env,
    name = "Soil movement 3",
    origin = dredging_site,
    destination = discharge_site_2,
    loader = dredging_site,
    mover = barge_1,
    unloader = barge_1,
    start_event = start_event(barge_1, [act_1,act_2]),
    stop_event = None
)

act_4 =model.Activity(
    env = my_env,
    name = "Soil movement 4",
    origin = dredging_site,
    destination = discharge_site_2,
    loader = dredging_site,
    mover = barge_2,
    unloader = barge_2,
    start_event = start_event(barge_1, [act_1,act_2]),
    stop_event = None
)

my_env.run()
objects =[dredging_site, discharge_site_1, barge_1, barge_2]
objects.extend([discharge_site_2])
objects.extend([act_1,act_2,act_3,act_4])

activities = []
for obj in objects:
    L = set(obj.log["Message"])
    for l in L:
        if l[-5:] == 'start' and l[:-6] not in activities:
            activities.append(l[:-6])

C = np.linspace(0,255, len(activities))
colors = {}
for i in range(len(activities)):
    colors[i] = f'rgb({int(C[i]/2)},{int(C[len(C) - 1 - i]/1.5)},{int(C[i])})'

plot.vessel_planning(objects, activities, colors)