Explorar o código

first prototype of debuggable cbd simulator

Simon Van Mierlo %!s(int64=9) %!d(string=hai) anos
pai
achega
92f9792ac7
Modificáronse 33 ficheiros con 5272 adicións e 0 borrados
  1. 17 0
      debugging_fsa_cbd_composition/cbdsimulator/.project
  2. 12 0
      debugging_fsa_cbd_composition/cbdsimulator/.pydevproject
  3. 900 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/CBD.py
  4. 54 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/CBDDraw.py
  5. 0 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/__init__.py
  6. 129 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/naivelog.py
  7. 49 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/plot.py
  8. 48 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/CounterTest.py
  9. 0 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/__init__.py
  10. 551 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/basicCBDTest.py
  11. 201 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/flattenCBDTest.py
  12. 201 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/hierarchyCBDTest.py
  13. 172 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/sortedGraphCBDTest.py
  14. 0 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/__init__.py
  15. 80 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/models/EvenNumbersCBD.py
  16. 21 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/models/HarmonicOscilator.py
  17. 300 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/models/TrainControlCBD.py
  18. 0 0
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/models/__init__.py
  19. 263 0
      debugging_fsa_cbd_composition/cbdsimulator/CBD_Controller.py
  20. 56 0
      debugging_fsa_cbd_composition/cbdsimulator/Options.py
  21. BIN=BIN
      debugging_fsa_cbd_composition/cbdsimulator/cbd-sim-sccd-visual.pdf
  22. 325 0
      debugging_fsa_cbd_composition/cbdsimulator/cbdsim.py
  23. 195 0
      debugging_fsa_cbd_composition/cbdsimulator/cbdsim.py.xml
  24. 127 0
      debugging_fsa_cbd_composition/cbdsimulator/cbdsim.sccd
  25. 449 0
      debugging_fsa_cbd_composition/cbdsimulator/cbdsim_debugging.py.xml
  26. 114 0
      debugging_fsa_cbd_composition/cbdsimulator/cbdsim_hierarchical.sccd
  27. 110 0
      debugging_fsa_cbd_composition/cbdsimulator/cbdsim_normal_form.sccd
  28. 6 0
      debugging_fsa_cbd_composition/cbdsimulator/generateSCCD.bat
  29. 0 0
      debugging_fsa_cbd_composition/cbdsimulator/log.txt
  30. 43 0
      debugging_fsa_cbd_composition/cbdsimulator/plot.html
  31. 30 0
      debugging_fsa_cbd_composition/cbdsimulator/run_cbd_sim.py
  32. 106 0
      debugging_fsa_cbd_composition/cbdsimulator/runner.py
  33. 713 0
      debugging_fsa_cbd_composition/cbdsimulator/target.py

+ 17 - 0
debugging_fsa_cbd_composition/cbdsimulator/.project

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>cbdsimulator</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.python.pydev.PyDevBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.python.pydev.pythonNature</nature>
+	</natures>
+</projectDescription>

+ 12 - 0
debugging_fsa_cbd_composition/cbdsimulator/.pydevproject

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?><pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
+<path>/${PROJECT_DIR_NAME}</path>
+</pydev_pathproperty>
+
+<pydev_pathproperty name="org.python.pydev.PROJECT_EXTERNAL_SOURCE_PATH">
+<path>C:\Users\clagms\Source Control\Git_SCCD\src\build\lib</path>
+</pydev_pathproperty>
+</pydev_project>

+ 900 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/CBD.py

