Я пытаюсь имитировать кучу задач, которые все вместе относятся к одному и тому же родовому проекту.
Задачи имеют длительность и приоритет (представлены списком задач, которые необходимо выполнить перед текущей задачей).Как моделировать приоритет задач?
Например:
/--->A --->B\
Start ---->C------->End
\--->D---->E/
Это означает, что задачи А, С и D могут быть выполнены одновременно, но задача Б должна быть выполнена после того, как задача А, а задача Е после задачи Д.
Я написал этот код:
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import simpy
class Task(object):
"""
Has an id i.e.: 'E',
duration i.e.: 5
a list with Task that precede the current
"""
def __init__(self, idTask, duration, env, previousTasks=None):
self.idTask = idTask
self.duration = duration
self.env = envs
self.completed = env.event()
self.action = env.process(self.run())
if previousTasks is None:
self.previousTasks = []
else:
self.previousTasks = previousTasks
def run(self):
while self.can_execute() and not self.completed.triggered:
print "Starting task %s at time %s" % (self.idTask, self.env.now)
yield self.env.timeout(self.duration)
print "Completed task %s in time %s" % (self.idTask, self.env.now)
self.completed.succeed(True)
def can_execute(self):
result = True
for task in self.previousTasks:
if not task.completed.triggered:
result = False
break
return result
if __name__ == "__main__":
env = simpy.Environment()
taskA = Task('A', 4, env)
taskB = Task('B', 5, env, [taskA])
env.run(until=20)
завершена атрибут в объект Task, это за то, что способ узнать, если текущая задача завершена или закончена. (Я пытался сделать это с помощью логического значения без каких-либо результатов).
taskB имеет taskA как задачу прецедента. Это означает, что taskB должен начаться до завершения Таски, но это выход, когда я запускаю его:
% python tasks.py
Starting task A at time 0
Completed task A at time 4
%
Я не понимаю, почему taskB не мог бежать.
---------------------------------------------- -----------------------------
решаемые
Я использовал "start_delayed" метод, доступный в simpy.util модуль от Simpy. В зависимости от того, выполняется ли текущая задача для выполнения предыдущих задач, «действие» каждой задачи - это простой процесс или отложенный процесс.
Задержка для каждой задачи вычисляется в add_precedences и evaluation_delays, но необходима для суммирования продолжительности предыдущих задач с предыдущей задачей текущего.
Вот окончательный код:
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import simpy
from simpy.util import start_delayed
delays = {}
completed = []
class Task(object):
""" Has an id i.e.: 'E',
duration i.e.: 5
a list with Task that precede the current
"""
def __init__(self, id, duration, env, previousTasks=None):
self.id = id
self.duration = duration
self.env = env
if previousTasks is None:
self.previousTasks = []
else:
self.previousTasks = previousTasks
self.action = None
def run(self):
while True:
if delays[self.id] == self.env.now:
print "Start task: %s at time: %s" % (self.id, self.env.now)
yield self.env.timeout(self.duration)
completed.append(self.id)
print "Finish task: %s at time: %s" % (self.id, self.env.now)
else:
if self.id in completed:
self.env.exit()
def add_precedences(prevTask, durations):
if len(prevTask) == 0:
return 0
else:
durations.extend(map(lambda x: x.duration, prevTask))
for prev in prevTask:
add_precedences(prev.previousTasks, durations)
return sum(durations)
def estimate_delays(tasks):
result = {}
for task in tasks:
durations = []
total = (add_precedences(task.previousTasks, durations))
result.update({task.id: total})
return result
def set_action(tasks):
for task in tasks:
if delays[task.id] > 0:
task.action = start_delayed(task.env, task.run(), delays[task.id])
else:
task.action = env.process(task.run())
if __name__ == '__main__':
env = simpy.Environment()
taskA = Task('A', 4, env)
taskB = Task('B', 5, env, previousTasks=[taskA])
taskC = Task('C', 2, env, previousTasks=[taskB])
tasks = [taskA, taskB, taskC]
delays.update(estimate_delays(tasks))
set_action(tasks)
env.run(until=20)
В этом случае проект имеет 3 задачи ('A', 'B', 'C') и вот дерево:
Start --->A--->B--->C--->End
B должен начинаться со временем: 4 (потому что это продолжительность A). И C, должен начинаться со временем: 9 (потому что это продолжительность B + A).
Чтобы узнать, какая задача уже завершена, я создал список, в котором каждая задача добавляет свой собственный идентификатор. Если его собственный идентификатор находится в этом списке, каждая задача удаляется из среды.
Небольшой комментарий к вашему коду: вы не должны использовать [изменяемые аргументы по умолчанию] (http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default- аргумент), они могут привести к неожиданностям. Чаще всего используется что-то вроде 'def __init __ (..., previousTasks = None): если previousTasks - None: previousTasks = []'. –
Вы правы, я отредактирую это прямо сейчас, спасибо! – pazitos10