Initial commit

This commit is contained in:
Yentl Van Tendeloo 2016-08-04 17:38:43 +02:00
commit 66a6860316
407 changed files with 1254365 additions and 0 deletions

View file

@ -0,0 +1,75 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Import code for model simulation:
from pypdevs.simulator import Simulator
# Import the model to be simulated
from model import TrafficSystem
# ======================================================================
# 1. Instantiate the (Coupled or Atomic) DEVS at the root of the
# hierarchical model. This effectively instantiates the whole model
# thanks to the recursion in the DEVS model constructors (__init__).
#
trafficSystem = TrafficSystem(name="trafficSystem")
# ======================================================================
# 2. Link the model to a DEVS Simulator:
# i.e., create an instance of the 'Simulator' class,
# using the model as a parameter.
sim = Simulator(trafficSystem)
# ======================================================================
# 3. Perform all necessary configurations, the most commonly used are:
# A. Termination time (or termination condition)
# Using a termination condition will execute a provided function at
# every simulation step, making it possible to check for certain states
# being reached.
# It should return True to stop simulation, or Falso to continue.
def terminate_whenStateIsReached(clock, model):
return model.trafficLight.state.get() == "manual"
sim.setTerminationCondition(terminate_whenStateIsReached)
# A termination time is prefered over a termination condition,
# as it is much simpler to use.
# e.g. to simulate until simulation time 400.0 is reached
sim.setTerminationTime(400.0)
# B. Set the use of a tracer to show what happened during the simulation run
# Both writing to stdout or file is possible:
# pass None for stdout, or a filename for writing to that file
sim.setVerbose(None)
# C. Use Classic DEVS instead of Parallel DEVS
# If your model uses Classic DEVS, this configuration MUST be set as
# otherwise errors are guaranteed to happen.
# Without this option, events will be remapped and the select function
# will never be called.
sim.setClassicDEVS()
# ======================================================================
# 4. Simulate the model
sim.simulate()
# ======================================================================
# 5. (optional) Extract data from the simulated model
print("Simulation terminated with traffic light in state %s" % (trafficSystem.trafficLight.state.get()))

View file

@ -0,0 +1,296 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
# Import code for DEVS model representation:
from pypdevs.DEVS import *
from pypdevs.infinity import INFINITY
class TrafficLightMode:
"""
Encapsulates the system's state
"""
def __init__(self, current="red"):
"""
Constructor (parameterizable).
"""
self.set(current)
def set(self, value="red"):
self.__colour=value
def get(self):
return self.__colour
def __str__(self):
return self.get()
class TrafficLight(AtomicDEVS):
"""
A traffic light
"""
def __init__(self, name=None):
"""
Constructor (parameterizable).
"""
# Always call parent class' constructor FIRST:
AtomicDEVS.__init__(self, name)
# STATE:
# Define 'state' attribute (initial sate):
self.state = TrafficLightMode("red")
# ELAPSED TIME:
# Initialize 'elapsed time' attribute if required
# (by default, value is 0.0):
self.elapsed = 1.5
# with elapsed time initially 1.5 and initially in
# state "red", which has a time advance of 60,
# there are 60-1.5 = 58.5time-units remaining until the first
# internal transition
# PORTS:
# Declare as many input and output ports as desired
# (usually store returned references in local variables):
self.INTERRUPT = self.addInPort(name="INTERRUPT")
self.OBSERVED = self.addOutPort(name="OBSERVED")
def extTransition(self, inputs):
"""
External Transition Function.
"""
# Compute the new state 'Snew' based (typically) on current
# State, Elapsed time parameters and calls to 'self.peek(self.IN)'.
input = inputs.get(self.INTERRUPT)
state = self.state.get()
if input == "toManual":
if state == "manual":
# staying in manual mode
return TrafficLightMode("manual")
elif state in ("red", "green", "yellow"):
return TrafficLightMode("manual")
elif input == "toAutonomous":
if state == "manual":
return TrafficLightMode("red")
elif state in ("red", "green", "yellow"):
# If toAutonomous is given while still autonomous, just stay in this state
return self.state
raise DEVSException(\
"unknown state <%s> in TrafficLight external transition function"\
% state)
def intTransition(self):
"""
Internal Transition Function.
"""
state = self.state.get()
if state == "red":
return TrafficLightMode("green")
elif state == "green":
return TrafficLightMode("yellow")
elif state == "yellow":
return TrafficLightMode("red")
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight internal transition function"\
% state)
def outputFnc(self):
"""
Output Funtion.
"""
# A colourblind observer sees "grey" instead of "red" or "green".
# BEWARE: ouput is based on the OLD state
# and is produced BEFORE making the transition.
# We'll encode an "observation" of the state the
# system will transition to !
# Send messages (events) to a subset of the atomic-DEVS'
# output ports by means of the 'poke' method, i.e.:
# The content of the messages is based (typically) on current State.
state = self.state.get()
if state == "red":
return {self.OBSERVED: "grey"}
elif state == "green":
return {self.OBSERVED: "yellow"}
elif state == "yellow":
return {self.OBSERVED: "grey"}
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight external transition function"\
% state)
def timeAdvance(self):
"""
Time-Advance Function.
"""
# Compute 'ta', the time to the next scheduled internal transition,
# based (typically) on current State.
state = self.state.get()
if state == "red":
return 60
elif state == "green":
return 50
elif state == "yellow":
return 10
elif state == "manual":
return INFINITY
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight time advance transition function"\
% state)
class PolicemanMode:
"""
Encapsulates the Policeman's state
"""
def __init__(self, current="idle"):
"""
Constructor (parameterizable).
"""
self.set(current)
def set(self, value="idle"):
self.__mode=value
def get(self):
return self.__mode
def __str__(self):
return self.get()
class Policeman(AtomicDEVS):
"""
A policeman producing "toManual" and "toAutonomous" events:
"toManual" when going from "idle" to "working" mode
"toAutonomous" when going from "working" to "idle" mode
"""
def __init__(self, name=None):
"""
Constructor (parameterizable).
"""
# Always call parent class' constructor FIRST:
AtomicDEVS.__init__(self, name)
# STATE:
# Define 'state' attribute (initial sate):
self.state = PolicemanMode("idle")
# ELAPSED TIME:
# Initialize 'elapsed time' attribute if required
# (by default, value is 0.0):
self.elapsed = 0
# PORTS:
# Declare as many input and output ports as desired
# (usually store returned references in local variables):
self.OUT = self.addOutPort(name="OUT")
def intTransition(self):
"""
Internal Transition Function.
The policeman works forever, so only one mode.
"""
state = self.state.get()
if state == "idle":
return PolicemanMode("working")
elif state == "working":
return PolicemanMode("idle")
else:
raise DEVSException(\
"unknown state <%s> in Policeman internal transition function"\
% state)
def outputFnc(self):
"""
Output Funtion.
"""
# Send messages (events) to a subset of the atomic-DEVS'
# output ports by means of the 'poke' method, i.e.:
# The content of the messages is based (typically) on current State.
state = self.state.get()
if state == "idle":
return {self.OUT: "toManual"}
elif state == "working":
return {self.OUT: "toAutonomous"}
else:
raise DEVSException(\
"unknown state <%s> in Policeman output function"\
% state)
def timeAdvance(self):
"""
Time-Advance Function.
"""
# Compute 'ta', the time to the next scheduled internal transition,
# based (typically) on current State.
state = self.state.get()
if state == "idle":
return 200
elif state == "working":
return 100
else:
raise DEVSException(\
"unknown state <%s> in Policeman time advance function"\
% state)
class TrafficSystem(CoupledDEVS):
def __init__(self, name=None):
"""
A simple traffic system consisting of a Policeman and a TrafficLight.
"""
# Always call parent class' constructor FIRST:
CoupledDEVS.__init__(self, name)
# Declare the coupled model's output ports:
# Autonomous, so no output ports
# Declare the coupled model's sub-models:
# The Policeman generating interrupts
self.policeman = self.addSubModel(Policeman(name="policeman"))
# The TrafficLight
self.trafficLight = self.addSubModel(TrafficLight(name="trafficLight"))
# Only connect ...
self.connectPorts(self.policeman.OUT, self.trafficLight.INTERRUPT)
def select(self, immChildren):
"""
Choose a model to transition from all possible models.
"""
# Policeman has priority over the traffic light
if self.policeman in immChildren:
return self.policeman
else:
# Doesn't really matter, as they don't influence each other
return immChildren[0]

