Updated DirectConnect algorithm and minimal simulation algorithm
This commit is contained in:
parent
8fa7d4aff0
commit
8d4a173c11
2 changed files with 70 additions and 43 deletions
|
|
@ -881,13 +881,76 @@ class ExternalWrapper(AtomicDEVS):
|
||||||
# Fake object is created with a single fake port, so unpack that
|
# Fake object is created with a single fake port, so unpack that
|
||||||
self.f(self.my_input.values()[0])
|
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):
|
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
|
# The new contents of the line
|
||||||
outport.routing_outline = []
|
outport.routing_outline = []
|
||||||
worklist = [(p, outport.z_functions.get(p, None))
|
worklist = [(p, outport.z_functions.get(p, None))
|
||||||
for p in outport.outline]
|
for p in outport.outline]
|
||||||
|
listener_keys = set(listeners.keys())
|
||||||
for outline, z in worklist:
|
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
|
# This port is being listened on, so just add it as a fake model
|
||||||
fake_port = Port(is_input=False,name="Fake")
|
fake_port = Port(is_input=False,name="Fake")
|
||||||
fake_port.host_DEVS = ExternalWrapper(listeners[outline])
|
fake_port.host_DEVS = ExternalWrapper(listeners[outline])
|
||||||
|
|
@ -914,36 +977,3 @@ def directConnectPort(outport, listeners):
|
||||||
# it is a lot cleaner to do so.
|
# it is a lot cleaner to do so.
|
||||||
# This will greatly increase the complexity of the connector though
|
# This will greatly increase the complexity of the connector though
|
||||||
outport.routing_outline.append((outline, z))
|
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
|
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,7 @@ While it behaves exactly the same as the normal simulation kernel with default o
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from pypdevs.DEVS import CoupledDEVS, AtomicDEVS, RootDEVS
|
|
||||||
|
|
||||||
"""
|
|
||||||
# Uncomment this part to make a completely stand-alone simulation kernel
|
# Uncomment this part to make a completely stand-alone simulation kernel
|
||||||
class BaseDEVS(object):
|
class BaseDEVS(object):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
|
|
@ -99,10 +97,11 @@ class CoupledDEVS(BaseDEVS):
|
||||||
p2.inline.append(p1)
|
p2.inline.append(p1)
|
||||||
|
|
||||||
class RootDEVS(object):
|
class RootDEVS(object):
|
||||||
def __init__(self, components, scheduler):
|
def __init__(self, components):
|
||||||
|
from schedulers.schedulerAuto import SchedulerAuto as Scheduler
|
||||||
self.component_set = components
|
self.component_set = components
|
||||||
self.time_next = float('inf')
|
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):
|
class Port(object):
|
||||||
def __init__(self, is_input, name=None):
|
def __init__(self, is_input, name=None):
|
||||||
|
|
@ -113,7 +112,6 @@ class Port(object):
|
||||||
|
|
||||||
def getPortname(self):
|
def getPortname(self):
|
||||||
return self.name
|
return self.name
|
||||||
"""
|
|
||||||
|
|
||||||
def directConnect(component_set):
|
def directConnect(component_set):
|
||||||
"""
|
"""
|
||||||
|
|
@ -171,14 +169,14 @@ class Simulator(object):
|
||||||
m.time_next = (-m.elapsed + m.timeAdvance(), 1)
|
m.time_next = (-m.elapsed + m.timeAdvance(), 1)
|
||||||
m.model_id = ids
|
m.model_id = ids
|
||||||
ids += 1
|
ids += 1
|
||||||
self.model = RootDEVS(component_set, component_set, None)
|
self.model = RootDEVS(component_set)
|
||||||
elif isinstance(model, AtomicDEVS):
|
elif isinstance(model, AtomicDEVS):
|
||||||
for p in model.OPorts:
|
for p in model.OPorts:
|
||||||
p.routing_outline = []
|
p.routing_outline = []
|
||||||
model.time_last = (-model.elapsed, 0)
|
model.time_last = (-model.elapsed, 0)
|
||||||
model.time_next = (model.time_last[0] + model.timeAdvance(), 1)
|
model.time_next = (model.time_last[0] + model.timeAdvance(), 1)
|
||||||
model.model_id = 0
|
model.model_id = 0
|
||||||
self.model = RootDEVS([model], [model], None)
|
self.model = RootDEVS([model])
|
||||||
self.termination_time = float('inf')
|
self.termination_time = float('inf')
|
||||||
|
|
||||||
def setTerminationTime(self, time):
|
def setTerminationTime(self, time):
|
||||||
|
|
@ -193,8 +191,7 @@ class Simulator(object):
|
||||||
"""
|
"""
|
||||||
Perform the simulation
|
Perform the simulation
|
||||||
"""
|
"""
|
||||||
from schedulers.schedulerAuto import SchedulerAuto
|
scheduler = self.model.scheduler
|
||||||
scheduler = SchedulerAuto(self.model.component_set, 1e-6, len(self.model.component_set))
|
|
||||||
tn = scheduler.readFirst()
|
tn = scheduler.readFirst()
|
||||||
tt = self.termination_time
|
tt = self.termination_time
|
||||||
while tt > tn[0]:
|
while tt > tn[0]:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue