Forráskód Böngészése

started on debuggeable hybrid simulator

Simon Van Mierlo 9 éve
szülő
commit
324db3f1f3
30 módosított fájl, 359995 hozzáadás és 7004 törlés
  1. 0 14
      debugging_fsa_cbd_composition/cbdsimulator/CBDMultipleOutput/Source/CBD.py
  2. 63 66
      debugging_fsa_cbd_composition/cbdsimulator/cbdsim_debugging.py.xml
  3. 347856 0
      debugging_fsa_cbd_composition/cbdsimulator/log.txt
  4. 3 3
      debugging_fsa_cbd_composition/cbdsimulator/plot.html
  5. 122 141
      debugging_fsa_cbd_composition/cbdsimulator/target.py
  6. 885 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/CBD.py
  7. 54 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/CBDDraw.py
  8. 0 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/__init__.py
  9. 129 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/naivelog.py
  10. 49 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/plot.py
  11. 48 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/CounterTest.py
  12. 0 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/__init__.py
  13. 551 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/basicCBDTest.py
  14. 201 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/flattenCBDTest.py
  15. 201 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/hierarchyCBDTest.py
  16. 172 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Test/sortedGraphCBDTest.py
  17. 0 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/__init__.py
  18. 80 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/EvenNumbersCBD.py
  19. 21 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/HarmonicOscilator.py
  20. 300 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/TrainControlCBD.py
  21. 0 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/models/__init__.py
  22. 262 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/CBD_Controller.py
  23. 56 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/Options.py
  24. 129 129
      debugging_fsa_cbd_composition/fsa_cbd_simulator/events.csv
  25. 222 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/fsaclasses.py
  26. 149 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/run_debug.py
  27. 6494 6494
      debugging_fsa_cbd_composition/fsa_cbd_simulator/signals.csv
  28. 1079 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/target.py
  29. 158 157
      debugging_fsa_cbd_composition/fsa_cbd_simulator/weaved_cbd_fsa_lib.py
  30. 711 0
      debugging_fsa_cbd_composition/fsa_cbd_simulator/woven_fsa_cbd_simulator_hierarchical_debugging.xml

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

@@ -76,13 +76,6 @@ class BaseBlock:
         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() ]))
@@ -538,13 +531,6 @@ class CBD(BaseBlock):
         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):
     """

+ 63 - 66
debugging_fsa_cbd_composition/cbdsimulator/cbdsim_debugging.py.xml

@@ -53,7 +53,27 @@
         <method name="hasNextStrongComponent">
             <body>
             <![CDATA[
-                return (self.currentCompIdx + 1) < len(self.strongComponentList)
+                return self.currentCompIdx < len(self.strongComponentList)
+            ]]>
+            </body>
+        </method>
+        <method name="computeBlock">
+            <body>
+            <![CDATA[
+                if self.currentComponentIsCycle():
+                    self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+                else:
+                    self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
+            ]]>
+            </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>
@@ -85,16 +105,6 @@
             ]]>
             </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="finalize">
             <body>
             <![CDATA[
@@ -234,9 +244,7 @@
                         </transition>
                     </state>
                     <state id="Running" initial="Continuous">
-                        <transition target="../PreStopped" cond="self.endCondition()">
-                            <raise event="termination_condition" />
-                        </transition>
+                        <transition target="../PreStopped" cond="self.endCondition()" />
                         <transition target="../PrePaused" event="pause" port="user_input" />
                         <transition target="../PreBreakpointTriggered" cond="self.breakpointTriggers(INSTATE('./Realtime'))" />
                         <state id="Continuous" />
@@ -273,7 +281,13 @@
                             <raise event="termination_condition" />
                         </transition>
                     </state>
-                    <state id="Stopped" />
+                    <state id="Stopped">
+                        <onentry>
+                            <script>
+                                print 'arriving in SimulationState/Stopped'
+                            </script>
+                        </onentry>
+                    </state>
                 </state>
                 <state id="SimulationFlow" initial="Initialize">
                     <state id="Initialize">
@@ -297,9 +311,17 @@
                         <transition target="../CheckTerminationCondition" />
                     </state>
                     <state id="CheckTerminationCondition">
-                        <transition target="../CreateDependencyGraph" cond="INSTATE('/Main/SimulationState/Running/Continuous') or INSTATE('/Main/SimulationState/Running/BigStep') or INSTATE('/Main/SimulationState/Running/SmallStep')" />
-                        <transition target="../Waiting" cond="INSTATE('/Main/SimulationState/Running/Realtime')" />
-                        <transition target="../Stopped" cond="INSTATE('/Main/SimulationState/Stopped')" after="self.sccd_yield()" />
+                        <state id="MacroStepProcessed">
+                            <transition target="../../DoSimulation" cond="INSTATE('/Main/SimulationState/Running/Continuous') or INSTATE('/Main/SimulationState/Running/BigStep') or INSTATE('/Main/SimulationState/Running/SmallStep')">
+                                <script>
+                                    self.currentCompIdx = 0
+                                    self.depGraph = self.cbdController.createDepGraph(self.iteration)
+                                    self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
+                                </script>
+                            </transition>
+                            <transition target="../../Waiting" cond="INSTATE('/Main/SimulationState/Running/Realtime')" />
+                            <transition target="../../Stopped" cond="INSTATE('/Main/SimulationState/Stopped')" />
+                        </state>
                     </state>
                     <state id="Waiting">
                         <!-- We schedule to go back to the check_termination state after the smallest possible delay (to accomodate for pauses). -->
@@ -311,78 +333,53 @@
                             </script>
                         </transition>
                         <!-- 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()" />
-                    </state>
-                    <state id="CreateDependencyGraph">
-                        <onentry>
+                        <transition target="../DoSimulation" cond="self.waitTime() / 1000.0 &lt;= self.sccd_yield()">
                             <script>
-                            <![CDATA[
+                                self.currentCompIdx = 0
                                 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>
+                            </script>                        
                         </transition>
                     </state>
-                    <state id="ExecuteSimulationStep" initial="CheckNextComponent">
-                        <state id="CheckNextComponent">
-                            <!-- Here, we wait long enough for the simulation state to settle to 'Paused' if we are small stepping. -->
-                            <transition target="../PreCheckCycle" cond="self.hasNextStrongComponent()" after="self.sccd_yield() * 2">
-                                <script>
-                                    <![CDATA[
-                                        self.currentCompIdx = self.currentCompIdx + 1
-                                    ]]>
-                                </script>
-                            </transition>
+                    <state id="DoSimulation" initial="MacroStepPrepared">
+                        <state id="MacroStepPrepared">
+                            <transition target="../MicroStepProcessed" />
+                        </state>
+                        <state id="MicroStepProcessed">
                             <!-- 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>
+                            <!-- Here, we wait long enough for the simulation state to settle to 'Paused' if we are small stepping. -->
+                            <transition target="../PreMicroStepPrepared" cond="self.hasNextStrongComponent()" after="self.sccd_yield() * 3" />
                         </state>
-                        <state id="PreCheckCycle">
-                            <transition target="../CheckCycle" cond="INSTATE('/Main/SimulationState/Running')" />
+                        <state id="PreMicroStepPrepared">
+                            <transition target="../MicroStepPrepared" cond="INSTATE('/Main/SimulationState/Running')" />
                         </state>
-                        <state id="CheckCycle">
-                            <transition target="../CheckNextComponent" cond="not self.currentComponentIsCycle()">
-                                <script>
-                                    <![CDATA[
-                                        self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
-                                    ]]>
-                                </script>
-                                <raise event="small_step_done" />
-                            </transition>
-                            <transition target="../CheckNextComponent" cond="self.currentComponentIsCycle()">
+                        <state id="MicroStepPrepared">
+                            <transition target="../MicroStepProcessed">
                                 <script>
                                     <![CDATA[
-                                        self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+                                        self.computeBlock()
+                                        self.currentCompIdx = self.currentCompIdx + 1
                                     ]]>
                                 </script>
                                 <raise event="small_step_done" />
                             </transition>
                         </state>
                     </state>
-                    <state id="Stopped" />
+                    <state id="Stopped">
+                        <onentry>
+                            <script>
+                                print 'arriving in SimulationFlow/Stopped'
+                            </script>
+                        </onentry>
+                    </state>
                 </state>
                 <state id="BreakpointManager" initial="Listening">
                     <state id="Listening">

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 347856 - 0
debugging_fsa_cbd_composition/cbdsimulator/log.txt


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 3 - 3
debugging_fsa_cbd_composition/cbdsimulator/plot.html


+ 122 - 141
debugging_fsa_cbd_composition/cbdsimulator/target.py

@@ -1,7 +1,7 @@
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
-Date:   Wed Oct 12 17:10:43 2016
+Date:   Fri Oct 21 13:30:15 2016
 
 Model author: Sadaf Mustafiz and Claudio Gomes and Simon Van Mierlo
 Model name:   CBDSimulator
@@ -68,7 +68,23 @@ class CBDSimulator(RuntimeClassBase):
     
     # user defined method
     def hasNextStrongComponent(self):
-        return (self.currentCompIdx + 1) < len(self.strongComponentList)
+        return self.currentCompIdx < len(self.strongComponentList)
+    
+    
+    # user defined method
+    def computeBlock(self):
+        if self.currentComponentIsCycle():
+            self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+        else:
+            self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
+    
+    
+    # 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
@@ -93,14 +109,6 @@ class CBDSimulator(RuntimeClassBase):
         return self.initialized and 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 finalize(self):
         from bokeh.plotting import figure, output_file, show    
@@ -248,6 +256,7 @@ class CBDSimulator(RuntimeClassBase):
         
         # state /Main/SimulationState/Stopped
         self.states["/Main/SimulationState/Stopped"] = State(14, self)
+        self.states["/Main/SimulationState/Stopped"].setEnter(self._Main_SimulationState_Stopped_enter)
         
         # state /Main/SimulationFlow
         self.states["/Main/SimulationFlow"] = State(15, self)
@@ -262,38 +271,35 @@ class CBDSimulator(RuntimeClassBase):
         
         # state /Main/SimulationFlow/CheckTerminationCondition
         self.states["/Main/SimulationFlow/CheckTerminationCondition"] = State(18, 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/CheckTerminationCondition/MacroStepProcessed
+        self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"] = State(19, self)
         
         # state /Main/SimulationFlow/Waiting
-        self.states["/Main/SimulationFlow/Waiting"] = State(19, self)
+        self.states["/Main/SimulationFlow/Waiting"] = State(20, 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(20, self)
-        self.states["/Main/SimulationFlow/CreateDependencyGraph"].setEnter(self._Main_SimulationFlow_CreateDependencyGraph_enter)
+        # state /Main/SimulationFlow/DoSimulation
+        self.states["/Main/SimulationFlow/DoSimulation"] = State(21, self)
         
-        # state /Main/SimulationFlow/IsolateStrongComponents
-        self.states["/Main/SimulationFlow/IsolateStrongComponents"] = State(21, self)
-        self.states["/Main/SimulationFlow/IsolateStrongComponents"].setEnter(self._Main_SimulationFlow_IsolateStrongComponents_enter)
+        # state /Main/SimulationFlow/DoSimulation/MacroStepPrepared
+        self.states["/Main/SimulationFlow/DoSimulation/MacroStepPrepared"] = State(22, self)
         
-        # state /Main/SimulationFlow/ExecuteSimulationStep
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep"] = State(22, self)
+        # state /Main/SimulationFlow/DoSimulation/MicroStepProcessed
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"] = State(23, self)
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"].setEnter(self._Main_SimulationFlow_DoSimulation_MicroStepProcessed_enter)
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"].setExit(self._Main_SimulationFlow_DoSimulation_MicroStepProcessed_exit)
         
-        # state /Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckNextComponent"] = State(23, 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/DoSimulation/PreMicroStepPrepared
+        self.states["/Main/SimulationFlow/DoSimulation/PreMicroStepPrepared"] = State(24, self)
         
-        # state /Main/SimulationFlow/ExecuteSimulationStep/PreCheckCycle
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/PreCheckCycle"] = State(24, self)
-        
-        # state /Main/SimulationFlow/ExecuteSimulationStep/CheckCycle
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"] = State(25, self)
+        # state /Main/SimulationFlow/DoSimulation/MicroStepPrepared
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepPrepared"] = State(25, self)
         
         # state /Main/SimulationFlow/Stopped
         self.states["/Main/SimulationFlow/Stopped"] = State(26, self)
+        self.states["/Main/SimulationFlow/Stopped"].setEnter(self._Main_SimulationFlow_Stopped_enter)
         
         # state /Main/BreakpointManager
         self.states["/Main/BreakpointManager"] = State(27, self)
@@ -340,13 +346,13 @@ class CBDSimulator(RuntimeClassBase):
         self.states["/Main/SimulationFlow"].addChild(self.states["/Main/SimulationFlow/InitializeDebugger"])
         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/DoSimulation"])
         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/PreCheckCycle"])
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep"].addChild(self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"])
+        self.states["/Main/SimulationFlow/CheckTerminationCondition"].addChild(self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"])
+        self.states["/Main/SimulationFlow/DoSimulation"].addChild(self.states["/Main/SimulationFlow/DoSimulation/MacroStepPrepared"])
+        self.states["/Main/SimulationFlow/DoSimulation"].addChild(self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"])
+        self.states["/Main/SimulationFlow/DoSimulation"].addChild(self.states["/Main/SimulationFlow/DoSimulation/PreMicroStepPrepared"])
+        self.states["/Main/SimulationFlow/DoSimulation"].addChild(self.states["/Main/SimulationFlow/DoSimulation/MicroStepPrepared"])
         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"])
@@ -355,7 +361,8 @@ class CBDSimulator(RuntimeClassBase):
         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/SimulationFlow/CheckTerminationCondition"].default_state = self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"]
+        self.states["/Main/SimulationFlow/DoSimulation"].default_state = self.states["/Main/SimulationFlow/DoSimulation/MacroStepPrepared"]
         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"]
@@ -427,70 +434,59 @@ class CBDSimulator(RuntimeClassBase):
         _Main_SimulationFlow_InitializeDebugger_0.setTrigger(None)
         self.states["/Main/SimulationFlow/InitializeDebugger"].addTransition(_Main_SimulationFlow_InitializeDebugger_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("_5after"))
-        _Main_SimulationFlow_CheckTerminationCondition_2.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_2_guard)
-        self.states["/Main/SimulationFlow/CheckTerminationCondition"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_2)
+        # transition /Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"], [self.states["/Main/SimulationFlow/DoSimulation"]])
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0.setAction(self._Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0_exec)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0.setTrigger(None)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0_guard)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"], [self.states["/Main/SimulationFlow/Waiting"]])
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1.setTrigger(None)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1_guard)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_2 = Transition(self, self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"], [self.states["/Main/SimulationFlow/Stopped"]])
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_2.setTrigger(None)
+        _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_2.setGuard(self._Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_2_guard)
+        self.states["/Main/SimulationFlow/CheckTerminationCondition/MacroStepProcessed"].addTransition(_Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_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.setAction(self._Main_SimulationFlow_Waiting_0_exec)
-        _Main_SimulationFlow_Waiting_0.setTrigger(Event("_6after"))
+        _Main_SimulationFlow_Waiting_0.setTrigger(Event("_5after"))
         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 = Transition(self, self.states["/Main/SimulationFlow/Waiting"], [self.states["/Main/SimulationFlow/DoSimulation"]])
+        _Main_SimulationFlow_Waiting_1.setAction(self._Main_SimulationFlow_Waiting_1_exec)
         _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/PreCheckCycle"]])
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0.setAction(self._Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0_exec)
-        _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_0.setTrigger(Event("_7after"))
-        _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("_8after"))
-        _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/PreCheckCycle
-        _Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0 = Transition(self, self.states["/Main/SimulationFlow/ExecuteSimulationStep/PreCheckCycle"], [self.states["/Main/SimulationFlow/ExecuteSimulationStep/CheckCycle"]])
-        _Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0.setTrigger(None)
-        _Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0.setGuard(self._Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0_guard)
-        self.states["/Main/SimulationFlow/ExecuteSimulationStep/PreCheckCycle"].addTransition(_Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0)
-        
-        # 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/SimulationFlow/DoSimulation/MacroStepPrepared
+        _Main_SimulationFlow_DoSimulation_MacroStepPrepared_0 = Transition(self, self.states["/Main/SimulationFlow/DoSimulation/MacroStepPrepared"], [self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"]])
+        _Main_SimulationFlow_DoSimulation_MacroStepPrepared_0.setTrigger(None)
+        self.states["/Main/SimulationFlow/DoSimulation/MacroStepPrepared"].addTransition(_Main_SimulationFlow_DoSimulation_MacroStepPrepared_0)
+        
+        # transition /Main/SimulationFlow/DoSimulation/MicroStepProcessed
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0 = Transition(self, self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"], [self.states["/Main/SimulationFlow/CheckTerminationCondition"]])
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0.setAction(self._Main_SimulationFlow_DoSimulation_MicroStepProcessed_0_exec)
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0.setTrigger(Event("_6after"))
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0.setGuard(self._Main_SimulationFlow_DoSimulation_MicroStepProcessed_0_guard)
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"].addTransition(_Main_SimulationFlow_DoSimulation_MicroStepProcessed_0)
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_1 = Transition(self, self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"], [self.states["/Main/SimulationFlow/DoSimulation/PreMicroStepPrepared"]])
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_1.setTrigger(Event("_7after"))
+        _Main_SimulationFlow_DoSimulation_MicroStepProcessed_1.setGuard(self._Main_SimulationFlow_DoSimulation_MicroStepProcessed_1_guard)
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"].addTransition(_Main_SimulationFlow_DoSimulation_MicroStepProcessed_1)
+        
+        # transition /Main/SimulationFlow/DoSimulation/PreMicroStepPrepared
+        _Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0 = Transition(self, self.states["/Main/SimulationFlow/DoSimulation/PreMicroStepPrepared"], [self.states["/Main/SimulationFlow/DoSimulation/MicroStepPrepared"]])
+        _Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0.setTrigger(None)
+        _Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0.setGuard(self._Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0_guard)
+        self.states["/Main/SimulationFlow/DoSimulation/PreMicroStepPrepared"].addTransition(_Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0)
+        
+        # transition /Main/SimulationFlow/DoSimulation/MicroStepPrepared
+        _Main_SimulationFlow_DoSimulation_MicroStepPrepared_0 = Transition(self, self.states["/Main/SimulationFlow/DoSimulation/MicroStepPrepared"], [self.states["/Main/SimulationFlow/DoSimulation/MicroStepProcessed"]])
+        _Main_SimulationFlow_DoSimulation_MicroStepPrepared_0.setAction(self._Main_SimulationFlow_DoSimulation_MicroStepPrepared_0_exec)
+        _Main_SimulationFlow_DoSimulation_MicroStepPrepared_0.setTrigger(None)
+        self.states["/Main/SimulationFlow/DoSimulation/MicroStepPrepared"].addTransition(_Main_SimulationFlow_DoSimulation_MicroStepPrepared_0)
         
         # transition /Main/BreakpointManager/Listening
         _Main_BreakpointManager_Listening_0 = Transition(self, self.states["/Main/BreakpointManager/Listening"], [self.states["/Main/BreakpointManager/Listening"]])
@@ -550,7 +546,6 @@ class CBDSimulator(RuntimeClassBase):
         
         # transition /Main/SimulationState/Running
         _Main_SimulationState_Running_0 = Transition(self, self.states["/Main/SimulationState/Running"], [self.states["/Main/SimulationState/PreStopped"]])
-        _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)
@@ -599,47 +594,39 @@ class CBDSimulator(RuntimeClassBase):
     def _Main_SimulationState_PreStopped_exit(self):
         self.removeTimer(4)
     
+    def _Main_SimulationState_Stopped_enter(self):
+        print 'arriving in SimulationState/Stopped'
+    
     def _Main_SimulationFlow_Initialize_enter(self):
         self.initialize()
     
     def _Main_SimulationFlow_InitializeDebugger_enter(self):
         self.initializeDebugger()
     
-    def _Main_SimulationFlow_CheckTerminationCondition_enter(self):
+    def _Main_SimulationFlow_Waiting_enter(self):
         self.addTimer(5, self.sccd_yield())
     
-    def _Main_SimulationFlow_CheckTerminationCondition_exit(self):
+    def _Main_SimulationFlow_Waiting_exit(self):
         self.removeTimer(5)
     
-    def _Main_SimulationFlow_Waiting_enter(self):
+    def _Main_SimulationFlow_DoSimulation_MicroStepProcessed_enter(self):
         self.addTimer(6, self.sccd_yield())
+        self.addTimer(7, self.sccd_yield() * 3)
     
-    def _Main_SimulationFlow_Waiting_exit(self):
+    def _Main_SimulationFlow_DoSimulation_MicroStepProcessed_exit(self):
         self.removeTimer(6)
-    
-    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(7, self.sccd_yield() * 2)
-        self.addTimer(8, self.sccd_yield())
-    
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckNextComponent_exit(self):
         self.removeTimer(7)
-        self.removeTimer(8)
+    
+    def _Main_SimulationFlow_Stopped_enter(self):
+        print 'arriving in SimulationFlow/Stopped'
     
     def _Main_0_exec(self, parameters):
+        print 'finalizing'
         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()
     
@@ -662,56 +649,50 @@ class CBDSimulator(RuntimeClassBase):
     def _Main_SimulationState_PreStopped_0_exec(self, parameters):
         self.raiseInternalEvent(Event("termination_condition", None, []))
     
-    def _Main_SimulationFlow_CheckTerminationCondition_0_guard(self, parameters):
+    def _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0_exec(self, parameters):
+        self.currentCompIdx = 0
+        self.depGraph = self.cbdController.createDepGraph(self.iteration)
+        self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
+    
+    def _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_0_guard(self, parameters):
         return self.inState(["/Main/SimulationState/Running/Continuous"]) or self.inState(["/Main/SimulationState/Running/BigStep"]) or self.inState(["/Main/SimulationState/Running/SmallStep"])
     
-    def _Main_SimulationFlow_CheckTerminationCondition_1_guard(self, parameters):
+    def _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_1_guard(self, parameters):
         return self.inState(["/Main/SimulationState/Running/Realtime"])
     
-    def _Main_SimulationFlow_CheckTerminationCondition_2_guard(self, parameters):
+    def _Main_SimulationFlow_CheckTerminationCondition_MacroStepProcessed_2_guard(self, parameters):
         return self.inState(["/Main/SimulationState/Stopped"])
     
     def _Main_SimulationFlow_Waiting_0_exec(self, parameters):
         diff = accurate_time.time() - self.realtime_start_time
         self.clock = diff * self.realtime_scale
     
+    def _Main_SimulationFlow_Waiting_1_exec(self, parameters):
+        self.currentCompIdx = 0
+        self.depGraph = self.cbdController.createDepGraph(self.iteration)
+        self.strongComponentList = self.cbdController.createStrongComponents(self.depGraph, self.iteration)
+    
     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):
+    def _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0_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):
+    def _Main_SimulationFlow_DoSimulation_MicroStepProcessed_0_guard(self, parameters):
         return not self.hasNextStrongComponent()
     
-    def _Main_SimulationFlow_ExecuteSimulationStep_PreCheckCycle_0_guard(self, parameters):
-        return self.inState(["/Main/SimulationState/Running"])
-    
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_exec(self, parameters):
-        self.cbdController.computeNextBlock(self.strongComponentList[self.currentCompIdx], self.iteration)
-        self.raiseInternalEvent(Event("small_step_done", None, []))
+    def _Main_SimulationFlow_DoSimulation_MicroStepProcessed_1_guard(self, parameters):
+        return self.hasNextStrongComponent()
     
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_0_guard(self, parameters):
-        return not self.currentComponentIsCycle()
+    def _Main_SimulationFlow_DoSimulation_PreMicroStepPrepared_0_guard(self, parameters):
+        return self.inState(["/Main/SimulationState/Running"])
     
-    def _Main_SimulationFlow_ExecuteSimulationStep_CheckCycle_1_exec(self, parameters):
-        self.cbdController.computeNextAlgebraicLoop(self.strongComponentList[self.currentCompIdx], self.iteration)
+    def _Main_SimulationFlow_DoSimulation_MicroStepPrepared_0_exec(self, parameters):
+        self.computeBlock()
+        self.currentCompIdx = self.currentCompIdx + 1
         self.raiseInternalEvent(Event("small_step_done", None, []))
     
-    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]

+ 885 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBDMultipleOutput/Source/CBD.py

@@ -0,0 +1,885 @@
+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"]
+
+    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"]
+            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")
+    
+    
+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/fsa_cbd_simulator/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/fsa_cbd_simulator/CBDMultipleOutput/Source/__init__.py


+ 129 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/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/fsa_cbd_simulator/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/fsa_cbd_simulator/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/fsa_cbd_simulator/CBDMultipleOutput/Test/__init__.py


+ 551 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/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/fsa_cbd_simulator/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/fsa_cbd_simulator/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/fsa_cbd_simulator/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/fsa_cbd_simulator/CBDMultipleOutput/__init__.py


+ 80 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/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/fsa_cbd_simulator/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/fsa_cbd_simulator/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/fsa_cbd_simulator/CBDMultipleOutput/models/__init__.py


+ 262 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/CBD_Controller.py

@@ -0,0 +1,262 @@
+"""
+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/fsa_cbd_simulator/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

+ 129 - 129
debugging_fsa_cbd_composition/fsa_cbd_simulator/events.csv

@@ -1,130 +1,130 @@
 fsatime,Event

-3.6299999999999666,when(x +-)

-7.009999999999895,when(x +-)

-9.729999999999837,when(x +-)

-11.91999999999979,when(x +-)

-12.999999999999767,kick

-16.87999999999984,when(x +-)

-20.160000000000352,when(x +-)

-22.800000000000765,when(x +-)

-23.000000000000796,kick

-28.870000000001713,when(x +-)

-33.640000000001876,when(x +-)

-37.00000000000121,kick

-38.99000000000081,when(x +-)

-41.240000000000364,when(x +-)

-43.050000000000004,when(x +-)

-44.509999999999714,when(x +-)

-45.69999999999948,when(x +-)

-46.669999999999284,when(x +-)

-47.45999999999913,when(x +-)

-48.109999999999,when(x +-)

-48.63999999999889,when(x +-)

-49.079999999998805,when(x +-)

-49.44999999999873,when(x +-)

-49.75999999999867,when(x +-)

-50.029999999998616,when(x +-)

-50.25999999999857,when(x +-)

-50.45999999999853,when(x +-)

-50.639999999998494,when(x +-)

-50.79999999999846,when(x +-)

-50.94999999999843,when(x +-)

-51.089999999998405,when(x +-)

-51.20999999999838,when(x +-)

-51.31999999999836,when(x +-)

-51.42999999999834,when(x +-)

-51.539999999998315,when(x +-)

-51.639999999998295,when(x +-)

-51.739999999998275,when(x +-)

-51.839999999998255,when(x +-)

-51.92999999999824,when(x +-)

-52.01999999999822,when(x +-)

-52.1099999999982,when(x +-)

-52.199999999998184,when(x +-)

-52.289999999998166,when(x +-)

-52.37999999999815,when(x +-)

-52.46999999999813,when(x +-)

-52.55999999999811,when(x +-)

-52.649999999998094,when(x +-)

-52.739999999998076,when(x +-)

-52.82999999999806,when(x +-)

-52.91999999999804,when(x +-)

-53.00999999999802,when(x +-)

-53.099999999998005,when(x +-)

-53.18999999999799,when(x +-)

-53.27999999999797,when(x +-)

-53.36999999999795,when(x +-)

-53.45999999999793,when(x +-)

-53.549999999997915,when(x +-)

-53.6399999999979,when(x +-)

-53.72999999999788,when(x +-)

-53.81999999999786,when(x +-)

-53.909999999997844,when(x +-)

-53.999999999997826,when(x +-)

-54.08999999999781,when(x +-)

-54.17999999999779,when(x +-)

-54.26999999999777,when(x +-)

-54.359999999997754,when(x +-)

-54.449999999997736,when(x +-)

-54.53999999999772,when(x +-)

-54.6299999999977,when(x +-)

-54.71999999999768,when(x +-)

-54.809999999997665,when(x +-)

-54.89999999999765,when(x +-)

-54.98999999999763,when(x +-)

-55.07999999999761,when(x +-)

-55.16999999999759,when(x +-)

-55.259999999997575,when(x +-)

-55.34999999999756,when(x +-)

-55.43999999999754,when(x +-)

-55.52999999999752,when(x +-)

-55.6199999999975,when(x +-)

-55.709999999997486,when(x +-)

-55.79999999999747,when(x +-)

-55.88999999999745,when(x +-)

-55.97999999999743,when(x +-)

-56.069999999997414,when(x +-)

-56.159999999997396,when(x +-)

-56.24999999999738,when(x +-)

-56.33999999999736,when(x +-)

