diff --git a/src/pypdevs/DEVS.py b/src/pypdevs/DEVS.py index 63646c0..38e6832 100644 --- a/src/pypdevs/DEVS.py +++ b/src/pypdevs/DEVS.py @@ -881,13 +881,76 @@ class ExternalWrapper(AtomicDEVS): # Fake object is created with a single fake port, so unpack that self.f(self.my_input.values()[0]) +def directConnect(component_set, listeners): + """ + Perform direct connection on this CoupledDEVS model + + :param component_set: the iterable to direct connect + :returns: the direct connected component_set + """ + new_list = [] + for i in component_set: + if isinstance(i, CoupledDEVS): + component_set.extend(i.component_set) + else: + # Found an atomic model + new_list.append(i) + component_set = new_list + + # All and only all atomic models are now direct children of this model + listener_keys = set(listeners.keys()) + for i in component_set: + # Remap the output ports + for outport in i.OPorts: + # The new contents of the line + outport.routing_outline = [] + worklist = [(p, outport.z_functions.get(p, None)) + for p in outport.outline] + for outline, z in worklist: + if outline in listener_keys: + # This port is being listened on, so just add it as a fake model + fake_port = Port(is_input=False,name="Fake") + fake_port.host_DEVS = ExternalWrapper(listeners[outline]) + outport.routing_outline.append((fake_port, z)) + # If it is a coupled model, we must expand this model + if isinstance(outline.host_DEVS, CoupledDEVS): + for inline in outline.outline: + # Add it to the current iterating list, so we can just continue + entry = (inline, appendZ(z, outline.z_functions[inline])) + worklist.append(entry) + # If it is a Coupled model, we should just continue + # expanding it and not add it to the finished line + if not isinstance(inline.host_DEVS, CoupledDEVS): + entry = (inline, appendZ(z, outline.z_functions[inline])) + outport.routing_outline.append(entry) + else: + for ol, z in outport.routing_outline: + if ol == outline: + break + else: + # Add to the new line if it isn't already there + # Note that it isn't really mandatory to check for this, + # it is a lot cleaner to do so. + # This will greatly increase the complexity of the connector though + outport.routing_outline.append((outline, z)) + return component_set + def directConnectPort(outport, listeners): + """ + Perform direct connection on a single port. + + :param outpurt: the port to reconnect + :param listeners: the listeners that exist, potentially on this port + :returns: None + """ + # The new contents of the line outport.routing_outline = [] worklist = [(p, outport.z_functions.get(p, None)) for p in outport.outline] + listener_keys = set(listeners.keys()) for outline, z in worklist: - if outline in listeners.keys(): + if outline in listener_keys: # This port is being listened on, so just add it as a fake model fake_port = Port(is_input=False,name="Fake") fake_port.host_DEVS = ExternalWrapper(listeners[outline]) @@ -914,36 +977,3 @@ def directConnectPort(outport, listeners): # it is a lot cleaner to do so. # This will greatly increase the complexity of the connector though outport.routing_outline.append((outline, z)) - -def directConnect(component_set, listeners): - """ - Perform direct connection on this CoupledDEVS model - - :param component_set: the iterable to direct connect - :returns: the direct connected component_set - """ - new_list = [] - # Search for root model - root = component_set[0] - while root.parent is not None: - root = root.parent - - component_set = [root] - for i in component_set: - if isinstance(i, CoupledDEVS): - component_set.extend(i.component_set) - else: - # Found an atomic model - new_list.append(i) - - # Also perform direct connection on all ports of the Coupled DEVS models, should injection ever be wanted - for i in component_set: - # Remap the output ports - for outport in i.OPorts: - directConnectPort(outport, listeners) - - if isinstance(i, CoupledDEVS): - for inport in i.IPorts: - directConnectPort(inport, listeners) - - return new_list diff --git a/src/pypdevs/minimal.py b/src/pypdevs/minimal.py index ca6c5a6..b069948 100644 --- a/src/pypdevs/minimal.py +++ b/src/pypdevs/minimal.py @@ -19,9 +19,7 @@ While it behaves exactly the same as the normal simulation kernel with default o """ from collections import defaultdict -from pypdevs.DEVS import CoupledDEVS, AtomicDEVS, RootDEVS -""" # Uncomment this part to make a completely stand-alone simulation kernel class BaseDEVS(object): def __init__(self, name): @@ -99,10 +97,11 @@ class CoupledDEVS(BaseDEVS): p2.inline.append(p1) class RootDEVS(object): - def __init__(self, components, scheduler): + def __init__(self, components): + from schedulers.schedulerAuto import SchedulerAuto as Scheduler self.component_set = components self.time_next = float('inf') - self.scheduler = scheduler(self.component_set, 1e-6, len(self.component_set)) + self.scheduler = Scheduler(self.component_set, 1e-6, len(self.component_set)) class Port(object): def __init__(self, is_input, name=None): @@ -113,7 +112,6 @@ class Port(object): def getPortname(self): return self.name -""" def directConnect(component_set): """ @@ -171,14 +169,14 @@ class Simulator(object): m.time_next = (-m.elapsed + m.timeAdvance(), 1) m.model_id = ids ids += 1 - self.model = RootDEVS(component_set, component_set, None) + self.model = RootDEVS(component_set) elif isinstance(model, AtomicDEVS): for p in model.OPorts: p.routing_outline = [] model.time_last = (-model.elapsed, 0) model.time_next = (model.time_last[0] + model.timeAdvance(), 1) model.model_id = 0 - self.model = RootDEVS([model], [model], None) + self.model = RootDEVS([model]) self.termination_time = float('inf') def setTerminationTime(self, time): @@ -193,8 +191,7 @@ class Simulator(object): """ Perform the simulation """ - from schedulers.schedulerAuto import SchedulerAuto - scheduler = SchedulerAuto(self.model.component_set, 1e-6, len(self.model.component_set)) + scheduler = self.model.scheduler tn = scheduler.readFirst() tt = self.termination_time while tt > tn[0]: