Skip to content

Commit

Permalink
Merge pull request #82 from TUDelft-CITG/release/version_1.2.0
Browse files Browse the repository at this point in the history
Release/version 1.2.0
  • Loading branch information
markvankoningsveld committed Jan 27, 2020
2 parents 2452edc + f69fa4e commit 253b135
Show file tree
Hide file tree
Showing 7 changed files with 454 additions and 159 deletions.
12 changes: 12 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@
History
=======

1.2.0 (2020-01-27)
------------------

* Major updates to the Movable class
* You can now enter multiple origins and destinations in one activity
* Optimisation of the schedule is possible by enhanding the Movable

1.1.1 (2019-12-11)
------------------

* Minor bug fixes

1.1.0 (2019-08-30)
------------------

Expand Down
2 changes: 1 addition & 1 deletion openclsim/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

__author__ = """Mark van Koningsveld"""
__email__ = "M.vanKoningsveld@tudelft.nl"
__version__ = "1.1.0"
__version__ = "1.2.0"
118 changes: 112 additions & 6 deletions openclsim/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import json
import logging
import uuid
import itertools

# you need these dependencies (you can get these from anaconda)
# package(s) related to the simulation
Expand Down Expand Up @@ -1248,6 +1249,7 @@ def sailing_duration(self, origin, destination, engine_order, verbose=True):
return distance / (self.current_speed * engine_order)

def energy_use(self, distance, speed):
""" Determine the energy use """
if isinstance(self, EnergyUse):
# message depends on filling degree: if container is empty --> sailing empt
if not isinstance(self, HasContainer) or self.container.level == 0:
Expand Down Expand Up @@ -1278,6 +1280,112 @@ def __init__(self, compute_v, *args, **kwargs):
def current_speed(self):
return self.compute_v(self.container.level / self.container.capacity)

def determine_amount(self, origins, destinations, loader, unloader, filling=1):
""" Determine the maximum amount that can be carried """

# Determine the basic amount that should be transported
all_amounts = {}
all_amounts.update(
{
"origin." + origin.id: origin.container.expected_level
for origin in origins
}
)
all_amounts.update(
{
"destination."
+ destination.id: destination.container.capacity
- destination.container.expected_level
for destination in destinations
}
)

origin_requested = 0
destination_requested = 0

for key in all_amounts.keys():
if "origin." in key:
origin_requested += all_amounts[key]
else:
destination_requested += all_amounts[key]

amount = min(
self.container.capacity * filling - self.container.level,
origin_requested,
destination_requested,
)

# If the mover has a function to optimize its load, check if the amount should be changed
if not hasattr(self, "check_optimal_filling"):
return amount, all_amounts

else:
amounts = [amount]
amounts.extend(
[
self.check_optimal_filling(loader, unloader, origin, destination)
for origin, destination in itertools.product(origins, destinations)
]
)

return min(amounts), all_amounts

def determine_schedule(self, amount, all_amounts, origins, destinations):
"""
Define a strategy for passing through the origins and destinations
Implemented is FIFO: First origins will start and first destinations will start.
"""
self.vrachtbrief = {"Type": [], "ID": [], "Priority": [], "Amount": []}

def update_vrachtbrief(typestring, id, priority, amount):
""" Update the vrachtbrief """

self.vrachtbrief["Type"].append(typestring)
self.vrachtbrief["ID"].append(id)
self.vrachtbrief["Priority"].append(priority)
self.vrachtbrief["Amount"].append(amount)

to_retrieve = 0
to_place = 0

# reserve the amount in origin an destination
for origin in origins:
if all_amounts["origin." + origin.id] == 0:
continue
elif all_amounts["origin." + origin.id] <= amount - to_retrieve:
to_retrieve += all_amounts["origin." + origin.id]
origin.container.reserve_get(all_amounts["origin." + origin.id])
update_vrachtbrief(
"Origin", origin, 1, all_amounts["origin." + origin.id]
)

else:
origin.container.reserve_get(amount - to_retrieve)
update_vrachtbrief("Origin", origin, 1, amount - to_retrieve)
break

for destination in destinations:
if all_amounts["destination." + destination.id] == 0:
continue
elif all_amounts["destination." + destination.id] <= amount - to_place:
to_place += all_amounts["destination." + destination.id]
destination.container.reserve_put(
all_amounts["destination." + destination.id]
)
update_vrachtbrief(
"Destination",
destination,
1,
all_amounts["destination." + destination.id],
)

else:
destination.container.reserve_put(amount - to_place)
update_vrachtbrief("Destination", destination, 1, amount - to_place)
break

return pd.DataFrame.from_dict(self.vrachtbrief).sort_values("Priority")


class Routeable(Movable):
"""
Expand All @@ -1298,9 +1406,8 @@ def determine_route(self, origin, destination):
geom = nx.get_node_attributes(self.env.FG, "geometry")

for node in geom.keys():
if (
np.isclose(origin.x,geom[node].x,rtol = 1e-8)
and np.isclose(origin.y,geom[node].y,rtol = 1e-8)
if np.isclose(origin.x, geom[node].x, rtol=1e-8) and np.isclose(
origin.y, geom[node].y, rtol=1e-8
):
origin = node
break
Expand Down Expand Up @@ -1388,16 +1495,15 @@ def log_energy_use(self, energy):
)


class ContainerDependentRouteable(Routeable, HasContainer):
class ContainerDependentRouteable(ContainerDependentMovable, Routeable):
"""ContainerDependentRouteable class
Used for objects that move with a speed dependent on the container level
compute_v: a function, given the fraction the container is filled (in [0,1]), returns the current speed"""

def __init__(self, compute_v, *args, **kwargs):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
"""Initialization"""
self.compute_v = compute_v

@property
def current_speed(self):
Expand Down

0 comments on commit 253b135

Please sign in to comment.