-56.42999999999734,when(x +-)

-56.519999999997324,when(x +-)

-56.60999999999731,when(x +-)

-56.69999999999729,when(x +-)

-56.78999999999727,when(x +-)

-56.87999999999725,when(x +-)

-56.969999999997235,when(x +-)

-57.05999999999722,when(x +-)

-57.1499999999972,when(x +-)

-57.23999999999718,when(x +-)

-57.32999999999716,when(x +-)

-57.419999999997145,when(x +-)

-57.50999999999713,when(x +-)

-57.59999999999711,when(x +-)

-57.68999999999709,when(x +-)

-57.779999999997074,when(x +-)

-57.869999999997056,when(x +-)

-57.95999999999704,when(x +-)

-58.04999999999702,when(x +-)

-58.139999999997,when(x +-)

-58.229999999996984,when(x +-)

-58.319999999996966,when(x +-)

-58.40999999999695,when(x +-)

-58.49999999999693,when(x +-)

-58.58999999999691,when(x +-)

-58.679999999996895,when(x +-)

-58.76999999999688,when(x +-)

-58.85999999999686,when(x +-)

-58.94999999999684,when(x +-)

-59.03999999999682,when(x +-)

-59.129999999996805,when(x +-)

-59.21999999999679,when(x +-)

-59.30999999999677,when(x +-)

-59.39999999999675,when(x +-)

-59.48999999999673,when(x +-)

-59.579999999996716,when(x +-)

-59.6699999999967,when(x +-)

-59.75999999999668,when(x +-)

-59.84999999999666,when(x +-)

-59.939999999996644,when(x +-)

-59.99999999999663,enough

+3.63,when(x +-)

+7.01,when(x +-)

+9.73,when(x +-)

+11.92,when(x +-)

+13.0,kick

+16.88,when(x +-)

+20.16,when(x +-)

+22.8,when(x +-)

+23.0,kick

+28.87,when(x +-)

+33.64,when(x +-)

+37.0,kick

+38.99,when(x +-)

+41.24,when(x +-)

+43.05,when(x +-)

+44.51,when(x +-)

+45.7,when(x +-)

+46.67,when(x +-)

+47.46,when(x +-)

+48.11,when(x +-)

+48.64,when(x +-)

+49.08,when(x +-)

+49.45,when(x +-)

+49.76,when(x +-)

+50.03,when(x +-)

+50.26,when(x +-)

+50.46,when(x +-)

+50.64,when(x +-)

+50.8,when(x +-)

+50.95,when(x +-)

+51.09,when(x +-)

+51.21,when(x +-)

+51.32,when(x +-)

+51.43,when(x +-)

+51.54,when(x +-)

+51.64,when(x +-)

+51.74,when(x +-)

+51.84,when(x +-)

+51.93,when(x +-)

+52.02,when(x +-)

+52.11,when(x +-)

+52.2,when(x +-)

+52.29,when(x +-)

+52.38,when(x +-)

+52.47,when(x +-)

+52.56,when(x +-)

+52.65,when(x +-)

+52.74,when(x +-)

+52.83,when(x +-)

+52.92,when(x +-)

+53.01,when(x +-)

+53.1,when(x +-)

+53.19,when(x +-)

+53.28,when(x +-)

+53.37,when(x +-)

+53.46,when(x +-)

+53.55,when(x +-)

+53.64,when(x +-)

+53.73,when(x +-)

+53.82,when(x +-)

+53.91,when(x +-)

+54.0,when(x +-)

+54.09,when(x +-)

+54.18,when(x +-)

+54.27,when(x +-)

+54.36,when(x +-)

+54.45,when(x +-)

+54.54,when(x +-)

+54.63,when(x +-)

+54.72,when(x +-)

+54.81,when(x +-)

+54.9,when(x +-)

+54.99,when(x +-)

+55.08,when(x +-)

+55.17,when(x +-)

+55.26,when(x +-)

+55.35,when(x +-)

+55.44,when(x +-)

+55.53,when(x +-)

+55.62,when(x +-)

+55.71,when(x +-)

+55.8,when(x +-)

+55.89,when(x +-)

+55.98,when(x +-)

+56.07,when(x +-)

+56.16,when(x +-)

+56.25,when(x +-)

+56.34,when(x +-)

+56.43,when(x +-)

+56.52,when(x +-)

+56.61,when(x +-)

+56.7,when(x +-)

+56.79,when(x +-)

+56.88,when(x +-)

+56.97,when(x +-)

+57.06,when(x +-)

+57.15,when(x +-)

+57.24,when(x +-)

+57.33,when(x +-)

+57.42,when(x +-)

+57.51,when(x +-)

+57.6,when(x +-)

+57.69,when(x +-)

+57.78,when(x +-)

+57.87,when(x +-)

+57.96,when(x +-)

+58.05,when(x +-)

+58.14,when(x +-)

+58.23,when(x +-)

+58.32,when(x +-)

+58.41,when(x +-)

+58.5,when(x +-)

+58.59,when(x +-)

+58.68,when(x +-)

+58.77,when(x +-)

+58.86,when(x +-)

+58.95,when(x +-)

+59.04,when(x +-)

+59.13,when(x +-)

+59.22,when(x +-)

+59.31,when(x +-)

+59.4,when(x +-)

+59.49,when(x +-)

+59.58,when(x +-)

+59.67,when(x +-)

+59.76,when(x +-)

+59.85,when(x +-)

+59.94,when(x +-)

+60.0,enough


+ 222 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/fsaclasses.py

@@ -0,0 +1,222 @@
+import numpy
+from operator import attrgetter
+
+############### runtime classes
+
+class RunTimeEvent:
+    def __init__(self, name, time):
+        self.name = name
+        self.time = time
+        self.processed = False
+
+class Events:
+    def __init__(self, events):
+        self.events = sorted(events, key=attrgetter('time'))
+    
+    '''
+    Returns the most recent event with the timestamp smaller than time.
+    '''
+    def getInputAt(self,time):
+        event = None
+        if self.events != []:
+            # Claudio: this approach is assuming that the queue is sorted according the time of the events.
+            for e in self.events:
+                if e.time < time or numpy.isclose(e.time, time, 1e-05, 1e-08):
+                    event = e
+                else:
+                    # stop at the first event that satisfies e.time > time
+                    break
+        return event
+    
+    '''
+        Removes event all other older events from the queue.
+    '''
+    def popEvent(self, event):
+        if event == None:
+            return
+        
+        assert event in self.events
+        # Claudio: this approach is assuming that the queue is sorted according the time of the events.
+        # first collect list of events to be removed.
+        # then remove them.
+        eventsToBeRemoved = []
+        for e in self.events:
+            eventsToBeRemoved.append(e)
+            if e == event:
+                break
+        assert len(eventsToBeRemoved)>0
+        for e in eventsToBeRemoved:
+            self.events.remove(e)
+        
+
+############### static classes - invariants
+
+class Expression:
+    def __init__(self):
+        pass
+
+class FSAModel:
+    def __init__(self,states,transitions):
+        self.transitions = transitions
+        self.states = states
+        self.initialState = None
+        
+    def getTransitionFrom(self, state, event, elapsed):
+        assert state != None
+        assert elapsed >= 0.0
+        
+        # Priotiry goes to event.
+        selectedTransition = None
+        
+        if event!=None:
+            selectedTransition = self.getTriggeredTransition(state, event)
+        
+        # Then to after 
+        if (selectedTransition == None):
+            selectedTransition = self.getTransitionAfter(state, elapsed)
+        
+        # And finally to default transitions
+        if (selectedTransition == None):
+            selectedTransition = self.getDefaultTransition(state)
+        
+        return selectedTransition
+    
+    def getDefaultTransition(self, state):
+        assert state != None
+        for t in self.transitions:
+                if t.source == state and t.trigger == None:
+                    return t
+        
+        return None
+    
+    
+    def getTriggeredTransition(self, state, event):
+        assert event != None
+        for t in self.transitions:
+                if t.source == state and isinstance(t.trigger,Event) and t.trigger.name == event.name:
+                        return t
+        
+        return None
+    
+    def getTransitionAfter(self, state, elapsed):
+        for t in self.transitions:
+            if t.source == state and isinstance(t.trigger,After):
+                if ExpressionVisitor(t.trigger.after).visit() <= elapsed:
+                    return t
+        return None 
+
+class ExpressionVisitor:
+    def __init__(self, expression):
+        self.expression = expression
+        
+    def visit(self):
+        if(isinstance(self.expression,AtomValue)):
+            return self.expression.value
+        if(isinstance(self.expression,Operation)):
+            left = ExpressionVisitor(self.expression.left).visit()
+            right = ExpressionVisitor(self.expression.right).visit()
+            if(self.expression.op == '+'):
+                return left + right
+            if(self.expression.op == '-'):
+                return left - right
+            if(self.expression.op == '*'):
+                return left * right
+            if(self.expression.op == '/'):
+                return left / right
+            if(self.expression.op == 'and'):
+                return left and right
+            if(self.expression.op == 'or'):
+                return left or right
+        if(isinstance(self.expression,Not)):
+            return not ExpressionVisitor(self.expression.expression).visit()
+
+class State:
+    def __init__(self, name, final = False):
+        self.name = name
+        self.final = final
+        
+    def getName(self):
+        return self.name
+    
+    def __str__(self):
+        return self.name
+    
+    
+class Operation(Expression):
+    def __init__(self, left, right, op):
+        self.op = op
+        self.left = left
+        self.right = right
+        
+class Transition:
+    def __init__(self,name, source,target):
+        self.name = name
+        self.source = source
+        self.target = target
+        self.trigger = None
+        self.guard = None
+    
+    def __str__(self):
+        return str(self.source) + "--" + self.name + ": " +  str(self.trigger) + "-->" + str(self.target)
+    
+class Trigger:
+    def __init__(self):
+        pass
+
+class Event(Trigger):
+    def __init__(self,name):
+        self.name = name
+        
+    def __str__(self):
+        return self.name
+    
+class After(Trigger):
+    def __init__(self, expression):
+        self.after = expression
+    
+    def __str__(self):
+        return "after("+ str(self.after) + ")"
+    
+class Guard:
+    def __init__(self, expression):
+        self.expression = expression
+
+class And(Operation):
+    def __init__(self, lexpression, rexpression):
+        self.left = lexpression
+        self.right = rexpression
+        self.op = "and"
+
+class Or(Operation):
+    def __init__(self, lexpression, rexpression):
+        self.left = lexpression
+        self.right = rexpression
+        self.op = "or"
+
+class Not(Expression):
+    def __init__(self, expression):
+        self.expression = expression
+
+class Variable(Expression):
+    def __init__(self, varname):
+        self.name = varname
+
+class AtomValue(Expression):
+    def __init__(self, value):
+        self.value = value
+        
+    def __str__(self):
+        return str(self.value)
+    
+
+class Integer(AtomValue):
+    def __init__(self, value):
+        self.value = value
+    
+class Float(AtomValue):
+    def __init__(self, value):
+        self.value = value
+
+class String(AtomValue):
+    def __init__(self, value):
+        self.value = value