@@ -0,0 +1,900 @@
+import math
+import naivelog
+from collections import namedtuple
+
+InputLink = namedtuple("InputLink", ["block", "output_port"])
+Signal = namedtuple("Signal", ["time", "value"])
+def enum(**enums):
+            return type('Enum', (), enums)
+level = enum(WARNING=1, ERROR=2, FATAL=3)	
+epsilon = 0.001		
+
+class BaseBlock:
+    """
+    A base class for all types of basic blocks
+    """
+    def __init__(self, name, input_ports, output_ports):
+        self.setBlockName(name)
+
+        #The output signals produced by this block is encoded as a dictionary.
+        #The key of this dictionary is the name of the output port.
+        #Each element of the dictionary contains an ordered list of values.
+        self.__signals = dict()
+        for output_port in output_ports:
+            self.__signals[output_port] = []
+        
+        self._output_ports = output_ports
+        
+        #The input links produced by this block is encoded as a dictionary.
+        #The key of this dictionary is the name of the input port.
+        #Each element of the dictionary contains
+        #an tuple of the block and the output name of the other block.
+        self._linksIn = dict()
+
+        #The list of possible input ports
+        self.__nameLinks = input_ports
+        #In wich CBD the baseblock is situated
+        self._parent = None
+    
+    def getOutputPorts(self):
+        return self._output_ports
+    
+    def resetSignals(self):
+        for output_port in self.__signals:
+            self.__signals[output_port] = []
+    
+    def getBlockName(self):
+        return self.__block_name
+
+    def setBlockName(self, block_name):
+        self.__block_name = block_name
+
+    def setParent(self, parent):
+        self._parent = parent
+
+    def getBlockType(self):
+        return self.__class__.__name__
+
+    def getLinksIn(self):
+        return self._linksIn
+
+    def getOutputNameOfInput(self, inputBlock):
+        return [ y for (x,y) in self._linksIn.iteritems() if y.block == inputBlock ][0].output_port
+
+    def getInputName(self, inputBlock):
+        return [ x for (x,y) in self._linksIn.iteritems() if y.block == inputBlock ]
+
+    def getClock(self):
+        return self._parent.getClock()
+
+    def appendToSignal(self, value, name_output = None):
+        name_output = "OUT1" if name_output == None else name_output
+        assert name_output in self.__signals.keys()
+        self.__signals[name_output].append(Signal(self.getClock().getTime(), value))
+
+    def getSignal(self, name_output = None):
+        name_output = "OUT1" if name_output == None else name_output
+        assert name_output in self.__signals.keys()
+        return self.__signals[name_output] if name_output != None else self.__signals["OUT1"]
+    
+    # TODO: probably remove this feature
+    def setSignal(self, value, name_output = None):    
+        name_output = "OUT1" if name_output == None else name_output
+        assert name_output in self.__signals.keys()
+        if self.__signals[name_output]:
+            self.__signals[name_output][-1] = Signal(self.__signals[name_output][-1].time, value)
+
+    def getDependencies(self, curIteration):
+        return list(set([ tup.block for tup in self._linksIn.values() ]))
+
+    def getBlockConnectedToInput(self, input_port):
+        return self._linksIn[input_port]
+
+    def getInputSignal(self, curIteration, input_port = None):
+        """
+        Returns the signal sent out by the input block (IN1 if none given,
+        at the last time if no curIteration is given).
+        """
+        input_port = "IN1" if input_port == None else input_port
+        curIteration = -1 if curIteration == None else curIteration
+
+        (incoming_block, out_port_name) = self._linksIn[input_port]
+        return incoming_block.getSignal(out_port_name)[curIteration]
+
+    def compute(self, curIteration):
+        exit("BaseBlock has nothing to compute")
+
+    def linkInput(self, in_block, name_input, name_output):
+        """
+        linkInput will link the output of the from_block to the input of the to_block
+        -if no name_input was given for the to_block, we will derive the right input,
+        by checking which input IN has nothing connected to it yet
+        -if no name_output was given we use the first OUT output
+        """
+        name_output = "OUT1" if name_output == None else name_output
+        if name_input != None:
+            assert name_input in self.__nameLinks
+            self._linksIn[name_input] = InputLink(in_block, name_output)
+        else:
+            i = 1
+            while True:
+                nextIn = "IN" + str(i)
+                if nextIn in self.__nameLinks:
+                    if not nextIn in self._linksIn:
+                        self._linksIn[nextIn] = InputLink(in_block, name_output)
+                        return
+                else:
+                    exit("There are no open IN inputs left in block %s" % self.getBlockName())
+                i += 1
+
+    def __repr__(self):
+        repr = self.getBlockName() + ":" + self.getBlockType() + "\n"
+        if len(self._linksIn) == 0:
+            repr+= "  No incoming connections to IN ports\n"
+        else:
+            for (key, (in_block, out_port)) in self._linksIn.iteritems():
+                repr += "In input " + key + ":  IN <- " + in_block.getBlockName() + ":" + in_block.getBlockType() + "\n"
+        return repr
+
+class ConstantBlock(BaseBlock):
+    """
+    The constant block will always output its constant value
+    """
+    def __init__(self, block_name, value=0.0):
+        BaseBlock.__init__(self, block_name, [], ["OUT1"])
+        self.__value = value
+
+    def getValue(self):
+        return self.__value
+
+    def setValue(self, value):
+        self.__value = value
+
+    def compute(self, curIteration):
+        self.appendToSignal(self.getValue())
+
+    def __repr__(self):
+        return BaseBlock.__repr__(self) + "  Value = " + str(self.getValue()) + "\n"
+
+class NegatorBlock(BaseBlock):
+    """
+    The negator block will output the value of the input multiplied with -1
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+
+    def compute(self, curIteration):
+        self.appendToSignal(-self.getInputSignal(curIteration).value)
+
+class InverterBlock(BaseBlock):
+    """
+    The invertblock will output 1/IN
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+
+    def compute(self, curIteration):
+        self.appendToSignal(1.0/self.getInputSignal(curIteration).value)
+
+class AdderBlock(BaseBlock):
+    """
+    The adderblock will add the 2 inputs
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1", "IN2"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.getInputSignal(curIteration, "IN1").value + self.getInputSignal(curIteration, "IN2").value)
+
+class ProductBlock(BaseBlock):
+    """
+    The product block will multiply the two inputs
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1", "IN2"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.getInputSignal(curIteration, "IN1").value * self.getInputSignal(curIteration, "IN2").value)
+
+class GenericBlock(BaseBlock):
+    """
+    The generic block will evaluate the operator on the input
+    operator is the name (a string) of a Python function from the math library
+    which will be called when the block is evaluated
+    by default, initialized to None
+    """
+    def __init__(self, block_name, block_operator=None):
+        # operator is the name (a string) of a Python function from the math library
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+        self.__block_operator = block_operator
+
+    def getBlockOperator(self):
+        return self.__block_operator
+
+    def compute(self, curIteration):
+        operator = getattr(math, self.getBlockOperator())
+        self.appendToSignal(operator(self.getInputSignal(curIteration).value))
+
+    def __repr__(self):
+        repr = BaseBlock.__repr__(self)
+        if self.__block_operator == None:
+            repr += "  No operator given\n"
+        else:
+            repr += "  Operator :: " + self.__block_operator + "\n"
+        return repr
+
+class RootBlock(BaseBlock):
+    """
+    A basic block that computes the IN2-th root from IN1
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1", "IN2"], ["OUT1"])
+
+    def compute(self, curIteration):
+        self.appendToSignal(pow(self.getInputSignal(curIteration, "IN1").value, 1.0/self.getInputSignal(curIteration, "IN2").value))
+
+class ModuloBlock(BaseBlock):
+    """
+    A basic block that computes the IN1 modulo IN3
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1", "IN2"], ["OUT1"])
+
+    def compute(self, curIteration):
+        self.appendToSignal(math.fmod(self.getInputSignal(curIteration, "IN1").value, self.getInputSignal(curIteration, "IN2").value))
+
+class DelayBlock(BaseBlock):
+    """
+    A delay block that takes the last value from the list
+    IC: Initial Condition
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1", "IC"], ["OUT1"])
+        self.__values = []
+
+    def getDependencies(self, curIteration):
+        if curIteration == 0:
+            return [self._linksIn["IC"].block]
+        return []
+    
+    def resetSignals(self):
+        BaseBlock.resetSignals(self)
+        self.__values = []
+    
+    def compute(self, curIteration):
+        if curIteration == 0:
+            outputValue = self.getInputSignal(curIteration, "IC")
+            self.appendToSignal(outputValue.value)
+        else:
+            assert curIteration == len(self.__values)+1
+            (incoming_block, out_port_name) = self._linksIn["IN1"]
+            print incoming_block.getSignal(out_port_name)
+            self.__values.append(incoming_block.getSignal(out_port_name)[curIteration-1])
+            self.appendToSignal(self.__values[curIteration-1].value)
+    
+class InputPortBlock(BaseBlock):
+    """
+    The input port of a CBD
+    """
+    def __init__(self, block_name, parent):
+        BaseBlock.__init__(self, block_name, [], ["OUT1"])
+        self.parent = parent
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.parent.getInputSignal(curIteration, self.getBlockName()).value)
+
+class OutputPortBlock(BaseBlock):
+    """
+    The output port of a CBD
+    """
+    def __init__(self, block_name, parent):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+        self.parent = parent
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.getInputSignal(curIteration, "IN1").value)
+
+class WireBlock(BaseBlock):
+    """
+    When a CBD gets flattened, the port blocks will be replaced by a wire block
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.getInputSignal(curIteration, "IN1").value)
+
+class TimeBlock(BaseBlock):
+    """
+    Outputs the current time of the simulation
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, [], ["OUT1"])
+
+    def	compute(self, curIteration):
+        self.appendToSignal(self.getClock().getTime())
+
+class LessThanBlock(BaseBlock):
+    """
+    A simple block that will test if the IN1 is smaller than IC (output == 1 if true else 0)
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IC", "IN1"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        gisv = lambda s: self.getInputSignal(curIteration, s).value
+        self.appendToSignal(1 if gisv("IN1") < gisv("IC") else 0)
+
+class EqualsBlock(BaseBlock):
+    """
+    A simple block that will test if the IN1 is equal to IC (output == 1 if true else 0)
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IC", "IN1"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        gisv = lambda s: self.getInputSignal(curIteration, s).value
+        self.appendToSignal(1 if gisv("IN1") == gisv("IC") else 0)
+
+class NotBlock(BaseBlock):
+    """
+    A simple Not block that will set a 0 to 1 and vice versa
+    """
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+
+    def	compute(self, curIteration):
+        result = 0 if self.getInputSignal(curIteration, "IN1").value else 1
+        self.appendToSignal(result)    
+
+class OrBlock(BaseBlock):
+    """
+    A simple Or block with possibly multiple inputlines
+    """
+    def __init__(self, block_name, numberOfInputs=2):
+        BaseBlock.__init__(self, block_name, ["IN{0}".format(i) for i in xrange(1,numberOfInputs+1)], ["OUT1"])
+        self.__numberOfInputs = numberOfInputs
+
+    def	compute(self, curIteration):
+        result = 0
+        for i in xrange(1, self.__numberOfInputs+1):
+            result = result or self.getInputSignal(curIteration, "IN"+str(i)).value
+        self.appendToSignal(result)    
+
+class AndBlock(BaseBlock):
+    """
+    A simple And block with possibly multiple inputlines
+    """
+    def __init__(self, block_name, numberOfInputs=2):
+        BaseBlock.__init__(self, block_name, ["IN{0}".format(i) for i in xrange(1,numberOfInputs+1)], ["OUT1"])
+        self.__numberOfInputs = numberOfInputs
+
+    def	compute(self, curIteration):
+        result = 1
+        for i in xrange(1, self.__numberOfInputs+1):
+            result = result and self.getInputSignal(curIteration, "IN"+str(i)).value
+        self.appendToSignal(result)
+
+class SequenceBlock(BaseBlock):
+    """
+    A simple Sequence block: block initializes signal input with given sequence
+    Use only for the tests please
+    """
+    def __init__(self, block_name, sequence):
+        BaseBlock.__init__(self, block_name, [], ["OUT1"])
+        self.__sequence = sequence
+
+    def	compute(self, curIteration):
+        if len(self.__sequence) < curIteration:
+            self.__logger.fatal("Sequence is not long enough")
+        self.appendToSignal(self.__sequence[curIteration])
+
+class LoggingBlock(BaseBlock):
+    """
+    A simple Logging block
+    """
+    def __init__(self, block_name, string, lev = level.WARNING):
+        BaseBlock.__init__(self, block_name, ["IN1"], [])
+        self.__string = string
+        self.__logger = naivelog.getLogger("WarningLog")
+        self.__lev = lev
+
+    def	compute(self, curIteration):
+        if self.getInputSignal(curIteration, "IN1").value == 1:
+            if self.__lev == level.WARNING:
+                self.__logger.warning("Time " + str(self.getClock().getTime()) + ": " + self.__string)
+            elif self.__lev == level.ERROR:
+                self.__logger.error("Time " + str(self.getClock().getTime()) + ": " + self.__string)
+            elif self.__lev == level.FATAL:
+                self.__logger.fatal("Time " + str(self.getClock().getTime()) + ": " + self.__string)
+
+class Clock:
+    """
+    The clock of the simulation
+    delta_t is the timestep of the simulation
+    """
+    def __init__(self, delta_t):
+        self.__delta_t = delta_t
+        self.__time = 0.0
+
+    def getTime(self):
+        return self.__time
+
+    def step(self):
+        self.__time = self.__time + self.__delta_t
+
+    def setDeltaT(self, new_delta_t):
+        self.__delta_t = new_delta_t
+
+    def getDeltaT(self):
+        return self.__delta_t
+
+class CBD(BaseBlock):
+    """
+    The CBD class, contains an entire Causal Block Diagram
+    Call the run function to simulate the model.
+    """
+    def __init__(self, block_name, input_ports = None, output_ports = None):
+        input_ports = input_ports if input_ports != None else []
+        output_ports = output_ports if output_ports != None else []
+        BaseBlock.__init__(self, block_name, input_ports, output_ports)
+        #The blocks in the CBD will be stored both
+        #-as an ordered list __blocks and
+        #-as a dictionary __blocksDict with the blocknames as keys
+        #for fast name-based retrieval and to ensure block names are unique within a single CBD
+        self.__blocks = []
+        self.__blocksDict = {}
+        self.__clock = None
+        self.__deltaT = None
+        self.__logger = naivelog.getLogger("CBD")
+
+        for input_port in input_ports:
+            self.addBlock(InputPortBlock(input_port, self))
+
+        for output_port in output_ports:
+            self.addBlock(OutputPortBlock(output_port, self))
+
+    def getTopCBD(self):
+        return self if self._parent == None else self._parent.getTopCBD()
+
+    def setBlocks(self, blocks):
+        # blocks must be a list of BaseBlock (subclass) instances
+        assert type(blocks) == list, ("CBD.setBlocks() takes a list as argument, not a %s" % type(blocks))
+        for block in blocks:
+            assert isinstance(block, BaseBlock), "CBD.setBlocks() takes a list of BaseBlock (subclass) instances"
+
+    def getBlocks(self):
+        return self.__blocks
+
+    def getBlockByName(self, name):
+        return self.__blocksDict[name]
+    
+    def setClock(self, clock):
+        self.__clock = clock;
+    
+    def getClock(self):
+        return self.__clock if self._parent == None else self._parent.getClock()
+
+    def setDeltaT(self, deltaT):
+        self.__deltaT = deltaT
+
+    def addBlock(self, block):
+        """
+        Add a block to the CBD model
+        """
+        assert isinstance(block, BaseBlock), "Can only add BaseBlock (subclass) instances to a CBD"
+        block.setParent(self)
+
+        if not self.__blocksDict.has_key(block.getBlockName()):
+            self.__blocks.append(block)
+            self.__blocksDict[block.getBlockName()] = block
+        else:
+            print("Warning: did not add this block as it has the same name %s as an existing block" % block.getBlockName())
+
+    def removeBlock(self, block):
+        assert isinstance(block, BaseBlock), "Can only delete BaseBlock (subclass) instances to a CBD"
+
+        if self.__blocksDict.has_key(block.getBlockName()):
+            self.__blocks.remove(block)
+            del self.__blocksDict[block.getBlockName()]
+        else:
+            exit("Warning: did not remove this block %s as it was not found" % block.getBlockName())
+
+    def addConnection(self, from_block, to_block, input_port_name = None, output_port_name = None):
+        """
+        Add a connection between from_block with input_port_name to to_block with outport_port_name
+        """
+        if type(from_block) == str:
+            from_block = self.getBlockByName(from_block)
+        if type(to_block) == str:
+            to_block = self.getBlockByName(to_block)
+        to_block.linkInput(from_block, input_port_name, output_port_name)
+
+    def __repr__(self):
+        repr = BaseBlock.__repr__(self)
+        repr += "\n"
+        for block in self.getBlocks():
+            repr+= block.__repr__()
+        return repr
+
+    def dump(self):
+        print("=========== Start of Model Dump ===========")
+        print(self)
+        print("=========== End of Model Dump =============\n")
+
+    def dumpSignals(self):
+        print("=========== Start of Signals Dump ===========")
+        for block in self.getBlocks():
+            print("%s:%s" % (block.getBlockName(), block.getBlockType()))
+            print(str(block.getSignal()) + "\n")
+        print("=========== End of Signals Dump =============\n")
+    
+    def resetSignals(self):
+        for block in self.getBlocks():
+            block.resetSignals()
+    
+    def getSignal(self, name_output = None):
+        name_output = "OUT1" if name_output == None else name_output
+        portBlock = self.getBlockByName(name_output)
+        assert portBlock != None
+        return portBlock.getSignal("OUT1")
+    
+    # TODO: probably remove this feature
+    def setSignal(self, value, name_output = None):    
+        name_output = "OUT1" if name_output == None else name_output
+        portBlock = self.getBlockByName(name_output)
+        assert portBlock != None
+        portBlock.setSignal(value, "OUT1")
+    
+    
+class AddOneBlock(CBD):
+    """
+    Block adds a one to the input (used a lot for mux)
+    """
+    def __init__(self, block_name, faultOrder=3):
+        CBD.__init__(self, block_name, ["IN1"], ["OUT1"])
+        self.addBlock(ConstantBlock(block_name="OneConstant", value=1))
+        self.addBlock(AdderBlock("PlusOne"))
+        self.addConnection("IN1", "PlusOne")
+        self.addConnection("OneConstant", "PlusOne")
+        self.addConnection("PlusOne", "OUT1")
+
+class DerivatorBlock(CBD):
+    """
+    The derivator block is a CBD that calculates the derivative
+    """
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["IN1", "delta_t", "IC"], ["OUT1"])
+        self.addBlock(ProductBlock(block_name="multIc"))
+        self.addBlock(NegatorBlock(block_name="neg1"))
+        self.addBlock(AdderBlock(block_name="sum1"))
+        self.addBlock(DelayBlock(block_name="delay"))
+        self.addBlock(NegatorBlock(block_name="neg2"))
+        self.addBlock(AdderBlock(block_name="sum2"))
+        self.addBlock(ProductBlock(block_name="mult"))
+        self.addBlock(InverterBlock(block_name="inv"))
+        
+        self.addConnection("IC", "multIc")
+        self.addConnection("delta_t", "multIc")
+        self.addConnection("multIc", "neg1")
+        self.addConnection("neg1", "sum1")
+        self.addConnection("IN1", "sum1")
+        self.addConnection("sum1", "delay", input_port_name="IC")
+        self.addConnection("IN1", "delay", input_port_name="IN1")
+        self.addConnection("delay", "neg2")
+        self.addConnection("neg2", "sum2")
+        self.addConnection("IN1", "sum2")
+        self.addConnection("sum2", "mult")
+        self.addConnection("delta_t", "inv")
+        self.addConnection("inv", "mult")
+        self.addConnection("mult", "OUT1")
+        
+
+class IntegratorBlock(CBD):
+    """
+    The integrator block is a CBD that calculates the integration
+    """
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["IN1", "delta_t", "IC"], ["OUT1"])
+        self.addBlock(ConstantBlock(block_name="zero", value=0))
+        self.addBlock(DelayBlock(block_name="delayIn"))
+        self.addBlock(ProductBlock(block_name="multDelta"))
+        self.addBlock(DelayBlock(block_name="delayState"))
+        self.addBlock(AdderBlock(block_name="sumState"))
+        
+        self.addConnection("zero", "delayIn", input_port_name="IC")
+        self.addConnection("IN1", "delayIn", input_port_name="IN1")
+        self.addConnection("delayIn", "multDelta")
+        self.addConnection("delta_t", "multDelta")
+        self.addConnection("multDelta", "sumState")
+        self.addConnection("IC", "delayState", input_port_name="IC")
+        self.addConnection("delayState", "sumState")
+        self.addConnection("sumState", "delayState", input_port_name="IN1")
+        self.addConnection("sumState", "OUT1")
+        
+        
+
+""" This module implements a dependency graph
+    @author: Marc Provost
+    @organization: McGill University
+    @license: GNU General Public License
+    @contact: marc.provost@mail.mcgill.ca
+"""
+
+import copy
+class DepNode:
+    """ Class implementing a node in the dependency graph.
+    """
+
+    def __init__(self, object):
+        """ DepNode's constructor.
+                @param object: Reference to a semantic object identifying the node
+                @type object: Object
+        """
+        self.__object = object
+        self.__isMarked	 = False
+
+    def mark(self):
+        self.__isMarked = True
+
+    def unMark(self):
+        self.__isMarked = False
+
+    def isMarked(self):
+        return self.__isMarked
+
+    def getMappedObj(self):
+        return self.__object
+
+    def __repr__(self):
+        return "DepNode :: "+str(self.__object)
+
+class DepGraph:
+    """ Class implementing dependency graph.
+    """
+
+    def __init__(self):
+        """ DepGraph's constructor.
+        """
+        #Dict holding a mapping "Object -> DepNode"
+        self.__semanticMapping = {}
+
+        #map object->list of objects depending on object
+        self.__dependents = {}
+        #map object->list of objects that influences object
+        self.__influencers = {}
+
+    def __repr__(self):
+        repr = "Dependents: \n"
+        for dep in self.__dependents:
+            repr += dep.getBlockName() + ":" + str(self.__dependents[dep]) + "\n"
+        repr += "Influencers: \n"
+        for infl in self.__influencers:
+            repr += infl.getBlockName() + ":" + str(self.__influencers[infl]) + "\n"
+        return repr
+
+    def addMember(self, object):
+        """ Add an object mapped to this graph.
+                @param object: the object to be added
+                @type object: Object
+                @raise ValueError: If object is already in the graph
+        """
+        if not self.hasMember(object):
+            if not isinstance(object, CBD):
+                node = DepNode(object)
+                self.__dependents[object] = []
+                self.__influencers[object] = []
+                self.__semanticMapping[object] = node
+            else:
+                for block in object.getBlocks():
+                    self.addMember(block)
+        else:
+            raise ValueError("Specified object is already member of this graph")
+
+    def hasMember(self, object):
+        return self.__semanticMapping.has_key(object)
+
+    def removeMember(self, object):
+        """ Remove a object from this graph.
+                @param object: the object to be removed
+                @type object: Object
+                @raise ValueError: If object is not in the graph
+        """
+        if self.hasMember(object):
+            for dependent in self.getDependents(object):
+                self.__influencers[dependent].remove(object)
+            for influencer in self.getInfluencers(object):
+                self.__dependents[influencer].remove(object)
+
+            del self.__dependents[object]
+            del self.__influencers[object]
+            del self.__semanticMapping[object]
+        else:
+            raise ValueError("Specified object is not member of this graph")
+
+    def setDependency(self, dependent, influencer, curIt):
+        """
+            Creates a dependency between two objects.
+                @param dependent: The object which depends on the other
+                @param influcencer: The object which influences the other
+                @type dependent: Object
+                @type dependent: Object
+                @raise ValueError: if depedent or influencer is not member of this graph
+                @raise ValueError: if the dependency already exists
+        """
+
+        # Link CBD outputs
+        if isinstance(influencer, CBD):
+            # When there is more than one connection from a CBD to one and the same block,
+            # more than one dependency should be set, as there is more than one underlying
+            # output block
+            for output_port in [ y.output_port for (x,y) in dependent.getLinksIn().iteritems() if y.block == influencer ]:
+                self.setDependency(dependent, influencer.getBlockByName(output_port), curIt)
+            return
+
+        # Link CBD inputs
+        if isinstance(dependent, CBD):
+            cbd = dependent
+            directlyConnected = influencer.parent if isinstance(influencer, OutputPortBlock) else influencer
+            inputnames = dependent.getInputName(directlyConnected)
+
+            # When one influencer has multiple connections to this CBD, call this function once fo
+            for inputname in inputnames:
+                inputtingBlock = dependent.getBlockByName(inputname)
+                thisdep = inputtingBlock
+                self.setDependency(thisdep, influencer, curIt)
+            return
+
+        if self.hasMember(dependent) and self.hasMember(influencer):
+            if not influencer in self.__influencers[dependent] and\
+                 not dependent in self.__dependents[influencer]:
+                self.__influencers[dependent].append(influencer)
+                self.__dependents[influencer].append(dependent)
+        else:
+            if not self.hasMember(dependent):
+                raise ValueError("Specified dependent object is not member of this graph")
+            if not self.hasMember(influencer):
+                print(influencer)
+                raise ValueError("Specified influencer object is not member of this graph")
+
+    def hasDependency(self, dependent, influencer):
+        if self.hasMember(dependent) and self.hasMember(influencer):
+            return influencer in self.__influencers[dependent] and\
+                         dependent in self.__dependents[influencer]
+        else:
+            if not self.hasMember(dependent):
+                raise ValueError("Specified dependent object is not member of this graph")
+            if not self.hasMember(influencer):
+                raise ValueError("Specified influencer object is not member of this graph")
+
+    def unsetDependency(self, dependent, influencer):
+        """ Removes a dependency between two objects.
+                @param dependent: The object which depends on the other
+                @param influcencer: The object which influences the other
+                @type dependent: Object
+                @type dependent: Object
+                @raise ValueError: if depedent or influencer is not member of this graph
+                @raise ValueError: if the dependency does not exists
+        """
+        if self.hasMember(dependent) and self.hasMember(influencer):
+            if influencer in self.__influencers[dependent] and\
+                 dependent in self.__dependents[influencer]:
+                self.__influencers[dependent].remove(influencer)
+                self.__dependents[influencer].remove(dependent)
+            else:
+                raise ValueError("Specified dependency does not exists")
+        else:
+            if not self.hasMember(dependent):
+                raise ValueError("Specified dependent object is not member of this graph")
+            if not self.hasMember(influencer):
+                raise ValueError("Specified influencer object is not member of this graph")
+
+    def getDependents(self, object):
+        if self.hasMember(object):
+            return copy.copy(self.__dependents[object])
+        else:
+            raise ValueError("Specified object is not member of this graph")
+
+    def getInfluencers(self, object):
+        if self.hasMember(object):
+            return copy.copy(self.__influencers[object])
+        else:
+            raise ValueError("Specified object is not member of this graph")
+
+    def getStrongComponents(self, curIt = 1):
+        return self.__strongComponents(curIt)
+
+    def __getDepNode(self, object):
+        if self.hasMember(object):
+            return self.__semanticMapping[object]
+        else:
+            raise ValueError("Specified object is not a member of this graph")
+
+    def __mark(self, object):
+        self.__getDepNode(object).mark()
+
+    def __unMark(self, object):
+        self.__getDepNode(object).unMark()
+
+    def __isMarked(self, object):
+        return self.__getDepNode(object).isMarked()
+
+    def __topoSort(self):
+        """ Performs a topological sort on the graph.
+        """
+        for object in self.__semanticMapping.keys():
+            self.__unMark(object)
+
+        sortedList = []
+
+        for object in self.__semanticMapping.keys():
+            if not self.__isMarked(object):
+                self.__dfsSort(object, sortedList)
+
+        return sortedList
+
+    def __dfsSort(self, object, sortedList):
+        """ Performs a depth first search collecting
+                the objects in topological order.
+                @param object: the currently visited object.
+                @param sortedList: partial sorted list of objects
+                @type object: Object
+                @type sortedList: list Of Object
+        """
+
+        if not self.__isMarked(object):
+            self.__mark(object)
+
+            for influencer in self.getInfluencers(object):
+                self.__dfsSort(influencer, sortedList)
+
+            sortedList.append(object)
+
+    def __strongComponents(self, curIt):
+        """ Determine the strong components of the graph
+                @rtype: list of list of Object
+        """
+        strongComponents = []
+        sortedList = self.__topoSort()
+
+        for object in self.__semanticMapping.keys():
+            self.__unMark(object)
+
+        sortedList.reverse()
+
+        for object in sortedList:
+            if not self.__isMarked(object):
+                component = []
+                self.__dfsCollect(object, component, curIt)
+                strongComponents.append(component)
+
+        strongComponents.reverse()
+        return strongComponents
+
+    def __dfsCollect(self, object, component, curIt):
+        """ Collects objects member of a strong component.
+                @param object: Node currently visited
+                @param component: current component
+                @type object: Object
+                @type component: List of Object
+        """
+        if not self.__isMarked(object):
+            self.__mark(object)
+
+            for dependent in self.getDependents(object):
+                self.__dfsCollect(dependent, component, curIt)
+
+            component.append(object)
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 54 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/CBDDraw.py

@@ -0,0 +1,54 @@
+from CBD import *
+
+def draw(cbd, filename, colors=None):
+	""" Output cbd as a dot script to filename.
+
+	colors is a dictionary of blockname => color
+	"""
+	f = open(filename, "w")
+	write = lambda s: f.write(s)
+
+	write("""
+digraph graphname {
+ """)
+
+	if colors == None:
+		colors = {}
+
+	def writeBlock(block):
+		if isinstance(block, ConstantBlock):
+			label = block.getBlockType() + " (" + block.getBlockName() + ")\\n" + str(block.getValue())
+		else:
+			label = block.getBlockType() + " (" + block.getBlockName() + ")"
+
+		shape = ""
+		if isinstance(block, CBD):
+			shape=",shape=Msquare"
+
+		col = ""
+		if block.getBlockName() in colors:
+			col = ", color=\"{0}\", fontcolor=\"{0}\"".format(colors[block.getBlockName()])
+
+		write("{b} [label=\"{lbl}\"{shape}{col}];\n".format(b=block.getBlockName(),
+			lbl=label,
+			shape=shape,
+			col=col))
+
+
+	for block in cbd.getBlocks():
+		writeBlock(block)
+		for (name, other) in  block.getLinksIn().iteritems():
+			label = ""
+
+			if not name.startswith("IN"):
+				label=name
+
+			if not other.output_port.startswith("OUT"):
+				label = label + " / " + other.output_port
+
+			write("{a} -> {b} [label=\"{lbl}\"];\n".format(a=other.block.getBlockName(),
+				b=block.getBlockName(),
+				lbl=label))
+
+	write("\n}")
+

+ 0 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/__init__.py


+ 129 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/naivelog.py

@@ -0,0 +1,129 @@
+import os
+import sys
+import datetime
+(DEBUG, INFO, WARNING, ERROR, FATAL) = (0, 1, 2, 3, 4)
+
+def strToLevel(elvl):
+	if elvl == "DEBUG":
+		return DEBUG
+	if elvl == "INFO":
+		return INFO
+	if elvl == "WARNING":
+		return WARNING
+	if elvl == "ERROR":
+		return ERROR
+	if elvl == "FATAL":
+		return FATAL
+	else:
+		return None
+
+def levelToStr(lvl):
+	if lvl == DEBUG:
+		return "DEBUG"
+	if lvl == INFO:
+		return "INFO"
+	if lvl == WARNING:
+		return "WARNING"
+	if lvl == ERROR:
+		return "ERROR"
+	if lvl == FATAL:
+		return "FATAL"
+	return None
+
+
+def levelToShortStr(lvl):
+	if lvl == DEBUG:
+		return "DBUG"
+	if lvl == INFO:
+		return "INFO"
+	if lvl == WARNING:
+		return "WARN"
+	if lvl == ERROR:
+		return "ERROR"
+	if lvl == FATAL:
+		return "FATAL"
+	return None
+
+class Logger:
+	def __init__(self, modulename, level, crashlevel):
+		self.__modulename = modulename
+		self.__level = level
+		self.__crashlevel = crashlevel
+
+	def debug(self, mainstr, *args, **kwargs):
+		self.log(DEBUG, mainstr, *args, **kwargs)
+	def info(self, mainstr, *args, **kwargs):
+		self.log(INFO, mainstr, *args, **kwargs)
+	def warning(self, mainstr, *args, **kwargs):
+		self.log(WARNING, mainstr, *args, **kwargs)
+	def error(self, mainstr, *args, **kwargs):
+		self.log(ERROR, mainstr, *args, **kwargs)
+	def fatal(self, mainstr, *args, **kwargs):
+		self.log(FATAL, mainstr, *args, **kwargs)
+
+	def log(self, level, mainstr, *args, **kwargs):
+		if level >= self.__level:
+			sys.stdout.write(self.formatmsg(level,str(mainstr).format(*args, **kwargs)))
+
+		if level >= self.__crashlevel:
+			exit(1)
+
+	def setLevel(self, level):
+		self.__level = level
+
+	def formatmsg(self, level, mainstr):
+		class bcolors:
+			HEADER = '\033[95m'
+			OKBLUE = '\033[94m'
+			OKGREEN = '\033[92m'
+			WARNING = '\033[93m'
+			FAIL = '\033[91m'
+			ENDC = '\033[0m'
+	
+
+		col = bcolors.OKGREEN
+		if level >= WARNING:
+			col = bcolors.WARNING
+		if level >= ERROR:
+			col = bcolors.FAIL
+
+		return "{startcol}[{now:%H:%M:%S.%f} {module} {lvl}] {mainstr}{endcol}\n".format(
+				lvl=levelToShortStr(level),
+				module=self.__modulename,
+				now=datetime.datetime.today(),
+				mainstr=mainstr,
+				startcol=col,
+				endcol=bcolors.ENDC);
+
+defaultLogLevel = INFO
+defaultCrashLevel = FATAL
+
+def getAbstractLogLevel(env, default):
+	elvl = os.environ[env] if env in os.environ else ''
+
+	lvl = strToLevel(elvl)
+	if lvl:
+		return lvl
+	else:
+		return default
+
+def getLogLevel():
+	return getAbstractLogLevel('NAIVE_LOGLEVEL', defaultLogLevel)
+
+def getCrashLevel():
+	return getAbstractLogLevel('NAIVE_CRASHLEVEL', defaultCrashLevel)
+
+def getLogger(modulename):
+	return Logger(modulename, getLogLevel(), getCrashLevel())
+
+if __name__ == "__main__":
+	l = getLogger('testmodule')
+	l.info("bla");
+	l.info("test nummer {}{}", 2, " is good")
+	l.info("test {hier} is ook ok", hier=3, daar=4)
+	l.info("should not see this")
+
+
+	l2 = getLogger('testmodule.m2')
+	l2.info("More info")
+	l2.info("and even more")

+ 49 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/plot.py

@@ -0,0 +1,49 @@
+__author__ = 'joachimdenil'
+
+from math import ceil
+import matplotlib
+matplotlib.use('TkAgg')
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
+from matplotlib.figure import Figure
+from matplotlib.lines import Line2D
+import numpy as np
+import threading
+
+try:
+    import Tkinter as Tk
+except ImportError:
+    import tkinter as Tk
+
+class ScopeWindow():
+    def __init__(self, theOutportRefs, names):
+        """
+        Plot results in a Tk window using matlplotlib
+        @param theOutportRefs: array of values to plot: [[x1,x2,xn], ... ,[y1,y2, , yn]]
+        @param names: the labels for each of the plots: list [name1, name2, ...,  namen]
+        @return:
+        """
+        self.root = Tk.Tk()
+        self.f = Figure()
+        n = len(theOutportRefs)
+        n = int(ceil(n*1.00/2))
+        index = 1
+        self.ax = []
+        for outport in theOutportRefs:
+            self.ax.append(self.f.add_subplot(n, 2, index))
+            # add values:
+            self.ax[index-1].plot(outport, 'ro')
+            self.ax[index-1].set_xlabel('t')
+            self.ax[index-1].set_ylabel(names[index-1])
+            index+=1
+
+        self.canvas = FigureCanvasTkAgg(self.f, master=self.root)
+        self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
+        self.canvas.show()
+
+        self.toolbar = NavigationToolbar2TkAgg( self.canvas, self.root )
+        self.toolbar.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
+        self.toolbar.update()
+
+        self.button = Tk.Button(master=self.root, text='Quit', command=self.root.destroy)
+        self.button.pack(side=Tk.BOTTOM)
+        self.root.mainloop()

+ 48 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/CounterTest.py

@@ -0,0 +1,48 @@
+__author__ = 'joachimdenil'
+
+import unittest
+from CBDMultipleOutput.Source.CBD import *
+from CBDMultipleOutput.Source.plot import ScopeWindow
+from basicCBDTest import BasicCBDTestCase
+
+NUM_DISCR_TIME_STEPS = 10
+
+class FlattenCBDTest(unittest.TestCase):
+    def setUp(self):
+        self.CBD = CBD("block_under_test")
+
+    def _run(self, num_steps=1, step = 1):
+        self.CBD.run(num_steps, step)
+
+    def _getSignal(self, blockname, output_port = None):
+        foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
+        signal =  foundBlocks[0].getSignal(name_output = output_port)
+        if len(foundBlocks) == 1:
+            return [x.value for x in signal]
+        else:
+            raise Exception("No single block with name " + blockname + " found")
+
+    def testCounter(self):
+        self.CBD.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.CBD.addBlock(DelayBlock(block_name="s"))
+        self.CBD.addConnection("zero", "s", input_port_name="IC")
+        self.CBD.addBlock(ConstantBlock(block_name="one", value=1.0))
+        self.CBD.addBlock(AdderBlock(block_name="plusOne"))
+        self.CBD.addConnection("one", "plusOne")
+        self.CBD.addConnection("s", "plusOne")
+        self.CBD.addConnection("plusOne", "s")
+
+        self._run(NUM_DISCR_TIME_STEPS)
+        ScopeWindow([self._getSignal("zero"), self._getSignal("one"), self._getSignal("s")],
+            ["zero", "one", "s"] )
+        self.assertEquals(self._getSignal("s"), [float(x) for x in range(NUM_DISCR_TIME_STEPS)])
+
+def suite():
+    """Returns a suite containing all the test cases in this module."""
+    suite1 = unittest.makeSuite(BasicCBDTestCase)
+
+    return unittest.TestSuite((suite1))
+
+if __name__ == '__main__':
+    # When this module is executed from the command-line, run all its tests
+    unittest.main()

+ 0 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/__init__.py


+ 551 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/basicCBDTest.py

@@ -0,0 +1,551 @@
+#!/usr/bin/env python
+#
+# Unit tests for all the basic CBD blocks, discrete-time CBD. 
+
+import unittest
+
+from CBDMultipleOutput.Source.CBD import *
+
+NUM_DISCR_TIME_STEPS = 5
+
+class BasicCBDTestCase(unittest.TestCase):
+  def setUp(self):
+    self.CBD = CBD("CBD_for_block_under_test")    
+    
+  def _run(self, num_steps=1, delta_t = 1.0):
+    self.CBD.run(num_steps, delta_t)      
+      
+  def _getSignal(self, blockname, output_port = None):
+    foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
+    numFoundBlocks = len(foundBlocks)  
+    if numFoundBlocks == 1:
+      signal =  foundBlocks[0].getSignal(name_output = output_port)
+      return [x.value for x in signal]
+    else:
+      raise Exception(str(numFoundBlocks) + " blocks with name " + blockname + " found.\nExpected a single block.")  
+  
+  def testConstantBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=3.3))
+
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("c1"), [3.3] * NUM_DISCR_TIME_STEPS)
+    
+  def testNegatorBlockPos(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
+    self.CBD.addBlock(NegatorBlock(block_name="n"))
+    self.CBD.addConnection("c1", "n")
+
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("n"), [-6.0] * NUM_DISCR_TIME_STEPS)  
+  
+  def testNegatorBlockNeg(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=-6.0))
+    self.CBD.addBlock(NegatorBlock(block_name="n"))
+    self.CBD.addConnection("c1", "n")
+
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("n"), [6.0] * NUM_DISCR_TIME_STEPS)  
+    
+  def testNegatorBlockZero(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=0.0))
+    self.CBD.addBlock(NegatorBlock(block_name="n"))
+    self.CBD.addConnection("c1", "n")
+
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("n"), [0.0] * NUM_DISCR_TIME_STEPS)  
+    
+  def testInverterBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=5.0))
+    self.CBD.addBlock(InverterBlock(block_name="i1"))
+    self.CBD.addBlock(InverterBlock(block_name="i2"))
+
+    self.CBD.addConnection("c1", "i1")
+    self.CBD.addConnection("i1", "i2")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("i1"), [0.2] * NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("i2"), [5.0] * NUM_DISCR_TIME_STEPS)
+
+  def testAdderBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=6.0))
+    self.CBD.addBlock(AdderBlock(block_name="a"))
+    
+    self.CBD.addConnection("c1", "a")
+    self.CBD.addConnection("c2", "a")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a"), [8.0] * NUM_DISCR_TIME_STEPS)
+    
+  def testAdderBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=-6.0))
+    self.CBD.addBlock(AdderBlock(block_name="a"))
+    
+    self.CBD.addConnection("c1", "a")
+    self.CBD.addConnection("c2", "a")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a"), [-4.0] * NUM_DISCR_TIME_STEPS)    
+    
+  def testProductBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
+    self.CBD.addBlock(ProductBlock(block_name="p"))
+    
+    self.CBD.addConnection("c1", "p")
+    self.CBD.addConnection("c2", "p")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("p"), [10.0] * 5)
+
+  def testProductBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=1.0/2.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=4.0))
+    self.CBD.addBlock(ProductBlock(block_name="p"))
+    
+    self.CBD.addConnection("c1", "p")
+    self.CBD.addConnection("c2", "p")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("p"), [2.0] * 5)
+    
+  def testGenericBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.2))
+    self.CBD.addBlock(GenericBlock(block_name="g", block_operator="ceil"))
+    
+    self.CBD.addConnection("c1", "g")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("g"), [3.0] * 5)  
+    
+  def testRootBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
+    self.CBD.addBlock(RootBlock(block_name="g"))
+
+    self.CBD.addConnection("c1", "g")
+    self.CBD.addConnection("c2", "g")
+    self._run(1)
+    self.assertEquals(self._getSignal("g"), [2.0])
+        
+  def testRootBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=9.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=2.0))
+    self.CBD.addBlock(RootBlock(block_name="g"))
+
+    self.CBD.addConnection("c1", "g")
+    self.CBD.addConnection("c2", "g")
+    self._run(1)
+    self.assertEquals(self._getSignal("g"), [3.0])
+        
+  def testModuloBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
+    self.CBD.addBlock(ModuloBlock(block_name="g"))
+
+    self.CBD.addConnection("c1", "g")
+    self.CBD.addConnection("c2", "g")
+    self._run(1)
+    self.assertEquals(self._getSignal("g"), [2.0])
+
+  def testModuloBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=8.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=8.0))
+    self.CBD.addBlock(ModuloBlock(block_name="g"))
+
+    self.CBD.addConnection("c1", "g")
+    self.CBD.addConnection("c2", "g")
+    self._run(1)
+    self.assertEquals(self._getSignal("g"), [0.0])
+
+  def testPreviousValueDelayBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="ZeroConstant", value=0.0))
+    self.CBD.addBlock(SequenceBlock(block_name="seq", sequence=[0, 2, 4, 6, 8, 10, 12]))
+    self.CBD.addBlock(DelayBlock(block_name="d"))
+    
+    self.CBD.addConnection("ZeroConstant", "d", input_port_name="IC")
+    self.CBD.addConnection("seq", "d")
+    
+    self._run(7, 0.5)
+    self.assertEquals(self._getSignal("d"), [0, 0, 2, 4, 6, 8, 10])    
+    
+  def testPreviousValueDelayBlock2(self):
+    self.CBD.addBlock(SequenceBlock(block_name="FirstSeq", sequence=[2, 12, 22, 23, 32, 11, 91]))
+    self.CBD.addBlock(SequenceBlock(block_name="SecSeq", sequence=[5, 5, 5, 5, 3, 3, 3]))
+    self.CBD.addBlock(DelayBlock(block_name="prev"))
+    self.CBD.addConnection(self.CBD.getBlockByName("FirstSeq"), "prev")
+    self.CBD.addConnection(self.CBD.getBlockByName("SecSeq"), "prev", input_port_name="IC")
+    self._run(7)  
+    self.assertEquals(self._getSignal("prev"), [5, 2, 12, 22, 23, 32, 11])    
+          
+  def testTimeBlock(self):
+    self.CBD.addBlock(TimeBlock(block_name="t"))
+    self._run(4)
+    self.assertEquals(self._getSignal("t"), [0.0, 1.0, 2.0, 3.0])
+
+  def testLessThanBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=-5.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c3", value=0))
+    self.CBD.addBlock(LessThanBlock(block_name="lt1"))
+    self.CBD.addBlock(LessThanBlock(block_name="lt2"))
+    self.CBD.addBlock(LessThanBlock(block_name="lt3"))
+    
+    self.CBD.addConnection("c1", "lt1")
+    self.CBD.addConnection("c1", "lt1", input_port_name="IC")
+    self.CBD.addConnection("c1", "lt2")
+    self.CBD.addConnection("c2", "lt2", input_port_name="IC")
+    self.CBD.addConnection("c2", "lt3")
+    self.CBD.addConnection("c3", "lt3", input_port_name="IC")
+
+    self._run(1)
+    self.assertEquals(self._getSignal("lt1"), [0.0])  
+    self.assertEquals(self._getSignal("lt2"), [0.0])  
+    self.assertEquals(self._getSignal("lt3"), [1.0])  
+    
+  def testEqualsBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=-5.0))
+    self.CBD.addBlock(EqualsBlock(block_name="eq1"))
+    self.CBD.addBlock(EqualsBlock(block_name="eq2"))
+    
+    self.CBD.addConnection("c1", "eq1")
+    self.CBD.addConnection("c1", "eq1", input_port_name="IC")
+    self.CBD.addConnection("c1", "eq2")
+    self.CBD.addConnection("c2", "eq2", input_port_name="IC")
+    
+    self._run(1)
+    self.assertEquals(self._getSignal("eq1"), [1.0])  
+    self.assertEquals(self._getSignal("eq2"), [0.0])  
+    
+  def testNotBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
+    self.CBD.addBlock(NotBlock(block_name="NotBlock"))
+    self.CBD.addConnection("One", "NotBlock")      
+    self._run(1)
+    self.assertEquals(self._getSignal("NotBlock"), [0])    
+    
+  def testNotBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="Zero", value=0))
+    self.CBD.addBlock(NotBlock(block_name="NotBlock"))
+    self.CBD.addConnection("Zero", "NotBlock")      
+    self._run(1)      
+    self.assertEquals(self._getSignal("NotBlock"), [1])        
+    
+  def testOrBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
+    self.CBD.addBlock(ConstantBlock(block_name="Zero", value=0))
+    self.CBD.addBlock(OrBlock(block_name="OrBlock1"))
+    self.CBD.addConnection("Zero", "OrBlock1")    
+    self.CBD.addConnection("Zero", "OrBlock1")  
+    
+    self.CBD.addBlock(OrBlock(block_name="OrBlock2"))
+    self.CBD.addConnection("One", "OrBlock2")    
+    self.CBD.addConnection("Zero", "OrBlock2")
+    
+    self.CBD.addBlock(OrBlock(block_name="OrBlock3"))    
+    self.CBD.addConnection("One", "OrBlock3")    
+    self.CBD.addConnection("One", "OrBlock3")
+    
+    self.CBD.addBlock(OrBlock(block_name="OrBlock4", numberOfInputs=4))
+    self.CBD.addConnection("Zero", "OrBlock4")    
+    self.CBD.addConnection("Zero", "OrBlock4")
+    self.CBD.addConnection("One", "OrBlock4")
+    self.CBD.addConnection("Zero", "OrBlock4")
+        
+    self._run(1)
+    self.assertEquals(self._getSignal("OrBlock1"), [0])      
+    self.assertEquals(self._getSignal("OrBlock2"), [1])      
+    self.assertEquals(self._getSignal("OrBlock3"), [1])      
+    self.assertEquals(self._getSignal("OrBlock4"), [1])      
+    
+  def testAndBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
+    self.CBD.addBlock(ConstantBlock(block_name="Zero", value=0))
+    self.CBD.addBlock(AndBlock(block_name="AndBlock1"))
+    self.CBD.addConnection("Zero", "AndBlock1")    
+    self.CBD.addConnection("Zero", "AndBlock1")  
+    
+    self.CBD.addBlock(AndBlock(block_name="AndBlock2"))
+    self.CBD.addConnection("One", "AndBlock2")    
+    self.CBD.addConnection("Zero", "AndBlock2")
+    
+    self.CBD.addBlock(AndBlock(block_name="AndBlock3"))    
+    self.CBD.addConnection("One", "AndBlock3")    
+    self.CBD.addConnection("One", "AndBlock3")
+    
+    self.CBD.addBlock(AndBlock(block_name="AndBlock4"))    
+    self.CBD.addConnection("Zero", "AndBlock4")    
+    self.CBD.addConnection("One", "AndBlock4")
+    
+    self.CBD.addBlock(AndBlock(block_name="AndBlock5", numberOfInputs=4))
+    self.CBD.addConnection("Zero", "AndBlock5")    
+    self.CBD.addConnection("Zero", "AndBlock5")
+    self.CBD.addConnection("One", "AndBlock5")
+    self.CBD.addConnection("Zero", "AndBlock5")
+        
+    self._run(1)
+    self.assertEquals(self._getSignal("AndBlock1"), [0])      
+    self.assertEquals(self._getSignal("AndBlock2"), [0])      
+    self.assertEquals(self._getSignal("AndBlock3"), [1])      
+    self.assertEquals(self._getSignal("AndBlock4"), [0])      
+    self.assertEquals(self._getSignal("AndBlock5"), [0])      
+    
+  def testSequenceBlock(self):
+    self.CBD.addBlock(SequenceBlock(block_name="FirstSeq", sequence=[2, 2, 2, 3, 2, 1, 1]))
+    self._run(7)  
+    self.assertEquals(self._getSignal("FirstSeq"), [2, 2, 2, 3, 2, 1, 1])
+
+  def testLoggingBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="One", value=1))
+    self.CBD.addBlock(LoggingBlock("Test", "Logging block test with level is error", level.ERROR))
+    self.CBD.addConnection("One", "Test")
+    self._run(1)
+    
+
+  def testLinearStrongComponent(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.5))
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=-5))
+    self.CBD.addBlock(AdderBlock(block_name="a1"))
+    self.CBD.addBlock(AdderBlock(block_name="a3"))
+    self.CBD.addBlock(AdderBlock(block_name="a2"))
+
+    self.CBD.addConnection("a3", "a1")
+    self.CBD.addConnection("c1", "a1")
+    self.CBD.addConnection("a1", "a3")
+    self.CBD.addConnection("a2", "a3")
+    self.CBD.addConnection("c2", "a2")
+    self.CBD.addConnection("a3", "a2")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a1"), [-5.5]*5)
+    self.assertEquals(self._getSignal("a2"), [5.0]*5)
+    self.assertEquals(self._getSignal("a3"), [-0.5]*5)
+    
+  def testLinearStrongComponentWithDelay(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=3.0))
+    self.CBD.addBlock(AdderBlock(block_name="sum"))
+    self.CBD.addBlock(DelayBlock(block_name="delay"))
+    self.CBD.addBlock(NegatorBlock(block_name="neg"))
+
+    self.CBD.addConnection("c1", "sum")
+    self.CBD.addConnection("neg", "sum")
+    self.CBD.addConnection("sum", "delay", input_port_name="IC")
+    self.CBD.addConnection("delay", "neg")
+    self.CBD.addConnection("neg", "delay")
+    
+    self._run(1)
+    self.assertEquals(self._getSignal("delay"), [1.5])
+    
+  def testLinearStrongComponentWithMult(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=3))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=5))
+    self.CBD.addBlock(AdderBlock(block_name="a"))
+    self.CBD.addBlock(ProductBlock(block_name="p"))
+
+    self.CBD.addConnection("c1", "a")
+    self.CBD.addConnection("p", "a")
+    self.CBD.addConnection("a", "p")
+    self.CBD.addConnection("c2", "p")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a"), [-0.75]*5)
+    self.assertEquals(self._getSignal("p"), [-3.75]*5)
+    
+  def testLinearStrongComponentWithNeg(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=5))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=8))
+    self.CBD.addBlock(AdderBlock(block_name="a1"))
+    self.CBD.addBlock(AdderBlock(block_name="a2"))
+    self.CBD.addBlock(NegatorBlock(block_name="n"))
+
+    self.CBD.addConnection("c1", "a1")
+    self.CBD.addConnection("a2", "a1")
+    self.CBD.addConnection("c2", "a2")
+    self.CBD.addConnection("n", "a2")
+    self.CBD.addConnection("a1", "n")  
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a1"), [6.5]*5)
+    self.assertEquals(self._getSignal("a2"), [1.5]*5)  
+    self.assertEquals(self._getSignal("n"), [-6.5]*5)  
+    
+  def testTwoLinearStrongComponent(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=3))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=2))
+    self.CBD.addBlock(ConstantBlock(block_name="c3", value=1.5))
+    self.CBD.addBlock(ConstantBlock(block_name="c4", value=1))
+    self.CBD.addBlock(AdderBlock(block_name="a1"))
+    self.CBD.addBlock(AdderBlock(block_name="a2"))
+    self.CBD.addBlock(AdderBlock(block_name="a3"))
+    self.CBD.addBlock(AdderBlock(block_name="a4"))
+    self.CBD.addBlock(AdderBlock(block_name="a5"))
+    self.CBD.addBlock(ProductBlock(block_name="p"))
+    self.CBD.addBlock(NegatorBlock(block_name="n1"))
+    self.CBD.addBlock(NegatorBlock(block_name="n2"))
+
+    self.CBD.addConnection("a3", "a1")
+    self.CBD.addConnection("c1", "a1")
+    self.CBD.addConnection("c2", "a2")
+    self.CBD.addConnection("a3", "a2")
+    self.CBD.addConnection("a1", "a3")
+    self.CBD.addConnection("a2", "a3")
+    self.CBD.addConnection("a3", "p")
+    self.CBD.addConnection("c3", "p")
+    self.CBD.addConnection("p", "n1")
+    self.CBD.addConnection("n1", "a4")
+    self.CBD.addConnection("a5", "a4")
+    self.CBD.addConnection("c4", "a5")
+    self.CBD.addConnection("n2", "a5")
+    self.CBD.addConnection("a4", "n2")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("a1"), [-2.0]*5)
+    self.assertEquals(self._getSignal("a2"), [-3.0]*5)
+    self.assertEquals(self._getSignal("a3"), [-5.0]*5)
+    self.assertEquals(self._getSignal("a4"), [4.25]*5)
+    self.assertEquals(self._getSignal("a5"), [-3.25]*5)
+    self.assertEquals(self._getSignal("p"), [-7.5]*5)
+    self.assertEquals(self._getSignal("n1"), [7.5]*5)
+    self.assertEquals(self._getSignal("n2"), [-4.25]*5)
+        
+  def testNonLinearStrongComponent(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=15))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=10))
+    self.CBD.addBlock(AdderBlock(block_name="a1"))
+    self.CBD.addBlock(AdderBlock(block_name="a2"))
+    self.CBD.addBlock(ProductBlock(block_name="p"))
+
+    self.CBD.addConnection("c2", "a1")
+    self.CBD.addConnection("p", "a1")
+    self.CBD.addConnection("a1", "p")
+    self.CBD.addConnection("a2", "p")
+    self.CBD.addConnection("p", "a2")
+    self.CBD.addConnection("c1", "a2")
+    self.assertRaises(SystemExit, self._run, 5)    
+    
+  def initializeFuncDerBas(self):
+    #f(t) = 5*t  
+    CBDFunc = CBD("function", output_ports = ["OUT1"])
+    CBDFunc.addBlock(TimeBlock(block_name="t"))
+    CBDFunc.addBlock(ProductBlock(block_name="p"))
+    CBDFunc.addBlock(ConstantBlock(block_name="c", value=5.0))
+    CBDFunc.addConnection("t", "p") 
+    CBDFunc.addConnection("c", "p")
+    CBDFunc.addConnection("p", "OUT1")
+    return CBDFunc      
+      
+  def initializeFunc(self):
+    #f(t) = (t-2)^3  
+    CBDFunc = CBD("function", output_ports = ["OUT1"])
+    CBDFunc.addBlock(TimeBlock(block_name="t"))
+    CBDFunc.addBlock(ProductBlock(block_name="p"))
+    CBDFunc.addBlock(ProductBlock(block_name="p2"))
+    CBDFunc.addBlock(AdderBlock(block_name="a"))
+    CBDFunc.addBlock(ConstantBlock(block_name="c", value=-2.0))
+    CBDFunc.addConnection("t", "a") 
+    CBDFunc.addConnection("c", "a")
+    CBDFunc.addConnection("a", "p")
+    CBDFunc.addConnection("a", "p")
+    CBDFunc.addConnection("p", "p2")
+    CBDFunc.addConnection("a", "p2")
+    CBDFunc.addConnection("p2", "OUT1")
+    return CBDFunc  
+      
+  def initializeFunc2(self):
+    #f(t) = (t-2)^4
+    CBDFunc = CBD("function", output_ports = ["OUT1"])
+    CBDFunc.addBlock(TimeBlock(block_name="t"))
+    CBDFunc.addBlock(ProductBlock(block_name="p"))
+    CBDFunc.addBlock(ProductBlock(block_name="p2"))
+    CBDFunc.addBlock(ProductBlock(block_name="p3"))
+    CBDFunc.addBlock(AdderBlock(block_name="a"))
+    CBDFunc.addBlock(ConstantBlock(block_name="c", value=-2.0))
+    CBDFunc.addConnection("t", "a") 
+    CBDFunc.addConnection("c", "a")
+    CBDFunc.addConnection("a", "p")
+    CBDFunc.addConnection("a", "p")
+    CBDFunc.addConnection("p", "p2")
+    CBDFunc.addConnection("a", "p2")
+    CBDFunc.addConnection("p2", "p3")
+    CBDFunc.addConnection("a", "p3")
+    CBDFunc.addConnection("p3", "OUT1")
+    return CBDFunc      
+  
+  def initializeFuncInt(self):
+    #f(t) = 2*t  
+    CBDFunc = CBD("function", output_ports = ["OUT1"])
+    CBDFunc.addBlock(TimeBlock(block_name="t"))
+    CBDFunc.addBlock(ProductBlock(block_name="p"))
+    CBDFunc.addBlock(ConstantBlock(block_name="c", value=2.0))
+    CBDFunc.addConnection("t", "p") 
+    CBDFunc.addConnection("c", "p")
+    CBDFunc.addConnection("p", "OUT1")
+    return CBDFunc  
+     
+  def testDerivatorBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c3", value=1.0))
+    self.CBD.addBlock(ConstantBlock(block_name="zero", value=0.0))
+    CBDFunc = self.initializeFuncDerBas()
+    self.CBD.addBlock(CBDFunc) 
+    self.CBD.addBlock(DerivatorBlock(block_name="der"))
+    
+    self.CBD.addConnection("c3", "der", input_port_name="delta_t")
+    self.CBD.addConnection("zero", "der", input_port_name="IC")
+    self.CBD.addConnection("function", "der")
+    self._run(5)
+    self.assertEquals(self._getSignal("der"), [0.0]+[5.0]*4)    
+
+            
+  def testIntegratorBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=6.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=0.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c3", value=0.001))
+    self.CBD.addBlock(AdderBlock(block_name="a"))
+    self.CBD.addBlock(DelayBlock(block_name="d"))
+    
+    self.CBD.addBlock(IntegratorBlock(block_name="int"))
+    self.CBD.addConnection("c3", "int", input_port_name="delta_t")
+    self.CBD.addConnection("a", "int")
+    self.CBD.addConnection("c2", "int", input_port_name="IC")
+    
+    self.CBD.addConnection("c1", "a")
+    self.CBD.addConnection("d", "a")
+    self.CBD.addConnection("a", "d")
+    self.CBD.addConnection("c2", "d", input_port_name="IC")
+    self._run(NUM_DISCR_TIME_STEPS)
+    self.assertEquals(self._getSignal("int"), [0.0, 0.006, 0.018000000000000002, 0.036000000000000004, 0.060000000000000005])
+  
+  def testDelayBlock(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=5.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=3.0))
+    self.CBD.addBlock(DelayBlock(block_name="d"))
+    
+    self.CBD.addConnection("c2", "d")
+    self.CBD.addConnection("c1", "d", input_port_name="IC")
+    self._run(4)
+    self.assertEquals(self._getSignal("d"), [5.0, 3.0, 3.0, 3.0])
+
+  def testDelayBlock2(self):
+    self.CBD.addBlock(ConstantBlock(block_name="c1", value=1.0))
+    self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
+    self.CBD.addBlock(DelayBlock(block_name="d"))
+    self.CBD.addBlock(AdderBlock(block_name="a"))
+
+    self.CBD.addConnection("c2", "a")
+    self.CBD.addConnection("d", "a")
+    self.CBD.addConnection("c1", "d", input_port_name="IC")
+    self.CBD.addConnection("a", "d")
+    self._run(5)
+    self.assertEquals(self._getSignal("d"), [1.0, 6.0, 11.0, 16.0, 21.0])
+      
+
+def suite():
+    """Returns a test suite containing all the test cases in this module."""
+    suite = unittest.makeSuite(BasicCBDTestCase)
+    
+    return unittest.TestSuite((suite))
+
+if __name__ == '__main__':
+    # When this module is executed from the command-line, run all its tests
+    unittest.main(verbosity=2)
+
+  
+  
+  
+  
+  
+  
+  
+  

+ 201 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/flattenCBDTest.py

@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+#
+# Unit tests for the flatten function on the CBD
+
+import unittest
+from CBDMultipleOutput.Source.CBD import *
+from basicCBDTest import BasicCBDTestCase
+
+class FlattenCBDTest(unittest.TestCase):
+	def setUp(self):
+		self.CBD = CBD("block_under_test")		
+		
+	def _run(self, num_steps=1, step = 1):
+		self.CBD.run(num_steps, step)			
+			
+	def _getSignal(self, blockname, output_port = None):
+		foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
+		
+		signal =  foundBlocks[0].getSignal(name_output = output_port)
+		
+		if len(foundBlocks) == 1:
+			return [x.value for x in signal]
+		else:
+			raise Exception("No single block with name " + blockname + " found")
+							
+	def testInterCBD(self):
+		CBDLittle1 = CBD("first_child", output_ports = ["outCBD1"])
+		CBDLittle2 = CBD("second_child", input_ports = ["inCBD2"])
+		
+		self.CBD.addBlock(CBDLittle1)
+		self.CBD.addBlock(CBDLittle2)
+		self.CBD.addConnection("first_child", "second_child", input_port_name = "inCBD2", output_port_name = "outCBD1") 
+
+		CBDLittle1.addBlock(ConstantBlock(block_name="c1", value=2.0))
+		CBDLittle1.addConnection("c1", "outCBD1")
+		
+		self.CBD.flatten()
+		self._run(5)
+		self.assertEquals(self._getSignal("second_child.inCBD2"), [2.0]*5)
+
+		
+	def testLinearStrongComponentWithMult(self):
+		CBDConstant1 = CBD("constantCBD1", output_ports = ["outConstant1"])
+		CBDConstant1.addBlock(ConstantBlock(block_name="c", value=3))
+		CBDConstant1.addConnection("c", "outConstant1")
+		
+		CBDConstant2 = CBD("constantCBD2", output_ports = ["outConstant2"])
+		CBDConstant2.addBlock(ConstantBlock(block_name="c", value=5))
+		CBDConstant2.addConnection("c", "outConstant2")
+		
+		CBDAdder = CBD("adderCBD", input_ports = ["in1Add", "in2Add"], output_ports = ["outAdd"])
+		CBDAdder.addBlock(AdderBlock(block_name="a"))
+		CBDAdder.addConnection("in1Add", "a")
+		CBDAdder.addConnection("in2Add", "a")
+		CBDAdder.addConnection("a", "outAdd")
+		
+		CBDProduct = CBD("productCBD", input_ports = ["in1Prod", "in2Prod"], output_ports = ["outProd"])
+		CBDProduct.addBlock(ProductBlock(block_name="p"))
+		CBDProduct.addConnection("in1Prod", "p")
+		CBDProduct.addConnection("in2Prod", "p")
+		CBDProduct.addConnection("p", "outProd")
+		
+		self.CBD.addBlock(CBDConstant1)
+		self.CBD.addBlock(CBDConstant2)
+		self.CBD.addBlock(CBDAdder)
+		self.CBD.addBlock(CBDProduct)
+		self.CBD.addConnection("constantCBD1", "adderCBD", input_port_name="in1Add", output_port_name = "outConstant1")
+		self.CBD.addConnection("productCBD", "adderCBD", input_port_name="in2Add", output_port_name = "outProd")
+		self.CBD.addConnection("adderCBD", "productCBD", input_port_name="in1Prod", output_port_name = "outAdd")
+		self.CBD.addConnection("constantCBD2", "productCBD", input_port_name="in2Prod", output_port_name = "outConstant2")
+			
+		self.CBD.flatten()
+		self._run(5)
+		self.assertEquals(self._getSignal("adderCBD.outAdd"), [-0.75]*5)
+		self.assertEquals(self._getSignal("productCBD.outProd"), [-3.75]*5)
+		
+	def testLinearStrongComponentWithNeg(self):
+		CBDConstant1 = CBD("constantCBD1", output_ports = ["outConstant1"])
+		CBDConstant1.addBlock(ConstantBlock(block_name="c", value=5))
+		CBDConstant1.addConnection("c", "outConstant1")
+		
+		CBDConstant2 = CBD("constantCBD2", output_ports = ["outConstant2"])
+		CBDConstant2.addBlock(ConstantBlock(block_name="c", value=8))
+		CBDConstant2.addConnection("c", "outConstant2")
+		
+		CBDAdder1 = CBD("adder1CBD", input_ports = ["in1Add1", "in2Add1"], output_ports = ["outAdd1"])
+		CBDAdder1.addBlock(AdderBlock(block_name="a"))
+		CBDAdder1.addConnection("in1Add1", "a")
+		CBDAdder1.addConnection("in2Add1", "a")
+		CBDAdder1.addConnection("a", "outAdd1")
+		
+		CBDAdder2 = CBD("adder2CBD", input_ports = ["in1Add2", "in2Add2"], output_ports = ["outAdd2"])
+		CBDAdder2.addBlock(AdderBlock(block_name="a"))
+		CBDAdder2.addConnection("in1Add2", "a")
+		CBDAdder2.addConnection("in2Add2", "a")
+		CBDAdder2.addConnection("a", "outAdd2")
+		
+		CBDNegator = CBD("negatorCBD", input_ports = ["inNeg"], output_ports = ["outNeg"])
+		CBDNegator.addBlock(NegatorBlock(block_name="n"))
+		CBDNegator.addConnection("inNeg", "n")
+		CBDNegator.addConnection("n", "outNeg")
+		
+		self.CBD.addBlock(CBDConstant1)
+		self.CBD.addBlock(CBDConstant2)
+		self.CBD.addBlock(CBDAdder1)
+		self.CBD.addBlock(CBDAdder2)
+		self.CBD.addBlock(CBDNegator)
+		self.CBD.addConnection("constantCBD1", "adder1CBD", input_port_name="in1Add1", output_port_name = "outConstant1")
+		self.CBD.addConnection("adder2CBD", "adder1CBD", input_port_name="in2Add1", output_port_name = "outAdd2")
+		self.CBD.addConnection("constantCBD2", "adder2CBD", input_port_name="in1Add2", output_port_name = "outConstant2")
+		self.CBD.addConnection("negatorCBD", "adder2CBD", input_port_name="in2Add2", output_port_name = "outNeg")
+		self.CBD.addConnection("adder1CBD", "negatorCBD", input_port_name="inNeg", output_port_name = "outAdd1")
+		
+		self.CBD.flatten()
+		self._run(5)
+		self.assertEquals(self._getSignal("adder1CBD.outAdd1"), [6.5]*5)
+		self.assertEquals(self._getSignal("adder2CBD.outAdd2"), [1.5]*5)	
+		self.assertEquals(self._getSignal("negatorCBD.outNeg"), [-6.5]*5)		
+		
+	def testInterInterCBD(self):
+		"""
+							  +--------------------------------------------+
+				   +----+     |                    +------+                |
+				   |    |+--->|+------------------>|      |                |
+				   |  2 |     ||                   |  +   +--------------->+-------+
+		+----+     +----+     || +---------+   +-->|      |                |       |
+		|    |                |+>|         |   |   +------+                |       v
+		| 5  |   +------+     |  |         |   |                           |    +------+
+		+----++->|      |     |  |    *    |   |                           |    |      |
+				 |  +   |     |  |         |   |                           |    |  +   +------> 0
+		+----++->|      |+--->|+>|         |   |                           |    |      |
+		| 2  |   +------+     |  +--+------+   +--------------+            |    +------+
+		|    |                |     |                         |   +-----+  |       ^
+		+----+                |     |   +--------------------+|   |     |  |       |
+							  |     |   |     +-----+        ||   | 12  +->+-------+
+							  |     |   |     |     |        ||   |     |  |
+							  |     +-->+---->|  -  +------->++   +-----+  |
+							  |         |     |     |        |             |
+							  |         |     +-----+        |             |
+							  |         +--------------------+             |
+							  +--------------------------------------------+
+		"""		  
+		CBDLittle1 = CBD("first_child", input_ports = ["in1CBD1", "in2CBD1"], output_ports = ["out1CBD1", "out2CBD1"])
+		CBDLittle2 = CBD("first_child_of_first_child", input_ports = ["inCBD2"], output_ports = ["outCBD2"])
+		
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c3", value=2.0))
+		self.CBD.addBlock(AdderBlock(block_name="a"))
+		self.CBD.addBlock(AdderBlock(block_name="a2"))
+		self.CBD.addBlock(CBDLittle1)
+		self.CBD.addConnection("c3", "a")
+		self.CBD.addConnection("c2", "a")
+		self.CBD.addConnection("c1", "first_child", input_port_name = "in1CBD1")
+		self.CBD.addConnection("a", "first_child", input_port_name = "in2CBD1")
+		self.CBD.addConnection("first_child", "a2", output_port_name = "out1CBD1")
+		self.CBD.addConnection("first_child", "a2", output_port_name = "out2CBD1")
+				
+		CBDLittle1.addBlock(ProductBlock(block_name="p"))
+		CBDLittle1.addBlock(AdderBlock(block_name="a"))
+		CBDLittle1.addBlock(CBDLittle2)
+		CBDLittle1.addBlock(ConstantBlock(block_name="c", value=12.0))
+		CBDLittle1.addConnection("in1CBD1", "p")
+		CBDLittle1.addConnection("in2CBD1", "p")
+		CBDLittle1.addConnection("in1CBD1", "a")
+		CBDLittle1.addConnection("first_child_of_first_child", "a", output_port_name = "outCBD2")
+		CBDLittle1.addConnection("p", "first_child_of_first_child", input_port_name = "inCBD2")
+		CBDLittle1.addConnection("c", "out1CBD1")
+		CBDLittle1.addConnection("a", "out2CBD1")
+		
+		CBDLittle2.addBlock(NegatorBlock(block_name="n"))
+		CBDLittle2.addConnection("inCBD2", "n")
+		CBDLittle2.addConnection("n", "outCBD2")
+		
+		self.CBD.flatten()
+		self._run(5)		
+		self.assertEquals(self._getSignal("first_child.p"), [14.0]*5)
+		self.assertEquals(self._getSignal("first_child.first_child_of_first_child.n"), [-14.0]*5)
+		self.assertEquals(self._getSignal("first_child.in1CBD1"), [2.0]*5)
+		self.assertEquals(self._getSignal("first_child.a"), [-12.0]*5)		
+		self.assertEquals(self._getSignal("a2"), [0.0]*5)
+		
+		
+def suite():
+    """Returns a suite containing all the test cases in this module."""
+    suite1 = unittest.makeSuite(BasicCBDTestCase)
+    
+    return unittest.TestSuite((suite1))
+
+if __name__ == '__main__':
+    # When this module is executed from the command-line, run all its tests
+    unittest.main()
+
+	
+	
+	
+	
+	
+	
+	
+	

+ 201 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/hierarchyCBDTest.py

@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+#
+# Unit tests for the hierarchy functionality of the CBD
+
+import unittest
+from CBDMultipleOutput.Source.CBD import *
+from basicCBDTest import BasicCBDTestCase
+
+class HierarchyCBDTest(unittest.TestCase):
+	def setUp(self):
+		self.CBD = CBD("block_under_test")		
+		
+	def _run(self, num_steps=1, step = 1):
+		self.CBD.run(num_steps, step)			
+			
+	def _getSignal(self, blockname, output_port = None):
+		foundBlocks = [ block for block in self.CBD.getBlocks() if block.getBlockName() == blockname ]
+		
+		signal =  foundBlocks[0].getSignal(name_output = output_port)
+		
+		if len(foundBlocks) == 1:
+			return [x.value for x in signal]
+		else:
+			raise Exception("No single block with name " + blockname + " found")			
+		
+	def testInterCBD(self):		
+		CBDLittle1 = CBD("first_child", output_ports = ["outCBD1"])
+		CBDLittle1.addBlock(ConstantBlock(block_name="c1", value=2.0))
+		CBDLittle1.addConnection("c1", "outCBD1")
+		
+		CBDLittle2 = CBD("second_child", input_ports = ["inCBD2"], output_ports = ["outCBD2"])
+		CBDLittle2.addBlock(NegatorBlock(block_name="n"))
+		CBDLittle2.addConnection("inCBD2", "n")
+		CBDLittle2.addConnection("n", "outCBD2")
+		
+		self.CBD.addBlock(CBDLittle1)
+		self.CBD.addBlock(CBDLittle2)
+		neg = NegatorBlock(block_name="n")
+		self.CBD.addBlock(neg)
+		self.CBD.addConnection("first_child", "second_child", input_port_name = "inCBD2", output_port_name = "outCBD1") 
+		self.CBD.addConnection("second_child", "n", output_port_name = "outCBD2") 
+
+		self._run(5)
+		self.assertEquals(self._getSignal("n"), [2.0]*5)
+
+		
+	def testLinearStrongComponentWithMult(self):
+		CBDConstant1 = CBD("constantCBD1", output_ports = ["outConstant1"])
+		CBDConstant1.addBlock(ConstantBlock(block_name="c", value=3))
+		CBDConstant1.addConnection("c", "outConstant1")
+		
+		CBDConstant2 = CBD("constantCBD2", output_ports = ["outConstant2"])
+		CBDConstant2.addBlock(ConstantBlock(block_name="c", value=5))
+		CBDConstant2.addConnection("c", "outConstant2")
+		
+		CBDAdder = CBD("adderCBD", input_ports = ["in1Add", "in2Add"], output_ports = ["outAdd"])
+		CBDAdder.addBlock(AdderBlock(block_name="a"))
+		CBDAdder.addConnection("in1Add", "a")
+		CBDAdder.addConnection("in2Add", "a")
+		CBDAdder.addConnection("a", "outAdd")
+		
+		CBDProduct = CBD("productCBD", input_ports = ["in1Prod", "in2Prod"], output_ports = ["outProd"])
+		CBDProduct.addBlock(ProductBlock(block_name="p"))
+		CBDProduct.addConnection("in1Prod", "p")
+		CBDProduct.addConnection("in2Prod", "p")
+		CBDProduct.addConnection("p", "outProd")
+		
+		self.CBD.addBlock(CBDConstant1)
+		self.CBD.addBlock(CBDConstant2)
+		self.CBD.addBlock(CBDAdder)
+		self.CBD.addBlock(CBDProduct)
+		self.CBD.addConnection("constantCBD1", "adderCBD", input_port_name="in1Add", output_port_name = "outConstant1")
+		self.CBD.addConnection("productCBD", "adderCBD", input_port_name="in2Add", output_port_name = "outProd")
+		self.CBD.addConnection("adderCBD", "productCBD", input_port_name="in1Prod", output_port_name = "outAdd")
+		self.CBD.addConnection("constantCBD2", "productCBD", input_port_name="in2Prod", output_port_name = "outConstant2")
+
+		self._run(5)
+		self.assertEquals(self._getSignal("adderCBD", output_port = "outAdd"), [-0.75]*5)
+		self.assertEquals(self._getSignal("productCBD", output_port = "outProd"), [-3.75]*5)	
+		
+	def testLinearStrongComponentWithNeg(self):
+		CBDConstant1 = CBD("constantCBD1", output_ports = ["outConstant1"])
+		CBDConstant1.addBlock(ConstantBlock(block_name="c", value=5))
+		CBDConstant1.addConnection("c", "outConstant1")
+		
+		CBDConstant2 = CBD("constantCBD2", output_ports = ["outConstant2"])
+		CBDConstant2.addBlock(ConstantBlock(block_name="c", value=8))
+		CBDConstant2.addConnection("c", "outConstant2")
+		
+		CBDAdder1 = CBD("adder1CBD", input_ports = ["in1Add1", "in2Add1"], output_ports = ["outAdd1"])
+		CBDAdder1.addBlock(AdderBlock(block_name="a"))
+		CBDAdder1.addConnection("in1Add1", "a")
+		CBDAdder1.addConnection("in2Add1", "a")
+		CBDAdder1.addConnection("a", "outAdd1")
+		
+		CBDAdder2 = CBD("adder2CBD", input_ports = ["in1Add2", "in2Add2"], output_ports = ["outAdd2"])
+		CBDAdder2.addBlock(AdderBlock(block_name="a"))
+		CBDAdder2.addConnection("in1Add2", "a")
+		CBDAdder2.addConnection("in2Add2", "a")
+		CBDAdder2.addConnection("a", "outAdd2")
+		
+		CBDNegator = CBD("negatorCBD", input_ports = ["inNeg"], output_ports = ["outNeg"])
+		CBDNegator.addBlock(NegatorBlock(block_name="n"))
+		CBDNegator.addConnection("inNeg", "n")
+		CBDNegator.addConnection("n", "outNeg")
+		
+		self.CBD.addBlock(CBDConstant1)
+		self.CBD.addBlock(CBDConstant2)
+		self.CBD.addBlock(CBDAdder1)
+		self.CBD.addBlock(CBDAdder2)
+		self.CBD.addBlock(CBDNegator)
+		self.CBD.addConnection("constantCBD1", "adder1CBD", input_port_name="in1Add1", output_port_name = "outConstant1")
+		self.CBD.addConnection("adder2CBD", "adder1CBD", input_port_name="in2Add1", output_port_name = "outAdd2")
+		self.CBD.addConnection("constantCBD2", "adder2CBD", input_port_name="in1Add2", output_port_name = "outConstant2")
+		self.CBD.addConnection("negatorCBD", "adder2CBD", input_port_name="in2Add2", output_port_name = "outNeg")
+		self.CBD.addConnection("adder1CBD", "negatorCBD", input_port_name="inNeg", output_port_name = "outAdd1")
+
+		self._run(5)
+		self.assertEquals(self._getSignal("adder1CBD", output_port = "outAdd1"), [6.5]*5)
+		self.assertEquals(self._getSignal("adder2CBD", output_port = "outAdd2"), [1.5]*5)	
+		self.assertEquals(self._getSignal("negatorCBD", output_port = "outNeg"), [-6.5]*5)	
+		
+	def testInterInterCBD(self):
+		"""
+							  +--------------------------------------------+
+				   +----+     |                    +------+                |
+				   |    |+--->|+------------------>|      |                |
+				   |  2 |     ||                   |  +   +--------------->+-------+
+		+----+     +----+     || +---------+   +-->|      |                |       |
+		|    |                |+>|         |   |   +------+                |       v
+		| 5  |   +------+     |  |         |   |                           |    +------+
+		+----++->|      |     |  |    *    |   |                           |    |      |
+				 |  +   |     |  |         |   |                           |    |  +   +------> 0
+		+----++->|      |+--->|+>|         |   |                           |    |      |
+		| 2  |   +------+     |  +--+------+   +--------------+            |    +------+
+		|    |                |     |                         |   +-----+  |       ^
+		+----+                |     |   +--------------------+|   |     |  |       |
+							  |     |   |     +-----+        ||   | 12  +->+-------+
+							  |     |   |     |     |        ||   |     |  |
+							  |     +-->+---->|  -  +------->++   +-----+  |
+							  |         |     |     |        |             |
+							  |         |     +-----+        |             |
+							  |         +--------------------+             |
+							  +--------------------------------------------+
+		"""		  
+		CBDLittle1 = CBD("first_child", input_ports = ["in1CBD1", "in2CBD1"], output_ports = ["out1CBD1", "out2CBD1"])
+		CBDLittle2 = CBD("first_child_of_first_child", input_ports = ["inCBD2"], output_ports = ["outCBD2"])
+		
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=2.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.0))
+		self.CBD.addBlock(ConstantBlock(block_name="c3", value=2.0))
+		self.CBD.addBlock(AdderBlock(block_name="a"))
+		self.CBD.addBlock(AdderBlock(block_name="a2"))
+		self.CBD.addBlock(CBDLittle1)
+		self.CBD.addConnection("c3", "a")
+		self.CBD.addConnection("c2", "a")
+		self.CBD.addConnection("c1", "first_child", input_port_name = "in1CBD1")
+		self.CBD.addConnection("a", "first_child", input_port_name = "in2CBD1")
+		self.CBD.addConnection("first_child", "a2", output_port_name = "out1CBD1")
+		self.CBD.addConnection("first_child", "a2", output_port_name = "out2CBD1")
+				
+		CBDLittle1.addBlock(ProductBlock(block_name="p"))
+		CBDLittle1.addBlock(AdderBlock(block_name="a"))
+		CBDLittle1.addBlock(CBDLittle2)
+		CBDLittle1.addBlock(ConstantBlock(block_name="c", value=12.0))
+		CBDLittle1.addConnection("in1CBD1", "p")
+		CBDLittle1.addConnection("in2CBD1", "p")
+		CBDLittle1.addConnection("in1CBD1", "a")
+		CBDLittle1.addConnection("first_child_of_first_child", "a", output_port_name = "outCBD2")
+		CBDLittle1.addConnection("p", "first_child_of_first_child", input_port_name = "inCBD2")
+		CBDLittle1.addConnection("c", "out1CBD1")
+		CBDLittle1.addConnection("a", "out2CBD1")
+		
+		CBDLittle2.addBlock(NegatorBlock(block_name="n"))
+		CBDLittle2.addConnection("inCBD2", "n")
+		CBDLittle2.addConnection("n", "outCBD2")
+		
+		self._run(5)		
+		self.assertEquals(self._getSignal("first_child", output_port = "p"), [14.0]*5)
+		self.assertEquals(self._getSignal("first_child", output_port = "in1CBD1"), [2.0]*5)
+		self.assertEquals(self._getSignal("first_child", output_port = "a"), [-12.0]*5)		
+		self.assertEquals(self._getSignal("a2"), [0.0]*5)	
+		
+def suite():
+    """Returns a suite containing all the test cases in this module."""
+    suite1 = unittest.makeSuite(BasicCBDTestCase)
+    
+    return unittest.TestSuite((suite1))
+
+if __name__ == '__main__':
+    # When this module is executed from the command-line, run all its tests
+    unittest.main()
+
+	
+	
+	
+	
+	
+	
+	
+	

+ 172 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Test/sortedGraphCBDTest.py

@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+#
+# Unit tests for the sorting of a CBD.
+
+import unittest
+from CBDMultipleOutput.Source.CBD import *
+from basicCBDTest import BasicCBDTestCase
+
+class SortedGraphCBDTest(unittest.TestCase):
+	def setUp(self):
+		self.CBD = CBD("block_under_test")		
+		
+	def _run(self, num_steps=1):
+		self.CBD.run(num_steps)			
+	
+	def testSortedGraph(self):
+		CBDNegator = CBD("negatorCBD", input_ports = ["inNegator"], output_ports = ["outNegator"])
+		negCbd = NegatorBlock(block_name="nC")
+		CBDNegator.addBlock(negCbd)
+		CBDNegator.addConnection("inNegator", "nC")	
+		CBDNegator.addConnection("nC", "outNegator")	
+		
+		const = ConstantBlock(block_name="c", value=5.5)
+		self.CBD.addBlock(const)
+		neg = NegatorBlock(block_name="n")
+		self.CBD.addBlock(neg)
+		self.CBD.addBlock(CBDNegator)
+		self.CBD.addConnection("negatorCBD", "n", output_port_name = "outNegator")
+		self.CBD.addConnection("c", "negatorCBD", input_port_name = "inNegator")
+		
+		depGraph = self.CBD._CBD__createDepGraph(0)
+		sortedGraph = depGraph.getStrongComponents()
+		
+		self.assertEquals(len(sortedGraph), 5)
+		self.assertEquals(sortedGraph[0][0], const)
+		self.assertEquals(sortedGraph[2][0], negCbd)
+		self.assertEquals(sortedGraph[4][0], neg)
+		
+	def testSortedGraph2(self):
+		CBDAdder = CBD("adderCBD", input_ports = ["in1", "in2"], output_ports = ["outAdd"])
+		addCBD = AdderBlock(block_name="aC")
+		CBDAdder.addBlock(addCBD)
+		CBDAdder.addConnection("in1", "aC")	
+		CBDAdder.addConnection("in2", "aC")	
+		CBDAdder.addConnection("aC", "outAdd")	
+		
+		const1 = ConstantBlock(block_name="c1", value=5.5)
+		const2 = ConstantBlock(block_name="c2", value=4.5)
+		self.CBD.addBlock(const1)
+		self.CBD.addBlock(const2)
+		neg = NegatorBlock(block_name="n")
+		self.CBD.addBlock(neg)
+		self.CBD.addBlock(CBDAdder)
+		self.CBD.addConnection("adderCBD", "n", output_port_name = "outAdd")
+		self.CBD.addConnection("c1", "adderCBD", input_port_name = "in1")
+		self.CBD.addConnection("c2", "adderCBD", input_port_name = "in2")
+		
+		depGraph = self.CBD._CBD__createDepGraph(0)
+		sortedGraph = depGraph.getStrongComponents()
+		comps = [ x[0] for x in sortedGraph ]
+		
+		tester = self
+		ag = lambda x,y: tester.assertTrue(comps.index(x) > comps.index(y))
+		
+		self.assertEquals(len(sortedGraph), 7)
+		ag(addCBD, const1)
+		ag(addCBD, const2)
+		ag(neg, addCBD)
+		
+	def testSortedGraph3(self):	
+		CBDNegator = CBD("negatorCBD", input_ports = ["inNegator"], output_ports = ["outNegator", "outInverter"])
+		negCbd = NegatorBlock(block_name="nC")
+		invCBD = InverterBlock(block_name="iC")
+		CBDNegator.addBlock(negCbd)
+		CBDNegator.addBlock(invCBD)
+		CBDNegator.addConnection("inNegator", "nC")	
+		CBDNegator.addConnection("inNegator", "iC")	
+		CBDNegator.addConnection("nC", "outNegator")	
+		CBDNegator.addConnection("iC", "outInverter")	
+		
+		const = ConstantBlock(block_name="c", value=5.5)
+		self.CBD.addBlock(const)
+		add = AdderBlock(block_name="a")
+		self.CBD.addBlock(add)
+		self.CBD.addBlock(CBDNegator)
+		self.CBD.addConnection("negatorCBD", "a", output_port_name = "outNegator")
+		self.CBD.addConnection("negatorCBD", "a", output_port_name = "outInverter")
+		self.CBD.addConnection("c", "negatorCBD", input_port_name = "inNegator")
+		
+		depGraph = self.CBD._CBD__createDepGraph(0)
+		sortedGraph = depGraph.getStrongComponents()
+		comps = [ x[0] for x in sortedGraph ]
+		
+		tester = self
+		ag = lambda x,y: tester.assertTrue(comps.index(x) > comps.index(y))
+
+		self.assertEquals(len(sortedGraph), 7)
+		ag(negCbd, const)
+		ag(invCBD, const)
+		ag(add, negCbd)
+		ag(add, invCBD)
+		
+	def testSortedGraph4(self):
+		CBDStrong = CBD("strongCBD", input_ports = ["inC1", "inC2"], output_ports = [])
+		CBDStrong.addBlock(AdderBlock(block_name="a1"))
+		CBDStrong.addBlock(AdderBlock(block_name="a3"))
+		CBDStrong.addBlock(AdderBlock(block_name="a2"))
+		CBDStrong.addConnection("a3", "a1")		
+		CBDStrong.addConnection("a1", "a3")
+		CBDStrong.addConnection("a2", "a3")
+		CBDStrong.addConnection("inC1", "a1")
+		CBDStrong.addConnection("inC2", "a2")
+		CBDStrong.addConnection("a3", "a2")
+		
+		self.CBD.addBlock(CBDStrong)
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.5))
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=-5))
+		self.CBD.addConnection("c1", "strongCBD", input_port_name = "inC1")
+		self.CBD.addConnection("c2", "strongCBD", input_port_name = "inC2")
+		
+		depGraph = self.CBD._CBD__createDepGraph(0)
+		sortedGraph = depGraph.getStrongComponents()
+				
+		self.assertEquals(len(sortedGraph), 5)
+		self.assertEquals(len(sortedGraph[4]), 3)
+		
+	def testSortedGraph5(self):
+		CBDStrong = CBD("strongCBD", input_ports = ["inC1", "inC2", "inA"], output_ports = ["out1", "out2"])
+		CBDStrong.addBlock(AdderBlock(block_name="a1"))
+		CBDStrong.addBlock(AdderBlock(block_name="a2"))
+		CBDStrong.addConnection("inA", "a1")		
+		CBDStrong.addConnection("a1", "out1")
+		CBDStrong.addConnection("a2", "out2")
+		CBDStrong.addConnection("inC1", "a1")
+		CBDStrong.addConnection("inC2", "a2")
+		CBDStrong.addConnection("inA", "a2")
+		
+		self.CBD.addBlock(CBDStrong)
+		self.CBD.addBlock(AdderBlock(block_name="a3"))
+		self.CBD.addBlock(ConstantBlock(block_name="c2", value=5.5))
+		self.CBD.addBlock(ConstantBlock(block_name="c1", value=-5))
+		self.CBD.addConnection("c1", "strongCBD", input_port_name = "inC1")
+		self.CBD.addConnection("c2", "strongCBD", input_port_name = "inC2")
+		self.CBD.addConnection("a3", "strongCBD", input_port_name = "inA")
+		self.CBD.addConnection("strongCBD", "a3", output_port_name = "out1")
+		self.CBD.addConnection("strongCBD", "a3", output_port_name = "out2")
+		
+		depGraph = self.CBD._CBD__createDepGraph(0)
+		sortedGraph = depGraph.getStrongComponents()
+				
+		self.assertEquals(len(sortedGraph), 5)
+		self.assertEquals(len(sortedGraph[4]), 6)	
+		
+		
+def suite():
+    """Returns a suite containing all the test cases in this module."""
+    suite1 = unittest.makeSuite(BasicCBDTestCase)
+    
+    return unittest.TestSuite((suite1))
+
+if __name__ == '__main__':
+    # When this module is executed from the command-line, run all its tests
+    unittest.main()
+
+	
+	
+	
+	
+	
+	
+	
+	

+ 0 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/__init__.py


+ 80 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/models/EvenNumbersCBD.py

@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+from bokeh.plotting import figure, output_file, show
+from CBDMultipleOutput.Source.CBD import *
+from CBDMultipleOutput.Source.CBDDraw import draw
+
+
+class Counter(CBD):
+    def __init__(self, block_name):
+        CBD.__init__(self, 
+                    block_name, 
+                    input_ports=[], 
+                    output_ports=["OutCount"])
+        
+        self.addBlock(DelayBlock(block_name="delay"))
+        self.addBlock(AdderBlock(block_name="sum"))
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(ConstantBlock(block_name="one", value=1.0))
+        
+        self.addConnection("zero", "delay", 
+                            input_port_name="IC")
+        self.addConnection("delay", "OutCount")
+        self.addConnection("delay", "sum")
+        self.addConnection("sum", "delay", input_port_name="IN1")
+        self.addConnection("one", "sum")
+        
+class Double(CBD):        
+    def __init__(self, block_name):
+        CBD.__init__(self, 
+                     block_name, 
+                     input_ports=["InNumber"], 
+                     output_ports=["OutDouble"])
+        self.addBlock(ProductBlock(block_name="mult"))
+        self.addBlock(ConstantBlock(block_name="two", value=2.0))
+        
+        self.addConnection("InNumber", "mult")
+        self.addConnection("two", "mult")
+        self.addConnection("mult", "OutDouble")
+    
+    
+class EvenNumberGen(CBD):
+    def __init__(self, block_name):
+        CBD.__init__(self, 
+                     block_name, 
+                     input_ports=[],
+                     output_ports=["OutEven"])
+        
+        self.addBlock(Counter(block_name="counter"))
+        self.addBlock(Double(block_name="double"))
+        
+        self.addConnection("counter", "double", 
+                           input_port_name="InNumber",
+                           output_port_name="OutCount")
+        self.addConnection("double", "OutEven",
+                           output_port_name="OutDouble")
+        
+
+
+if __name__ == "__main__":
+    
+    cbd = EvenNumberGen("number_gen")
+    draw(cbd, "number_gen.dot")
+    draw(cbd.getBlockByName("counter"), "counter.dot")
+    cbd.run(10)
+    
+    times = []
+    output = []
+    
+    for timeValuePair in cbd.getSignal("OutEven"):
+        times.append(timeValuePair.time)
+        output.append(timeValuePair.value)
+                
+    #Plot
+    output_file("./number_gen.html", title="Even Numbers")
+    p = figure(title="Even Numbers", x_axis_label='time', y_axis_label='N')
+    p.circle(x=times, y=output, legend="Even numbers")
+    show(p)
+
+
+
+

+ 21 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/models/HarmonicOscilator.py

@@ -0,0 +1,21 @@
+from CBDMultipleOutput.Source.CBD import *
+
+class CircleCBDDerivative(CBD):
+    def __init__(self, blockName, delta_t):
+        CBD.__init__(self,blockName, [], [])
+        self.delta=delta_t;
+        self.addBlock(ConstantBlock(block_name="one", value=1.0))
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(ConstantBlock(block_name="delta", value=self.delta))
+        self.addBlock(NegatorBlock(block_name="neg"))
+        self.addBlock(DerivatorBlock(block_name="derxv"))
+        self.addBlock(DerivatorBlock(block_name="derva"))
+        
+        self.addConnection("delta", "derxv",  input_port_name="delta_t")
+        self.addConnection("delta", "derva",  input_port_name="delta_t")
+        self.addConnection("zero", "derva",  input_port_name="IC")
+        self.addConnection("one", "derxv",  input_port_name="IC")
+        self.addConnection("derva", "neg")
+        self.addConnection("neg", "derxv")
+        self.addConnection("derxv", "derva")
+        

+ 300 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/models/TrainControlCBD.py

@@ -0,0 +1,300 @@
+#!/usr/bin/env python
+from CBDMultipleOutput.Source.CBD import *
+
+DELTA = 0.1
+MASS_PERSON = 73
+MASS_TRAIN = 6000
+K = 300
+C = 150
+
+
+
+class TrainControlCBD(CBD):
+    def __init__(self, block_name, kp, ki, kd):
+        CBD.__init__(self, block_name)
+        self.addBlock(FixedTimeCBD(block_name="time"))
+        self.addBlock(LookUpBlockFixed(block_name="computer"))
+        self.addBlock(AdderBlock(block_name="sum"))
+        self.addBlock(NegatorBlock(block_name="neg"))
+        self.addBlock(TrainPIDController("controller", kp, ki, kd))
+        self.addBlock(TrainPerson(block_name="plant"))
+        self.addBlock(CostFunctionCBD(block_name="cost"))
+        
+        # the connections follow the topological sort.
+        self.addConnection("time", "computer", 
+                            input_port_name="IN1", output_port_name="OutTime")
+        self.addConnection("time", "plant", 
+                            input_port_name="InDelta", output_port_name="OutDelta")
+        self.addConnection("time", "controller", 
+                            input_port_name="InDelta", output_port_name="OutDelta")
+        self.addConnection("computer", "sum", 
+                            input_port_name="IN1", output_port_name="OUT1")
+        self.addConnection("plant", "neg", 
+                            input_port_name="IN1", output_port_name="OutVTrain")
+        self.addConnection("neg", "sum", 
+                            input_port_name="IN2", output_port_name="OUT1")
+        self.addConnection("sum", "controller", 
+                            input_port_name="InError", output_port_name="OUT1")
+        self.addConnection("controller", "plant", 
+                            input_port_name="InTraction", output_port_name="OutTraction")
+        self.addConnection("sum", "cost", 
+                            input_port_name="InError")
+        self.addConnection("time", "cost", 
+                            input_port_name="InDelta", output_port_name="OutDelta")
+        self.addConnection("plant", "cost", 
+                            input_port_name="InXPerson", output_port_name="OutXPerson")
+        
+        
+
+class CostFunctionCBD(CBD):        
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["InError","InDelta","InXPerson"], ["OutCost"])
+        self.addBlock(ABSBlock(block_name="abs"))
+        self.addBlock(ABSBlock(block_name="absError"))
+        self.addBlock(IntegratorBlock(block_name="integral"))
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(AboveThresholdBlock(block_name="above04", threshold=0.4))
+        self.addBlock(StopSimulationBlock(block_name="stop"))
+        
+        self.addConnection("InError", "absError")
+        self.addConnection("absError", "integral", input_port_name="IN1")
+        self.addConnection("InDelta", "integral", input_port_name="delta_t")
+        self.addConnection("zero", "integral", input_port_name="IC")
+        self.addConnection("integral", "OutCost")
+        self.addConnection("InXPerson", "abs")
+        self.addConnection("abs", "above04")
+        self.addConnection("above04", "stop")
+        
+
+class ABSBlock(BaseBlock):
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+
+    def compute(self, curIteration):
+        self.appendToSignal(abs(self.getInputSignal(curIteration).value))
+
+class LookUpBlockFixed(BaseBlock):
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+        
+    def compute(self, curIteration):
+        currentTime = self.getInputSignal(curIteration, "IN1").value
+        if currentTime < 0:
+            result = 0
+        elif currentTime < 160:
+            result = 14
+        elif currentTime < 200:
+            result = 2
+        elif currentTime < 260:
+            result = 15
+        else:
+            result = 0
+        
+        self.appendToSignal(result)
+
+
+
+class AboveThresholdBlock(BaseBlock):
+    def __init__(self, block_name, threshold):
+        BaseBlock.__init__(self, block_name, ["IN1"], ["OUT1"])
+        self.threshold = threshold
+
+    def compute(self, curIteration):
+        self.appendToSignal(1.0 if self.getInputSignal(curIteration).value > self.threshold else -1.0)
+
+
+
+class StopSimulationBlock(BaseBlock):
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["IN1"], [])
+
+    def compute(self, curIteration):
+        inSignalValue = self.getInputSignal(curIteration).value
+        if inSignalValue > 0.0:
+            raise StopSimulationException()
+        
+
+class StopSimulationException(Exception):
+    pass
+        
+class FixedTimeCBD(CBD):        
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, [], ["OutTime", "OutDelta"])
+        self.addBlock(ConstantBlock(block_name="delta", value=DELTA))
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(AdderBlock(block_name="sum"))
+        self.addBlock(DelayBlock(block_name="delay"))
+        
+        self.addConnection("delta", "OutDelta")
+        self.addConnection("delay", "OutTime")
+        self.addConnection("delay", "sum")
+        self.addConnection("delta", "sum")
+        self.addConnection("sum", "delay")
+        self.addConnection("zero", "delay",
+                            input_port_name="IC")
+    
+
+class TrainPIDController(CBD):
+    def __init__(self, block_name, kp, ki, kd):
+        CBD.__init__(self, block_name, ["InError","InDelta"],["OutTraction"])
+        self.addBlock(IntegratorBlock(block_name="integral"))
+        self.addBlock(DerivatorBlock(block_name="derivative"))
+        self.addBlock(ConstantBlock(block_name="Kp", value=kp))
+        self.addBlock(ProductBlock(block_name="multKp"))
+        self.addBlock(ConstantBlock(block_name="Ki", value=ki))
+        self.addBlock(ProductBlock(block_name="multKi"))
+        self.addBlock(ConstantBlock(block_name="Kd", value=kd))
+        self.addBlock(ProductBlock(block_name="multKd"))
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(AdderBlock(block_name="sum1"))
+        self.addBlock(AdderBlock(block_name="sum2"))
+        
+        self.addConnection("InError", "multKp")
+        self.addConnection("Kp", "multKp")
+        self.addConnection("InError", "integral")
+        self.addConnection("InError", "derivative")
+        self.addConnection("InDelta", "derivative", 
+                            input_port_name="delta_t")
+        self.addConnection("InDelta", "integral", 
+                            input_port_name="delta_t")
+        self.addConnection("zero", "derivative", 
+                            input_port_name="IC")
+        self.addConnection("zero", "integral", 
+                            input_port_name="IC")
+        self.addConnection("integral", "multKi")
+        self.addConnection("Ki", "multKi")
+        self.addConnection("derivative", "multKd")
+        self.addConnection("Kd", "multKd")
+        self.addConnection("multKd", "sum1")
+        self.addConnection("multKi", "sum1")
+        self.addConnection("sum1", "sum2")
+        self.addConnection("multKp", "sum2")
+        self.addConnection("sum2", "OutTraction")
+        
+        
+class TrainPerson(CBD):
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["InTraction","InDelta"],["OutVTrain", "OutXPerson", "OutATrain"])
+        self.addBlock(ConstantBlock(block_name="zero", value=0.0))
+        self.addBlock(AccelerationPerson(block_name="accelerationPerson"))
+        self.addBlock(AccelerationTrain(block_name="accelerationTrain"))
+        self.addBlock(IntegratorBlock(block_name="integral_person_a_v"))
+        self.addBlock(IntegratorBlock(block_name="integral_person_v_x"))
+        self.addBlock(IntegratorBlock(block_name="integral_train_a_v"))
+        
+        self.addConnection("zero", "integral_person_a_v", 
+                            input_port_name="IC")
+        self.addConnection("zero", "integral_person_v_x", 
+                            input_port_name="IC")
+        self.addConnection("zero", "integral_train_a_v", 
+                            input_port_name="IC")
+        
+        self.addConnection("InDelta", "integral_person_a_v", 
+                            input_port_name="delta_t")
+        self.addConnection("InDelta", "integral_person_v_x", 
+                            input_port_name="delta_t")
+        self.addConnection("InDelta", "integral_train_a_v", 
+                            input_port_name="delta_t")
+        
+        self.addConnection("InTraction", "accelerationPerson", 
+                            input_port_name="InTraction")
+        self.addConnection("InTraction", "accelerationTrain", 
+                            input_port_name="InTraction")
+        
+        self.addConnection("accelerationPerson", "integral_person_a_v", 
+                            input_port_name="IN1", output_port_name="OutAPerson")
+        self.addConnection("integral_person_a_v", "accelerationPerson", 
+                            input_port_name="InVPerson", output_port_name="OUT1")
+        self.addConnection("integral_person_a_v", "integral_person_v_x", 
+                            input_port_name="IN1", output_port_name="OUT1")
+        self.addConnection("integral_person_v_x", "accelerationPerson", 
+                            input_port_name="InXPerson", output_port_name="OUT1")
+        
+        self.addConnection("accelerationTrain", "integral_train_a_v", 
+                            input_port_name="IN1", output_port_name="OutATrain")
+        
+        self.addConnection("integral_train_a_v", "OutVTrain")
+        
+        self.addConnection("integral_person_v_x", "OutXPerson")
+        
+        self.addConnection("accelerationTrain", "OutATrain", input_port_name=None, output_port_name="OutATrain")
+        
+        
+        
+class AccelerationPerson(CBD):
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["InTraction","InVPerson","InXPerson"],["OutAPerson"])
+        self.addBlock(ConstantBlock(block_name="m_train", value=MASS_TRAIN))
+        self.addBlock(ConstantBlock(block_name="m_person", value=MASS_PERSON))
+        self.addBlock(ConstantBlock(block_name="c", value=C))
+        self.addBlock(ConstantBlock(block_name="k", value=K))
+        self.addBlock(AdderBlock(block_name="sum_masses"))
+        self.addBlock(InverterBlock(block_name="inv_sum_masses"))
+        self.addBlock(ProductBlock(block_name="mult_inv_sum_masses"))
+        self.addBlock(ProductBlock(block_name="mult_mult_inv_sum_masses"))
+        self.addBlock(InverterBlock(block_name="inv_mperson"))
+        self.addBlock(NegatorBlock(block_name="neg_mult_mult_inv_sum_masses"))
+        self.addBlock(NegatorBlock(block_name="neg_vperson"))
+        self.addBlock(NegatorBlock(block_name="neg_xperson"))
+        self.addBlock(ProductBlock(block_name="mult_neg_vperson"))
+        self.addBlock(ProductBlock(block_name="mult_neg_xperson"))
+        self.addBlock(AdderBlock(block_name="sum_mults_person"))
+        self.addBlock(AdderBlock(block_name="sum_sum_mults_person"))
+        self.addBlock(ProductBlock(block_name="mult_inv_mperson"))
+        
+        self.addConnection("m_train", "sum_masses")
+        self.addConnection("m_person", "sum_masses")
+        self.addConnection("sum_masses", "inv_sum_masses")
+        self.addConnection("inv_sum_masses", "mult_inv_sum_masses")
+        self.addConnection("InTraction", "mult_inv_sum_masses")
+        self.addConnection("mult_inv_sum_masses", "mult_mult_inv_sum_masses")
+        
+        self.addConnection("m_person", "mult_mult_inv_sum_masses")
+        
+        self.addConnection("m_person", "inv_mperson")
+        self.addConnection("inv_mperson", "mult_inv_mperson")
+        
+        self.addConnection("mult_mult_inv_sum_masses", "neg_mult_mult_inv_sum_masses")
+        self.addConnection("neg_mult_mult_inv_sum_masses", "sum_sum_mults_person")
+        
+        self.addConnection("InVPerson", "neg_vperson")
+        self.addConnection("neg_vperson", "mult_neg_vperson")
+        self.addConnection("c", "mult_neg_vperson")
+        
+        self.addConnection("InXPerson", "neg_xperson")
+        self.addConnection("neg_xperson", "mult_neg_xperson")
+        self.addConnection("k", "mult_neg_xperson")
+        
+        self.addConnection("mult_neg_vperson", "sum_mults_person")
+        self.addConnection("mult_neg_xperson", "sum_mults_person")
+        
+        self.addConnection("sum_mults_person", "sum_sum_mults_person")
+        self.addConnection("sum_sum_mults_person", "mult_inv_mperson")
+        self.addConnection("mult_inv_mperson", "OutAPerson")
+        
+        
+        
+class AccelerationTrain(CBD):
+    def __init__(self, block_name):
+        CBD.__init__(self, block_name, ["InTraction"],["OutATrain"])
+        self.addBlock(ConstantBlock(block_name="m_train", value=MASS_TRAIN))
+        self.addBlock(ConstantBlock(block_name="m_person", value=MASS_PERSON))
+        self.addBlock(AdderBlock(block_name="sum"))
+        self.addBlock(InverterBlock(block_name="inv"))
+        self.addBlock(ProductBlock(block_name="mult"))
+        
+        self.addConnection("InTraction", "mult")
+        self.addConnection("m_train", "sum")
+        self.addConnection("m_person", "sum")
+        self.addConnection("sum", "inv")
+        self.addConnection("inv", "mult")
+        self.addConnection("mult", "OutATrain")
+
+
+
+
+
+
+
+
+

+ 0 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/models/__init__.py


+ 263 - 0
debugging_fsa_cbd_composition/cbdsimulator/CBD_Controller.py

@@ -0,0 +1,263 @@
+"""
+This is CBD simulator controller exposing the most relevant methods of 
+a CBD simulator (See CBDMultipleOutput.Source.CBD.run) to allow for control from a SCCD.
+
+date: Oct 2015
+author (responsible): Claudio Gomes
+"""
+
+import math
+from CBDMultipleOutput.Source.CBD import Clock, DepGraph
+from CBDMultipleOutput.Source.CBD import CBD
+
+
+class CBDController:
+    """The CBD contoller acts as a facade to the simulator methods that are in the CBD objects.
+    The original design decision to keep the methods in the CBD Domain classes 
+    (as opposed to, for instance, keep them in a visitor/interpreter was not the decision of the current author.)"""
+    
+    def __init__(self, cbdModel, delta_t):
+        self.model = cbdModel
+        self.model.setDeltaT(delta_t)
+        self.delta = delta_t
+        
+    def initSimulation(self):
+        self.model.resetSignals();
+        self.model.setClock(Clock(self.delta))
+    
+    def createDepGraph(self, iteratonStep):
+        return self.__createDepGraph(iteratonStep)
+    
+    def createStrongComponents(self, depGraph, iteratonStep):
+        return depGraph.getStrongComponents(iteratonStep)
+    
+    def componentIsCycle(self, component, depGraph):
+        return self.__hasCycle(component, depGraph)
+    
+    
+    def computeNextBlock(self, comp, iteratonStep):
+        block = comp[0]   # the strongly connected component has a single element
+        block.compute(iteratonStep)
+    
+    def computeNextAlgebraicLoop(self, comp, iteratonStep):
+        currentComponent = comp
+        # Detected a strongly connected component
+        if not self.__isLinear(currentComponent):
+            raise NotImplementedError("Cannot solve non-linear algebraic loop")
+        solverInput = self.__constructLinearInput(currentComponent, iteratonStep)
+        self.__gaussjLinearSolver(solverInput)
+        solutionVector = solverInput[1]
+        for block in currentComponent:
+            blockIndex = currentComponent.index(block)
+            block.appendToSignal(solutionVector[blockIndex])
+    
+    def advanceTimeStep(self):
+        self.model.getClock().step()
+    
+    def getCurrentSimulationTime(self):
+        return self.model.getClock().getTime()
+    
+    def __isLinear(self, strongComponent):
+        """
+        Determines if an algebraic loop describes a linear equation or not
+        As input you get the detected loop in a list.
+        If the loop is linear return True
+        Else: call exit(1) to exit the simulation with exit code 1
+        
+        The strong component parameter is a list of blocks that comprise the strong component.
+        For a block to comprise the strong component, at least one of its dependencies must be in the strong component as well.
+        A non-linear equation is generated when the following conditions occur:
+         (1) there is a multiplication operation being performed between two unknowns.
+         (2) there is an invertion operatioon being performed in an unknown.
+         (3) some non linear block belongs to the strong component
+        
+        The condition (1) can be operationalized by finding a product block that has two dependencies belonging to the strong component.
+        This will immediatly tell us that it is a product between two unknowns.
+        The condition (2) can be operationalized simply by finding an inverter block in the strong component. 
+        Because the inverter block only has one input, if it is in the strong component, it means that its only dependency is in the strong component.
+        
+        """
+        for block in strongComponent:
+            if not block.getBlockType() == "AdderBlock" and not block.getBlockType() == "NegatorBlock":
+                # condition (1)
+                if block.getBlockType() == "ProductBlock":
+                    dependenciesUnknown = [x for x in block.getDependencies(0) if x in strongComponent ]
+                    if (len(dependenciesUnknown) == 2):
+                        return False
+                
+                # conditions (2) and (3)
+                if block.getBlockType() in ["InverterBlock", "LessThanBlock", "ModuloBlock", "RootBlock", "EqualsBlock", "NotBlock", "OrBlock", "AndBlock", "SequenceBlock"]:
+                    return False
+        
+        return True
+    
+    def __hasCycle(self, component, depGraph):
+        """
+        Determine whether a component is cyclic
+        """
+        assert len(component)>=1, "A component should have at least one element"
+        if len(component)>1:
+            return True
+        else: # a strong component of size one may still have a cycle: a self-loop
+            if depGraph.hasDependency(component[0], component[0]):
+                return True
+            else:
+                return False
+
+    def __constructLinearInput(self, strongComponent, curIteration):
+        """
+        Constructs input for a solver of systems of linear equations
+        Input consists of two matrices:
+        M1: coefficient matrix, where each row represents an equation of the system
+        M2: result matrix, where each element is the result for the corresponding equation in M1
+        """
+        size = len(strongComponent)
+        row = []
+        M1 = []
+        M2 = []
+
+        # Initialize matrices with zeros
+        i = 0
+        while (i < size):
+            j = 0
+            row = []
+            while (j < size):
+                row.append(0)
+                j += 1
+            M1.append(row)
+            M2.append(0)
+            i += 1
+
+        # block -> index of block
+        indexdict = dict()
+
+        for (i,block) in enumerate(strongComponent):
+            indexdict[block] = i
+
+        resolveBlock = lambda possibleDep, output_port: possibleDep if not isinstance(possibleDep, CBD) else possibleDep.getBlockByName(output_port)
+
+        def getBlockDependencies2(block):
+            return [ resolveBlock(b,output_port) for (b, output_port) in [block.getBlockConnectedToInput("IN1"),  block.getBlockConnectedToInput("IN2")]]
+
+        for (i, block) in enumerate(strongComponent):
+            if block.getBlockType() == "AdderBlock":
+                for external in [ x for x in getBlockDependencies2(block) if x not in strongComponent ]:
+                    M2[i] -= external.getSignal()[curIteration].value
+                M1[i][i] = -1
+
+                for compInStrong in [ x for x in getBlockDependencies2(block) if x in strongComponent ]:
+                    M1[i][indexdict[compInStrong]] = 1
+            elif block.getBlockType() == "ProductBlock":
+                #M2 can stay 0
+                M1[i][i] = -1
+                M1[i][indexdict[[ x for x in getBlockDependencies2(block)  if x in strongComponent ][0]]] = reduce(lambda x,y: x*y, [ x.getSignal()[curIteration].value for x in getBlockDependencies2(block) if x not in strongComponent ])
+            elif block.getBlockType() == "NegatorBlock":
+                #M2 can stay 0
+                M1[i][i] = -1
+                possibleDep, output_port = block.getBlockConnectedToInput("IN1")
+                M1[i][indexdict[resolveBlock(possibleDep, output_port)]] = - 1
+            elif block.getBlockType() == "InputPortBlock":
+                #M2 can stay 0
+                M1[i][i] = 1
+                possibleDep, output_port = block.parent.getBlockConnectedToInput(block.getBlockName())
+                M1[i][indexdict[resolveBlock(possibleDep, output_port)]] = - 1
+            elif block.getBlockType() == "OutputPortBlock" or block.getBlockType() == "WireBlock":
+                #M2 can stay 0
+                M1[i][i] = 1
+                M1[i][indexdict[block.getDependencies(0)[0]]] = - 1
+            elif block.getBlockType() == "DelayBlock":
+                # If a delay is in a strong component, this is the first iteration
+                assert curIteration == 0
+                # And so the dependency is the IC
+                # M2 can stay 0 because we have an equation of the type -x = -ic <=> -x + ic = 0
+                M1[i][i] = -1
+                possibleDep, output_port = block.getBlockConnectedToInput("IC")
+                dependency = resolveBlock(possibleDep, output_port)
+                assert dependency in strongComponent
+                M1[i][indexdict[dependency]] = 1
+            else:
+                self.__logger.fatal("Unknown element, please implement")
+        return [M1, M2]
+
+    
+    def __gaussjLinearSolver(self, solverInput):
+        M1 = solverInput[0]
+        M2 = solverInput[1]
+        n = len(M1)
+        indxc = self.__ivector(n)
+        indxr = self.__ivector(n)
+        ipiv = self.__ivector(n)
+        icol = 0
+        irow = 0
+        for i in range(n):
+            big = 0.0
+            for j in range(n):
+                if (ipiv[j] != 1):
+                    for k in range(n):
+                        if (ipiv[k] == 0):
+                            if (math.fabs(M1[j][k]) >= big):
+                                big = math.fabs(M1[j][k])
+                                irow = j
+                                icol = k
+                        elif (ipiv[k] > 1):
+                            raise ValueError("GAUSSJ: Singular Matrix-1")
+            ipiv[icol] += 1
+            if (irow != icol):
+                for l in range(n):
+                    (M1[irow][l], M1[icol][l]) = self.__swap(M1[irow][l], M1[icol][l])
+                (M2[irow], M2[icol]) = self.__swap(M2[irow], M2[icol])
+            indxr[i] = irow
+            indxc[i] = icol
+            if (M1[icol][icol] == 0.0):
+                raise ValueError("GAUSSJ: Singular Matrix-2")
+            pivinv = 1.0/M1[icol][icol]
+            M1[icol][icol] = 1.0
+            for l in range(n):
+                M1[icol][l] *= pivinv
+            M2[icol] *= pivinv
+            for ll in range(n):
+                if (ll != icol):
+                    dum = M1[ll][icol]
+                    M1[ll][icol] = 0.0
+                    for l in range(n):
+                        M1[ll][l] -= M1[icol][l] * dum
+                    M2[ll] -= M2[icol] * dum
+        l = n
+        while (l > 0):
+            l -= 1
+            if (indxr[l] != indxc[l]):
+                for k in range(n):
+                    (M1[k][indxr[l]], M1[k][indxc[l]]) = self.__swap(M1[k][indxr[l]], M1[k][indxc[l]])
+
+    def __createDepGraph(self, curIteration):
+        """
+         Create a dependency graph of the CBD model.
+         Use the curIteration to differentiate between the first and other iterations
+         Watch out for dependencies with sub-models.
+        """
+        blocks = self.model.getBlocks()
+        depGraph = DepGraph()
+        for block in blocks:      
+            depGraph.addMember(block);
+        
+        def recSetInternalDependencies(blocks, curIteration):
+            for block in blocks:
+                for dep in block.getDependencies(curIteration):
+                    depGraph.setDependency(block, dep, curIteration)
+                if isinstance(block, CBD):
+                    recSetInternalDependencies(block.getBlocks(), curIteration)
+        
+        recSetInternalDependencies(blocks, curIteration);
+        
+        return depGraph
+    
+    def __ivector(self, n):
+        v = []
+        for i in range(n):
+            v.append(0)
+        return v
+
+    def __swap(self, a, b):
+        return (b, a)
+
+    

+ 56 - 0
debugging_fsa_cbd_composition/cbdsimulator/Options.py

@@ -0,0 +1,56 @@
+AUTO_TIME_MODE = 0X01
+MANUAL_TIME_MODE = 0x02
+MANUAL_STEP_TIME_MODE = 0x03
+FAST_TIME_MODE = 0x04
+
+#a list containg the aboves modes so that the option class can do an 'in' check instead of == one by one
+#to check the legality of a received mode. 
+LEGAL_TIME_MODES = [AUTO_TIME_MODE, MANUAL_TIME_MODE, MANUAL_STEP_TIME_MODE, FAST_TIME_MODE]
+
+class Options:
+  """A class that contains options that should be given trough the interface)"""
+  def __init__(self,maxIter = 10, mode = AUTO_TIME_MODE, scaleFactor = 1, delta = 0.001):
+    """
+    a couple of options
+    @param maxIter the number or iterations of 1 simulation
+    @param mode the time mode
+    @param scaleFactor the scale factor by which to run an iteration default 1
+    """
+    self.__max_iter = maxIter
+    self.setTimeMode(mode)
+    self.setDeltaT(delta)
+    if scaleFactor >= 0:
+      self.__factor = scaleFactor 
+    else:
+      self.__factor  = 1
+        
+  def setMaxIterations(self, max):
+    self.__max_iter = max
+   
+  def getMaxIterations(self):
+    return self.__max_iter 
+  
+  def setDeltaT(self, delta):
+    self.__delta = delta
+   
+  def getDeltaT(self):
+    return self.__delta 
+  
+  
+  def setScaleFactor(self, factor):
+    if factor >= 0:
+      self.__factor = factor
+      #if value is illegal keep simply keep previous value
+
+  def getScaleFactor(self):
+    return self.__factor
+  
+  def setTimeMode(self, mode):
+    """Set the time mode. If it isn't a legal value set it to AUTO_TIME_MODE"""
+    if (mode in LEGAL_TIME_MODES): #since there is no enumeration in python this is a check to make sure a level has been added and not a random int
+      self.__mode = mode
+    else:
+      self.__mode = AUTO_TIME_MODE 
+
+  def getTimeMode(self):
+    return self.__mode