View file

@ -0,0 +1,73 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Import code for model simulation:
from pypdevs.simulator import Simulator
# Import the model to be simulated
from model import TrafficSystem
# ======================================================================
# 1. Instantiate the (Coupled or Atomic) DEVS at the root of the
# hierarchical model. This effectively instantiates the whole model
# thanks to the recursion in the DEVS model constructors (__init__).
#
trafficSystem = TrafficSystem(name="trafficSystem")
# ======================================================================
# 2. Link the model to a DEVS Simulator:
# i.e., create an instance of the 'Simulator' class,
# using the model as a parameter.
sim = Simulator(trafficSystem)
# ======================================================================
# 3. Perform all necessary configurations, the most commonly used are:
# A. Termination time (or termination condition)
# Using a termination condition will execute a provided function at
# every simulation step, making it possible to check for certain states
# being reached.
# It should return True to stop simulation, or Falso to continue.
def terminate_whenStateIsReached(clock, model):
return model.trafficLight.state.get() == "manual"
sim.setTerminationCondition(terminate_whenStateIsReached)
# A termination time is prefered over a termination condition,
# as it is much simpler to use.
# e.g. to simulate until simulation time 400.0 is reached
sim.setTerminationTime(500.0)
# B. Set the use of a tracer to show what happened during the simulation run
# Both writing to stdout or file is possible:
# pass None for stdout, or a filename for writing to that file
sim.setVerbose(None)
# C. Set the use of Dynamic Structure DEVS, to make sure that the modelTransition
# methods are invoked and changes are performed correctly.
sim.setDSDEVS(True)
# ======================================================================
# 4. Simulate the model
sim.simulate()
# ======================================================================
# 5. (optional) Extract data from the simulated model
print("Simulation terminated with traffic light 1 in state %s" % (trafficSystem.trafficLight1.state.get()))
print("Simulation terminated with traffic light 2 in state %s" % (trafficSystem.trafficLight2.state.get()))

View file

@ -0,0 +1,311 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
# Import code for DEVS model representation:
from pypdevs.DEVS import *
from pypdevs.infinity import INFINITY
class TrafficLightMode:
"""
Encapsulates the system's state
"""
def __init__(self, current="red"):
"""
Constructor (parameterizable).
"""
self.set(current)
def set(self, value="red"):
self.__colour=value
def get(self):
return self.__colour
def __str__(self):
return self.get()
class TrafficLight(AtomicDEVS):
"""
A traffic light
"""
def __init__(self, name=None):
"""
Constructor (parameterizable).
"""
# Always call parent class' constructor FIRST:
AtomicDEVS.__init__(self, name)
# STATE:
# Define 'state' attribute (initial sate):
self.state = TrafficLightMode("red")
# ELAPSED TIME:
# Initialize 'elapsed time' attribute if required
# (by default, value is 0.0):
self.elapsed = 1.5
# with elapsed time initially 1.5 and initially in
# state "red", which has a time advance of 60,
# there are 60-1.5 = 58.5time-units remaining until the first
# internal transition
# PORTS:
# Declare as many input and output ports as desired
# (usually store returned references in local variables):
self.INTERRUPT = self.addInPort(name="INTERRUPT")
self.OBSERVED = self.addOutPort(name="OBSERVED")
def extTransition(self, inputs):
"""
External Transition Function.
"""
# Compute the new state 'Snew' based (typically) on current
# State, Elapsed time parameters and calls to 'self.peek(self.IN)'.
input = inputs.get(self.INTERRUPT)[0]
state = self.state.get()
if input == "toManual":
if state == "manual":
# staying in manual mode
return TrafficLightMode("manual")
elif state in ("red", "green", "yellow"):
return TrafficLightMode("manual")
elif input == "toAutonomous":
if state == "manual":
return TrafficLightMode("red")
elif state in ("red", "green", "yellow"):
# If toAutonomous is given while still autonomous, just stay in this state
return self.state
raise DEVSException(\
"unknown state <%s> in TrafficLight external transition function"\
% state)
def intTransition(self):
"""
Internal Transition Function.
"""
state = self.state.get()
if state == "red":
return TrafficLightMode("green")
elif state == "green":
return TrafficLightMode("yellow")
elif state == "yellow":
return TrafficLightMode("red")
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight internal transition function"\
% state)
def outputFnc(self):
"""
Output Funtion.
"""
# A colourblind observer sees "grey" instead of "red" or "green".
# BEWARE: ouput is based on the OLD state
# and is produced BEFORE making the transition.
# We'll encode an "observation" of the state the
# system will transition to !
# Send messages (events) to a subset of the atomic-DEVS'
# output ports by means of the 'poke' method, i.e.:
# The content of the messages is based (typically) on current State.
state = self.state.get()
if state == "red":
return {self.OBSERVED: ["grey"]}
elif state == "green":
return {self.OBSERVED: ["yellow"]}
elif state == "yellow":
return {self.OBSERVED: ["grey"]}
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight external transition function"\
% state)
def timeAdvance(self):
"""
Time-Advance Function.
"""
# Compute 'ta', the time to the next scheduled internal transition,
# based (typically) on current State.
state = self.state.get()
if state == "red":
return 60
elif state == "green":
return 50
elif state == "yellow":
return 10
elif state == "manual":
return INFINITY
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight time advance transition function"\
% state)
class Policeman(AtomicDEVS):
"""
A policeman producing "toManual" and "toAutonomous" events:
"toManual" when going from "idle" to "working" mode
"toAutonomous" when going from "working" to "idle" mode
"""
def __init__(self, name=None):
"""
Constructor (parameterizable).
"""
# Always call parent class' constructor FIRST:
AtomicDEVS.__init__(self, name)
# STATE:
# Define 'state' attribute (initial sate):
self.state = "idle_at_1"
# ELAPSED TIME:
# Initialize 'elapsed time' attribute if required
# (by default, value is 0.0):
self.elapsed = 0
# PORTS:
# Declare as many input and output ports as desired
# (usually store returned references in local variables):
self.OUT = self.addOutPort(name="OUT")
def intTransition(self):
"""
Internal Transition Function.
The policeman works forever, so only one mode.
"""
state = self.state
if state == "idle_at_1":
return "working_at_1"
elif state == "working_at_1":
return "moving_from_1_to_2"
elif state == "moving_from_1_to_2":
return "idle_at_2"
elif state == "idle_at_2":
return "working_at_2"
elif state == "working_at_2":
return "moving_from_2_to_1"
elif state == "moving_from_2_to_1":
return "idle_at_1"
else:
raise DEVSException(\
"unknown state <%s> in Policeman internal transition function"\
% state)
def outputFnc(self):
"""
Output Funtion.
"""
# Send messages (events) to a subset of the atomic-DEVS'
# output ports by means of the 'poke' method, i.e.:
# The content of the messages is based (typically) on current State.
state = self.state
if state == "idle_at_1":
# Will start working
return {self.OUT: ["toManual"]}
elif state == "working_at_1":
# Will have to put it in autonomous mode again
return {self.OUT: ["toAutonomous"]}
elif state == "moving_from_1_to_2":
# Will simply stand idle while waiting
return {}
elif state == "idle_at_2":
return {self.OUT: ["toManual"]}
elif state == "working_at_2":
return {self.OUT: ["toAutonomous"]}
elif state == "moving_from_2_to_1":
return {}
else:
raise DEVSException(\
"unknown state <%s> in Policeman internal transition function"\
% state)
def timeAdvance(self):
"""
Time-Advance Function.
"""
# Compute 'ta', the time to the next scheduled internal transition,
# based (typically) on current State.
state = self.state
if "idle" in state:
return 50
elif "working" in state:
return 100
elif "moving" in state:
return 150
else:
raise DEVSException(\
"unknown state <%s> in Policeman time advance function"\
% state)
def modelTransition(self, state):
if self.state == "moving_from_1_to_2":
state["destination"] = "2"
return True
elif self.state == "moving_from_2_to_1":
state["destination"] = "1"
return True
else:
return False
class TrafficSystem(CoupledDEVS):
def __init__(self, name=None):
"""
A simple traffic system consisting of a Policeman and a TrafficLight.
"""
# Always call parent class' constructor FIRST:
CoupledDEVS.__init__(self, name)
# Declare the coupled model's output ports:
# Autonomous, so no output ports
# Declare the coupled model's sub-models:
# The Policeman generating interrupts
self.policeman = self.addSubModel(Policeman(name="policeman"))
# Two TrafficLights
self.trafficLight1 = self.addSubModel(TrafficLight(name="trafficLight1"))
self.trafficLight2 = self.addSubModel(TrafficLight(name="trafficLight2"))
# Only connect to the first traffic light
self.connectPorts(self.policeman.OUT, self.trafficLight1.INTERRUPT)
def modelTransition(self, state):
# Policeman triggered a mode, so switch the connection
if state["destination"] == "1":
self.disconnectPorts(self.policeman.OUT, self.trafficLight2.INTERRUPT)
self.connectPorts(self.policeman.OUT, self.trafficLight1.INTERRUPT)
elif state["destination"] == "2":
self.disconnectPorts(self.policeman.OUT, self.trafficLight1.INTERRUPT)
self.connectPorts(self.policeman.OUT, self.trafficLight2.INTERRUPT)
# Don't propagate
return False