+ 149 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/run_debug.py

@@ -0,0 +1,149 @@
+import target
+from sccd.runtime.statecharts_core import Event
+import threading
+import fsaclasses
+from fsa_cbd_weaved_classes import CBDState
+from CBDMultipleOutput.models.HarmonicOscilator import CircleCBDDerivative
+from weaved_cbd_fsa_simulator import Controller
+from Options import Options
+from models.bouncingball import BouncingBallFSA
+import os
+from weaved_cbd_fsa_lib import FSACBDLib
+
+CBD_DELTA = 0.01
+
+def buildModel():
+    statea = fsaclasses.State("a")
+    stateb = fsaclasses.State("b")
+    statec = CBDState("c", CircleCBDDerivative("Harmonic Oscilator", CBD_DELTA))
+    stated = fsaclasses.State("d")
+    statef = State("f", True)
+    
+    transitionab = fsaclasses.Transition("a2b",statea,stateb)
+    transitionab.trigger = fsaclasses.After(fsaclasses.Float(5.0))
+    
+    transitionbc = fsaclasses.Transition("b2c",stateb,statec)
+    transitionbc.trigger = fsaclasses.After(fsaclasses.Float(2.0))
+    
+    transitioncd = fsaclasses.Transition("c2d",statec,stated)
+    transitioncd.trigger = fsaclasses.Event("c")
+
+    transitiondf = fsaclasses.Transition("d2f",stated,statef)
+    transitiondf.trigger = fsaclasses.After(fsaclasses.Float(5.0))
+
+    fsamodel = fsaclasses.FSAModel(
+                        [statea,stateb,statec,stated,statef],
+                        [transitionab,transitionbc,transitioncd,transitiondf]
+                        )
+    fsamodel.initialState = statea
+    return fsamodel
+
+if __name__ == '__main__':    
+    if os.path.exists(FSACBDLib.OUTPUT_EVENTS):
+        os.remove(FSACBDLib.OUTPUT_EVENTS)
+    if os.path.exists(FSACBDLib.OUTPUT_SIGNALS):
+        os.remove(FSACBDLib.OUTPUT_SIGNALS)
+        
+    options = Options(delta = CBD_DELTA)
+    options.setMaxIterations(10000);
+    fsamodel = BouncingBallFSA()
+    events = fsaclasses.Events([fsaclasses.RunTimeEvent('kick',13.0), fsaclasses.RunTimeEvent('kick',23.0), fsaclasses.RunTimeEvent('kick',37.0) ,fsaclasses.RunTimeEvent('enough',60.0)])
+    controller = target.Controller(options, fsamodel, events, keep_running=True)
+    
+    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 == "small_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) != 2:
+                    print("God events require 1 parameter!")
+                    continue
+                params = [inp[1]]
+            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 big step")
+                print("  small_step")
+                print("   --> Simulate a small 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("  god_event new_state")
+                print("   --> Updates the current state")
+                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()

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 6494 - 6494
debugging_fsa_cbd_composition/fsa_cbd_simulator/signals.csv


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1079 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/target.py


+ 158 - 157
debugging_fsa_cbd_composition/fsa_cbd_simulator/weaved_cbd_fsa_lib.py

@@ -3,7 +3,7 @@
 '''
 
 from fsa_cbd_weaved_classes import WhenCrossesZeroTrigger, InputConstantBlock,\
-	CBDState
+    CBDState
 from CBDMultipleOutput.Source.CBD import OutputPortBlock
 import numpy
 import os
@@ -11,159 +11,160 @@ import csv
 from fsaclasses import Event, After
 
 class FSACBDLib():
-	BLOCK_NAME_OUT = "out_"
-	OUTPUT_SIGNALS = "./signals.csv"
-	OUTPUT_EVENTS = "./events.csv"
-		
-	def __init__(self):
-		pass
-	
-	def getTriggeredWhenTransition(self, fsaCbdModel, currentFSAState, globalState, previousGlobalState):
-		'''
-		This method will check whether there is any transition triggered by a zero crossing detection and if so,
-		if that zero crossing has in fact occurred when comparing the new globalState with the previousGlobalState.
-		'''
-		triggeredTransiton = None
-		
-		for t in fsaCbdModel.transitions:
-			if t.source == currentFSAState and isinstance(t.trigger,WhenCrossesZeroTrigger):
-				varNameToCheck = t.trigger.varname
-				if varNameToCheck in globalState and varNameToCheck in previousGlobalState:
-					if t.trigger.up_direction and previousGlobalState[varNameToCheck] <= 0 and 0 < globalState[varNameToCheck] :
-						triggeredTransiton = t
-						break
-					if not t.trigger.up_direction and globalState[varNameToCheck] < 0 and 0 <= previousGlobalState[varNameToCheck] :
-						triggeredTransiton = t
-						break
-		
-		assert triggeredTransiton == None or t.source == currentFSAState
-		
-		return triggeredTransiton
-	
-	def updateGlobalState(self ,globalState, cbdModel, cbdTime):
-		'''
-		The globalState is a dictionary mapping variable names to values.
-		This function will get the signals for the outputPorts in the cbdModel and then
-		update the globalState with the values of the outputPorts at time cbdTime
-		'''
-		for block in cbdModel.getBlocks():
-			if (isinstance(block, OutputPortBlock)):
-				port = block.getBlockName()
-				signal = block.getSignal()
-				# Convention: port is of the form "out_varName" to represent the global varName
-				assert port.startswith(self.BLOCK_NAME_OUT), "Convention violated for output port: " + str(port)
-				varName = self.stripConventionOutname(port)
-				assert len(varName)>0 , "Convention violated for output port: " + str(port)
-				
-				mostRecentSignal = signal[-1]
-				
-				assert numpy.isclose(mostRecentSignal.time,cbdTime, 1e-05, 1e-08), "Signal as not been computed up to time " + str(cbdTime)
-				
-				signalValue = mostRecentSignal.value
-				globalState[varName] = signalValue
-	
-	def stripConventionOutname(self, name):
-		return name.replace(self.BLOCK_NAME_OUT, "", 1)
-	
-	def updateCBDState(self, globalState, cbdModel):
-		'''
-		The globalState is a dictionary mapping variable names to values.
-		
-		This function is to be called when initializing the cbdModel.
-		This function will iterate the input blocks of the CBD, which have conventioned name as "in_varName" and it will set the values for those blocks. 
-		'''	
-		for block in cbdModel.getBlocks():
-			if isinstance(block, InputConstantBlock):
-				assert block.getBlockName().startswith("in_"), "Convention violated for input block of the CBD: " + str(block.getBlockName())
-				varName = block.getBlockName().replace("in_", "", 1)
-				assert len(varName)>0 , "Convention violated for input block of the CBD: " + str(block.getBlockName())
-				assert varName in globalState, "Input block not initialized before: " + str(block.getBlockName())
-				
-				block.setValue(globalState[varName])
-		
-		
-	def dumpGlobalState(self, fsaCbdModel, globalState, fsaTime, fsaState):
-		create_header = not os.path.exists(self.OUTPUT_SIGNALS);
-		
-		if create_header:
-			self.addRemainingSignals(globalState, fsaCbdModel)
-		
-		# It is not a good idea to write this directly to the global state but it is more efficient.
-		
-		globalState["fsatime"] = fsaTime
-		
-		if isinstance(fsaState, CBDState):
-			assert fsaState.cbd != None
-			if fsaState.cbd.getClock() != None:
-				globalState["current_cbdtime"] = fsaState.cbd.getClock().getTime()
-			else:
-				# Clock not yet initialized. Can happen.
-				globalState["current_cbdtime"] = -1.0
-		else:
-			globalState["current_cbdtime"] = -1.0
-		
-		globalState["fsastate"] = fsaState.name
-		
-		with open(self.OUTPUT_SIGNALS, "a") as csvFile:
-			writerCsv = csv.DictWriter(csvFile, fieldnames=globalState.keys())
-			if create_header:
-				writerCsv.writeheader()
-			writerCsv.writerow(globalState)
-	
-	def addRemainingSignals(self, stateDict, fsaCbdModel):
-		
-		for state in fsaCbdModel.states:
-			if (isinstance(state, CBDState)):
-				for block in state.cbd.getBlocks():
-					if isinstance(block, OutputPortBlock):
-						varName = self.stripConventionOutname(block.getBlockName())
-						if not varName in stateDict:
-							stateDict[varName] = None
-		
-		
-		return stateDict
-	
-	def dumpDiscreteEvent(self, fsaCbdModel, fsaTime, fsa_currentState, fsa_selectedTransition):
-		create_header = not os.path.exists(self.OUTPUT_EVENTS);
-		
-		event = None
-		if (fsa_selectedTransition != None):
-			if fsa_selectedTransition.trigger != None:
-				if isinstance(fsa_selectedTransition.trigger, Event):
-					event = fsa_selectedTransition.trigger.name
-				elif isinstance(fsa_selectedTransition.trigger, After):
-					event = "after("+str(fsa_selectedTransition.trigger.expression)+")"
-				elif isinstance(fsa_selectedTransition.trigger, WhenCrossesZeroTrigger):
-					event = "when("+str(fsa_selectedTransition.trigger.varname)+" " + ("-+" if fsa_selectedTransition.trigger.up_direction else "+-") + ")"
-		
-		if (event != None):
-			with open(self.OUTPUT_EVENTS, "a") as csvFile:
-				eventDict = {"fsatime" : fsaTime , "Event" : event}
-				writerCsv = csv.DictWriter(csvFile, fieldnames=eventDict.keys())
-				if create_header:
-					writerCsv.writeheader()
-				writerCsv.writerow(eventDict)
-				
-				
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-				
+    BLOCK_NAME_OUT = "out_"
+    OUTPUT_SIGNALS = "./signals.csv"
+    OUTPUT_EVENTS = "./events.csv"
+        
+    def __init__(self):
+        pass
+    
+    def getTriggeredWhenTransition(self, fsaCbdModel, currentFSAState, globalState, previousGlobalState):
+        '''
+        This method will check whether there is any transition triggered by a zero crossing detection and if so,
+        if that zero crossing has in fact occurred when comparing the new globalState with the previousGlobalState.
+        '''
+        triggeredTransiton = None
+        
+        for t in fsaCbdModel.transitions:
+            if t.source == currentFSAState and isinstance(t.trigger,WhenCrossesZeroTrigger):
+                varNameToCheck = t.trigger.varname
+                if varNameToCheck in globalState and varNameToCheck in previousGlobalState:
+                    if t.trigger.up_direction and previousGlobalState[varNameToCheck] <= 0 and 0 < globalState[varNameToCheck] :
+                        triggeredTransiton = t
+                        break
+                    if not t.trigger.up_direction and globalState[varNameToCheck] < 0 and 0 <= previousGlobalState[varNameToCheck] :
+                        triggeredTransiton = t
+                        break
+        
+        assert triggeredTransiton == None or t.source == currentFSAState
+        
+        return triggeredTransiton
+    
+    def updateGlobalState(self ,globalState, cbdModel, cbdTime):
+        '''
+        The globalState is a dictionary mapping variable names to values.
+        This function will get the signals for the outputPorts in the cbdModel and then
+        update the globalState with the values of the outputPorts at time cbdTime
+        '''
+        for block in cbdModel.getBlocks():
+            if (isinstance(block, OutputPortBlock)):
+                port = block.getBlockName()
+                signal = block.getSignal()
+                # Convention: port is of the form "out_varName" to represent the global varName
+                assert port.startswith(self.BLOCK_NAME_OUT), "Convention violated for output port: " + str(port)
+                varName = self.stripConventionOutname(port)
+                assert len(varName)>0 , "Convention violated for output port: " + str(port)
+                
+                mostRecentSignal = signal[-1]
+                
+                print mostRecentSignal.time,cbdTime
+                assert numpy.isclose(mostRecentSignal.time,cbdTime, 1e-05, 1e-08), "Signal has not been computed up to time " + str(cbdTime)
+                
+                signalValue = mostRecentSignal.value
+                globalState[varName] = signalValue
+    
+    def stripConventionOutname(self, name):
+        return name.replace(self.BLOCK_NAME_OUT, "", 1)
+    
+    def updateCBDState(self, globalState, cbdModel):
+        '''
+        The globalState is a dictionary mapping variable names to values.
+        
+        This function is to be called when initializing the cbdModel.
+        This function will iterate the input blocks of the CBD, which have conventioned name as "in_varName" and it will set the values for those blocks. 
+        '''    
+        for block in cbdModel.getBlocks():
+            if isinstance(block, InputConstantBlock):
+                assert block.getBlockName().startswith("in_"), "Convention violated for input block of the CBD: " + str(block.getBlockName())
+                varName = block.getBlockName().replace("in_", "", 1)
+                assert len(varName)>0 , "Convention violated for input block of the CBD: " + str(block.getBlockName())
+                assert varName in globalState, "Input block not initialized before: " + str(block.getBlockName())
+                
+                block.setValue(globalState[varName])
+        
+        
+    def dumpGlobalState(self, fsaCbdModel, globalState, fsaTime, fsaState):
+        create_header = not os.path.exists(self.OUTPUT_SIGNALS);
+        
+        if create_header:
+            self.addRemainingSignals(globalState, fsaCbdModel)
+        
+        # It is not a good idea to write this directly to the global state but it is more efficient.
+        
+        globalState["fsatime"] = fsaTime
+        
+        if isinstance(fsaState, CBDState):
+            assert fsaState.cbd != None
+            if fsaState.cbd.getClock() != None:
+                globalState["current_cbdtime"] = fsaState.cbd.getClock().getTime()
+            else:
+                # Clock not yet initialized. Can happen.
+                globalState["current_cbdtime"] = -1.0
+        else:
+            globalState["current_cbdtime"] = -1.0
+        
+        globalState["fsastate"] = fsaState.name
+        
+        with open(self.OUTPUT_SIGNALS, "a") as csvFile:
+            writerCsv = csv.DictWriter(csvFile, fieldnames=globalState.keys())
+            if create_header:
+                writerCsv.writeheader()
+            writerCsv.writerow(globalState)
+    
+    def addRemainingSignals(self, stateDict, fsaCbdModel):
+        
+        for state in fsaCbdModel.states:
+            if (isinstance(state, CBDState)):
+                for block in state.cbd.getBlocks():
+                    if isinstance(block, OutputPortBlock):
+                        varName = self.stripConventionOutname(block.getBlockName())
+                        if not varName in stateDict:
+                            stateDict[varName] = None
+        
+        
+        return stateDict
+    
+    def dumpDiscreteEvent(self, fsaCbdModel, fsaTime, fsa_currentState, fsa_selectedTransition):
+        create_header = not os.path.exists(self.OUTPUT_EVENTS);
+        
+        event = None
+        if (fsa_selectedTransition != None):
+            if fsa_selectedTransition.trigger != None:
+                if isinstance(fsa_selectedTransition.trigger, Event):
+                    event = fsa_selectedTransition.trigger.name
+                elif isinstance(fsa_selectedTransition.trigger, After):
+                    event = "after("+str(fsa_selectedTransition.trigger.expression)+")"
+                elif isinstance(fsa_selectedTransition.trigger, WhenCrossesZeroTrigger):
+                    event = "when("+str(fsa_selectedTransition.trigger.varname)+" " + ("-+" if fsa_selectedTransition.trigger.up_direction else "+-") + ")"
+        
+        if (event != None):
+            with open(self.OUTPUT_EVENTS, "a") as csvFile:
+                eventDict = {"fsatime" : fsaTime , "Event" : event}
+                writerCsv = csv.DictWriter(csvFile, fieldnames=eventDict.keys())
+                if create_header:
+                    writerCsv.writeheader()
+                writerCsv.writerow(eventDict)
+                
+                
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                

+ 711 - 0
debugging_fsa_cbd_composition/fsa_cbd_simulator/woven_fsa_cbd_simulator_hierarchical_debugging.xml

@@ -0,0 +1,711 @@
+<?xml version="1.0" ?>
+<diagram name="Weaved_CBD_FSA_Simulator_Manual" author="Sadaf Mustafiz and Bruno Barroca and Claudio Gomes">
+    <description>
+        Automatically woven CBD and FSA simulators with the FSA being the dominant.
+    </description>
+    
+    <inport name="user_input" />
+    <outport name="user_output" />
+    
+    <top>
+        <![CDATA[
+            from sccd.runtime.libs.ui import *
+            from sccd.runtime.libs.utils import *
+            import copy
+            from CBD_Controller import CBDController
+            import Options
+            from fsa_cbd_weaved_classes import CBDState
+            from weaved_cbd_fsa_lib import FSACBDLib
+        ]]>
+    </top>
+    <class name="Weaved_CBD_FSA_Simulator" default="True">
+        <attribute name="weaved_global_state"/>
+        <attribute name="fsa_elapsed"/>
+        <attribute name="cbd_options"/>
+        <attribute name="weaved_lib"/>
+        <attribute name="woven_child_initialized"/>
+        <attribute name="cbd_clock"/>
+        <attribute name="fsa_currentEvent"/>
+        <attribute name="weaved_delta"/>
+        <attribute name="weaved_model"/>
+        <attribute name="cbd_controller"/>
+        <attribute name="fsa_timestep"/>
+        <attribute name="cbd_currentCompIdx"/>
+        <attribute name="fsa_eventList"/>
+        <attribute name="cbd_depGraph"/>
+        <attribute name="fsa_selectedTransition"/>
+        <attribute name="cbd_strongComponentList"/>
+        <attribute name="weaved_previous_global_state"/>
+        <attribute name="cbd_delta"/>
+        <attribute name="weaved_triggered_when_transition"/>
+        <attribute name="cbd_iteration"/>
+        <attribute name="fsa_logicalTime"/>
+        <attribute name="fsa_currentState"/>
+        <method name="Weaved_CBD_FSA_Simulator">
+            <parameter name="cbd_options"/>
+            <parameter name="amodel"/>
+            <parameter name="fsa_events"/>
+            <body>
+            <![CDATA[
+                self.weaved_lib = FSACBDLib()
+                self.cbd_options = cbd_options
+                self.cbd_delta = self.cbd_options.getDeltaT() * 1000.0
+                self.weaved_model = amodel
+                self.fsa_eventList = fsa_events
+                self.fsa_timestep = 1.0 * 1000.0
+                self.initialized = False
+            ]]>
+            </body>
+        </method>
+        <method name="fsa_processEvent">
+            <parameter name="event"/>
+            <body>
+            <![CDATA[
+                if (event != None):
+                    self.fsa_eventList.popEvent(event)
+                    event.processed = True
+            ]]>
+            </body>
+        </method>
+        <method name="updateCBDState">
+            <body>
+            <![CDATA[
+                self.weaved_lib.updateCBDState(self.weaved_global_state, self.fsa_currentState.cbd)
+            ]]>
+            </body>
+        </method>
+        <method name="cbd_maxIterationsReached">
+            <body>
+            <![CDATA[
+                return self.cbd_iteration >= self.cbd_options.getMaxIterations()
+            ]]>
+            </body>
+        </method>
+        <method name="fsa_getInputEventAt">
+            <parameter name="time"/>
+            <body>
+            <![CDATA[
+                return self.fsa_eventList.getInputAt(time)
+            ]]>
+            </body>
+        </method>
+        <method name="cbd_computeBlock">
+            <body>
+            <![CDATA[
+                if self.cbd_currentComponentIsCycle():
+                    self.cbd_controller.computeNextAlgebraicLoop(self.cbd_strongComponentList[self.cbd_currentCompIdx], self.cbd_iteration)
+                else:
+                    self.cbd_controller.computeNextBlock(self.cbd_strongComponentList[self.cbd_currentCompIdx], self.cbd_iteration)
+            ]]>
+            </body>
+        </method>
+        <method name="updateGlobalState">
+            <body>
+            <![CDATA[
+                self.weaved_previous_global_state = copy.deepcopy(self.weaved_global_state)
+                self.weaved_lib.updateGlobalState(self.weaved_global_state, self.fsa_currentState.cbd, self.cbd_clock / 1000.0)
+            ]]>
+            </body>
+        </method>
+        <method name="cbd_currentComponentIsCycle">
+            <body>
+            <![CDATA[
+                return self.cbd_controller.componentIsCycle(self.cbd_strongComponentList[self.cbd_currentCompIdx], self.cbd_depGraph)
+            ]]>
+            </body>
+        </method>
+        <method name="cbd_hasNextStrongComponent">
+            <body>
+            <![CDATA[
+                return (self.cbd_currentCompIdx) < len(self.cbd_strongComponentList)
+            ]]>
+            </body>
+        </method>
+        <method name="getTriggeredWhenTransition">
+            <body>
+            <![CDATA[
+                return self.weaved_lib.getTriggeredWhenTransition(self.weaved_model, self.fsa_currentState, self.weaved_global_state, self.weaved_previous_global_state)
+            ]]>
+            </body>
+        </method>
+        <method name="fsa_initialize">
+            <body>
+            <![CDATA[
+                self.weaved_delta = min(self.fsa_timestep, self.cbd_delta)
+                self.fsa_logicalTime = 0.0
+                self.fsa_elapsed = 0
+                self.fsa_timestep = self.weaved_delta
+                self.fsa_currentState = self.weaved_model.initialState
+                self.initialized = True
+            ]]>
+            </body>
+        </method>
+        <method name="fsa_finalize">
+            <body>
+            <![CDATA[
+                print 'Simulation finalized.'
+            ]]>
+            </body>
+        </method>
+        <method name="weaved_initialize">
+            <body>
+            <![CDATA[
+                self.weaved_global_state = dict()
+                self.weaved_previous_global_state = dict()
+                self.woven_child_initialized = False
+            ]]>
+            </body>
+        </method>
+        <method name="initializeDebugger">
+            <body>
+            <![CDATA[
+                self.breakpoints = []
+                self.triggered_bp = None
+            ]]>
+            </body>
+        </method>
+        <method name="fsa_endCondition">
+            <body>
+            <![CDATA[
+                return self.initialized and self.fsa_currentState and self.fsa_currentState.final
+            ]]>
+            </body>
+        </method>
+        <method name="cbd_endCondition">
+            <body>
+            <![CDATA[
+                return self.initialized and self.cbd_iteration >= self.cbd_options.getMaxIterations()
+            ]]>
+            </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.currentState, 'event': self.currentEvent}):
+                        # 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="new_state" />
+            <body>
+            <![CDATA[
+                filtered_states = [s for s in self.model.states if s.name == new_state]
+                if not len(filtered_states) == 1:
+                    return -1
+                self.currentState = filtered_states[0]
+                return 0
+            ]]>
+            </body>
+        </method>
+        <scxml initial="Main" final="HybridTerminated">
+            <parallel id="Main">
+                <state id="SimulationState" initial="Paused">
+                    <state id="Paused">
+                        <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" />
+                        <transition target="../Running/SmallStep" event="small_step" port="user_input" />
+                        <!-- If a god event enables the end condition, the simulation should stop. -->
+                        <transition target="../PreStopped" cond="self.fsa_endCondition()" />
+                    </state>
+                    <state id="PrePaused">
+                        <!-- Here, we make sure the current step has finished, before we raise the 'paused' event. Otherwise, UserOutput will output the old state, not the latest one. -->
+                        <transition target="../Paused" after="self.sccd_yield() * 2">
+                            <raise event="paused" />
+                        </transition>
+                    </state>
+                    <state id="PreBreakpointTriggered">
+                        <!-- Here, we make sure the current step has finished, before we raise the 'paused' event. Otherwise, UserOutput will output the old state, not the latest one. -->
+                        <transition target="../Paused" after="self.sccd_yield() * 2">
+                            <raise event="breakpoint_triggered" />
+                        </transition>
+                    </state>
+                    <state id="Running" initial="Continuous">
+                        <transition target="../PreStopped" cond="self.fsa_endCondition()" />
+                        <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="SmallStep">
+                            <!-- We go to a special 'SmallStepDone' state because in the 'user_output' state, we need to check whether we are currently executing a small step.  -->
+                            <transition target="../SmallStepDone" event="small_step_done" />
+                        </state>
+                        <state id="SmallStepDone">
+                            <!-- We go back to the 'Paused' state once the small 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="PreStopped">
+                        <transition target="../Stopped" after="self.sccd_yield() * 2">
+                            <raise event="termination_condition" />
+                        </transition>
+                    </state>
+                    <state id="Stopped" />
+                </state>
+                <state id="SimulationFlow" initial="FSA">
+                    <state id="FSA" initial="Started">
+                        <state id="Started">
+                            <transition target="../../ParentStarted">
+                                <script>
+                                    <![CDATA[
+                                        print('From FSA/Started to ParentStarted... ')
+                                        self.fsa_initialize()
+                                    ]]>
+                                </script>
+                            </transition>
+                        </state>
+                        <state id="Initialized">
+                            <transition target="../DebuggerInitialized">
+                                <script>
+                                    <![CDATA[
+                                        print('From FSA/Initialized to FSA/CheckTermination... ')
+                                        self.initializeDebugger()
+                                    ]]>
+                                </script>
+                            </transition>
+                        </state>
+                        <state id="DebuggerInitialized">
+                            <transition target="../CheckTermination">
+                                <script>
+                                    <![CDATA[
+                                        print('From FSA/Initialized to FSA/CheckTermination... ')
+                                    ]]>
+                                </script>
+                            </transition>
+                        </state>
+                        <state id="CheckTermination" initial="MacroStepProcessed">
+                            <state id="MacroStepProcessed">
+                                <transition target="../../Terminated" cond="INSTATE('/Main/SimulationState/Stopped')" after="self.sccd_yield()">
+                                    <script>
+                                        <![CDATA[
+                                            print('From FSA/CheckTermination/MacroStepProcessed to Terminated... ')
+                                        ]]>
+                                    </script>
+                                </transition>
+                                <transition target="../../Waiting" cond="INSTATE('/Main/SimulationState/Running/Realtime')" />
+                                <transition target="../../DoSimulation" cond="INSTATE('/Main/SimulationState/Running/Continuous') or INSTATE('/Main/SimulationState/Running/BigStep') or INSTATE('/Main/SimulationState/Running/SmallStep')">
+                                    <script>
+                                        <![CDATA[
+                                            print('From FSA/CheckTermination/MacroStepProcessed to FSA/DoSimulation and reading events... ')
+                                            self.fsa_currentEvent = self.fsa_getInputEventAt(self.fsa_logicalTime / 1000.0)
+                                            self.fsa_selectedTransition = self.weaved_model.getTransitionFrom(self.fsa_currentState, self.fsa_currentEvent, self.fsa_elapsed)
+                                            print('Current event:' + str(self.fsa_currentEvent))
+                                            print('Current transition:' + str(self.fsa_selectedTransition))
+                                            print('Child detected?:' + str(isinstance(self.fsa_currentState, CBDState)))
+                                        ]]>
+                                    </script>
+                                </transition>
+                            </state>
+                        </state>
+                        <state id="Waiting" />
+                        <state id="DoSimulation" initial="MacroStepPrepared">
+                            <state id="MacroStepPrepared" initial="ParentPaused">
+                                <state id="ParentPaused">
+                                    <transition target="../ChildDetected" cond="isinstance(self.fsa_currentState, CBDState)">
+                                        <script>
+                                            <![CDATA[
+                                                print('From FSA/ParentPaused to FSA/ChildDetected... ')
+                                                self.cbd_model = self.fsa_currentState.cbd
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                    <transition target="../ChildNotDetected" cond="not isinstance(self.fsa_currentState, CBDState)">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ParentPaused to ChildNotDetected without any child to process... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildNotDetected">
+                                    <transition target="../ChildProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildNotDetected to ChildProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildDetected">
+                                    <transition target="../ChildInitialized" cond="self.woven_child_initialized">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildDetected to ChildInitialized... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                    <transition target="../ChildNotInitialized" cond="not self.woven_child_initialized">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildDetected to ChildNotInitialized... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildInitialized">
+                                    <transition target="../ChildProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildInitialized to ChildProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildNotInitialized">
+                                    <transition target="../CBD/Started">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildNotInitialized to CBD/Started... ')
+                                                self.cbd_delta = self.weaved_delta
+                                                self.updateCBDState()
+                                                self.woven_child_initialized = True
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="CBD" initial="Started">
+                                    <state id="Started">
+                                        <transition target="../Initialized">
+                                            <script>
+                                                <![CDATA[
+                                                    print('From CBD/Started to Initialized... ')
+                                                    print('Performing initialization...')
+                                                    self.cbd_iteration = 0
+                                                    self.cbd_clock = 0
+                                                    self.cbd_controller = CBDController(self.cbd_model, self.cbd_delta / 1000.0)
+                                                    self.cbd_controller.initSimulation()
+                                                    print('Performing initialization... DONE')
+                                                ]]>
+                                            </script>
+                                        </transition>
+                                    </state>
+                                    <state id="Initialized">
+                                        <transition target="../../ChildInitialized">
+                                            <script>
+                                                <![CDATA[
+                                                    print('From CBD/Initialized to ChildInitialized... ')
+                                                ]]>
+                                            </script>
+                                        </transition>
+                                    </state>
+                                </state>
+                                <state id="ChildProcessed">
+                                    <transition target="../../MicroStepProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From MacroStepPrepared/ChildProcessed to MicroStepProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                            </state>
+                            <state id="MicroStepProcessed" initial="ParentPaused">
+                                <state id="ParentPaused">
+                                    <transition target="../ChildDetected" cond="isinstance(self.fsa_currentState, CBDState)">
+                                        <script>
+                                            <![CDATA[
+                                                print('From FSA/ParentPaused to FSA/ChildDetected... ')
+                                                self.cbd_model = self.fsa_currentState.cbd
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                    <transition target="../ChildNotDetected" cond="not isinstance(self.fsa_currentState, CBDState)">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ParentPaused to ChildNotDetected without any child to process... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildNotDetected">
+                                    <transition target="../ChildProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildNotDetected to ChildProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildDetected">
+                                    <transition target="../ChildInitialized" cond="self.woven_child_initialized">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildDetected to ChildInitialized... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildInitialized">
+                                    <transition target="../CBD/CheckTermination">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildInitialized to ChildProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="CBD" initial="CheckTermination">
+                                    <state id="CheckTermination" initial="MacroStepProcessed">
+                                        <state id="MacroStepProcessed">
+                                            <transition target="../../Terminated" cond="self.cbd_endCondition()">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MacroStepProcessed to Terminated... ')
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                            <transition target="../../DoSimulation" cond="not self.cbd_endCondition()">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MacroStepProcessed to MacroStepPrepared... ')
+                                                        self.cbd_currentCompIdx = 0
+                                                        self.cbd_depGraph = self.cbd_controller.createDepGraph(self.cbd_iteration)
+                                                        self.cbd_strongComponentList = self.cbd_controller.createStrongComponents(self.cbd_depGraph, self.cbd_iteration)
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                        </state>
+                                    </state>
+                                    <state id="DoSimulation" initial="MacroStepPrepared">
+                                        <state id="MacroStepPrepared">
+                                            <transition target="../MicroStepProcessed">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MacroStepPrepared to MicroStepProcessed... ')
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                        </state>
+                                        <state id="MicroStepProcessed">
+                                            <transition target="../MicroStepPrepared" cond="self.cbd_hasNextStrongComponent()">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MicroStepProcessed to MicroStepPrepared')
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                            <transition target="../../../ChildPaused" cond="not self.cbd_hasNextStrongComponent()">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MicroStepProcessed to ChildPaused and detecting triggered transitions... ')
+                                                        self.updateGlobalState()
+                                                        self.weaved_lib.dumpGlobalState(self.weaved_model, self.weaved_global_state, self.fsa_logicalTime / 1000.0, self.fsa_currentState)
+                                                        self.weaved_triggered_when_transition = self.getTriggeredWhenTransition()
+                                                        self.cbd_clock = self.cbd_clock + self.cbd_delta
+                                                        self.cbd_iteration = self.cbd_iteration + 1
+                                                        self.cbd_controller.advanceTimeStep()
+                                                        print('CBD clock: ' + str(self.cbd_clock / 1000.0))
+                                                        print('CBD iteration: ' + str(self.cbd_iteration))
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                        </state>
+                                        <state id="MicroStepPrepared">
+                                            <transition target="../MicroStepProcessed">
+                                                <script>
+                                                    <![CDATA[
+                                                        print('From CBD/MicroStepPrepared to MicroStepProcessed...')
+                                                        self.cbd_computeBlock()
+                                                        self.cbd_currentCompIdx = self.cbd_currentCompIdx + 1
+                                                    ]]>
+                                                </script>
+                                            </transition>
+                                        </state>
+                                    </state>
+                                    <state id="Terminated" />
+                                </state>
+                                <state id="ChildPaused">
+                                    <transition target="../NoStateEventDetected" cond="self.weaved_triggered_when_transition == None">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildPaused to NoStateEventDetected... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                    <transition target="../StateEventDetected" cond="self.weaved_triggered_when_transition != None">
+                                        <script>
+                                            <![CDATA[
+                                                print('From ChildPaused to StateEventDetected... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="NoStateEventDetected">
+                                    <transition target="../ChildProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From NoStateEventDetected to ChildProcessed... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="StateEventDetected">
+                                    <transition target="../ChildProcessed">
+                                        <script>
+                                            <![CDATA[
+                                                print('From StateEventDetected to ChildProcessed... ')
+                                                if self.fsa_selectedTransition == None:
+                                                    self.fsa_selectedTransition = self.weaved_triggered_when_transition
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                                <state id="ChildProcessed">
+                                    <transition target="../../MicroStepPrepared" cond="self.fsa_selectedTransition != None">
+                                        <script>
+                                            <![CDATA[
+                                                print('From FSA/MicroStepProcessed/ChildProcessed to MicroStepPrepared... ')
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                    <transition target="../../../CheckTermination" cond="self.fsa_selectedTransition == None">
+                                        <script>
+                                            <![CDATA[
+                                                print('From FSA/MicroStepProcessed/ChildProcessed to FSA/CheckTermination and advancing time... ')
+                                                self.fsa_logicalTime = self.fsa_logicalTime + self.fsa_timestep
+                                                self.fsa_elapsed = self.fsa_elapsed + self.fsa_timestep
+                                                print('fsa_logicalTime: %s' % (self.fsa_logicalTime / 1000.0))
+                                                print('fsa_elapsed: %s' % (self.fsa_elapsed / 1000.0))
+                                            ]]>
+                                        </script>
+                                    </transition>
+                                </state>
+                            </state>
+                            <state id="MicroStepPrepared">
+                                <transition target="../ParentMicroStepProcessed">
+                                    <script>
+                                        <![CDATA[
+                                            print('From FSA/MicroStepPrepared to ParentMicroStepProcessed and attempting to take transition... ')
+                                            print('Transition to be taken: ' + str(self.fsa_selectedTransition))
+                                            self.fsa_currentState = self.fsa_selectedTransition.target
+                                            self.fsa_elapsed = 0
+                                            self.fsa_processEvent(self.fsa_currentEvent)
+                                            self.weaved_lib.dumpDiscreteEvent(self.weaved_model, self.fsa_logicalTime / 1000.0, self.fsa_currentState, self.fsa_selectedTransition)
+                                            self.weaved_lib.dumpGlobalState(self.weaved_model, self.weaved_global_state, self.fsa_logicalTime / 1000.0, self.fsa_currentState)
+                                            print('New state: ' + str(self.fsa_currentState))
+                                            print('Reading events:')
+                                            self.fsa_currentEvent = self.fsa_getInputEventAt(self.fsa_logicalTime / 1000.0)
+                                            self.fsa_selectedTransition = self.weaved_model.getTransitionFrom(self.fsa_currentState, self.fsa_currentEvent, self.fsa_elapsed /1000.0)
+                                            print(self.fsa_currentEvent)
+                                            print(self.fsa_selectedTransition)
+                                        ]]>
+                                    </script>
+                                </transition>
+                            </state>
+                            <state id="ParentMicroStepProcessed">
+                                <transition target="../MacroStepPrepared">
+                                    <script>
+                                        <![CDATA[
+                                            print('From ParentMicroStepProcessed to ParentPaused and resetting the child... ')
+                                            self.woven_child_initialized = False
+                                        ]]>
+                                    </script>
+                                </transition>
+                            </state>
+                        </state>
+                        <state id="Terminated" />
+                    </state>
+                    <state id="ParentStarted">
+                        <transition target="../FSA/Initialized">
+                            <script>
+                                <![CDATA[
+                                    print('From ParentStarted to FSA/Initialized... ')
+                                    self.weaved_initialize()
+                                ]]>
+                            </script>
+                        </transition>
+                    </state>
+                </state>
+                <transition target="../HybridTerminated" cond="INSTATE('./SimulationState/Stopped') and (INSTATE('./SimulationFlow/FSA/Terminated') or INSTATE('./SimulationFlow/FSA/DoSimulation/MicroStepProcessed/CBD/Terminated'))">
+                    <script>
+                        self.fsa_finalize()
+                    </script>
+                </transition>
+            </parallel>
+            <state id="HybridTerminated">
+            </state>
+        </scxml>
+    </class>
+</diagram>