BIN=BIN
debugging_fsa_cbd_composition/cbdsimulator/cbd-sim-sccd-visual.pdf


+ 325 - 0
debugging_fsa_cbd_composition/cbdsimulator/cbdsim.py

@@ -0,0 +1,325 @@
+"""
+Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
+
+Date:   Tue Oct 11 11:56:10 2016
+
+Model author: Sadaf Mustafiz and Claudio Gomes and Simon Van Mierlo
+Model name:   CBDSimulator
+Model description:
+SCCD HUTN model of a CBD simulator
+"""
+
+from sccd.runtime.statecharts_core import *
+from sccd.runtime.libs.ui import *
+from sccd.runtime.libs.utils import *
+from CBD_Controller import CBDController
+import Options
+
+# package "CBDSimulator"
+
+class CBDSimulator(RuntimeClassBase):
+    def __init__(self, controller, options, model):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # user defined attributes
+        self.iteration = None
+        self.cbdController = None
+        self.delta = None
+        self.clock = None
+        self.model = None
+        self.depGraph = None
+        self.strongComponentList = None
+        self.currentCompIdx = None
+        
+        # call user defined constructor
+        CBDSimulator.user_defined_constructor(self, options, model)
+    
+    def user_defined_constructor(self, options, model):
+        self.options = options
+        self.delta = self.options.getDeltaT()
+        self.model = model
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # user defined method
+    def endCondition(self):
+        return self.iteration >= self.options.getMaxIterations()
+    
+    
+    # user defined method
+    def advanceTime(self):
+        self.iteration = self.iteration + 1
+        self.clock = self.clock + self.delta
+        self.cbdController.advanceTimeStep()
+    
+    
+    # user defined method
+    def currentComponentIsCycle(self):
+        return self.cbdController.componentIsCycle(self.strongComponentList[self.currentCompIdx], self.depGraph)
+    
+    
+    # user defined method
+    def hasNextStrongComponent(self):
+        return (self.currentCompIdx + 1) < len(self.strongComponentList)
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, self)
+        
+        # state /Main
+        self.states["/Main"] = ParallelState(1, self)
+        self.states["/Main"].setEnter(self._Main_enter)
+        self.states["/Main"].setExit(self._Main_exit)
+        
+        # state /Main/SimulationState
+        self.states["/Main/SimulationState"] = State(2, self)
+        
+        # state /Main/SimulationState/Waiting
+        self.states["/Main/SimulationState/Waiting"] = State(3, self)
+        self.states["/Main/SimulationState/Waiting"].setEnter(self._Main_SimulationState_Waiting_enter)
+        self.states["/Main/SimulationState/Waiting"].setExit(self._Main_SimulationState_Waiting_exit)
+        
+        # state /Main/SimulationState/Running
+        self.states["/Main/SimulationState/Running"] = State(4, self)
+        self.states["/Main/SimulationState/Running"].setEnter(self._Main_SimulationState_Running_enter)
+        self.states["/Main/SimulationState/Running"].setExit(self._Main_SimulationState_Running_exit)
+        
+        # state /Main/SimulationState/Running/Continuous
+        self.states["/Main/SimulationState/Running/Continuous"] = State(5, self)
+        
+        # state /Main/SimulationState/Stopped
+        self.states["/Main/SimulationState/Stopped"] = State(6, self)
+        self.states["/Main/SimulationState/Stopped"].setEnter(self._Main_SimulationState_Stopped_enter)
+        self.states["/Main/SimulationState/Stopped"].setExit(self._Main_SimulationState_Stopped_exit)
+        
+        # state /Main/SimulationFlow
+        self.states["/Main/SimulationFlow"] = State(7, self)
+        
+        # state /Main/SimulationFlow/Initialize
+        self.states["/Main/SimulationFlow/Initialize"] = State(8, self)
+        self.states["/Main/SimulationFlow/Initialize"].setEnter(self._Main_SimulationFlow_Initialize_enter)
+        
+        # state /Main/SimulationFlow/CheckTerminationCondition
+        self.states["/Main/SimulationFlow/CheckTerminationCondition"] = State(9, self)
+        
+        # state /Main/SimulationFlow/CreateDependencyGraph
+        self.states["/Main/SimulationFlow/CreateDependencyGraph"] = State(10, self)
+        self.states["/Main/SimulationFlow/CreateDependencyGraph"].setEnter(self._Main_SimulationFlow_CreateDependencyGraph_enter)
+        
+        # state /Main/SimulationFlow/IsolateStrongComponents
+        self.states["/Main/SimulationFlow/IsolateStrongComponents"] = State(11, self)
+        self.states["/Main/SimulationFlow/IsolateStrongComponents"].setEnter(self._Main_SimulationFlow_IsolateStrongComponents_enter)
+        
+        # state /Main/SimulationFlow/ExecuteSimulationStep
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep"] = State(12, self)
+        
+        # state /Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"] = State(13, self)
+        
+        # state /Main/SimulationFlow/ExecuteSimulationStep/CheckCycle
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"] = State(14, self)
+        
+        # state /SimulationComplete
+        self.states["/SimulationComplete"] = State(15, self)
+        
+        # add children
+        self.states[""].addChild(self.states["/Main"])
+        self.states[""].addChild(self.states["/SimulationComplete"])
+        self.states["/Main"].addChild(self.states["/Main/SimulationState"])
+        self.states["/Main"].addChild(self.states["/Main/SimulationFlow"])
+        self.states["/Main/SimulationState"].addChild(self.states["/Main/SimulationState/Waiting"])
+        self.states["/Main/SimulationState"].addChild(self.states["/Main/SimulationState/Running"])
+        self.states["/Main/SimulationState"].addChild(self.states["/Main/SimulationState/Stopped"])
+        self.states["/Main/SimulationState/Running"].addChild(self.states["/Main/SimulationState/Running/Continuous"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/Initialize"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/CheckTerminationCondition"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/CreateDependencyGraph"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/IsolateStrongComponents"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/ExecuteSimulationStep"])
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep"].addChild(self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"])
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep"].addChild(self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/Main"]
+        self.states["/Main/SimulationState"].default_state = self.states["/Main/SimulationState/Waiting"]
+        self.states["/Main/SimulationState/Running"].default_state = self.states["/Main/SimulationState/Running/Continuous"]
+        self.states["/Main/SimulationFlow"].default_state = self.states["/Main/SimulationFlow/Initialize"]
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep"].default_state = self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"]
+        
+        # transition /Main/SimulationState/Waiting
+        _Main_SimulationState_Waiting_0 = Transition(self, self.states["/Main/SimulationState/Waiting"], [self.states["/Main/SimulationState/Running/Continuous"]])
+        _Main_SimulationState_Waiting_0.setTrigger(Event("continuous", "user_input"))
+        self.states["/Main/SimulationState/Waiting"].addTransition(_Main_SimulationState_Waiting_0)
+        
+        # transition /Main/SimulationFlow/Initialize
+        _Main_SimulationFlow_Initialize_0 = Transition(self, self.states["/Main/SimulationFlow/Initialize"], [self.states["/Main/SimulationFlow/CheckTerminationCondition"]])
+        _Main_SimulationFlow_Initialize_0.setTrigger(None)
+        self.states["/Main/SimulationFlow/Initialize"].addTransition(_Main_SimulationFlow_Initialize_0)
+        
+        # transition /Main/SimulationFlow/CheckTerminationCondition
+        _Main_SimulationFlow_CheckTerminationCondition_0 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition"], [self.states["/Main/SimulationFlow/CreateDependencyGraph"]])
+        _Main_SimulationFlow_CheckTerminationCondition_0.setTrigger(None)
+        _Main_SimulationFlow_CheckTerminationCondition_0.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_0_guard)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_0)
+        
+        # transition /Main/SimulationFlow/CreateDependencyGraph
+        _Main_SimulationFlow_CreateDependencyGraph_0 = Transition(self, self.states["/Main/SimulationFlow/CreateDependencyGraph"], [self.states["/Main/SimulationFlow/IsolateStrongComponents"]])
+        _Main_SimulationFlow_CreateDependencyGraph_0.setTrigger(None)
+        self.states["/Main/SimulationFlow/CreateDependencyGraph"].addTransition(_Main_SimulationFlow_CreateDependencyGraph_0)
+        
+        # transition /Main/SimulationFlow/IsolateStrongComponents
+        _Main_SimulationFlow_IsolateStrongComponents_0 = Transition(self, self.states["/Main/SimulationFlow/IsolateStrongComponents"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep"]])
+        _Main_SimulationFlow_IsolateStrongComponents_0.setAction(self._Main_SimulationFlow_IsolateStrongComponents_0_exec)
+        _Main_SimulationFlow_IsolateStrongComponents_0.setTrigger(None)
+        self.states["/Main/SimulationFlow/IsolateStrongComponents"].addTransition(_Main_SimulationFlow_IsolateStrongComponents_0)
+        
+        # transition /Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"]])
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_exec)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0.setTrigger(None)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_guard)
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"], [self.states["/Main/SimulationFlow/CheckTerminationCondition"]])
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_exec)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1.setTrigger(None)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_guard)
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1)
+        
+        # transition /Main/SimulationFlow/ExecuteSimulationStep/CheckCycle
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"]])
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_exec)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0.setTrigger(None)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_guard)
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"]])
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_exec)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1.setTrigger(None)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_guard)
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1)
+        
+        # transition /Main
+        _Main_0 = Transition(self, self.states["/Main"], [self.states["/SimulationComplete"]])
+        _Main_0.setTrigger(Event("_0after"))
+        _Main_0.setGuard(self._Main_0_guard)
+        self.states["/Main"].addTransition(_Main_0)
+        
+        # transition /Main/SimulationState/Running
+        _Main_SimulationState_Running_0 = Transition(self, self.states["/Main/SimulationState/Running"], [self.states["/Main/SimulationState/Stopped"]])
+        _Main_SimulationState_Running_0.setAction(self._Main_SimulationState_Running_0_exec)
+        _Main_SimulationState_Running_0.setTrigger(None)
+        _Main_SimulationState_Running_0.setGuard(self._Main_SimulationState_Running_0_guard)
+        self.states["/Main/SimulationState/Running"].addTransition(_Main_SimulationState_Running_0)
+    
+    def _Main_enter(self):
+        self.addTimer(0, self.sccd_yield())
+    
+    def _Main_exit(self):
+        self.removeTimer(0)
+    
+    def _Main_SimulationState_Running_enter(self):
+        print 'entering SimulationState/Running'
+    
+    def _Main_SimulationState_Running_exit(self):
+        print 'exiting SimulationState/Running'
+    
+    def _Main_SimulationState_Waiting_enter(self):
+        print 'entering SimulationState/Waiting'
+    
+    def _Main_SimulationState_Waiting_exit(self):
+        print 'exiting SimulationState/Waiting'
+    
+    def _Main_SimulationState_Stopped_enter(self):
+        print 'entering SimulationState/Stopped'
+    
+    def _Main_SimulationState_Stopped_exit(self):
+        print 'exiting SimulationState/Stopped'
+    
+    def _Main_SimulationFlow_Initialize_enter(self):
+        self.iteration = 0
+        self.clock = 0
+        self.cbdController = CBDController(self.model, self.delta)
+        self.cbdController.initSimulation()
+    
+    def _Main_SimulationFlow_CreateDependencyGraph_enter(self):
+        self.depGraph = self.cbdController.createDepGraph(self.iteration)
+    
+    def _Main_SimulationFlow_IsolateStrongComponents_enter(self):
+        self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
+    
+    def _Main_0_guard(self, parameters):
+        return self.inState(["/Main/SimulationState/Stopped"])
+    
+    def _Main_SimulationState_Running_0_exec(self, parameters):
+        self.raiseInternalEvent(Event("termination_condition", None, []))
+    
+    def _Main_SimulationState_Running_0_guard(self, parameters):
+        return self.endCondition()
+    
+    def _Main_SimulationFlow_CheckTerminationCondition_0_guard(self, parameters):
+        return self.inState(["/Main/SimulationState/Running"])
+    
+    def _Main_SimulationFlow_IsolateStrongComponents_0_exec(self, parameters):
+        self.currentCompIdx = -1
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_exec(self, parameters):
+        self.currentCompIdx = self.currentCompIdx + 1
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_guard(self, parameters):
+        return self.hasNextStrongComponent()
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_exec(self, parameters):
+        self.advanceTime()
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_guard(self, parameters):
+        return not self.hasNextStrongComponent()
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_exec(self, parameters):
+        self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_guard(self, parameters):
+        return not self.currentComponentIsCycle()
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_exec(self, parameters):
+        self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_guard(self, parameters):
+        return self.currentComponentIsCycle()
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/Main"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class ObjectManager(ObjectManagerBase):
+    def __init__(self, controller):
+        ObjectManagerBase.__init__(self, controller)
+    
+    def instantiate(self, class_name, construct_params):
+        if class_name == "CBDSimulator":
+            instance = CBDSimulator(self.controller, construct_params[0], construct_params[1])
+            instance.associations = {}
+        else:
+            raise Exception("Cannot instantiate class " + class_name)
+        return instance
+
+class Controller(ThreadsControllerBase):
+    def __init__(self, options, model, keep_running = None, behind_schedule_callback = None):
+        if keep_running == None: keep_running = True
+        if behind_schedule_callback == None: behind_schedule_callback = None
+        ThreadsControllerBase.__init__(self, ObjectManager(self), keep_running, behind_schedule_callback)
+        self.addInputPort("user_input")
+        self.addInputPort("user_output")
+        self.object_manager.createInstance("CBDSimulator", [options, model])