View file

@ -0,0 +1,51 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Import code for model simulation, but using the minimal kernel:
from pypdevs.minimal import Simulator
# Import the model to be simulated
from model import TrafficSystem
# ======================================================================
# 1. Instantiate the (Coupled or Atomic) DEVS at the root of the
# hierarchical model. This effectively instantiates the whole model
# thanks to the recursion in the DEVS model constructors (__init__).
#
trafficSystem = TrafficSystem(name="trafficSystem")
# ======================================================================
# 2. Link the model to a DEVS Simulator:
# i.e., create an instance of the 'Simulator' class,
# using the model as a parameter.
sim = Simulator(trafficSystem)
# ======================================================================
# 3. Perform all necessary configurations, with the minimal kernel, only setTerminationTime is supported.
# e.g. to simulate until simulation time 400.0 is reached
sim.setTerminationTime(400.0)
# ======================================================================
# 4. Simulate the model
sim.simulate()
# ======================================================================
# 5. (optional) Extract data from the simulated model
print("Simulation terminated with traffic light in state %s" % (trafficSystem.trafficLight.state.get()))

View file

@ -0,0 +1,286 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
# Import code for DEVS model representation:
from pypdevs.DEVS import *
from pypdevs.infinity import INFINITY
class TrafficLightMode:
"""
Encapsulates the system's state
"""
def __init__(self, current="red"):
"""
Constructor (parameterizable).
"""
self.set(current)
def set(self, value="red"):
self.__colour=value
def get(self):
return self.__colour
def __str__(self):
return self.get()
class TrafficLight(AtomicDEVS):
"""
A traffic light
"""
def __init__(self, name=None):
"""
Constructor (parameterizable).
"""
# Always call parent class' constructor FIRST:
AtomicDEVS.__init__(self, name)
# STATE:
# Define 'state' attribute (initial sate):
self.state = TrafficLightMode("red")
# ELAPSED TIME:
# Initialize 'elapsed time' attribute if required
# (by default, value is 0.0):
self.elapsed = 1.5
# with elapsed time initially 1.5 and initially in
# state "red", which has a time advance of 60,
# there are 60-1.5 = 58.5time-units remaining until the first
# internal transition
# PORTS:
# Declare as many input and output ports as desired
# (usually store returned references in local variables):
self.INTERRUPT = self.addInPort(name="INTERRUPT")
self.OBSERVED = self.addOutPort(name="OBSERVED")
def extTransition(self, inputs):
"""
External Transition Function.
"""
# Compute the new state 'Snew' based (typically) on current
# State, Elapsed time parameters and calls to 'self.peek(self.IN)'.
input = inputs.get(self.INTERRUPT)[0]
state = self.state.get()
if input == "toManual":
if state == "manual":
# staying in manual mode
return TrafficLightMode("manual")
elif state in ("red", "green", "yellow"):
return TrafficLightMode("manual")
elif input == "toAutonomous":
if state == "manual":
return TrafficLightMode("red")
elif state in ("red", "green", "yellow"):
# If toAutonomous is given while still autonomous, just stay in this state
return self.state
raise DEVSException(\
"unknown state <%s> in TrafficLight external transition function"\
% state)
def intTransition(self):
"""
Internal Transition Function.
"""
state = self.state.get()
if state == "red":
return TrafficLightMode("green")
elif state == "green":
return TrafficLightMode("yellow")
elif state == "yellow":
return TrafficLightMode("red")
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight internal transition function"\
% state)
def outputFnc(self):
"""
Output Funtion.
"""
# A colourblind observer sees "grey" instead of "red" or "green".
# BEWARE: ouput is based on the OLD state
# and is produced BEFORE making the transition.
# We'll encode an "observation" of the state the
# system will transition to !
# Send messages (events) to a subset of the atomic-DEVS'
# output ports by means of the 'poke' method, i.e.:
# The content of the messages is based (typically) on current State.
state = self.state.get()
if state == "red":
return {self.OBSERVED: ["grey"]}
elif state == "green":
return {self.OBSERVED: ["yellow"]}
elif state == "yellow":
return {self.OBSERVED: ["grey"]}
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight external transition function"\
% state)
def timeAdvance(self):
"""
Time-Advance Function.
"""
# Compute 'ta', the time to the next scheduled internal transition,
# based (typically) on current State.
state = self.state.get()
if state == "red":
return 60
elif state == "green":
return 50
elif state == "yellow":
return 10
elif state == "manual":
return INFINITY
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight time advance transition function"\
% state)
class PolicemanMode:
"""
Encapsulates the Policeman's state
"""
def __init__(self, current="idle"):
"""
Constructor (parameterizable).
"""
self.set(current)
def set(self, value="idle"):
self.__mode=value
def get(self):
return self.__mode
def __str__(self):
return self.get()
class Policeman(AtomicDEVS):
"""
A policeman producing "toManual" and "toAutonomous" events:
"toManual" when going from "idle" to "working" mode
"toAutonomous" when going from "working" to "idle" mode
"""
def __init__(self, name=None):
"""
Constructor (parameterizable).
"""
# Always call parent class' constructor FIRST:
AtomicDEVS.__init__(self, name)
# STATE:
# Define 'state' attribute (initial sate):
self.state = PolicemanMode("idle")
# ELAPSED TIME:
# Initialize 'elapsed time' attribute if required
# (by default, value is 0.0):
self.elapsed = 0
# PORTS:
# Declare as many input and output ports as desired
# (usually store returned references in local variables):
self.OUT = self.addOutPort(name="OUT")
def intTransition(self):
"""
Internal Transition Function.
The policeman works forever, so only one mode.
"""
state = self.state.get()
if state == "idle":
return PolicemanMode("working")
elif state == "working":
return PolicemanMode("idle")
else:
raise DEVSException(\
"unknown state <%s> in Policeman internal transition function"\
% state)
def outputFnc(self):
"""
Output Funtion.
"""
# Send messages (events) to a subset of the atomic-DEVS'
# output ports by means of the 'poke' method, i.e.:
# The content of the messages is based (typically) on current State.
state = self.state.get()
if state == "idle":
return {self.OUT: ["toManual"]}
elif state == "working":
return {self.OUT: ["toAutonomous"]}
else:
raise DEVSException(\
"unknown state <%s> in Policeman output function"\
% state)
def timeAdvance(self):
"""
Time-Advance Function.
"""
# Compute 'ta', the time to the next scheduled internal transition,
# based (typically) on current State.
state = self.state.get()
if state == "idle":
return 200
elif state == "working":
return 100
else:
raise DEVSException(\
"unknown state <%s> in Policeman time advance function"\
% state)
class TrafficSystem(CoupledDEVS):
def __init__(self, name=None):
"""
A simple traffic system consisting of a Policeman and a TrafficLight.
"""
# Always call parent class' constructor FIRST:
CoupledDEVS.__init__(self, name)
# Declare the coupled model's output ports:
# Autonomous, so no output ports
# Declare the coupled model's sub-models:
# The Policeman generating interrupts
self.policeman = self.addSubModel(Policeman(name="policeman"))
# The TrafficLight
self.trafficLight = self.addSubModel(TrafficLight(name="trafficLight"))
# Only connect ...
self.connectPorts(self.policeman.OUT, self.trafficLight.INTERRUPT)

