2

同じ汎用プロジェクトに属する一連のタスクをシミュレートしようとしています。
タスクには期間と優先順位があります (現在のタスクの前に実行する必要があるタスクのリストによって表されます)。

例えば:

      /--->A --->B\
Start ---->C------->End
      \--->D---->E/

つまり、タスク A、C、D は同時に実行できますが、タスク B はタスク A の後に実行し、タスク 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 オブジェクトの Completed 属性は、現在のタスクが完了したか終了したかを知るためのものです。(ブール値を使用してこれを実行しようとしましたが、異なる結果はありませんでした。)

taskB には先行タスクとして taskA があります。つまり、taskB は taskA が終了する前に開始する必要がありますが、これを実行したときの出力は次のとおりです。

% python tasks.py
Starting task A at time 0
Completed task A at time 4
%

taskB が実行できなかった理由がわかりません。

-------------------------------------------------- -------------------------

解決した

Simpy の simpy.util モジュールで利用可能な「start_delayed」メソッドを使用しました。現在のタスクに実行する前のタスクがあるかどうかに応じて、各タスクの「アクション」は単純なプロセスまたは遅延プロセスになります。
各タスクの遅延は、add_precedences および Estimate_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 の持続時間であるため)。
どのタスクが既に終了しているかを知るために、各タスクが独自の ID を追加するリストを作成しました。独自の ID がそのリストにある場合、各タスクは環境から削除されます。

4

1 に答える 1

1

コメントとしてこれを行う必要がありますが、そうする評判がありません。それにもかかわらず、私はそれがあなたの問題に役立つかもしれないと思います.

私はsimpyに精通していませんが、タスク B の実行を許可していないトリガー処理を混同している可能性があります。このリンクを確認してください: http://simpy.readthedocs.org/en/latest/api_reference/simpy.events.html#module-simpy.events

于 2015-05-09T22:41:15.623 に答える