+ 195 - 0
debugging_fsa_cbd_composition/cbdsimulator/cbdsim.py.xml

@@ -0,0 +1,195 @@
+<?xml version="1.0" ?>
+<diagram name="CBDSimulator" author="Sadaf Mustafiz and Claudio Gomes">
+	<description>
+		SCCD HUTN model of a CBD simulator
+	</description>
+	<top>
+		from sccd.runtime.libs.ui import *
+		from sccd.runtime.libs.utils import *
+		from CBD_Controller import CBDController
+		import Options
+	</top>
+	<class name="CBDSimulator" default="True">
+		<attribute name="iteration"/>
+		<attribute name="cbdController"/>
+		<attribute name="delta"/>
+		<attribute name="clock"/>
+		<attribute name="model"/>
+		<attribute name="depGraph"/>
+		<attribute name="strongComponentList"/>
+		<attribute name="currentCompIdx"/>
+		<method name="CBDSimulator">
+			<parameter name="options"/>
+			<parameter name="model"/>
+			<body>
+			<![CDATA[
+				self.options = options
+				self.delta = self.options.getDeltaT()
+				self.model = model
+			]]>
+			</body>
+		</method>
+		<method name="maxIterationsReached">
+			<body>
+			<![CDATA[
+				return self.iteration >= self.options.getMaxIterations()
+			]]>
+			</body>
+		</method>
+		<method name="currentComponentIsCycle">
+			<body>
+			<![CDATA[
+				return self.cbdController.componentIsCycle(self.strongComponentList[self.currentCompIdx], self.depGraph)
+			]]>
+			</body>
+		</method>
+		<method name="advanceTime">
+			<body>
+			<![CDATA[
+				self.iteration = self.iteration + 1
+				self.clock = self.clock + self.delta
+				self.cbdController.advanceTimeStep()
+			]]>
+			</body>
+		</method>
+		<method name="hasNextStrongComponent">
+			<body>
+			<![CDATA[
+				return (self.currentCompIdx + 1) < len(self.strongComponentList)
+			]]>
+			</body>
+		</method>
+		<scxml initial="Initialize">
+			<state id="SimulationComplete">
+			</state>
+			<state id="CreateDependencyGraph">
+				<onentry>
+					<script>
+					<![CDATA[
+						print('Performing dependency graph creation...')
+						self.depGraph = self.cbdController.createDepGraph(self.iteration)
+						print('Performing dependency graph creation... DONE')
+					]]>
+					</script>
+				</onentry>
+				<transition target="../IsolateStrongComponents">
+					<script>
+						<![CDATA[
+							print('Transition to IsolateStrongComponents')
+						]]>
+					</script>
+				</transition>
+			</state>
+			<state id="Initialize">
+				<onentry>
+					<script>
+					<![CDATA[
+						print('Performing initialization...')
+						self.iteration = 0
+						self.clock = 0
+						self.cbdController = CBDController(self.model, self.delta)
+						self.cbdController.initSimulation()
+						print('Performing initialization... DONE')
+					]]>
+					</script>
+				</onentry>
+				<transition target="../CheckTerminationCondition">
+					<script>
+						<![CDATA[
+							print('Transition to CheckTerminationCondition')
+						]]>
+					</script>
+				</transition>
+			</state>
+			<state id="CheckTerminationCondition">
+				<transition target="../CreateDependencyGraph" cond="not self.maxIterationsReached()">
+					<script>
+						<![CDATA[
+							print('Transition to CreateDependencyGraph')
+						]]>
+					</script>
+				</transition>
+				<transition target="../SimulationComplete" cond="self.maxIterationsReached()">
+					<script>
+						<![CDATA[
+							print('Transition to SimulationComplete')
+						]]>
+					</script>
+				</transition>
+			</state>
+			<state id="IsolateStrongComponents">
+				<onentry>
+					<script>
+					<![CDATA[
+						print('Performing strong components isolation...')
+						self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
+						print('Performing strong components isolation... DONE')
+					]]>
+					</script>
+				</onentry>
+				<transition target="../ExecuteSimulationStep">
+					<script>
+						<![CDATA[
+							print('Transition to ExecuteSimulationStep')
+							self.currentCompIdx = -1
+						]]>
+					</script>
+				</transition>
+			</state>
+			<state id="ExecuteSimulationStep" initial="CheckNextComponent">
+				<state id="CheckNextComponent">
+					<onentry>
+						<script>
+						<![CDATA[
+							print('Performing CheckNextComponent...')
+							print('Performing CheckNextComponent... DONE')
+						]]>
+						</script>
+					</onentry>
+					<transition target="../CheckCycle" cond="self.hasNextStrongComponent()">
+						<script>
+							<![CDATA[
+								print('Transition to CheckCycle')
+								self.currentCompIdx = self.currentCompIdx + 1
+							]]>
+						</script>
+					</transition>
+					<transition target="../../CheckTerminationCondition" cond="not self.hasNextStrongComponent()">
+						<script>
+							<![CDATA[
+								print('Transition to CheckTerminationCondition')
+								self.advanceTime()
+							]]>
+						</script>
+					</transition>
+				</state>
+				<state id="CheckCycle">
+					<onentry>
+						<script>
+						<![CDATA[
+							print('Performing CheckCycle...')
+							print('Performing CheckCycle... DONE')
+						]]>
+						</script>
+					</onentry>
+					<transition target="../CheckNextComponent" cond="not self.currentComponentIsCycle()">
+						<script>
+							<![CDATA[
+								print('Transition to CheckNextComponent')
+								self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
+							]]>
+						</script>
+					</transition>
+					<transition target="../CheckNextComponent" cond="self.currentComponentIsCycle()">
+						<script>
+							<![CDATA[
+								print('Transition to CheckNextComponent')
+								self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+							]]>
+						</script>
+					</transition>
+				</state>
+			</state>
+		</scxml>
+	</class>
+</diagram>