View file

@ -0,0 +1,68 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Import code for model simulation:
from pypdevs.simulator import Simulator
# Import the model to be simulated
from model import TrafficSystem
# ======================================================================
# 1. Instantiate the (Coupled or Atomic) DEVS at the root of the
# hierarchical model. This effectively instantiates the whole model
# thanks to the recursion in the DEVS model constructors (__init__).
#
trafficSystem = TrafficSystem(name="trafficSystem")
# ======================================================================
# 2. Link the model to a DEVS Simulator:
# i.e., create an instance of the 'Simulator' class,
# using the model as a parameter.
sim = Simulator(trafficSystem)
# ======================================================================
# 3. Perform all necessary configurations, the most commonly used are:
# A. Termination time (or termination condition)
# Using a termination condition will execute a provided function at
# every simulation step, making it possible to check for certain states
# being reached.
# It should return True to stop simulation, or Falso to continue.
def terminate_whenStateIsReached(clock, model):
return model.trafficLight.state.get() == "manual"
sim.setTerminationCondition(terminate_whenStateIsReached)
# A termination time is prefered over a termination condition,
# as it is much simpler to use.
# e.g. to simulate until simulation time 400.0 is reached
sim.setTerminationTime(400.0)
# B. Set the use of a tracer to show what happened during the simulation run
# Both writing to stdout or file is possible:
# pass None for stdout, or a filename for writing to that file
sim.setVerbose(None)
# ======================================================================
# 4. Simulate the model
sim.simulate()
# ======================================================================
# 5. (optional) Extract data from the simulated model
print("Simulation terminated with traffic light in state %s" % (trafficSystem.trafficLight.state.get()))

View file

