Skip to content

Commit

Permalink
Zones in the end, Parallel SGS fixes (#63)
Browse files Browse the repository at this point in the history
Added zone status control in the end of the project. Now we can specify it.
Additionally, fixed Parallel SGS ugly computation time.
  • Loading branch information
StannisMod authored Nov 15, 2023
1 parent cbf55f1 commit d33fa22
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 20 deletions.
3 changes: 3 additions & 0 deletions sampo/scheduler/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ def build_scheduler(self,
start_time = assigned_parent_time
finish_time += start_time

if index == len(ordered_nodes) - 1: # we are scheduling the work `end of the project`
start_time = max(start_time, timeline.zone_timeline.finish_statuses())

# apply work to scheduling
timeline.schedule(node, node2swork, best_worker_team, contractor, work_spec,
start_time, work_spec.assigned_time, assigned_parent_time, work_estimator)
Expand Down
23 changes: 8 additions & 15 deletions sampo/scheduler/genetic/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from sampo.schemas.schedule_spec import ScheduleSpec
from sampo.schemas.time import Time
from sampo.schemas.time_estimator import WorkTimeEstimator, DefaultWorkEstimator
from sampo.schemas.zones import Zone
from sampo.utilities.linked_list import LinkedList

ChromosomeType = tuple[np.ndarray, np.ndarray, np.ndarray, ScheduleSpec, np.ndarray]
Expand Down Expand Up @@ -105,7 +106,7 @@ def convert_chromosome_to_schedule(chromosome: ChromosomeType,
for worker_index in worker_pool:
for contractor_index in worker_pool[worker_index]:
worker_pool[worker_index][contractor_index].with_count(border[contractor2index[contractor_index],
worker_name2index[worker_index]])
worker_name2index[worker_index]])

if not isinstance(timeline, JustInTimeTimeline):
timeline = JustInTimeTimeline(worker_pool, landscape)
Expand Down Expand Up @@ -152,22 +153,14 @@ def work_scheduled(args) -> bool:
if idx == 0: # we are scheduling the work `start of the project`
st = assigned_parent_time # this work should always have st = 0, so we just re-assign it

if idx == len(works_order) - 1: # we are scheduling the work `end of the project`
st = max(st, timeline.zone_timeline.finish_statuses())

# finish using time spec
ft = timeline.schedule(node, node2swork, worker_team, contractor, work_spec,
st, exec_time, assigned_parent_time, work_estimator)
timeline.schedule(node, node2swork, worker_team, contractor, work_spec,
st, exec_time, assigned_parent_time, work_estimator)

work_timeline.update_timeline(st, exec_time, None)

# process zones
zone_reqs = [ZoneReq(index2zone[i], zone_status) for i, zone_status in enumerate(zone_statuses[work_idx])]
zone_start_time = timeline.zone_timeline.find_min_start_time(zone_reqs, ft, 0)

# we should deny scheduling
# if zone status change can be scheduled only in delayed manner
if zone_start_time != ft:
node2swork[node].zones_post = timeline.zone_timeline.update_timeline(idx,
[z.to_zone() for z in zone_reqs],
zone_start_time, 0)
return True
return False

Expand All @@ -181,7 +174,7 @@ def work_scheduled(args) -> bool:
else:
start_time += 1

# find all works that can start at start_time moment
# find all works that can start at start_time moment and remove it if scheduled
enumerated_works_remaining.remove_if(work_scheduled)
cpkt_idx = min(cpkt_idx + 1, len(work_timeline))

Expand Down
24 changes: 23 additions & 1 deletion sampo/scheduler/timeline/zone_timeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,31 @@ def update_timeline(self, index: int, zones: list[Zone], start_time: Time, exec_

if start_status != zone.status and zone.status != 0:
# if we need to change status, record it
sworks.append(ZoneTransition(name=f'Access card {zone.name} status: {start_status} -> {zone.status}',
sworks.append(ZoneTransition(name=zone.name,
from_status=start_status,
to_status=zone.status,
start_time=start_time - change_cost,
end_time=start_time))
return sworks

def append_statuses(self, zones: list[Zone]) -> Time:
global_finish_time = Time(0)

for zone in zones:
state = self._timeline[zone.name]
latest_time = state[-1].time + 1
latest_status = state[-1].available_workers_time
change_cost = self._config.time_costs[latest_status, zone.status] \
if not self._config.statuses.match_status(latest_status, zone.status) \
else 0
finish_time = latest_time + change_cost

state.add(ScheduleEvent(Time.inf().value, EventType.START, latest_time, None, zone.status))
state.add(ScheduleEvent(Time.inf().value, EventType.END, finish_time, None, zone.status))

global_finish_time = max(global_finish_time, finish_time)

return global_finish_time

def finish_statuses(self) -> Time:
return self.append_statuses([Zone(*v) for v in self._config.end_statuses])
4 changes: 4 additions & 0 deletions sampo/schemas/zones.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def match_status(self, status_to_check: int, required_status: int) -> bool:
@dataclass
class ZoneConfiguration:
start_statuses: dict[str, int] = field(default_factory=dict)
end_statuses: dict[str, int] = field(default_factory=dict)
time_costs: np.ndarray = field(default_factory=lambda: np.array([[]]))
statuses: ZoneStatuses = field(default_factory=lambda: DefaultZoneStatuses())

Expand All @@ -60,3 +61,6 @@ class ZoneTransition(AutoJSONSerializable['ZoneTransition']):
to_status: int
start_time: Time
end_time: Time

def __str__(self):
return f'Access card {self.name} status {self.from_status} -> {self.to_status}'
7 changes: 3 additions & 4 deletions sampo/utilities/linked_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ def __init__(self, lst: 'LinkedList'):
self._prev = None

def __iter__(self):
yield self._node

while self._node is not None:
yield self.__next__()
while self._node.next is not None:
yield self._node
self.__next__()

def __next__(self) -> Node[T]:
return self.next()
Expand Down

0 comments on commit d33fa22

Please sign in to comment.