+ 127 - 0
debugging_fsa_cbd_composition/cbdsimulator/cbdsim.sccd

@@ -0,0 +1,127 @@
+Diagram(name = 'CBDSimulator',
+        author = 'Sadaf Mustafiz and Claudio Gomes',
+        description = 'SCCD HUTN model of a CBD simulator'):
+    Top {
+        from CBD_Controller import CBDController
+        import Options
+    }
+
+    Class(name = 'CBDSimulator', default = True):
+        Attribute(name='iteration')
+        Attribute(name='strongComponentList')
+        Attribute(name='currentCompIdx')
+        Attribute(name='clock')
+        Attribute(name='delta')
+        Attribute(name='cbdController')
+        Attribute(name='model')
+		Attribute(name='depGraph')
+		
+        Constructor(options, model) {
+            self.options = options
+			self.delta = self.options->getDeltaT()
+			self.model = model
+        }
+		
+		Method currentComponentIsCycle() {
+            return self.cbdController->componentIsCycle(self.strongComponentList[self.currentCompIdx], self.depGraph)
+        }
+		
+		Method hasNextStrongComponent() {
+			return (self.currentCompIdx + 1) < len(self.strongComponentList)
+        }
+		
+        Method advanceTime() {
+			self.iteration = self.iteration + 1
+			self.clock = self.clock + self.delta
+        	self.cbdController->advanceTimeStep()
+        }
+        
+		Method maxIterationsReached() {
+			return self.iteration >= self.options->getMaxIterations()
+        }
+		
+        StateMachine:
+            initial = 'Initialize'
+			State('Initialize'):
+				Transition(target='../CheckTerminationCondition'):
+					Actions {
+						print('Transition to CheckTerminationCondition')
+					}
+				OnEnter {
+					print('Performing initialization...')
+					self.iteration = 0
+					self.clock = 0
+					self.cbdController = CBDController(self.model,self.delta)
+					self.cbdController->initSimulation()
+					print('Performing initialization... DONE')
+				}
+			State('CheckTerminationCondition'):
+				Transition(target='../CreateDependencyGraph'):
+					guard = {not self->maxIterationsReached()}
+					Actions {
+						print('Transition to CreateDependencyGraph')
+					}
+				Transition(target='../SimulationComplete'):
+					guard = {self->maxIterationsReached()}
+					Actions {
+						print('Transition to SimulationComplete')
+					}
+			State('CreateDependencyGraph'):
+				Transition(target='../IsolateStrongComponents'):
+					Actions {
+						print('Transition to IsolateStrongComponents')
+					}
+				OnEnter {
+					print('Performing dependency graph creation...')
+					self.depGraph = self.cbdController->createDepGraph(self.iteration)
+					print('Performing dependency graph creation... DONE')
+				}
+			State('IsolateStrongComponents'):
+				Transition(target='../ExecuteSimulationStep'):
+					Actions {
+						print('Transition to ExecuteSimulationStep')
+						self.currentCompIdx = -1
+					}
+				OnEnter {
+					print('Performing strong components isolation...')
+					self.strongComponentList = self.cbdController->createStrongComponents(self.depGraph, self.iteration)
+					print('Performing strong components isolation... DONE')
+				}
+				
+			State('ExecuteSimulationStep'):
+				initial = 'CheckNextComponent'
+				State('CheckNextComponent'):
+					Transition(target='../CheckCycle'):
+						guard = {self->hasNextStrongComponent()}
+						Actions {
+							print('Transition to CheckCycle')
+							self.currentCompIdx = self.currentCompIdx + 1
+						}
+					Transition(target='../../CheckTerminationCondition'):
+						guard = {not self->hasNextStrongComponent()}
+						Actions {
+							print('Transition to CheckTerminationCondition')
+							self->advanceTime()
+						}
+					OnEnter {
+						print('Performing CheckNextComponent...')
+						print('Performing CheckNextComponent... DONE')
+					}
+				State('CheckCycle'):
+					Transition(target='../CheckNextComponent'):
+						guard = {self->currentComponentIsCycle()}
+						Actions {
+							print('Transition to CheckNextComponent')
+							self.cbdController->computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+						}
+					Transition(target='../CheckNextComponent'):
+						guard = {not self->currentComponentIsCycle()}
+						Actions {
+							print('Transition to CheckNextComponent')
+							self.cbdController->computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
+						}
+					OnEnter {
+						print('Performing CheckCycle...')
+						print('Performing CheckCycle... DONE')
+					}
+			State('SimulationComplete')