@ -0,0 +1,286 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
# Import code for DEVS model representation:
from pypdevs.DEVS import *
from pypdevs.infinity import INFINITY
class TrafficLightMode:
"""
Encapsulates the system's state
"""
def __init__(self, current="red"):
"""
Constructor (parameterizable).
"""
self.set(current)
def set(self, value="red"):
self.__colour=value
def get(self):
return self.__colour
def __str__(self):
return self.get()
class TrafficLight(AtomicDEVS):
"""
A traffic light
"""
def __init__(self, name=None):
"""
Constructor (parameterizable).
"""
# Always call parent class' constructor FIRST:
AtomicDEVS.__init__(self, name)
# STATE:
# Define 'state' attribute (initial sate):
self.state = TrafficLightMode("red")
# ELAPSED TIME:
# Initialize 'elapsed time' attribute if required
# (by default, value is 0.0):
self.elapsed = 1.5
# with elapsed time initially 1.5 and initially in
# state "red", which has a time advance of 60,
# there are 60-1.5 = 58.5time-units remaining until the first
# internal transition
# PORTS:
# Declare as many input and output ports as desired
# (usually store returned references in local variables):
self.INTERRUPT = self.addInPort(name="INTERRUPT")
self.OBSERVED = self.addOutPort(name="OBSERVED")
def extTransition(self, inputs):
"""
External Transition Function.
"""
# Compute the new state 'Snew' based (typically) on current
# State, Elapsed time parameters and calls to 'self.peek(self.IN)'.
input = inputs.get(self.INTERRUPT)[0]
state = self.state.get()
if input == "toManual":
if state == "manual":
# staying in manual mode
return TrafficLightMode("manual")
elif state in ("red", "green", "yellow"):
return TrafficLightMode("manual")
elif input == "toAutonomous":
if state == "manual":
return TrafficLightMode("red")
elif state in ("red", "green", "yellow"):
# If toAutonomous is given while still autonomous, just stay in this state
return self.state
raise DEVSException(\
"unknown state <%s> in TrafficLight external transition function"\
% state)
def intTransition(self):
"""
Internal Transition Function.
"""
state = self.state.get()
if state == "red":
return TrafficLightMode("green")
elif state == "green":
return TrafficLightMode("yellow")
elif state == "yellow":
return TrafficLightMode("red")
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight internal transition function"\
% state)
def outputFnc(self):
"""
Output Funtion.
"""
# A colourblind observer sees "grey" instead of "red" or "green".
# BEWARE: ouput is based on the OLD state
# and is produced BEFORE making the transition.
# We'll encode an "observation" of the state the
# system will transition to !
# Send messages (events) to a subset of the atomic-DEVS'
# output ports by means of the 'poke' method, i.e.:
# The content of the messages is based (typically) on current State.
state = self.state.get()
if state == "red":
return {self.OBSERVED: ["grey"]}
elif state == "green":
return {self.OBSERVED: ["yellow"]}
elif state == "yellow":
return {self.OBSERVED: ["grey"]}
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight external transition function"\
% state)
def timeAdvance(self):
"""
Time-Advance Function.
"""
# Compute 'ta', the time to the next scheduled internal transition,
# based (typically) on current State.
state = self.state.get()
if state == "red":
return 60
elif state == "green":
return 50
elif state == "yellow":
return 10
elif state == "manual":
return INFINITY
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight time advance transition function"\
% state)
class PolicemanMode:
"""
Encapsulates the Policeman's state
"""
def __init__(self, current="idle"):
"""
Constructor (parameterizable).
"""
self.set(current)
def set(self, value="idle"):
self.__mode=value
def get(self):
return self.__mode
def __str__(self):
return self.get()
class Policeman(AtomicDEVS):
"""
A policeman producing "toManual" and "toAutonomous" events:
"toManual" when going from "idle" to "working" mode
"toAutonomous" when going from "working" to "idle" mode
"""
def __init__(self, name=None):
"""
Constructor (parameterizable).
"""
# Always call parent class' constructor FIRST:
AtomicDEVS.__init__(self, name)
# STATE:
# Define 'state' attribute (initial sate):
self.state = PolicemanMode("idle")
# ELAPSED TIME:
# Initialize 'elapsed time' attribute if required
# (by default, value is 0.0):
self.elapsed = 0
# PORTS:
# Declare as many input and output ports as desired
# (usually store returned references in local variables):
self.OUT = self.addOutPort(name="OUT")
def intTransition(self):
"""
Internal Transition Function.
The policeman works forever, so only one mode.
"""
state = self.state.get()
if state == "idle":
return PolicemanMode("working")
elif state == "working":
return PolicemanMode("idle")
else:
raise DEVSException(\
"unknown state <%s> in Policeman internal transition function"\
% state)
def outputFnc(self):
"""
Output Funtion.
"""
# Send messages (events) to a subset of the atomic-DEVS'
# output ports by means of the 'poke' method, i.e.:
# The content of the messages is based (typically) on current State.
state = self.state.get()
if state == "idle":
return {self.OUT: ["toManual"]}
elif state == "working":
return {self.OUT: ["toAutonomous"]}
else:
raise DEVSException(\
"unknown state <%s> in Policeman output function"\
% state)
def timeAdvance(self):
"""
Time-Advance Function.
"""
# Compute 'ta', the time to the next scheduled internal transition,
# based (typically) on current State.
state = self.state.get()
if state == "idle":
return 200
elif state == "working":
return 100
else:
raise DEVSException(\
"unknown state <%s> in Policeman time advance function"\
% state)
class TrafficSystem(CoupledDEVS):
def __init__(self, name=None):
"""
A simple traffic system consisting of a Policeman and a TrafficLight.
"""
# Always call parent class' constructor FIRST:
CoupledDEVS.__init__(self, name)
# Declare the coupled model's output ports:
# Autonomous, so no output ports
# Declare the coupled model's sub-models:
# The Policeman generating interrupts
self.policeman = self.addSubModel(Policeman(name="policeman"))
# The TrafficLight
self.trafficLight = self.addSubModel(TrafficLight(name="trafficLight"))
# Only connect ...
self.connectPorts(self.policeman.OUT, self.trafficLight.INTERRUPT)

