A restricted PythonPDEVS simulator modelled in SCCD for classic, dynamic structure DEVS models. import cPickle as pickle import time # We basically just interface with the basesimulator from scheduler import Scheduler from DEVS import directConnect, CoupledDEVS, AtomicDEVS, RootDEVS from classicDEVSWrapper import ClassicDEVSWrapper from tracer import trace class Breakpoint(object): def __init__(self, breakpoint_id, function, enabled, disable_on_trigger): self.id = breakpoint_id self.function = function self.enabled = enabled self.disable_on_trigger = disable_on_trigger continue simulation # -1 --> termination condition # else --> breakpoint if realtime: check_time = self.simulation_time else: self.compute_timeNext() check_time = self.time_next # Just access the 'transitioned' dictionary # Kind of dirty though... if self.transitioning is None: transitioned = set() else: transitioned = set(self.transitioning.keys()) if check_time[0] == float('inf'): # Always terminate if we have reached infinity terminate = True elif self.termination_condition is not None: terminate = self.termination_condition(check_time, self.root_model, transitioned) else: terminate = self.termination_time < check_time[0] if terminate: # Always terminate, so don't check breakpoints return -1 else: # Have to check breakpoints for termination for bp in self.breakpoints: if not bp.enabled: continue # Include the function in the scope exec(bp.function) # And execute it, note that the breakpoint thus has to start with "def breakpoint(" if breakpoint(check_time, self.root_model, transitioned): # Triggered! return bp.id else: # Not triggered, so continue continue return -2 ]]> 1: # Perform all selects self.imminents.sort() pending = self.imminents level = 1 while len(pending) > 1: # Take the model each time, as we need to make sure that the selectHierarchy is valid everywhere model = pending[0] # Make a set first to remove duplicates colliding = list(set([m.select_hierarchy[level] for m in pending])) chosen = model.select_hierarchy[level-1].select( sorted(colliding, key=lambda i:i.getModelFullName())) pending = [m for m in pending if m.select_hierarchy[level] == chosen] level += 1 self.imminent = pending[0] else: self.imminent = self.imminents[0] self.imminent.time_next = (self.imminent.time_next[0], self.imminent.time_next[1] - 1) ]]> self.simulation_time: break config = self.inject_queue.pop(0) portname = config["port"] event = config["event"] port = self.find_port_with_name(portname) self.inbags.setdefault(port, []).append(event) ]]> internal transition # 2 --> external transition # 3 --> confluent transition # These codes are a legacy of efficient PyPDEVS, but is kept here for consistency self.transitioning = {self.imminent: 1} for inport in self.inbags: aDEVS = inport.host_DEVS aDEVS.my_input[inport] = self.inbags[inport] self.transitioning[aDEVS] = 2 self.reschedule.add(aDEVS) self.transitioning = {ClassicDEVSWrapper(m): self.transitioning[m] for m in self.transitioning} ]]> 0: self.time_next = min(model_timeNext, self.inject_queue[0]["time"]) else: self.time_next = model_timeNext ]]> 0 else (0.0, 0) ]]>