2016-04-06 5 views
1

Ich möchte eine Wartungsplanungssimulation für diskrete Ereignisse implementieren, bei der einige Wartungsaktivitäten stattfinden müssen, wenn eine andere auftritt.So teilen Sie abhängige Ereignisse in SimPy auf

Wenn zum Beispiel die Wände alle 5 Jahre neu gestrichen werden und der Trockenbau alle 14 Jahre erneuert wird, müssen die Wände neu gestrichen werden, wenn der Trockenbau ersetzt und die Uhr neu gestartet wird.

yr 5: paint walls 
yr 10: paint walls 
yr 14: replace dry-lining 
yr 14: paint walls 
yr 19: paint walls 
... 

Ich bin nicht sicher, ob ich jede Aktivität als Prozess implementieren sollte, die mit dem abhängigen Prozess bezieht, oder wenn „Wand Wartung“ sollte ein Prozess mit der intern oder auf anderer Weise von gehandhabt Logik sein.

Der Code, den ich habe, hat jede Aktivität als einen Prozess mit dem abhängigen Prozess als Attribut gespeichert, aber ich fühle mich wie ich vermisse die richtige Art und Weise dies zu tun, wie ich Ereignisse zweimal im selben Jahr passieren sehen.

Antwort

0

Dies ist der Ansatz, den ich am Ende nahm:

import simpy 
from simpy.events import Interrupt 


class Construction(object): 

    def __init__(self, name, components): 
     self.name = name 
     self.components = components 
     self.link_components() 

    def link_components(self): 
     """Link each component to the next outermost component  
     """ 
     for i, component in enumerate(self.components): 
      try: 
       component.dependent = self.components[i+1] 
      except IndexError: 
       component.dependent = None     

class Component(object): 

    def __init__(self, env, name, lifespan): 
     """Represents a component used in a construction. 

     """ 
     self.env = env 
     self.name = name 
     self.lifespan = lifespan  
     self.action = env.process(self.run()) 

    def run(self): 
     while True: 
      try: 
       yield self.env.timeout(self.lifespan) 
       self.replace() 
      except Interrupt: # don't replace 
       pass 

    def replace(self): 
     print "yr %d: replace %s" % (env.now, self.name) 
     if self.dependent: 
      self.dependent.action.interrupt() # stop the dependent process 
      self.dependent.replace() # replace the dependent component 


env = simpy.Environment() 
components = [Component(env, 'structure', 60), 
       Component(env, 'dry-lining', 14), 
       Component(env, 'paint', 5)] 
wall = Construction('wall', components) 
env.run(until=65) 
1

Sie sollten immer mit einer sehr einfachen (und falsch) Umsetzung beginnen nur ein besseres Verständnis für Ihren Anwendungsfall zu bekommen und ein Gefühl wie alles Werke, zum Beispiel:

import simpy 


def paint_walls(env, interval): 
    while True: 
     yield env.timeout(interval) 
     print('yr %2d: paint walls' % env.now) 


def replace_dry_lining(env, interval): 
    while True: 
     yield env.timeout(interval) 
     print('yr %d: replace dry-lining' % env.now) 


env = simpy.Environment() 
env.process(paint_walls(env, interval=5)) 
env.process(replace_dry_lining(env, interval=14)) 
env.run(until=20) 

Ausgang:

yr 5: paint walls 
yr 10: paint walls 
yr 14: replace dry-lining 
yr 15: paint walls 

Dann können Sie mit der Erweiterung/Änderung Ihrer Simulation beginnen. Hier sind zwei Möglichkeiten, wie Sie Ihr Problem modelliert werden kann:

Variante A

Wir halten mit zwei getrennten Prozessen, sondern brauchen eine Möglichkeit, die Veranstaltung zum Austausch zwischen ihnen „Trockenfutter ersetzt“, so dass wir auch malen die Wand:

import simpy 


class Maintenance: 
    PAINT_WALL_INTERVAL = 5 
    REPLACE_DRY_LINING_INTERVAL= 14 

    def __init__(self, env): 
     self.env = env 
     self.dry_lining_replaced = env.event() 

     self.p_paint_walls = env.process(self.paint_walls()) 
     self.p_replace_dry_lining = env.process(self.replace_dry_lining()) 

    def paint_walls(self): 
     timeout = self.PAINT_WALL_INTERVAL 
     while True: 
      yield self.env.timeout(timeout) | self.dry_lining_replaced 
      print('yr %2d: paint walls' % self.env.now) 

    def replace_dry_lining(self): 
     timeout = self.REPLACE_DRY_LINING_INTERVAL 
     while True: 
      yield self.env.timeout(timeout) 
      print('yr %2d: replace dry-lining' % self.env.now) 
      self.dry_lining_replaced.succeed() 
      self.dry_lining_replaced = self.env.event() 


env = simpy.Environment() 
m = Maintenance(env) 
env.run(until=20) 

Ausgang:

yr 5: paint walls 
yr 10: paint walls 
yr 14: replace dry-lining 
yr 14: paint walls 
yr 19: paint walls 

Variante B

Wir können es auch mit nur ein Prozessmodell, das entweder wartet eine „malen Wände“ oder ein „ersetzen Trockenfutter“ event:

import simpy 


def maintenance(env): 
    PAINT_WALL_INTERVAL = 5 
    REPLACE_DRY_LINING_INTERVAL = 14 

    paint_wall = env.timeout(PAINT_WALL_INTERVAL) 
    replace_dry_lining = env.timeout(REPLACE_DRY_LINING_INTERVAL) 

    while True: 
     results = yield paint_wall | replace_dry_lining 
     do_paint = paint_wall in results 
     do_replace = replace_dry_lining in results 

     if do_replace: 
      print('yr %2d: replace dry-lining' % env.now) 
      replace_dry_lining = env.timeout(REPLACE_DRY_LINING_INTERVAL) 

     if do_paint or do_replace: 
      print('yr %2d: paint walls' % env.now) 
      paint_wall = env.timeout(PAINT_WALL_INTERVAL) 


env = simpy.Environment() 
env.process(maintenance(env)) 
env.run(until=20) 

Ausgang:

yr 5: paint walls 
yr 10: paint walls 
yr 14: replace dry-lining 
yr 14: paint walls 
yr 19: paint walls 
+0

Vielen Dank für Dies. Gibt es einen Grund, warum die Antwort falsch ist? Der Grund, warum ich dabei war, ist, dass ich mehrere abhängige Aktivitäten zusammen "ketten" kann, wobei jeder nur den nächsten in der Kette kennen muss. –

+0

Es gibt zu wenig Code, um das zu beantworten. :) –

+0

Wahr! Ich habe jetzt ein vollständigeres Beispiel hinzugefügt. –

Verwandte Themen