View file

@ -0,0 +1,22 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from pypdevs.simulator import Simulator
from trafficLightModel import *
model = TrafficLight(name="trafficLight")
sim = Simulator(model)
sim.setVerbose(None)
sim.simulate()

View file

@ -0,0 +1,34 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from pypdevs.simulator import Simulator
from trafficLightModel import *
model = TrafficLight(name="trafficLight")
refs = {"INTERRUPT": model.INTERRUPT}
sim = Simulator(model)
sim.setRealTime(True)
sim.setRealTimeInputFile(None)
sim.setRealTimePorts(refs)
sim.setVerbose(None)
sim.setRealTimePlatformGameLoop()
sim.simulate()
import time
while 1:
before = time.time()
sim.realtime_loop_call()
time.sleep(0.1 - (before - time.time()))
print("Current state: " + str(model.state.get()))

View file

@ -0,0 +1,33 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from pypdevs.simulator import Simulator
from trafficLightModel import *
model = TrafficLight(name="trafficLight")
refs = {"INTERRUPT": model.INTERRUPT}
sim = Simulator(model)
sim.setRealTime(True)
sim.setRealTimeInputFile(None)
sim.setRealTimePorts(refs)
sim.setVerbose(None)
sim.setRealTimePlatformThreads()
sim.simulate()
# If we get here, simulation will also end, as the sleep calls are daemon threads
# (otherwise, they would make the simulation unkillable)
while 1:
sim.realtime_interrupt(raw_input())

View file

@ -0,0 +1,90 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from pypdevs.simulator import Simulator
from Tkinter import *
from trafficLightModel import *
isBlinking = None
model = TrafficLight(name="trafficLight")
refs = {"INTERRUPT": model.INTERRUPT}
root = Tk()
sim = Simulator(model)
sim.setRealTime(True)
sim.setRealTimeInputFile(None)
sim.setRealTimePorts(refs)
sim.setVerbose(None)
sim.setRealTimePlatformTk(root)
def toManual():
global isBlinking
isBlinking = False
sim.realtime_interrupt("INTERRUPT toManual")
def toAutonomous():
global isBlinking
isBlinking = None
sim.realtime_interrupt("INTERRUPT toAutonomous")
size = 50
xbase = 10
ybase = 10
frame = Frame(root)
canvas = Canvas(frame)
canvas.create_oval(xbase, ybase, xbase+size, ybase+size, fill="black", tags="red_light")
canvas.create_oval(xbase, ybase+size, xbase+size, ybase+2*size, fill="black", tags="yellow_light")
canvas.create_oval(xbase, ybase+2*size, xbase+size, ybase+3*size, fill="black", tags="green_light")
canvas.pack()
frame.pack()
def updateLights():
state = model.state.get()
if state == "red":
canvas.itemconfig("red_light", fill="red")
canvas.itemconfig("yellow_light", fill="black")
canvas.itemconfig("green_light", fill="black")
elif state == "yellow":
canvas.itemconfig("red_light", fill="black")
canvas.itemconfig("yellow_light", fill="yellow")
canvas.itemconfig("green_light", fill="black")
elif state == "green":
canvas.itemconfig("red_light", fill="black")
canvas.itemconfig("yellow_light", fill="black")
canvas.itemconfig("green_light", fill="green")
elif state == "manual":
canvas.itemconfig("red_light", fill="black")
global isBlinking
if isBlinking:
canvas.itemconfig("yellow_light", fill="yellow")
isBlinking = False
else:
canvas.itemconfig("yellow_light", fill="black")
isBlinking = True
canvas.itemconfig("green_light", fill="black")
root.after(500, updateLights)
b = Button(root, text="toManual", command=toManual)
b.pack()
c = Button(root, text="toAutonomous", command=toAutonomous)
c.pack()
root.after(100, updateLights)
sim.simulate()
root.mainloop()

View file