+ 449 - 0
debugging_fsa_cbd_composition/cbdsimulator/cbdsim_debugging.py.xml

@@ -0,0 +1,449 @@
+<?xml version="1.0" ?>
+<diagram name="CBDSimulator" author="Sadaf Mustafiz and Claudio Gomes and Simon Van Mierlo">
+    <description>
+        SCCD HUTN model of a CBD simulator
+    </description>
+    
+    <inport name="user_input" />
+    <inport name="user_output" />
+    
+    <top>
+        from sccd.runtime.libs.ui import *
+        from sccd.runtime.libs.utils import *
+        from CBD_Controller import CBDController
+        import Options
+        import sccd.runtime.accurate_time as accurate_time
+        
+        class Breakpoint:
+            def __init__(self, name, function, enabled, disable_on_trigger):
+                self.name = name
+                self.function = function
+                self.enabled = enabled
+                self.disable_on_trigger = disable_on_trigger
+    </top>
+    
+    <class name="CBDSimulator" default="True">
+        <attribute name="iteration"/>
+        <attribute name="cbdController"/>
+        <attribute name="delta"/>
+        <attribute name="clock"/>
+        <attribute name="model"/>
+        <attribute name="depGraph"/>
+        <attribute name="strongComponentList"/>
+        <attribute name="currentCompIdx"/>        
+        <method name="CBDSimulator">
+            <parameter name="options"/>
+            <parameter name="model"/>
+            <body>
+            <![CDATA[
+                self.options = options
+                self.delta = self.options.getDeltaT() * 1000.0
+                self.model = model
+            ]]>
+            </body>
+        </method>
+        <method name="initialize">
+            <body>
+            <![CDATA[
+                self.iteration = 0
+                self.clock = 0
+                self.time_next = self.delta
+                self.cbdController = CBDController(self.model, self.delta)
+                self.cbdController.initSimulation()
+                self.state = {b.getBlockName(): b.getSignal() for b in self.model.getBlocks()}
+                self.breakpoints = []
+                self.triggered_bp = None
+            ]]>
+            </body>
+        </method>
+        <method name="endCondition">
+            <body>
+            <![CDATA[
+                return self.iteration >= self.options.getMaxIterations()
+            ]]>
+            </body>
+        </method>
+        <method name="advanceTime">
+            <body>
+            <![CDATA[
+                self.iteration = self.iteration + 1
+                self.clock = self.time_next
+                self.cbdController.advanceTimeStep()
+                self.time_next = self.clock + self.delta
+            ]]>
+            </body>
+        </method>
+        <method name="currentComponentIsCycle">
+            <body>
+            <![CDATA[
+                return self.cbdController.componentIsCycle(self.strongComponentList[self.currentCompIdx], self.depGraph)
+            ]]>
+            </body>
+        </method>
+        <method name="hasNextStrongComponent">
+            <body>
+            <![CDATA[
+                return (self.currentCompIdx + 1) < len(self.strongComponentList)
+            ]]>
+            </body>
+        </method>
+        <method name="finalize">
+            <body>
+            <![CDATA[
+                from bokeh.plotting import figure, output_file, show    
+                times = []
+                values = []
+                for timeValuePair in self.model.getSignal("neg"):
+                    times.append(timeValuePair.time)
+                    values.append(timeValuePair.value)
+
+                output_file("./plot.html", title="Plot")
+                p = figure(title="Something vs Otherthing", x_axis_label="Time", y_axis_label="Values")
+                p.line(times, values, legend="Something", line_width=1, line_color="red")
+                show(p)
+            ]]>
+            </body>
+        </method>
+        <method name="waitTime">
+            <body>
+            <![CDATA[
+                # First, we convert from wall-clock time to simulated time.
+                # This means the elapsed time in wall-clock time needs to be scaled according to the realtime scale (for example, if the realtime scale is 2, an elapsed time of 1 second in wall-clock time is equal to an elapsed time of 2 seconds in simulated time).
+                simulated_diff = (accurate_time.time() - self.realtime_start_time) * self.realtime_scale
+                # time_next and simulated_diff are both in simulated time: so now scale back to wall-clock time by dividing.
+                # This function returns an amount of miliseconds.
+                return ((self.time_next - simulated_diff) / self.realtime_scale)
+            ]]>
+            </body>
+        </method>
+        <method name="addBreakpoint">
+            <parameter name="name" />
+            <parameter name="function" />
+            <parameter name="enabled" default="true" />
+            <parameter name="disable_on_trigger" default="true" />
+            <body>
+            <![CDATA[
+                if len([bp for bp in self.breakpoints if bp.name == name]) > 0:
+                    return -1
+                self.breakpoints.append(Breakpoint(name, function, enabled, disable_on_trigger))
+                return 0
+            ]]>
+            </body>
+        </method>
+        <method name="delBreakpoint">
+            <parameter name="name" />
+            <body>
+            <![CDATA[
+                if len([bp for bp in self.breakpoints if bp.name == name]) == 0:
+                    return -1
+                self.breakpoints = [bp for bp in self.breakpoints if bp.name != name]
+                return 0
+            ]]>
+            </body>
+        </method>
+        <method name="toggleBreakpoint">
+            <parameter name="name" />
+            <body>
+            <![CDATA[
+                if len([bp for bp in self.breakpoints if bp.name == name]) == 0:
+                    return -1
+                for bp in self.breakpoints:
+                    if bp.name == name:
+                        bp.enabled = enabled
+                        break
+                return 0
+            ]]>
+            </body>
+        </method>
+        <method name="breakpointTriggers">
+            <parameter name="is_realtime_simulation" />
+            <body>
+            <![CDATA[
+                self.triggered_bp = None
+                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("
+                    # note that we pass self.time_next instead of self.simulated_time in the case of as-fast-as-possible simulation (or stepping)
+                    # this is to make sure that the simulation is stopped BEFORE the specified time is reached, and not AFTER (because we don't necessarily implement 'step back')
+                    # in case of realtime simulation, we do pass the current simulated time, since we can stop at (more or less) exactly the right time
+                    if breakpoint({'clock': (self.clock if is_realtime_simulation else self.time_next) / 1000.0, 'state': self.state}):
+                        # triggered!
+                        self.triggered_bp = bp.name
+                        if bp.disable_on_trigger:
+                            bp.enabled = False
+                        return True
+                    else:
+                        # not triggered, so continue
+                        continue
+                return False
+            ]]>
+            </body>
+        </method>
+        <method name="godEvent">
+            <parameter name="block_name" />
+            <parameter name="new_val" />
+            <body>
+            <![CDATA[
+                if block_name not in self.state:
+                    return -1
+                for b in self.model.getBlocks():
+                    if b.getBlockName() == block_name:
+                        b.setSignal(new_val)
+                self.state = {b.getBlockName(): b.getSignal() for b in self.model.getBlocks()}
+                return 0
+            ]]>
+            </body>
+        </method>
+        <scxml initial="Main" internal_event_lifeline="next_combo_step">
+            <parallel id="Main">
+                <state id="SimulationState" initial="Paused">
+                    <state id="Paused">
+                        <onentry><script>print 'entering SimulationState/Paused'</script></onentry>
+                        <onexit><script>print 'exiting SimulationState/Paused'</script></onexit>
+                        <transition target="../Running/Continuous" event="continuous" port="user_input" />
+                        <transition target="../Running/Realtime" event="realtime" port="user_input">
+                            <parameter name="realtime_scale" default="1.0" />
+                            <script>
+                                self.realtime_scale = float(realtime_scale)
+                            </script>
+                        </transition>
+                        <transition target="../Running/BigStep" event="big_step" port="user_input" />
+                    </state>
+                    <state id="PrePaused">
+                        <transition target="../Paused" after="self.sccd_yield()">
+                            <raise event="paused" />
+                        </transition>
+                    </state>
+                    <state id="PreBreakpointTriggered">
+                        <transition target="../Paused" after="self.sccd_yield()">
+                            <raise event="breakpoint_triggered" />
+                        </transition>
+                    </state>
+                    <state id="Running" initial="Continuous">
+                        <onentry><script>print 'entering SimulationState/Running'</script></onentry>
+                        <onexit><script>print 'exiting SimulationState/Running'</script></onexit>
+                        <transition target="../Stopped" cond="self.endCondition()">
+                            <raise event="termination_condition" />
+                        </transition>
+                        <transition target="../PrePaused" event="pause" port="user_input" />
+                        <transition target="../PreBreakpointTriggered" cond="self.breakpointTriggers(INSTATE('./Realtime'))" />
+                        <state id="Continuous" />
+                        <state id="BigStep">
+                            <!-- We go to a special 'BigStepDone' state because in the 'user_output' state, we need to check whether we are currently executing a big step.  -->
+                            <transition target="../BigStepDone" event="big_step_done" />
+                        </state>
+                        <state id="BigStepDone">
+                            <!-- We go back to the 'paused' state once the big step has finished. -->
+                            <transition target="../../Paused" after="self.sccd_yield()" />
+                        </state>
+                        <state id="Realtime">
+                            <onentry>
+                                <script>
+                                    # If the simulation was paused, we need to reset the start time of the simulation.
+                                    # The start time of the simulation is equal to the point in wall-clock time where simulated time is 0.
+                                    # If the simulation was paused, we have to recompute this point in time: it is the difference of the wall-clock time and the simulated time.
+                                    # If the scale was changed after the pause, this point of course moves backwards (for scales smaller than 1) or forwards (for scales larger than 1)
+                                    self.realtime_start_time = accurate_time.time() - (self.clock / self.realtime_scale)
+                                </script>
+                            </onentry>
+                        </state>
+                    </state>
+                    <state id="Stopped">
+                        <onentry><script>print 'entering SimulationState/Stopped'</script></onentry>
+                        <onexit><script>print 'exiting SimulationState/Stopped'</script></onexit>
+                    </state>
+                </state>
+                <state id="SimulationFlow" initial="Initialize">
+                    <state id="Initialize">
+                        <onentry>
+                            <script>
+                            <![CDATA[
+                                self.initialize()
+                            ]]>
+                            </script>
+                        </onentry>
+                        <transition target="../CheckTerminationCondition" />
+                    </state>
+                    <state id="CheckTerminationCondition">
+                        <transition target="../CreateDependencyGraph" cond="INSTATE('/Main/SimulationState/Running/Continuous') or INSTATE('/Main/SimulationState/Running/BigStep')" />
+                        <transition target="../Waiting" cond="INSTATE('/Main/SimulationState/Running/Realtime')" />
+                        <transition target="../Stopped" cond="INSTATE('/Main/SimulationState/Stopped')" after="self.sccd_yield()" />
+                    </state>
+                    <state id="Waiting">
+                        <!-- We schedule to go back to the check_termination state after the smallest possible delay (to accomodate for pauses). -->
+                        <transition target="../CheckTerminationCondition" after="self.sccd_yield()" />
+                        <!-- We execute a step when the wait time is smaller than the smallest possible delay. -->
+                        <transition target="../CreateDependencyGraph" cond="self.waitTime() / 1000.0 &lt;= self.sccd_yield()" />
+                        <!-- We set the simulation time to the correct value. -->
+                        <onexit>
+                            <script>
+                                diff = accurate_time.time() - self.realtime_start_time
+                                self.clock = diff * self.realtime_scale
+                            </script>
+                        </onexit>
+                    </state>
+                    <state id="CreateDependencyGraph">
+                        <onentry>
+                            <script>
+                            <![CDATA[
+                                self.depGraph = self.cbdController.createDepGraph(self.iteration)
+                            ]]>
+                            </script>
+                        </onentry>
+                        <transition target="../IsolateStrongComponents" />
+                    </state>
+                    <state id="IsolateStrongComponents">
+                        <onentry>
+                            <script>
+                            <![CDATA[
+                                self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
+                            ]]>
+                            </script>
+                        </onentry>
+                        <transition target="../ExecuteSimulationStep">
+                            <script>
+                                <![CDATA[
+                                    self.currentCompIdx = -1
+                                ]]>
+                            </script>
+                        </transition>
+                    </state>
+                    <state id="ExecuteSimulationStep" initial="CheckNextComponent">
+                        <state id="CheckNextComponent">
+                            <transition target="../CheckCycle" cond="self.hasNextStrongComponent()">
+                                <script>
+                                    <![CDATA[
+                                        self.currentCompIdx = self.currentCompIdx + 1
+                                    ]]>
+                                </script>
+                            </transition>
+                            <!-- We wait a minimum amount of time to allow pause requests to be processed. -->
+                            <transition target="../../CheckTerminationCondition" cond="not self.hasNextStrongComponent()" after="self.sccd_yield()">
+                                <script>
+                                    <![CDATA[
+                                        self.advanceTime()
+                                        self.state = {b.getBlockName(): b.getSignal() for b in self.model.getBlocks()}
+                                    ]]>
+                                </script>
+                                <raise event="big_step_done" />
+                            </transition>
+                        </state>
+                        <state id="CheckCycle">
+                            <transition target="../CheckNextComponent" cond="not self.currentComponentIsCycle()">
+                                <script>
+                                    <![CDATA[
+                                        self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
+                                    ]]>
+                                </script>
+                            </transition>
+                            <transition target="../CheckNextComponent" cond="self.currentComponentIsCycle()">
+                                <script>
+                                    <![CDATA[
+                                        self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+                                    ]]>
+                                </script>
+                            </transition>
+                        </state>
+                    </state>
+                    <state id="Stopped" />
+                </state>
+                <state id="BreakpointManager" initial="Listening">
+                    <state id="Listening">
+                        <transition target="." event="add_breakpoint" port="user_input">
+                            <parameter name="name"/>
+                            <parameter name="function"/>
+                            <parameter name="enabled"/>
+                            <parameter name="disable_on_trigger"/>
+                            <script>
+                                result = self.addBreakpoint(name, function, bool(enabled), bool(disable_on_trigger))
+                            </script>
+                            <raise event="add_breakpoint_result" port="user_output">
+                                <parameter expr="result" />
+                            </raise>
+                        </transition>
+                        <transition target="." event="del_breakpoint" port="user_input">
+                            <parameter name="name"/>
+                            <script>
+                                result = self.delBreakpoint(name)
+                            </script>
+                            <raise event="del_breakpoint_result" port="user_output">
+                                <parameter expr="result" />
+                            </raise>
+                        </transition>
+                        <transition target="." event="toggle_breakpoint" port="user_input">
+                            <parameter name="name"/>
+                            <script>
+                                result = self.toggleBreakpoint(name)
+                            </script>
+                            <raise event="toggle_breakpoint_result" port="user_output">
+                                <parameter expr="result" />
+                            </raise>
+                        </transition>
+                        <transition target="." event="list_breakpoints" port="user_input">
+                            <raise event="list_breakpoints_result" port="user_output">
+                                <parameter expr="[bp.name for bp in self.breakpoints]" />
+                            </raise>
+                        </transition>
+                    </state>
+                </state>
+                <state id="GodEventManager" initial="Listening">
+                    <state id="Listening">
+                        <transition target="." event="god_event" port="user_input" cond="INSTATE('/Main/SimulationState/Paused')">
+                            <parameter name="block_name" />
+                            <parameter name="new_val" />
+                            <script>
+                                result = self.godEvent(block_name, new_val)
+                            </script>
+                            <raise event="god_event_result" port="user_output">
+                                <parameter expr="result" />
+                            </raise>
+                        </transition>
+                    </state>
+                </state>
+                <state id="UserOutput" initial="Waiting">
+                    <state id="Waiting">
+                        <transition target="." event="termination_condition">
+                            <raise event="terminated" port="user_output"/>
+                            <raise event="current_state" port="user_output">
+                                <parameter expr="self.clock / 1000.0" />
+                                <parameter expr="self.state" />
+                            </raise>
+                        </transition>
+                        <transition target="." event="paused">
+                            <raise event="paused" port="user_output" />
+                            <raise event="current_state" port="user_output">
+                                <parameter expr="self.clock / 1000.0" />
+                                <parameter expr="self.state" />
+                            </raise>
+                        </transition>
+                        <transition target="." event="big_step_done" cond="INSTATE('/Main/SimulationState/Running/Realtime') or INSTATE('/Main/SimulationState/Running/BigStep') or INSTATE('/Main/SimulationState/Running/BigStepDone')">
+                            <raise event="stepped" port="user_output" />
+                            <raise event="current_state" port="user_output">
+                                <parameter expr="self.clock / 1000.0" />
+                                <parameter expr="self.state" />
+                            </raise>
+                        </transition>
+                        <transition target="." event="breakpoint_triggered">
+                            <raise event="breakpoint_triggered" port="user_output">
+                                <parameter expr="self.triggered_bp" />
+                            </raise>
+                            <raise event="current_state" port="user_output">
+                                <parameter expr="self.clock / 1000.0" />
+                                <parameter expr="self.state" />
+                            </raise>
+                        </transition>
+                    </state>
+                </state>
+                <transition target="../SimulationComplete" cond="INSTATE('./SimulationState/Stopped') and INSTATE('./SimulationFlow/Stopped')">
+                    <script>
+                        self.finalize()
+                    </script>
+                </transition>
+            </parallel>
+            <state id="SimulationComplete" />
+        </scxml>
+    </class>
+</diagram>

+ 114 - 0
debugging_fsa_cbd_composition/cbdsimulator/cbdsim_hierarchical.sccd

@@ -0,0 +1,114 @@
+Diagram(name = 'CBDSimulator',
+        author = 'Sadaf Mustafiz and Bruno Barroca and Claudio Gomes',
+        description = 'SCCD HUTN model of a CBD simulator'):
+    Top {
+        from CBD_Controller import CBDController
+        import Options
+    }
+
+    Class(name = 'CBDSimulator', default = True):
+        Attribute(name='iteration')
+        Attribute(name='strongComponentList')
+        Attribute(name='currentCompIdx')
+        Attribute(name='clock')
+        Attribute(name='delta')
+        Attribute(name='cbdController')
+        Attribute(name='model')
+		Attribute(name='depGraph')
+		
+        Constructor(options, model) {
+            self.options = options
+			self.delta = self.options->getDeltaT()
+			self.model = model
+        }
+		
+		Method currentComponentIsCycle() {
+            return self.cbdController->componentIsCycle(self.strongComponentList[self.currentCompIdx], self.depGraph)
+        }
+		
+		Method hasNextStrongComponent() {
+			return (self.currentCompIdx) < len(self.strongComponentList)
+        }
+		
+		Method computeBlock(){
+			if self->currentComponentIsCycle():
+				self.cbdController->computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+			else:
+				self.cbdController->computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
+			end
+		}
+		
+        Method advanceTime() {
+			self.iteration = self.iteration + 1
+			self.clock = self.clock + self.delta
+        	self.cbdController->advanceTimeStep()
+        }
+        
+		Method maxIterationsReached() {
+			return self.iteration >= self.options->getMaxIterations()
+        }
+		
+        StateMachine:
+			initial = 'Started'
+			final = 'End'
+			State('Started'):
+				Transition(target='../Initialized'):
+					Actions {
+						print('Going to Initialized... ')
+						print('Performing initialization...')
+						self.iteration = 0
+						self.clock = 0
+						self.cbdController = CBDController(self.model,self.delta)
+						self.cbdController->initSimulation()
+						print('Performing initialization... DONE')
+					}
+			State('Initialized'):
+				Transition(target='../CheckTermination'):
+					Actions {
+						print('Going to CheckTermination... ')
+					}
+			State('CheckTermination'):
+				initial = 'MacroStepProcessed'
+				State('MacroStepProcessed'):
+					Transition(target='../../DoSimulation'):
+						guard = { not self->maxIterationsReached() }
+						Actions {
+							print('Going to DoSimulation... ')
+							self.currentCompIdx = 0
+							self.depGraph = self.cbdController->createDepGraph(self.iteration)
+							self.strongComponentList = self.cbdController->createStrongComponents(self.depGraph, self.iteration)
+						}
+					Transition(target='../../End'):
+						guard = { self->maxIterationsReached() }
+						Actions {
+							print('Going to End... ')
+						}
+			State('DoSimulation'):
+				initial = 'MacroStepPrepared'
+				State('MacroStepPrepared'):
+					Transition(target='../MicroStepProcessed'):
+						Actions {
+							print('Going to MicroStepProcessed... ')
+						}
+				State('MicroStepProcessed'):
+					Transition(target='../../CheckTermination'):
+						guard = { not self->hasNextStrongComponent() }
+						Actions {
+							print('Going to CheckTermination and advancing time... ')
+							self->advanceTime()
+							print(self.clock)
+							print(self.iteration)
+						}
+					Transition(target='../MicroStepPrepared'):
+						guard = { self->hasNextStrongComponent() }
+						Actions {
+							print('Going to MicroStepPrepared')
+						}
+				State('MicroStepPrepared'):
+					Transition(target='../MicroStepProcessed'):
+						Actions {
+							print('Going to MicroStepProcessed...')
+							self->computeBlock()
+							self.currentCompIdx = self.currentCompIdx + 1
+						}
+			State('End')

+ 110 - 0
debugging_fsa_cbd_composition/cbdsimulator/cbdsim_normal_form.sccd

@@ -0,0 +1,110 @@
+Diagram(name = 'CBDSimulator',
+        author = 'Sadaf Mustafiz and Bruno Barroca and Claudio Gomes',
+        description = 'SCCD HUTN model of a CBD simulator'):
+    Top {
+        from CBD_Controller import CBDController
+        import Options
+    }
+
+    Class(name = 'CBDSimulator', default = True):
+        Attribute(name='iteration')
+        Attribute(name='strongComponentList')
+        Attribute(name='currentCompIdx')
+        Attribute(name='clock')
+        Attribute(name='delta')
+        Attribute(name='cbdController')
+        Attribute(name='model')
+		Attribute(name='depGraph')
+		
+        Constructor(options, model) {
+            self.options = options
+			self.delta = self.options->getDeltaT()
+			self.model = model
+        }
+		
+		Method currentComponentIsCycle() {
+            return self.cbdController->componentIsCycle(self.strongComponentList[self.currentCompIdx], self.depGraph)
+        }
+		
+		Method hasNextStrongComponent() {
+			return (self.currentCompIdx) < len(self.strongComponentList)
+        }
+		
+		Method computeBlock(){
+			if self->currentComponentIsCycle():
+				self.cbdController->computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+			else:
+				self.cbdController->computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
+			end
+		}
+		
+        Method advanceTime() {
+			self.iteration = self.iteration + 1
+			self.clock = self.clock + self.delta
+        	self.cbdController->advanceTimeStep()
+        }
+        
+		Method maxIterationsReached() {
+			return self.iteration >= self.options->getMaxIterations()
+        }
+		
+        StateMachine:
+			initial = 'Started'
+			final = 'End'
+			State('Started'):
+				Transition(target='../Initialized'):
+					Actions {
+						print('Going to Initialized... ')
+						print('Performing initialization...')
+						self.iteration = 0
+						self.clock = 0
+						self.cbdController = CBDController(self.model,self.delta)
+						self.cbdController->initSimulation()
+						print('Performing initialization... DONE')
+					}
+			State('Initialized'):
+				Transition(target='../MacroStepProcessed'):
+					Actions {
+						print('Going to MacroStepProcessed... ')
+					}
+			State('MacroStepProcessed'):
+				Transition(target='../MacroStepPrepared'):
+					guard = { not self->maxIterationsReached() }
+					Actions {
+						print('Going to MacroStepPrepared... ')
+						self.currentCompIdx = 0
+						self.depGraph = self.cbdController->createDepGraph(self.iteration)
+						self.strongComponentList = self.cbdController->createStrongComponents(self.depGraph, self.iteration)
+					}
+				Transition(target='../End'):
+					guard = { self->maxIterationsReached() }
+					Actions {
+						print('Going to End... ')
+					}
+			State('MacroStepPrepared'):
+				Transition(target='../MicroStepProcessed'):
+					Actions {
+						print('Going to MicroStepProcessed... ')
+					}
+			State('MicroStepProcessed'):
+				Transition(target='../MacroStepProcessed'):
+					guard = { not self->hasNextStrongComponent() }
+					Actions {
+						print('Going to MacroStepProcessed and advancing time... ')
+						self->advanceTime()
+						print(self.clock)
+						print(self.iteration)
+					}
+				Transition(target='../MicroStepPrepared'):
+					guard = { self->hasNextStrongComponent() }
+					Actions {
+						print('Going to MicroStepPrepared')
+					}
+			State('MicroStepPrepared'):
+				Transition(target='../MicroStepProcessed'):
+					Actions {
+						print('Going to MicroStepProcessed...')
+						self->computeBlock()
+						self.currentCompIdx = self.currentCompIdx + 1
+					}
+			State('End')

+ 6 - 0
debugging_fsa_cbd_composition/cbdsimulator/generateSCCD.bat

@@ -0,0 +1,6 @@
+@ECHO OFF
+setlocal
+set PYTHONPATH=C:\Users\clagms\Source Control\Git_SCCD\src\build\lib;C:\Users\clagms\Source Control\SVN_MvK
+python "C:\Users\clagms\Source Control\Git_SCCD\textualnotations\sccdtnc.py" "C:\Users\clagms\Source Control\Git_MLE\fsa_cbd_composition\cbdsimulator\cbdsim.sccd" -o "C:\Users\clagms\Source Control\Git_MLE\fsa_cbd_composition\cbdsimulator\cbdsim.py"
+endlocal
+pause

+ 0 - 0
debugging_fsa_cbd_composition/cbdsimulator/log.txt


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 43 - 0
debugging_fsa_cbd_composition/cbdsimulator/plot.html


+ 30 - 0
debugging_fsa_cbd_composition/cbdsimulator/run_cbd_sim.py

@@ -0,0 +1,30 @@
+"""
+author: Claudio Gomes
+email: claudio.gomes[at]uantwerpen.be
+"""
+from bokeh.plotting import figure, output_file, show
+from cbdsim import Controller
+from Options import Options
+from CBDMultipleOutput.models.HarmonicOscilator import CircleCBDDerivative
+from CBDMultipleOutput.Source.CBD import CBD
+
+options = Options(delta = 0.01)
+options.setMaxIterations(1000);
+#cbdModel = EvenNumberGen("EvenNumbersGenerator")
+cbdModel = CircleCBDDerivative("CircleCBDDerivative",options.getDeltaT())
+# Use keep_running false for as fast as possible simulation.
+cbdSimController = Controller(options, cbdModel, keep_running=False)
+cbdSimController.start()
+
+times = []
+values = []
+for timeValuePair in cbdModel.getSignal("neg"):
+    times.append(timeValuePair.time)
+    values.append(timeValuePair.value)
+
+output_file("./plot.html", title="Plot")
+p = figure(title="Something vs Otherthing", x_axis_label="Time", y_axis_label="Values")
+p.line(times, values, legend="Something", line_width=1, line_color="red")
+show(p)
+
+print "DONE"

+ 106 - 0
debugging_fsa_cbd_composition/cbdsimulator/runner.py

@@ -0,0 +1,106 @@
+import target
+from sccd.runtime.statecharts_core import Event
+import threading
+from Options import Options
+from CBDMultipleOutput.models.HarmonicOscilator import CircleCBDDerivative
+from CBDMultipleOutput.Source.CBD import CBD
+
+if __name__ == '__main__':
+    options = Options(delta = 0.01)
+    options.setMaxIterations(1000);
+    #cbdModel = EvenNumberGen("EvenNumbersGenerator")
+    cbdModel = CircleCBDDerivative("CircleCBDDerivative", options.getDeltaT())
+    # Use keep_running false for as fast as possible simulation.
+    controller = target.Controller(options, cbdModel)
+    
+    def set_defaults(inp, defaultlist):
+        for i, v in enumerate(defaultlist):
+            if len(inp) == i + 1:
+                inp.append(v)
+                
+    def get_bool(val):
+        if val.lower() in ["true", "yes", "1"]:
+            return True
+        else:
+            return False
+
+    def raw_inputter():
+        while 1:
+            inp = raw_input().split(" ")
+            action = inp[0]
+            if action == "continuous":
+                params = []
+            elif action == "realtime":
+                set_defaults(inp, [1.0])
+                params = [inp[1]]
+            elif action == "big_step":
+                params = []
+            elif action == "pause":
+                params = []
+            elif action == "add_breakpoint":
+                if len(inp) < 5:
+                    print("Adding a breakpoint requires 4 parameters!")
+                    continue
+                # Merge together the final part again
+                params = [inp[1], " ".join(inp[2:-2]).replace("\\n", "\n").replace("\\t", "\t"), get_bool(inp[-2]), get_bool(inp[-1])]
+                print("Generated parameters: " + str(params))
+            elif action == "del_breakpoint":
+                if len(inp) < 2:
+                    print("Breakpoint removal requires 1 parameter!")
+                    continue
+                params = [inp[1]]
+            elif action == "toggle_breakpoint":
+                params = [inp[1]]
+            elif action == "list_breakpoints":
+                params = []
+            elif action == "god_event":
+                if len(inp) != 3:
+                    print("God events require 2 parameters!")
+                    continue
+                params = [inp[1], eval(inp[2])]
+            elif action == "help":
+                print("Supported operations:")
+                print("  continuous")
+                print("   --> Simulate until termination time is reached")
+                print("  pause")
+                print("   --> Pause the simulation")
+                print("  realtime [realtime_scale]")
+                print("   --> Simulate in realtime")
+                print("       realtime_scale can speed up or slow down the pace")
+                print("  big_step")
+                print("   --> Simulate a single step")
+                print("  add_breakpoint name function enabled disable_on_trigger")
+                print("   --> Add a breakpoint that will pause simulation when function returns True")
+                print("       the function should contain a definition of the 'breakpoint' function")
+                print("       and must take 1 parameter")
+                print("       enabled indicates whether or not the breakpoint should be checked")
+                print("       disable_on_trigger determines if the breakpoint should auto-disable")
+                print("       after being triggered")
+                print("  del_breakpoint name")
+                print("   --> Remove a breakpoint")
+                print("  toggle_breakpoint name")
+                print("   --> Toggle the designated breakpoint")
+                print("  list_breakpoints")
+                print("   --> List all breakpoints")
+                print("")
+                print("Defaults: ")
+                print("  realtime_scale   --> 1.0")
+                continue
+            else:
+                print("Command not understood: " + str(inp))
+                continue
+            controller.addInput(Event(action, "user_input", params))
+            
+    input_thread = threading.Thread(target=raw_inputter)
+    input_thread.daemon = True
+    input_thread.start()
+
+    output_listener = controller.addOutputListener(["user_output"])
+    def outputter():
+        while 1:
+            print output_listener.fetch(-1)
+    output_thread = threading.Thread(target=outputter)
+    output_thread.daemon = True
+    output_thread.start()
+
+    controller.start()

+ 713 - 0
debugging_fsa_cbd_composition/cbdsimulator/target.py

@@ -0,0 +1,713 @@
+"""
+Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
+
+Date:   Tue Oct 11 15:57:15 2016
+
+Model author: Sadaf Mustafiz and Claudio Gomes and Simon Van Mierlo
+Model name:   CBDSimulator
+Model description:
+SCCD HUTN model of a CBD simulator
+"""
+
+from sccd.runtime.statecharts_core import *
+from sccd.runtime.libs.ui import *
+from sccd.runtime.libs.utils import *
+from CBD_Controller import CBDController
+import Options
+import sccd.runtime.accurate_time as accurate_time
+
+class Breakpoint:
+    def __init__(self, name, function, enabled, disable_on_trigger):
+        self.name = name
+        self.function = function
+        self.enabled = enabled
+        self.disable_on_trigger = disable_on_trigger
+
+# package "CBDSimulator"
+
+class CBDSimulator(RuntimeClassBase):
+    def __init__(self, controller, options, model):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.NextComboStep
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # user defined attributes
+        self.iteration = None
+        self.cbdController = None
+        self.delta = None
+        self.clock = None
+        self.model = None
+        self.depGraph = None
+        self.strongComponentList = None
+        self.currentCompIdx = None
+        
+        # call user defined constructor
+        CBDSimulator.user_defined_constructor(self, options, model)
+    
+    def user_defined_constructor(self, options, model):
+        self.options = options
+        self.delta = self.options.getDeltaT() * 1000.0
+        self.model = model
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # user defined method
+    def initialize(self):
+        self.iteration = 0
+        self.clock = 0
+        self.time_next = self.delta
+        self.cbdController = CBDController(self.model, self.delta)
+        self.cbdController.initSimulation()
+        self.state = {b.getBlockName(): b.getSignal() for b in self.model.getBlocks()}
+        self.breakpoints = []
+        self.triggered_bp = None
+    
+    
+    # user defined method
+    def endCondition(self):
+        return self.iteration >= self.options.getMaxIterations()
+    
+    
+    # user defined method
+    def advanceTime(self):
+        self.iteration = self.iteration + 1
+        self.clock = self.time_next
+        self.cbdController.advanceTimeStep()
+        self.time_next = self.clock + self.delta
+    
+    
+    # user defined method
+    def currentComponentIsCycle(self):
+        return self.cbdController.componentIsCycle(self.strongComponentList[self.currentCompIdx], self.depGraph)
+    
+    
+    # user defined method
+    def hasNextStrongComponent(self):
+        return (self.currentCompIdx + 1) < len(self.strongComponentList)
+    
+    
+    # user defined method
+    def finalize(self):
+        from bokeh.plotting import figure, output_file, show    
+        times = []
+        values = []
+        for timeValuePair in self.model.getSignal("neg"):
+            times.append(timeValuePair.time)
+            values.append(timeValuePair.value)
+        
+        output_file("./plot.html", title="Plot")
+        p = figure(title="Something vs Otherthing", x_axis_label="Time", y_axis_label="Values")
+        p.line(times, values, legend="Something", line_width=1, line_color="red")
+        show(p)
+    
+    
+    # user defined method
+    def waitTime(self):
+        # First, we convert from wall-clock time to simulated time.
+        # This means the elapsed time in wall-clock time needs to be scaled according to the realtime scale (for example, if the realtime scale is 2, an elapsed time of 1 second in wall-clock time is equal to an elapsed time of 2 seconds in simulated time).
+        simulated_diff = (accurate_time.time() - self.realtime_start_time) * self.realtime_scale
+        # time_next and simulated_diff are both in simulated time: so now scale back to wall-clock time by dividing.
+        # This function returns an amount of miliseconds.
+        return ((self.time_next - simulated_diff) / self.realtime_scale)
+    
+    
+    # user defined method
+    def addBreakpoint(self, name, function, enabled = None, disable_on_trigger = None):
+        if enabled == None: enabled = true
+        if disable_on_trigger == None: disable_on_trigger = true
+        if len([bp for bp in self.breakpoints if bp.name == name]) > 0:
+            return -1
+        self.breakpoints.append(Breakpoint(name, function, enabled, disable_on_trigger))
+        return 0
+    
+    
+    # user defined method
+    def delBreakpoint(self, name):
+        if len([bp for bp in self.breakpoints if bp.name == name]) == 0:
+            return -1
+        self.breakpoints = [bp for bp in self.breakpoints if bp.name != name]
+        return 0
+    
+    
+    # user defined method
+    def toggleBreakpoint(self, name):
+        if len([bp for bp in self.breakpoints if bp.name == name]) == 0:
+            return -1
+        for bp in self.breakpoints:
+            if bp.name == name:
+                bp.enabled = enabled
+                break
+        return 0
+    
+    
+    # user defined method
+    def breakpointTriggers(self, is_realtime_simulation):
+        self.triggered_bp = None
+        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("
+            # note that we pass self.time_next instead of self.simulated_time in the case of as-fast-as-possible simulation (or stepping)
+            # this is to make sure that the simulation is stopped BEFORE the specified time is reached, and not AFTER (because we don't necessarily implement 'step back')
+            # in case of realtime simulation, we do pass the current simulated time, since we can stop at (more or less) exactly the right time
+            if breakpoint({'clock': (self.clock if is_realtime_simulation else self.time_next) / 1000.0, 'state': self.state}):
+                # triggered!
+                self.triggered_bp = bp.name
+                if bp.disable_on_trigger:
+                    bp.enabled = False
+                return True
+            else:
+                # not triggered, so continue
+                continue
+        return False
+    
+    
+    # user defined method
+    def godEvent(self, block_name, new_val):
+        if block_name not in self.state:
+            return -1
+        for b in self.model.getBlocks():
+            if b.getBlockName() == block_name:
+                b.setSignal(new_val)
+        self.state = {b.getBlockName(): b.getSignal() for b in self.model.getBlocks()}
+        return 0
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, self)
+        
+        # state /Main
+        self.states["/Main"] = ParallelState(1, self)
+        
+        # state /Main/SimulationState
+        self.states["/Main/SimulationState"] = State(2, self)
+        
+        # state /Main/SimulationState/Paused
+        self.states["/Main/SimulationState/Paused"] = State(3, self)
+        self.states["/Main/SimulationState/Paused"].setEnter(self._Main_SimulationState_Paused_enter)
+        self.states["/Main/SimulationState/Paused"].setExit(self._Main_SimulationState_Paused_exit)
+        
+        # state /Main/SimulationState/PrePaused
+        self.states["/Main/SimulationState/PrePaused"] = State(4, self)
+        self.states["/Main/SimulationState/PrePaused"].setEnter(self._Main_SimulationState_PrePaused_enter)
+        self.states["/Main/SimulationState/PrePaused"].setExit(self._Main_SimulationState_PrePaused_exit)
+        
+        # state /Main/SimulationState/PreBreakpointTriggered
+        self.states["/Main/SimulationState/PreBreakpointTriggered"] = State(5, self)
+        self.states["/Main/SimulationState/PreBreakpointTriggered"].setEnter(self._Main_SimulationState_PreBreakpointTriggered_enter)
+        self.states["/Main/SimulationState/PreBreakpointTriggered"].setExit(self._Main_SimulationState_PreBreakpointTriggered_exit)
+        
+        # state /Main/SimulationState/Running
+        self.states["/Main/SimulationState/Running"] = State(6, self)
+        self.states["/Main/SimulationState/Running"].setEnter(self._Main_SimulationState_Running_enter)
+        self.states["/Main/SimulationState/Running"].setExit(self._Main_SimulationState_Running_exit)
+        
+        # state /Main/SimulationState/Running/Continuous
+        self.states["/Main/SimulationState/Running/Continuous"] = State(7, self)
+        
+        # state /Main/SimulationState/Running/BigStep
+        self.states["/Main/SimulationState/Running/BigStep"] = State(8, self)
+        
+        # state /Main/SimulationState/Running/BigStepDone
+        self.states["/Main/SimulationState/Running/BigStepDone"] = State(9, self)
+        self.states["/Main/SimulationState/Running/BigStepDone"].setEnter(self._Main_SimulationState_Running_BigStepDone_enter)
+        self.states["/Main/SimulationState/Running/BigStepDone"].setExit(self._Main_SimulationState_Running_BigStepDone_exit)
+        
+        # state /Main/SimulationState/Running/Realtime
+        self.states["/Main/SimulationState/Running/Realtime"] = State(10, self)
+        self.states["/Main/SimulationState/Running/Realtime"].setEnter(self._Main_SimulationState_Running_Realtime_enter)
+        
+        # state /Main/SimulationState/Stopped
+        self.states["/Main/SimulationState/Stopped"] = State(11, self)
+        self.states["/Main/SimulationState/Stopped"].setEnter(self._Main_SimulationState_Stopped_enter)
+        self.states["/Main/SimulationState/Stopped"].setExit(self._Main_SimulationState_Stopped_exit)
+        
+        # state /Main/SimulationFlow
+        self.states["/Main/SimulationFlow"] = State(12, self)
+        
+        # state /Main/SimulationFlow/Initialize
+        self.states["/Main/SimulationFlow/Initialize"] = State(13, self)
+        self.states["/Main/SimulationFlow/Initialize"].setEnter(self._Main_SimulationFlow_Initialize_enter)
+        
+        # state /Main/SimulationFlow/CheckTerminationCondition
+        self.states["/Main/SimulationFlow/CheckTerminationCondition"] = State(14, self)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition"].setEnter(self._Main_SimulationFlow_CheckTerminationCondition_enter)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition"].setExit(self._Main_SimulationFlow_CheckTerminationCondition_exit)
+        
+        # state /Main/SimulationFlow/Waiting
+        self.states["/Main/SimulationFlow/Waiting"] = State(15, self)
+        self.states["/Main/SimulationFlow/Waiting"].setEnter(self._Main_SimulationFlow_Waiting_enter)
+        self.states["/Main/SimulationFlow/Waiting"].setExit(self._Main_SimulationFlow_Waiting_exit)
+        
+        # state /Main/SimulationFlow/CreateDependencyGraph
+        self.states["/Main/SimulationFlow/CreateDependencyGraph"] = State(16, self)
+        self.states["/Main/SimulationFlow/CreateDependencyGraph"].setEnter(self._Main_SimulationFlow_CreateDependencyGraph_enter)
+        
+        # state /Main/SimulationFlow/IsolateStrongComponents
+        self.states["/Main/SimulationFlow/IsolateStrongComponents"] = State(17, self)
+        self.states["/Main/SimulationFlow/IsolateStrongComponents"].setEnter(self._Main_SimulationFlow_IsolateStrongComponents_enter)
+        
+        # state /Main/SimulationFlow/ExecuteSimulationStep
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep"] = State(18, self)
+        
+        # state /Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"] = State(19, self)
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"].setEnter(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_enter)
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"].setExit(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_exit)
+        
+        # state /Main/SimulationFlow/ExecuteSimulationStep/CheckCycle
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"] = State(20, self)
+        
+        # state /Main/SimulationFlow/Stopped
+        self.states["/Main/SimulationFlow/Stopped"] = State(21, self)
+        
+        # state /Main/BreakpointManager
+        self.states["/Main/BreakpointManager"] = State(22, self)
+        
+        # state /Main/BreakpointManager/Listening
+        self.states["/Main/BreakpointManager/Listening"] = State(23, self)
+        
+        # state /Main/GodEventManager
+        self.states["/Main/GodEventManager"] = State(24, self)
+        
+        # state /Main/GodEventManager/Listening
+        self.states["/Main/GodEventManager/Listening"] = State(25, self)
+        
+        # state /Main/UserOutput
+        self.states["/Main/UserOutput"] = State(26, self)
+        
+        # state /Main/UserOutput/Waiting
+        self.states["/Main/UserOutput/Waiting"] = State(27, self)
+        
+        # state /SimulationComplete
+        self.states["/SimulationComplete"] = State(28, self)
+        
+        # add children
+        self.states[""].addChild(self.states["/Main"])
+        self.states[""].addChild(self.states["/SimulationComplete"])
+        self.states["/Main"].addChild(self.states["/Main/SimulationState"])
+        self.states["/Main"].addChild(self.states["/Main/SimulationFlow"])
+        self.states["/Main"].addChild(self.states["/Main/BreakpointManager"])
+        self.states["/Main"].addChild(self.states["/Main/GodEventManager"])
+        self.states["/Main"].addChild(self.states["/Main/UserOutput"])
+        self.states["/Main/SimulationState"].addChild(self.states["/Main/SimulationState/Paused"])
+        self.states["/Main/SimulationState"].addChild(self.states["/Main/SimulationState/PrePaused"])
+        self.states["/Main/SimulationState"].addChild(self.states["/Main/SimulationState/PreBreakpointTriggered"])
+        self.states["/Main/SimulationState"].addChild(self.states["/Main/SimulationState/Running"])
+        self.states["/Main/SimulationState"].addChild(self.states["/Main/SimulationState/Stopped"])
+        self.states["/Main/SimulationState/Running"].addChild(self.states["/Main/SimulationState/Running/Continuous"])
+        self.states["/Main/SimulationState/Running"].addChild(self.states["/Main/SimulationState/Running/BigStep"])
+        self.states["/Main/SimulationState/Running"].addChild(self.states["/Main/SimulationState/Running/BigStepDone"])
+        self.states["/Main/SimulationState/Running"].addChild(self.states["/Main/SimulationState/Running/Realtime"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/Initialize"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/CheckTerminationCondition"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/Waiting"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/CreateDependencyGraph"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/IsolateStrongComponents"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/ExecuteSimulationStep"])
+        self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/Stopped"])
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep"].addChild(self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"])
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep"].addChild(self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"])
+        self.states["/Main/BreakpointManager"].addChild(self.states["/Main/BreakpointManager/Listening"])
+        self.states["/Main/GodEventManager"].addChild(self.states["/Main/GodEventManager/Listening"])
+        self.states["/Main/UserOutput"].addChild(self.states["/Main/UserOutput/Waiting"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/Main"]
+        self.states["/Main/SimulationState"].default_state = self.states["/Main/SimulationState/Paused"]
+        self.states["/Main/SimulationState/Running"].default_state = self.states["/Main/SimulationState/Running/Continuous"]
+        self.states["/Main/SimulationFlow"].default_state = self.states["/Main/SimulationFlow/Initialize"]
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep"].default_state = self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"]
+        self.states["/Main/BreakpointManager"].default_state = self.states["/Main/BreakpointManager/Listening"]
+        self.states["/Main/GodEventManager"].default_state = self.states["/Main/GodEventManager/Listening"]
+        self.states["/Main/UserOutput"].default_state = self.states["/Main/UserOutput/Waiting"]
+        
+        # transition /Main/SimulationState/Paused
+        _Main_SimulationState_Paused_0 = Transition(self, self.states["/Main/SimulationState/Paused"], [self.states["/Main/SimulationState/Running/Continuous"]])
+        _Main_SimulationState_Paused_0.setTrigger(Event("continuous", "user_input"))
+        self.states["/Main/SimulationState/Paused"].addTransition(_Main_SimulationState_Paused_0)
+        _Main_SimulationState_Paused_1 = Transition(self, self.states["/Main/SimulationState/Paused"], [self.states["/Main/SimulationState/Running/Realtime"]])
+        _Main_SimulationState_Paused_1.setAction(self._Main_SimulationState_Paused_1_exec)
+        _Main_SimulationState_Paused_1.setTrigger(Event("realtime", "user_input"))
+        self.states["/Main/SimulationState/Paused"].addTransition(_Main_SimulationState_Paused_1)
+        _Main_SimulationState_Paused_2 = Transition(self, self.states["/Main/SimulationState/Paused"], [self.states["/Main/SimulationState/Running/BigStep"]])
+        _Main_SimulationState_Paused_2.setTrigger(Event("big_step", "user_input"))
+        self.states["/Main/SimulationState/Paused"].addTransition(_Main_SimulationState_Paused_2)
+        
+        # transition /Main/SimulationState/PrePaused
+        _Main_SimulationState_PrePaused_0 = Transition(self, self.states["/Main/SimulationState/PrePaused"], [self.states["/Main/SimulationState/Paused"]])
+        _Main_SimulationState_PrePaused_0.setAction(self._Main_SimulationState_PrePaused_0_exec)
+        _Main_SimulationState_PrePaused_0.setTrigger(Event("_0after"))
+        self.states["/Main/SimulationState/PrePaused"].addTransition(_Main_SimulationState_PrePaused_0)
+        
+        # transition /Main/SimulationState/PreBreakpointTriggered
+        _Main_SimulationState_PreBreakpointTriggered_0 = Transition(self, self.states["/Main/SimulationState/PreBreakpointTriggered"], [self.states["/Main/SimulationState/Paused"]])
+        _Main_SimulationState_PreBreakpointTriggered_0.setAction(self._Main_SimulationState_PreBreakpointTriggered_0_exec)
+        _Main_SimulationState_PreBreakpointTriggered_0.setTrigger(Event("_1after"))
+        self.states["/Main/SimulationState/PreBreakpointTriggered"].addTransition(_Main_SimulationState_PreBreakpointTriggered_0)
+        
+        # transition /Main/SimulationState/Running/BigStep
+        _Main_SimulationState_Running_BigStep_0 = Transition(self, self.states["/Main/SimulationState/Running/BigStep"], [self.states["/Main/SimulationState/Running/BigStepDone"]])
+        _Main_SimulationState_Running_BigStep_0.setTrigger(Event("big_step_done", None))
+        self.states["/Main/SimulationState/Running/BigStep"].addTransition(_Main_SimulationState_Running_BigStep_0)
+        
+        # transition /Main/SimulationState/Running/BigStepDone
+        _Main_SimulationState_Running_BigStepDone_0 = Transition(self, self.states["/Main/SimulationState/Running/BigStepDone"], [self.states["/Main/SimulationState/Paused"]])
+        _Main_SimulationState_Running_BigStepDone_0.setTrigger(Event("_2after"))
+        self.states["/Main/SimulationState/Running/BigStepDone"].addTransition(_Main_SimulationState_Running_BigStepDone_0)
+        
+        # transition /Main/SimulationFlow/Initialize
+        _Main_SimulationFlow_Initialize_0 = Transition(self, self.states["/Main/SimulationFlow/Initialize"], [self.states["/Main/SimulationFlow/CheckTerminationCondition"]])
+        _Main_SimulationFlow_Initialize_0.setTrigger(None)
+        self.states["/Main/SimulationFlow/Initialize"].addTransition(_Main_SimulationFlow_Initialize_0)
+        
+        # transition /Main/SimulationFlow/CheckTerminationCondition
+        _Main_SimulationFlow_CheckTerminationCondition_0 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition"], [self.states["/Main/SimulationFlow/CreateDependencyGraph"]])
+        _Main_SimulationFlow_CheckTerminationCondition_0.setTrigger(None)
+        _Main_SimulationFlow_CheckTerminationCondition_0.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_0_guard)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_0)
+        _Main_SimulationFlow_CheckTerminationCondition_1 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition"], [self.states["/Main/SimulationFlow/Waiting"]])
+        _Main_SimulationFlow_CheckTerminationCondition_1.setTrigger(None)
+        _Main_SimulationFlow_CheckTerminationCondition_1.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_1_guard)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_1)
+        _Main_SimulationFlow_CheckTerminationCondition_2 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition"], [self.states["/Main/SimulationFlow/Stopped"]])
+        _Main_SimulationFlow_CheckTerminationCondition_2.setTrigger(Event("_3after"))
+        _Main_SimulationFlow_CheckTerminationCondition_2.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_2_guard)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_2)
+        
+        # transition /Main/SimulationFlow/Waiting
+        _Main_SimulationFlow_Waiting_0 = Transition(self, self.states["/Main/SimulationFlow/Waiting"], [self.states["/Main/SimulationFlow/CheckTerminationCondition"]])
+        _Main_SimulationFlow_Waiting_0.setTrigger(Event("_4after"))
+        self.states["/Main/SimulationFlow/Waiting"].addTransition(_Main_SimulationFlow_Waiting_0)
+        _Main_SimulationFlow_Waiting_1 = Transition(self, self.states["/Main/SimulationFlow/Waiting"], [self.states["/Main/SimulationFlow/CreateDependencyGraph"]])
+        _Main_SimulationFlow_Waiting_1.setTrigger(None)
+        _Main_SimulationFlow_Waiting_1.setGuard(self._Main_SimulationFlow_Waiting_1_guard)
+        self.states["/Main/SimulationFlow/Waiting"].addTransition(_Main_SimulationFlow_Waiting_1)
+        
+        # transition /Main/SimulationFlow/CreateDependencyGraph
+        _Main_SimulationFlow_CreateDependencyGraph_0 = Transition(self, self.states["/Main/SimulationFlow/CreateDependencyGraph"], [self.states["/Main/SimulationFlow/IsolateStrongComponents"]])
+        _Main_SimulationFlow_CreateDependencyGraph_0.setTrigger(None)
+        self.states["/Main/SimulationFlow/CreateDependencyGraph"].addTransition(_Main_SimulationFlow_CreateDependencyGraph_0)
+        
+        # transition /Main/SimulationFlow/IsolateStrongComponents
+        _Main_SimulationFlow_IsolateStrongComponents_0 = Transition(self, self.states["/Main/SimulationFlow/IsolateStrongComponents"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep"]])
+        _Main_SimulationFlow_IsolateStrongComponents_0.setAction(self._Main_SimulationFlow_IsolateStrongComponents_0_exec)
+        _Main_SimulationFlow_IsolateStrongComponents_0.setTrigger(None)
+        self.states["/Main/SimulationFlow/IsolateStrongComponents"].addTransition(_Main_SimulationFlow_IsolateStrongComponents_0)
+        
+        # transition /Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"]])
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_exec)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0.setTrigger(None)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_guard)
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"], [self.states["/Main/SimulationFlow/CheckTerminationCondition"]])
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_exec)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1.setTrigger(Event("_5after"))
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_guard)
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1)
+        
+        # transition /Main/SimulationFlow/ExecuteSimulationStep/CheckCycle
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"]])
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_exec)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0.setTrigger(None)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_guard)
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"]])
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_exec)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1.setTrigger(None)
+        _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_guard)
+        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1)
+        
+        # transition /Main/BreakpointManager/Listening
+        _Main_BreakpointManager_Listening_0 = Transition(self, self.states["/Main/BreakpointManager/Listening"], [self.states["/Main/BreakpointManager/Listening"]])
+        _Main_BreakpointManager_Listening_0.setAction(self._Main_BreakpointManager_Listening_0_exec)
+        _Main_BreakpointManager_Listening_0.setTrigger(Event("add_breakpoint", "user_input"))
+        self.states["/Main/BreakpointManager/Listening"].addTransition(_Main_BreakpointManager_Listening_0)
+        _Main_BreakpointManager_Listening_1 = Transition(self, self.states["/Main/BreakpointManager/Listening"], [self.states["/Main/BreakpointManager/Listening"]])
+        _Main_BreakpointManager_Listening_1.setAction(self._Main_BreakpointManager_Listening_1_exec)
+        _Main_BreakpointManager_Listening_1.setTrigger(Event("del_breakpoint", "user_input"))
+        self.states["/Main/BreakpointManager/Listening"].addTransition(_Main_BreakpointManager_Listening_1)
+        _Main_BreakpointManager_Listening_2 = Transition(self, self.states["/Main/BreakpointManager/Listening"], [self.states["/Main/BreakpointManager/Listening"]])
+        _Main_BreakpointManager_Listening_2.setAction(self._Main_BreakpointManager_Listening_2_exec)
+        _Main_BreakpointManager_Listening_2.setTrigger(Event("toggle_breakpoint", "user_input"))
+        self.states["/Main/BreakpointManager/Listening"].addTransition(_Main_BreakpointManager_Listening_2)
+        _Main_BreakpointManager_Listening_3 = Transition(self, self.states["/Main/BreakpointManager/Listening"], [self.states["/Main/BreakpointManager/Listening"]])
+        _Main_BreakpointManager_Listening_3.setAction(self._Main_BreakpointManager_Listening_3_exec)
+        _Main_BreakpointManager_Listening_3.setTrigger(Event("list_breakpoints", "user_input"))
+        self.states["/Main/BreakpointManager/Listening"].addTransition(_Main_BreakpointManager_Listening_3)
+        
+        # transition /Main/GodEventManager/Listening
+        _Main_GodEventManager_Listening_0 = Transition(self, self.states["/Main/GodEventManager/Listening"], [self.states["/Main/GodEventManager/Listening"]])
+        _Main_GodEventManager_Listening_0.setAction(self._Main_GodEventManager_Listening_0_exec)
+        _Main_GodEventManager_Listening_0.setTrigger(Event("god_event", "user_input"))
+        _Main_GodEventManager_Listening_0.setGuard(self._Main_GodEventManager_Listening_0_guard)
+        self.states["/Main/GodEventManager/Listening"].addTransition(_Main_GodEventManager_Listening_0)
+        
+        # transition /Main/UserOutput/Waiting
+        _Main_UserOutput_Waiting_0 = Transition(self, self.states["/Main/UserOutput/Waiting"], [self.states["/Main/UserOutput/Waiting"]])
+        _Main_UserOutput_Waiting_0.setAction(self._Main_UserOutput_Waiting_0_exec)
+        _Main_UserOutput_Waiting_0.setTrigger(Event("termination_condition", None))
+        self.states["/Main/UserOutput/Waiting"].addTransition(_Main_UserOutput_Waiting_0)
+        _Main_UserOutput_Waiting_1 = Transition(self, self.states["/Main/UserOutput/Waiting"], [self.states["/Main/UserOutput/Waiting"]])
+        _Main_UserOutput_Waiting_1.setAction(self._Main_UserOutput_Waiting_1_exec)
+        _Main_UserOutput_Waiting_1.setTrigger(Event("paused", None))
+        self.states["/Main/UserOutput/Waiting"].addTransition(_Main_UserOutput_Waiting_1)
+        _Main_UserOutput_Waiting_2 = Transition(self, self.states["/Main/UserOutput/Waiting"], [self.states["/Main/UserOutput/Waiting"]])
+        _Main_UserOutput_Waiting_2.setAction(self._Main_UserOutput_Waiting_2_exec)
+        _Main_UserOutput_Waiting_2.setTrigger(Event("big_step_done", None))
+        _Main_UserOutput_Waiting_2.setGuard(self._Main_UserOutput_Waiting_2_guard)
+        self.states["/Main/UserOutput/Waiting"].addTransition(_Main_UserOutput_Waiting_2)
+        _Main_UserOutput_Waiting_3 = Transition(self, self.states["/Main/UserOutput/Waiting"], [self.states["/Main/UserOutput/Waiting"]])
+        _Main_UserOutput_Waiting_3.setAction(self._Main_UserOutput_Waiting_3_exec)
+        _Main_UserOutput_Waiting_3.setTrigger(Event("breakpoint_triggered", None))
+        self.states["/Main/UserOutput/Waiting"].addTransition(_Main_UserOutput_Waiting_3)
+        
+        # transition /Main
+        _Main_0 = Transition(self, self.states["/Main"], [self.states["/SimulationComplete"]])
+        _Main_0.setAction(self._Main_0_exec)
+        _Main_0.setTrigger(None)
+        _Main_0.setGuard(self._Main_0_guard)
+        self.states["/Main"].addTransition(_Main_0)
+        
+        # transition /Main/SimulationState/Running
+        _Main_SimulationState_Running_0 = Transition(self, self.states["/Main/SimulationState/Running"], [self.states["/Main/SimulationState/Stopped"]])
+        _Main_SimulationState_Running_0.setAction(self._Main_SimulationState_Running_0_exec)
+        _Main_SimulationState_Running_0.setTrigger(None)
+        _Main_SimulationState_Running_0.setGuard(self._Main_SimulationState_Running_0_guard)
+        self.states["/Main/SimulationState/Running"].addTransition(_Main_SimulationState_Running_0)
+        _Main_SimulationState_Running_1 = Transition(self, self.states["/Main/SimulationState/Running"], [self.states["/Main/SimulationState/PrePaused"]])
+        _Main_SimulationState_Running_1.setTrigger(Event("pause", "user_input"))
+        self.states["/Main/SimulationState/Running"].addTransition(_Main_SimulationState_Running_1)
+        _Main_SimulationState_Running_2 = Transition(self, self.states["/Main/SimulationState/Running"], [self.states["/Main/SimulationState/PreBreakpointTriggered"]])
+        _Main_SimulationState_Running_2.setTrigger(None)
+        _Main_SimulationState_Running_2.setGuard(self._Main_SimulationState_Running_2_guard)
+        self.states["/Main/SimulationState/Running"].addTransition(_Main_SimulationState_Running_2)
+    
+    def _Main_SimulationState_Running_enter(self):
+        print 'entering SimulationState/Running'
+    
+    def _Main_SimulationState_Running_exit(self):
+        print 'exiting SimulationState/Running'
+    
+    def _Main_SimulationState_Paused_enter(self):
+        print 'entering SimulationState/Paused'
+    
+    def _Main_SimulationState_Paused_exit(self):
+        print 'exiting SimulationState/Paused'
+    
+    def _Main_SimulationState_PrePaused_enter(self):
+        self.addTimer(0, self.sccd_yield())
+    
+    def _Main_SimulationState_PrePaused_exit(self):
+        self.removeTimer(0)
+    
+    def _Main_SimulationState_PreBreakpointTriggered_enter(self):
+        self.addTimer(1, self.sccd_yield())
+    
+    def _Main_SimulationState_PreBreakpointTriggered_exit(self):
+        self.removeTimer(1)
+    
+    def _Main_SimulationState_Running_BigStepDone_enter(self):
+        self.addTimer(2, self.sccd_yield())
+    
+    def _Main_SimulationState_Running_BigStepDone_exit(self):
+        self.removeTimer(2)
+    
+    def _Main_SimulationState_Running_Realtime_enter(self):
+        # If the simulation was paused, we need to reset the start time of the simulation.
+        # The start time of the simulation is equal to the point in wall-clock time where simulated time is 0.
+        # If the simulation was paused, we have to recompute this point in time: it is the difference of the wall-clock time and the simulated time.
+        # If the scale was changed after the pause, this point of course moves backwards (for scales smaller than 1) or forwards (for scales larger than 1)
+        self.realtime_start_time = accurate_time.time() - (self.clock / self.realtime_scale)
+    
+    def _Main_SimulationState_Stopped_enter(self):
+        print 'entering SimulationState/Stopped'
+    
+    def _Main_SimulationState_Stopped_exit(self):
+        print 'exiting SimulationState/Stopped'
+    
+    def _Main_SimulationFlow_Initialize_enter(self):
+        self.initialize()
+    
+    def _Main_SimulationFlow_CheckTerminationCondition_enter(self):
+        self.addTimer(3, self.sccd_yield())
+    
+    def _Main_SimulationFlow_CheckTerminationCondition_exit(self):
+        self.removeTimer(3)
+    
+    def _Main_SimulationFlow_Waiting_enter(self):
+        self.addTimer(4, self.sccd_yield())
+    
+    def _Main_SimulationFlow_Waiting_exit(self):
+        self.removeTimer(4)
+        diff = accurate_time.time() - self.realtime_start_time
+        self.clock = diff * self.realtime_scale
+    
+    def _Main_SimulationFlow_CreateDependencyGraph_enter(self):
+        self.depGraph = self.cbdController.createDepGraph(self.iteration)
+    
+    def _Main_SimulationFlow_IsolateStrongComponents_enter(self):
+        self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_enter(self):
+        self.addTimer(5, self.sccd_yield())
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_exit(self):
+        self.removeTimer(5)
+    
+    def _Main_0_exec(self, parameters):
+        self.finalize()
+    
+    def _Main_0_guard(self, parameters):
+        return self.inState(["/Main/SimulationState/Stopped"]) and self.inState(["/Main/SimulationFlow/Stopped"])
+    
+    def _Main_SimulationState_Running_0_exec(self, parameters):
+        self.raiseInternalEvent(Event("termination_condition", None, []))
+    
+    def _Main_SimulationState_Running_0_guard(self, parameters):
+        return self.endCondition()
+    
+    def _Main_SimulationState_Running_2_guard(self, parameters):
+        return self.breakpointTriggers(self.inState(["/Main/SimulationState/Running/Realtime"]))
+    
+    def _Main_SimulationState_Paused_1_exec(self, parameters):
+        realtime_scale = parameters[0]
+        self.realtime_scale = float(realtime_scale)
+    
+    def _Main_SimulationState_PrePaused_0_exec(self, parameters):
+        self.raiseInternalEvent(Event("paused", None, []))
+    
+    def _Main_SimulationState_PreBreakpointTriggered_0_exec(self, parameters):
+        self.raiseInternalEvent(Event("breakpoint_triggered", None, []))
+    
+    def _Main_SimulationFlow_CheckTerminationCondition_0_guard(self, parameters):
+        return self.inState(["/Main/SimulationState/Running/Continuous"]) or self.inState(["/Main/SimulationState/Running/BigStep"])
+    
+    def _Main_SimulationFlow_CheckTerminationCondition_1_guard(self, parameters):
+        return self.inState(["/Main/SimulationState/Running/Realtime"])
+    
+    def _Main_SimulationFlow_CheckTerminationCondition_2_guard(self, parameters):
+        return self.inState(["/Main/SimulationState/Stopped"])
+    
+    def _Main_SimulationFlow_Waiting_1_guard(self, parameters):
+        return self.waitTime() / 1000.0 <= self.sccd_yield()
+    
+    def _Main_SimulationFlow_IsolateStrongComponents_0_exec(self, parameters):
+        self.currentCompIdx = -1
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_exec(self, parameters):
+        self.currentCompIdx = self.currentCompIdx + 1
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_guard(self, parameters):
+        return self.hasNextStrongComponent()
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_exec(self, parameters):
+        self.advanceTime()
+        self.state = {b.getBlockName(): b.getSignal() for b in self.model.getBlocks()}
+        self.raiseInternalEvent(Event("big_step_done", None, []))
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_1_guard(self, parameters):
+        return not self.hasNextStrongComponent()
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_exec(self, parameters):
+        self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_guard(self, parameters):
+        return not self.currentComponentIsCycle()
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_exec(self, parameters):
+        self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+    
+    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_guard(self, parameters):
+        return self.currentComponentIsCycle()
+    
+    def _Main_BreakpointManager_Listening_0_exec(self, parameters):
+        name = parameters[0]
+        function = parameters[1]
+        enabled = parameters[2]
+        disable_on_trigger = parameters[3]
+        result = self.addBreakpoint(name, function, bool(enabled), bool(disable_on_trigger))
+        self.big_step.outputEvent(Event("add_breakpoint_result", "user_output", [result]))
+    
+    def _Main_BreakpointManager_Listening_1_exec(self, parameters):
+        name = parameters[0]
+        result = self.delBreakpoint(name)
+        self.big_step.outputEvent(Event("del_breakpoint_result", "user_output", [result]))
+    
+    def _Main_BreakpointManager_Listening_2_exec(self, parameters):
+        name = parameters[0]
+        result = self.toggleBreakpoint(name)
+        self.big_step.outputEvent(Event("toggle_breakpoint_result", "user_output", [result]))
+    
+    def _Main_BreakpointManager_Listening_3_exec(self, parameters):
+        self.big_step.outputEvent(Event("list_breakpoints_result", "user_output", [[bp.name for bp in self.breakpoints]]))
+    
+    def _Main_GodEventManager_Listening_0_exec(self, parameters):
+        block_name = parameters[0]
+        new_val = parameters[1]
+        result = self.godEvent(block_name, new_val)
+        self.big_step.outputEvent(Event("god_event_result", "user_output", [result]))
+    
+    def _Main_GodEventManager_Listening_0_guard(self, parameters):
+        block_name = parameters[0]
+        new_val = parameters[1]
+        return self.inState(["/Main/SimulationState/Paused"])
+    
+    def _Main_UserOutput_Waiting_0_exec(self, parameters):
+        self.big_step.outputEvent(Event("terminated", "user_output", []))
+        self.big_step.outputEvent(Event("current_state", "user_output", [self.clock / 1000.0, self.state]))
+    
+    def _Main_UserOutput_Waiting_1_exec(self, parameters):
+        self.big_step.outputEvent(Event("paused", "user_output", []))
+        self.big_step.outputEvent(Event("current_state", "user_output", [self.clock / 1000.0, self.state]))
+    
+    def _Main_UserOutput_Waiting_2_exec(self, parameters):
+        self.big_step.outputEvent(Event("stepped", "user_output", []))
+        self.big_step.outputEvent(Event("current_state", "user_output", [self.clock / 1000.0, self.state]))
+    
+    def _Main_UserOutput_Waiting_2_guard(self, parameters):
+        return self.inState(["/Main/SimulationState/Running/Realtime"]) or self.inState(["/Main/SimulationState/Running/BigStep"]) or self.inState(["/Main/SimulationState/Running/BigStepDone"])
+    
+    def _Main_UserOutput_Waiting_3_exec(self, parameters):
+        self.big_step.outputEvent(Event("breakpoint_triggered", "user_output", [self.triggered_bp]))
+        self.big_step.outputEvent(Event("current_state", "user_output", [self.clock / 1000.0, self.state]))
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/Main"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class ObjectManager(ObjectManagerBase):
+    def __init__(self, controller):
+        ObjectManagerBase.__init__(self, controller)
+    
+    def instantiate(self, class_name, construct_params):
+        if class_name == "CBDSimulator":
+            instance = CBDSimulator(self.controller, construct_params[0], construct_params[1])
+            instance.associations = {}
+        else:
+            raise Exception("Cannot instantiate class " + class_name)
+        return instance
+
+class Controller(ThreadsControllerBase):
+    def __init__(self, options, model, keep_running = None, behind_schedule_callback = None):
+        if keep_running == None: keep_running = True
+        if behind_schedule_callback == None: behind_schedule_callback = None
+        ThreadsControllerBase.__init__(self, ObjectManager(self), keep_running, behind_schedule_callback)
+        self.addInputPort("user_input")
+        self.addInputPort("user_output")
+        self.object_manager.createInstance("CBDSimulator", [options, model])