@ -0,0 +1,311 @@
# Copyright 2014 Modelling, Simulation and Design Lab (MSDL) at
# McGill University and the University of Antwerp (http://msdl.cs.mcgill.ca/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Import code for DEVS model representation:
from pypdevs.infinity import *
from pypdevs.DEVS import *
# ====================================================================== #
class TrafficLightMode:
"""Encapsulates the system's state
"""
###
def __init__(self, current="red"):
"""Constructor (parameterizable).
"""
self.set(current)
def set(self, value="red"):
self.__colour=value
def get(self):
return self.__colour
def __str__(self):
return self.get()
class TrafficLight(AtomicDEVS):
"""A traffic light
"""
###
def __init__(self, name=None):
"""Constructor (parameterizable).
"""
# Always call parent class' constructor FIRST:
AtomicDEVS.__init__(self, name)
# STATE:
# Define 'state' attribute (initial sate):
self.state = TrafficLightMode("red")
# PORTS:
# Declare as many input and output ports as desired
# (usually store returned references in local variables):
self.INTERRUPT = self.addInPort(name="INTERRUPT")
self.OBSERVED = self.addOutPort(name="OBSERVED")
###
def extTransition(self, inputs):
"""External Transition Function."""
# Compute the new state 'Snew' based (typically) on current
# State, Elapsed time parameters and calls to 'self.peek(self.IN)'.
#input = self.peek(self.INTERRUPT)
input = inputs[self.INTERRUPT][0]
state = self.state.get()
if input == "toManual":
if state == "manual":
# staying in manual mode
return TrafficLightMode("manual")
if state in ("red", "green", "yellow"):
return TrafficLightMode("manual")
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight external transition function"\
% state)
if input == "toAutonomous":
if state == "manual":
return TrafficLightMode("red")
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight external transition function"\
% state)
raise DEVSException(\
"unknown input <%s> in TrafficLight external transition function"\
% input)
###
def intTransition(self):
"""Internal Transition Function.
"""
state = self.state.get()
if state == "red":
return TrafficLightMode("green")
elif state == "green":
return TrafficLightMode("yellow")
elif state == "yellow":
return TrafficLightMode("red")
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight internal transition function"\
% state)
###
def outputFnc(self):
"""Output Funtion.
"""
# A colourblind observer sees "grey" instead of "red" or "green".
# BEWARE: ouput is based on the OLD state
# and is produced BEFORE making the transition.
# We'll encode an "observation" of the state the
# system will transition to !
# Send messages (events) to a subset of the atomic-DEVS'
# output ports by means of the 'poke' method, i.e.:
# The content of the messages is based (typically) on current State.
state = self.state.get()
if state == "red":
return {self.OBSERVED: ["grey"]}
#self.poke(self.OBSERVED, "grey")
# NOT self.poke(self.OBSERVED, "grey")
elif state == "green":
return {self.OBSERVED: ["yellow"]}
#self.poke(self.OBSERVED, "yellow")
# NOT self.poke(self.OBSERVED, "grey")
elif state == "yellow":
return {self.OBSERVED: ["grey"]}
#self.poke(self.OBSERVED, "grey")
# NOT self.poke(self.OBSERVED, "yellow")
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight external transition function"\
% state)
###
def timeAdvance(self):
"""Time-Advance Function.
"""
# Compute 'ta', the time to the next scheduled internal transition,
# based (typically) on current State.
state = self.state.get()
if state == "red":
return 3
elif state == "green":
return 2
elif state == "yellow":
return 1
elif state == "manual":
return INFINITY
else:
raise DEVSException(\
"unknown state <%s> in TrafficLight time advance transition function"\
% state)
# ====================================================================== #
class PolicemanMode:
"""Encapsulates the Policeman's state
"""
###
def __init__(self, current="idle"):
"""Constructor (parameterizable).
"""
self.set(current)
def set(self, value="idle"):
self.__mode=value
def get(self):
return self.__mode
def __str__(self):
return self.get()
class Policeman(AtomicDEVS):
"""A policeman producing "toManual" and "toAutonomous" events:
"toManual" when going from "idle" to "working" mode
"toAutonomous" when going from "working" to "idle" mode
"""
###
def __init__(self, name=None):
"""Constructor (parameterizable).
"""
# Always call parent class' constructor FIRST:
AtomicDEVS.__init__(self, name)
# STATE:
# Define 'state' attribute (initial sate):
self.state = PolicemanMode("idle")
# ELAPSED TIME:
# Initialize 'elapsed time' attribute if required
# (by default, value is 0.0):
self.elapsed = 0
# PORTS:
# Declare as many input and output ports as desired
# (usually store returned references in local variables):
self.OUT = self.addOutPort(name="OUT")
###
# Autonomous system (no input ports),
# so no External Transition Function required
#
###
def intTransition(self):
"""Internal Transition Function.
The policeman works forever, so only one mode.
"""
state = self.state.get()
if state == "idle":
return PolicemanMode("working")
elif state == "working":
return PolicemanMode("idle")
else:
raise DEVSException(\
"unknown state <%s> in Policeman internal transition function"\
% state)
###
def outputFnc(self):
"""Output Funtion.
"""
# Send messages (events) to a subset of the atomic-DEVS'
# output ports by means of the 'poke' method, i.e.:
# The content of the messages is based (typically) on current State.
state = self.state.get()
if state == "idle":
return {self.OUT: ["toManual"]}
#self.poke(self.OUT, "toManual")
elif state == "working":
return {self.OUT: ["toAutonomous"]}
#self.poke(self.OUT, "toAutonomous")
else:
raise DEVSException(\
"unknown state <%s> in Policeman output function"\
% state)
###
def timeAdvance(self):
"""Time-Advance Function.
"""
# Compute 'ta', the time to the next scheduled internal transition,
# based (typically) on current State.
state = self.state.get()
if state == "idle":
return 200
elif state == "working":
return 100
else:
raise DEVSException(\
"unknown state <%s> in Policeman time advance function"\
% state)
# ====================================================================== #
class TrafficSystem(CoupledDEVS):
def __init__(self, name=None):
""" A simple traffic system consisting of a Policeman and a TrafficLight.
"""
# Always call parent class' constructor FIRST:
CoupledDEVS.__init__(self, name)
# Declare the coupled model's output ports:
# Autonomous, so no output ports
#self.OUT = self.addOutPort(name="OUT")
# Declare the coupled model's sub-models:
# The Policeman generating interrupts
self.policeman = self.addSubModel(Policeman(name="policeman"))
# The TrafficLight
self.trafficLight = self.addSubModel(TrafficLight(name="trafficLight"))
# Only connect ...
self.connectPorts(self.policeman.OUT, self.trafficLight.INTERRUPT)