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

Merge branch 'master' of claudio/19.09.15-20.MoDELS.Munich_tutorials_PhysicalSystemsForSoftwareModellers into master

claudio 6 éve
szülő
commit
5e00d6cec9
26 módosított fájl, 3634 hozzáadás és 3 törlés
  1. 2 0
      .gitignore
  2. 103 0
      materials/5-CBDModeling/CBDModelling.ipynb
  3. 46 0
      materials/DockerfileTutorials123567
  4. 21 0
      materials/DockerfileTutorials4
  5. 2 2
      materials/README.md
  6. 0 0
      materials/lib/CBDSimulatorInterpreter/cbd/__init__.py
  7. 114 0
      materials/lib/CBDSimulatorInterpreter/cbd/examples/SimulateTrainControlCBD.py
  8. 0 0
      materials/lib/CBDSimulatorInterpreter/cbd/examples/__init__.py
  9. 206 0
      materials/lib/CBDSimulatorInterpreter/cbd/examples/circlePlot.py
  10. 84 0
      materials/lib/CBDSimulatorInterpreter/cbd/models/EvenNumbersCBD.py
  11. 269 0
      materials/lib/CBDSimulatorInterpreter/cbd/models/TrainControlCBD.py
  12. 73 0
      materials/lib/CBDSimulatorInterpreter/cbd/models/TrainCostModelBlock.py
  13. 0 0
      materials/lib/CBDSimulatorInterpreter/cbd/models/__init__.py
  14. 149 0
      materials/lib/CBDSimulatorInterpreter/cbd/models/power_window.py
  15. 1182 0
      materials/lib/CBDSimulatorInterpreter/cbd/src/CBD.py
  16. 42 0
      materials/lib/CBDSimulatorInterpreter/cbd/src/CBDDraw.py
  17. 0 0
      materials/lib/CBDSimulatorInterpreter/cbd/src/__init__.py
  18. 129 0
      materials/lib/CBDSimulatorInterpreter/cbd/src/naivelog.py
  19. 49 0
      materials/lib/CBDSimulatorInterpreter/cbd/src/plot.py
  20. 44 0
      materials/lib/CBDSimulatorInterpreter/cbd/test/TestCounter.py
  21. 0 0
      materials/lib/CBDSimulatorInterpreter/cbd/test/__init__.py
  22. 551 0
      materials/lib/CBDSimulatorInterpreter/cbd/test/testBasicCBD.py
  23. 201 0
      materials/lib/CBDSimulatorInterpreter/cbd/test/testFlattenCBD.py
  24. 202 0
      materials/lib/CBDSimulatorInterpreter/cbd/test/testHierarchyCBD.py
  25. 164 0
      materials/lib/CBDSimulatorInterpreter/cbd/test/testSortedGraphCBD.py
  26. 1 1
      materials/notes.drawio

+ 2 - 0
.gitignore

@@ -2,3 +2,5 @@
 /*.aux
 /*.log
 /*.gz
+*.pyc
+/materials/lib/CBDSimulatorInterpreter/.idea

+ 103 - 0
materials/5-CBDModeling/CBDModelling.ipynb

@@ -0,0 +1,103 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "data": {
+      "image/svg+xml": [
+       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n",
+       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\r\n",
+       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\r\n",
+       "<!-- Generated by graphviz version 2.38.0 (20140413.2041)\r\n",
+       " -->\r\n",
+       "<!-- Title: %3 Pages: 1 -->\r\n",
+       "<svg width=\"269pt\" height=\"204pt\"\r\n",
+       " viewBox=\"0.00 0.00 268.98 204.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n",
+       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 200)\">\r\n",
+       "<title>%3</title>\r\n",
+       "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-200 264.984,-200 264.984,4 -4,4\"/>\r\n",
+       "<!-- A -->\r\n",
+       "<g id=\"node1\" class=\"node\"><title>A</title>\r\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"179.992\" cy=\"-178\" rx=\"53.8905\" ry=\"18\"/>\r\n",
+       "<text text-anchor=\"middle\" x=\"179.992\" y=\"-174.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">King Arthur</text>\r\n",
+       "</g>\r\n",
+       "<!-- B -->\r\n",
+       "<g id=\"node2\" class=\"node\"><title>B</title>\r\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"90.9919\" cy=\"-105\" rx=\"90.9839\" ry=\"18\"/>\r\n",
+       "<text text-anchor=\"middle\" x=\"90.9919\" y=\"-101.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">Sir Bedevere the Wise</text>\r\n",
+       "</g>\r\n",
+       "<!-- A&#45;&gt;B -->\r\n",
+       "<g id=\"edge1\" class=\"edge\"><title>A&#45;&gt;B</title>\r\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M160.24,-161.243C148.365,-151.77 133.043,-139.547 119.832,-129.007\"/>\r\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"121.929,-126.203 111.929,-122.702 117.563,-131.675 121.929,-126.203\"/>\r\n",
+       "</g>\r\n",
+       "<!-- L -->\r\n",
+       "<g id=\"node3\" class=\"node\"><title>L</title>\r\n",
+       "<ellipse fill=\"none\" stroke=\"black\" cx=\"169.992\" cy=\"-18\" rx=\"90.9839\" ry=\"18\"/>\r\n",
+       "<text text-anchor=\"middle\" x=\"169.992\" y=\"-14.3\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">Sir Lancelot the Brave</text>\r\n",
+       "</g>\r\n",
+       "<!-- A&#45;&gt;L -->\r\n",
+       "<g id=\"edge2\" class=\"edge\"><title>A&#45;&gt;L</title>\r\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M184.456,-159.626C186.927,-149.107 189.744,-135.375 190.992,-123 192.597,-107.081 193.379,-102.821 190.992,-87 188.889,-73.0645 184.491,-58.0477 180.261,-45.6797\"/>\r\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"183.461,-44.2348 176.801,-35.9954 176.869,-46.59 183.461,-44.2348\"/>\r\n",
+       "</g>\r\n",
+       "<!-- B&#45;&gt;L -->\r\n",
+       "<g id=\"edge3\" class=\"edge\"><title>B&#45;&gt;L</title>\r\n",
+       "<path fill=\"none\" stroke=\"black\" d=\"M106.6,-87.2067C118.286,-74.6335 134.44,-57.252 147.516,-43.1825\"/>\r\n",
+       "<polygon fill=\"black\" stroke=\"black\" points=\"150.172,-45.466 154.416,-35.7584 145.045,-40.7005 150.172,-45.466\"/>\r\n",
+       "<text text-anchor=\"middle\" x=\"148.992\" y=\"-57.8\" font-family=\"Times New Roman,serif\" font-size=\"14.00\">false</text>\r\n",
+       "</g>\r\n",
+       "</g>\r\n",
+       "</svg>\r\n"
+      ],
+      "text/plain": [
+       "<graphviz.dot.Digraph at 0x28d45fe8588>"
+      ]
+     },
+     "execution_count": 8,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "from graphviz import Digraph\n",
+    "\n",
+    "dot = Digraph(comment='The Round Table')\n",
+    "\n",
+    "dot.node('A', 'King Arthur', {'shape':''})\n",
+    "dot.node('B', 'Sir Bedevere the Wise')\n",
+    "dot.node('L', 'Sir Lancelot the Brave')\n",
+    "dot.edges(['AB', 'AL'])\n",
+    "dot.edge('B', 'L', 'false')\n",
+    "\n",
+    "dot"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.6.8"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}

+ 46 - 0
materials/DockerfileTutorials123567

@@ -0,0 +1,46 @@
+FROM jupyter/minimal-notebook:latest
+
+# Install simpy
+RUN /opt/conda/bin/conda install sympy
+
+# Install scipy
+RUN /opt/conda/bin/conda install scipy
+
+USER root
+
+# Install Julia 0.6
+RUN mkdir /opt/julia && \
+		cd /opt/julia && \
+		wget --quiet https://julialang-s3.julialang.org/bin/linux/x64/0.6/julia-0.6.4-linux-x86_64.tar.gz && \
+		tar -xzf julia-0.6.4-linux-x86_64.tar.gz --directory . --strip-components=1 && \
+		ln -s /opt/julia/bin/julia /usr/bin/julia && \
+		julia --version
+
+RUN mkdir /opt/bondgraphs
+
+COPY test_bondgraphs.py /opt/bondgraphs/
+
+# Install BondGraphTools and run test file (forces installation of dependencies)
+RUN apt-get update -y && \
+		apt-get install -y dvipng && \
+		pip install BondGraphTools && \
+		python3 /opt/bondgraphs/test_bondgraphs.py
+
+# Copy local files to the remote notebooks
+RUN mkdir /opt/notebooks
+
+COPY 1-NewtonsLaws /opt/notebooks/1-NewtonsLaws
+COPY 2-StationaryAction /opt/notebooks/2-StationaryAction
+COPY 3-BondGraphs /opt/notebooks/3-BondGraphs
+
+WORKDIR /opt/notebooks/
+
+# Port
+EXPOSE 8888
+
+# Run Jupyter Notebook
+CMD ["/opt/conda/bin/jupyter", "notebook", "--notebook-dir=/opt/notebooks", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--allow-root"]
+
+# Uncomment to access command line on the docker container
+CMD ["bash"]
+# to start jupyter run: /opt/conda/bin/jupyter notebook --notebook-dir=/opt/notebooks --ip=0.0.0.0 --port=8888 --no-browser --allow-root

+ 21 - 0
materials/DockerfileTutorials4

@@ -0,0 +1,21 @@
+FROM mechatronics3d/jjmodelica
+
+USER root
+
+# Copy local files to the remote notebooks
+RUN mkdir /opt/notebooks
+
+COPY 4-Modelica /opt/notebooks/4-Modelica
+
+WORKDIR /opt/notebooks/
+
+# Port
+EXPOSE 8888
+
+# Run Jupyter Notebook
+CMD ["jupyter", "notebook", "--notebook-dir=/opt/notebooks", "--ip=0.0.0.0", "--port=8888", "--no-browser"]
+
+# Uncomment to access command line on the docker container
+# CMD ["bash"]
+# to start jupyter run: 
+# jupyter notebook --notebook-dir=/opt/notebooks --ip=0.0.0.0 --port=8888 --no-browser --allow-root

+ 2 - 2
materials/README.md

@@ -10,12 +10,12 @@ This repository contains the materials that are used in the MoDELS tutorial of p
 
 3. Build the corresponding docker image: 
     ```
-    docker build -f DockerfileTutorials123 -t jupyter .
+    docker build -f DockerfileTutorials123567 -t jupyter .
     ```
 or 
 
     ```
-    docker build -f DockerfileTutorials45 -t jupyter .
+    docker build -f DockerfileTutorials4 -t jupyter .
     ```
 
 This will download all dependencies you need to run the examples. You might need root access.

+ 0 - 0
materials/lib/CBDSimulatorInterpreter/cbd/__init__.py


+ 114 - 0
materials/lib/CBDSimulatorInterpreter/cbd/examples/SimulateTrainControlCBD.py

@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+from bokeh.plotting import figure, output_file, show
+from cbd.models.TrainControlCBD import TrainControlCBD, TrainUncontrolledCBD
+from cbd.models.TrainCostModelBlock import StopSimulationException
+
+def simulateCBD(optimalKp, optimalKi, optimalKd):
+    cbd = TrainControlCBD("train_control", optimalKp, optimalKi, optimalKd)
+    #cbd = TrainUncontrolledCBD("train_control", optimalKp, optimalKi, optimalKd)
+    cbd.run(3500, 0.1)
+    
+    times = []
+    velocity = []
+    ideal_velocity = []
+    displacement_person = []
+    acceleration_train = []
+    costs = []
+    
+    for timeValuePair in cbd.getBlockByName("time").getSignal("OutTime"):
+        times.append(timeValuePair.value)
+    
+    for timeValuePair in cbd.getBlockByName("plant").getSignal("OutVTrain"):
+        velocity.append(timeValuePair.value)
+        
+    for timeValuePair in cbd.getBlockByName("computer").getSignal():
+        ideal_velocity.append(timeValuePair.value)
+    
+    for timeValuePair in cbd.getBlockByName("plant").getSignal("OutXPerson"):
+        displacement_person.append(timeValuePair.value)
+    
+    for timeValuePair in cbd.getBlockByName("plant").getSignal("OutATrain"):
+        acceleration_train.append(timeValuePair.value)
+    
+    for timeValuePair in cbd.getBlockByName("cost").getSignal("OutCost"):
+        costs.append(timeValuePair.value)
+    
+    #Plot
+    output_file("./train_velocity.html", title="Ideal and real velocity of the train")
+    p = figure(title="Ideal and real velocity of the train ("+str(optimalKp)+", "+str(optimalKi)+", "+str(optimalKd)+")", x_axis_label='t', y_axis_label='m/s')
+    p.line(times, ideal_velocity, legend="ideal velocity", line_width=2, line_color="red")
+    p.line(times, velocity, legend="velocity", line_width=2, line_color="blue")
+    show(p)
+    
+    output_file("./train_ideal_velocity.html", title="Ideal velocity of the train")
+    p = figure(title="Ideal velocity of the train", x_axis_label='t', y_axis_label='m/s')
+    p.line(times, ideal_velocity, legend="ideal velocity", line_width=2, line_color="red")
+    show(p)
+    
+    
+    #Plot
+    output_file("./people_displacement.html", title="People displacement and train acceleration")
+    p = figure(title="People displacement and train acceleration ("+str(optimalKp)+", "+str(optimalKi)+", "+str(optimalKd)+")", x_axis_label='t', y_axis_label='')
+    p.line(times, displacement_person, legend="People displacement (m)", line_width=2, line_color="red")
+    p.line(times, acceleration_train, legend="Train acceleration (m/s^2)", line_width=2, line_color="blue")
+    show(p)
+    
+    output_file("./costs.html", title="Costs")
+    p = figure(title="Costs ("+str(optimalKp)+", "+str(optimalKi)+", "+str(optimalKd)+")", x_axis_label='t', y_axis_label='')
+    p.line(times, costs, legend="Cost", line_width=2, line_color="red")
+    show(p)
+    
+    return cbd
+
+'''
+cbd = TrainControlCBD("train_control")
+draw(cbd, "train_control.dot")
+draw(cbd.getBlockByName("time"), "fixed_time_cbd.dot")
+draw(cbd.getBlockByName("controller"), "controller.dot")
+draw(cbd.getBlockByName("plant"), "plant.dot")
+draw(cbd.getBlockByName("plant").getBlockByName("accelerationPerson"), "accelerationPerson.dot")
+draw(cbd.getBlockByName("plant").getBlockByName("accelerationTrain"), "accelerationTrain.dot")
+'''
+
+'''
+Optimal parameters list
+Kp            Ki            Kd
+570           100            190
+490           147            183
+
+'''
+
+optimalKp = 570.0
+optimalKps = []
+
+optimalKi = 100.0
+optimalKis = []
+
+optimalKd = 190.0
+optimalKds = []
+
+cost = float("inf")
+costs = []
+for i in range(1):
+    newOptimalKp = input("Kp: ")
+    newOptimalKi = input("Ki: ")
+    newOptimalKd = input("Kd: ")
+    try:
+        cbd = simulateCBD(newOptimalKp, newOptimalKi, newOptimalKd)
+        
+        # commit new parameters
+        optimalKp = newOptimalKp
+        optimalKps.append(optimalKp)
+        
+        optimalKi = newOptimalKi
+        optimalKis.append(optimalKi)
+        
+        optimalKd = newOptimalKd
+        optimalKds.append(optimalKd)
+        
+        costs.append(cbd.getBlockByName("cost").getSignal("OutCost")[-1].value)
+        print("cost: " + str(costs[-1]))
+    except StopSimulationException:
+        print("StopSimulationException")
+
+

+ 0 - 0
materials/lib/CBDSimulatorInterpreter/cbd/examples/__init__.py


+ 206 - 0
materials/lib/CBDSimulatorInterpreter/cbd/examples/circlePlot.py

@@ -0,0 +1,206 @@
+#!/usr/bin/env python
+from bokeh.plotting import figure, output_file, show
+from cbd.src.CBD import *
+import math
+        
+class CircleCBDIntegrator(CBD):
+    def __init__(self, delta_t):
+        CBD.__init__(self,"HarmonicOscilatorIntegrator", [], [])
+        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(IntegratorBlock(block_name="intx"))
+        self.addBlock(IntegratorBlock(block_name="intv"))
+        
+        self.addConnection("delta", "intx",  input_port_name="delta_t")
+        self.addConnection("delta", "intv",  input_port_name="delta_t")
+        self.addConnection("zero", "intx",  input_port_name="IC")
+        self.addConnection("one", "intv",  input_port_name="IC")
+        self.addConnection("intx", "neg")
+        self.addConnection("neg", "intv")
+        self.addConnection("intv", "intx")
+        
+        # error measurement blocks
+        self.addBlock(IntegratorBlock(block_name="inte"))
+        self.addBlock(NegatorBlock(block_name="negX"))
+        self.addBlock(AdderBlock(block_name="addNeg"))
+        self.addBlock(ABSBlock(block_name="absError"))
+        self.addBlock(SinBlock(block_name="sin"))
+        self.addConnection("zero", "inte",  input_port_name="IC")
+        self.addConnection("delta", "inte",  input_port_name="delta_t")
+        self.addConnection("intx", "negX")
+        self.addConnection("negX", "addNeg")
+        self.addConnection("sin", "addNeg")
+        self.addConnection("addNeg", "absError")
+        self.addConnection("absError", "inte", input_port_name="IN1")
+        
+
+
+class SinBlock(BaseBlock):
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, [], ["OUT1"])
+
+    def compute(self, curIteration):
+        self.appendToSignal(math.sin(self.getClock().getTime()))
+        
+     
+
+class CircleCBDDerivative(CBD):
+    def __init__(self, delta_t):
+        CBD.__init__(self,"HarmonicOscilatorDerivative", [], [])
+        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")
+        
+        # error measuring blocks 
+        self.addBlock(IntegratorBlock(block_name="inte"))
+        self.addBlock(NegatorBlock(block_name="negX"))
+        self.addBlock(AdderBlock(block_name="addNeg"))
+        self.addBlock(ABSBlock(block_name="absError"))
+        self.addBlock(SinBlock(block_name="sin"))
+        self.addConnection("zero", "inte",  input_port_name="IC")
+        self.addConnection("delta", "inte",  input_port_name="delta_t")
+        self.addConnection("neg", "negX")
+        self.addConnection("negX", "addNeg")
+        self.addConnection("sin", "addNeg")
+        self.addConnection("addNeg", "absError")
+        self.addConnection("absError", "inte", input_port_name="IN1")
+
+
+def plotTime(cbd, blockToInspect, fileName, title, label):
+    
+    times = []
+    values = []
+    
+    for timeValuePair in cbd.getBlockByName(blockToInspect).getSignal():
+        times.append(timeValuePair.time)
+        values.append(timeValuePair.value)
+    
+    #Output solution and numerical approximation
+    output_file("./"+fileName+".html", title=title)
+    p = figure(title=title, x_axis_label='time', y_axis_label=label)
+    p.line(times, values, legend=label, line_width=1, line_color="red")
+    
+    show(p)
+
+def plotError(cbd, fileName, title):
+    
+    times = []
+    values = []
+    
+    for timeValuePair in cbd.getBlockByName("inte").getSignal():
+        times.append(timeValuePair.time)
+        values.append(timeValuePair.value)
+    
+    #Output solution and numerical approximation
+    output_file("./"+fileName+".html", title=title)
+    p = figure(title=title, x_axis_label='time', y_axis_label="error")
+    p.line(times, values, legend="error", line_width=1, line_color="red")
+    show(p)
+
+def plotParametric(cbd, blockToInspectHorAxis, blockToInspectVerAxis, fileName, title, horLabel, verLabel):
+    
+    times = []
+    values = []
+    
+    for timeValuePair in cbd.getBlockByName(blockToInspectHorAxis).getSignal():
+        times.append(timeValuePair.value)
+    
+    for timeValuePair in cbd.getBlockByName(blockToInspectVerAxis).getSignal():
+        values.append(timeValuePair.value)
+    
+    #Output solution and numerical approximation
+    output_file("./"+fileName+".html", title=title)
+    p = figure(title=title, x_axis_label=horLabel, y_axis_label=verLabel)
+    p.line(times, values, legend=horLabel + " vs " + verLabel, line_width=1, line_color="red")
+    show(p)
+
+def getErrorSin(cbd, blockThatGivesSin):
+    error = 0.0
+    fullSignal = cbd.getBlockByName(blockThatGivesSin).getSignal()
+    for timeValuePair in fullSignal:
+        error += abs(timeValuePair.value - math.sin(timeValuePair.time))
+    return error/len(fullSignal)
+
+NUM_STEPS = 100
+
+delta = 0.1
+cbdInt = CircleCBDIntegrator(delta)
+cbdInt.run(int(NUM_STEPS/delta), delta_t = delta)    
+
+times = []
+values = []
+valuesSin = []
+
+for timeValuePair in cbdInt.getBlockByName("intx").getSignal():
+    times.append(timeValuePair.time)
+    values.append(timeValuePair.value)
+    valuesSin.append(math.sin(timeValuePair.time))
+
+#Output solution and numerical approximation
+output_file("./plots.html", title="title")
+p = figure(title="", x_axis_label='time', y_axis_label="asas")
+p.line(times, values, legend="asas", line_width=1, line_color="red")
+p.line(times, valuesSin, legend="eeeee", line_width=1, line_color="blue")
+show(p)
+
+'''
+#General plotting
+for delta in [0.1, 0.01 , 0.001, 0.0001]:
+    cbdInt = CircleCBDIntegrator(delta)
+    cbdInt.run(int(NUM_STEPS/delta), delta_t = delta)
+    plotTime(cbdInt, "intx", "circle_integrator_delta"+str(delta), "Harmonic Oscillator with integrators and delta " + str(delta), "position (x)")
+    plotParametric(cbdInt, "intx", "intv", "circle_integrator_parametric_delta"+str(delta), "Circle with integrators and delta " + str(delta), "x", "y")
+    plotError(cbdInt, "circle_integrator_delta"+str(delta)+"_error", "Error of Harmonic Oscillator with integrators and delta " + str(delta))
+    
+    cbdDer = CircleCBDDerivative(delta)
+    cbdDer.run(int(NUM_STEPS/delta), delta_t = delta)
+    plotTime(cbdDer, "neg", "circle_derivative_delta"+str(delta), "Harmonic Oscillator with derivatives and delta " + str(delta), "position (x)")
+    plotParametric(cbdDer, "neg", "derxv", "circle_derivative_parametric_delta"+str(delta), "Circle test with derivatives and delta " + str(delta), "x", "y")
+    plotError(cbdDer, "circle_derivative_delta"+str(delta)+"_error", "Error of Harmonic Oscillator with derivatives and delta " + str(delta))
+'''
+
+'''
+# Error plotting
+MAX_TIME_ERROR = 10
+errorValuesInt = []
+errorValuesDer = []
+#deltas = map((lambda x: 10 ** (-x)),range(5))
+deltas = map((lambda x: (x+1)/10000.0),range(10000))
+for delta in deltas:
+    cbdInt = CircleCBDIntegrator(delta)
+    cbdInt.run(int(MAX_TIME_ERROR/delta), delta_t = delta)
+    errorValuesInt.append(getErrorSin(cbdInt, "intx"))
+    
+    cbdDer = CircleCBDDerivative(delta)
+    cbdDer.run(int(MAX_TIME_ERROR/delta), delta_t = delta)
+    errorValuesDer.append(getErrorSin(cbdDer, "neg"))
+
+
+output_file("./error_vs_delta.html", title="Error vs Step Size")
+p = figure(title="Error vs Step Size", x_axis_label="Step size", y_axis_label="Error")
+p.line(deltas, errorValuesInt, legend="Integrator", line_width=1, line_color="red")
+p.line(deltas, errorValuesDer, legend="Derivative", line_width=1, line_color="blue")
+show(p)
+'''
+
+
+
+
+
+
+

+ 84 - 0
materials/lib/CBDSimulatorInterpreter/cbd/models/EvenNumbersCBD.py

@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+from bokeh.plotting import figure, output_file, show
+from cbd.src.CBD import *
+from cbd.src.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")
+        
+
+
+
+cbd = EvenNumberGen("number_gen")
+
+# Get cbd dot and render them.
+cbdDot = draw(cbd)
+counterDot = draw(cbd.getBlockByName("counter"))
+cbdDot.render('evenCBD.pdf')
+counterDot.render('counterCBD')
+
+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)
+
+
+
+

+ 269 - 0
materials/lib/CBDSimulatorInterpreter/cbd/models/TrainControlCBD.py

@@ -0,0 +1,269 @@
+#!/usr/bin/env python
+from cbd.src.CBD import *
+from TrainCostModelBlock import CostFunctionBlock
+
+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(CostFunctionBlock(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("plant", "cost", 
+                            input_port_name="InVTrain", output_port_name="OutVTrain")
+        self.addConnection("time", "cost", 
+                            input_port_name="InDelta", output_port_name="OutDelta")
+        self.addConnection("plant", "cost", 
+                            input_port_name="InXPerson", output_port_name="OutXPerson")
+        self.addConnection("computer", "cost", 
+                            input_port_name="InVi", output_port_name="OUT1")       
+
+
+class TrainUncontrolledCBD(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(ConstantBlock(block_name="gainConstant", value=MASS_TRAIN))
+        self.addBlock(ProductBlock(block_name="gainAmp"))
+        self.addBlock(TrainPerson(block_name="plant"))
+        
+        # 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("computer", "gainAmp")
+        self.addConnection("gainConstant", "gainAmp")
+        self.addConnection("gainAmp", "plant", 
+                            input_port_name="InTraction")
+        
+
+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 < 10:
+            result = 0
+        elif currentTime < 160:
+            result = 10
+        elif currentTime < 200:
+            result = 4
+        elif currentTime < 260:
+            result = 14
+        else:
+            result = 6
+        
+        self.appendToSignal(result)
+
+
+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")
+
+
+
+
+
+
+
+
+

+ 73 - 0
materials/lib/CBDSimulatorInterpreter/cbd/models/TrainCostModelBlock.py

@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+from cbd.src.CBD import *
+
+class CostFunctionBlock(BaseBlock):        
+    def __init__(self, block_name):
+        BaseBlock.__init__(self, block_name, ["InVi","InVTrain","InDelta","InXPerson"], ["OutCost"])
+        self.viChanged = False
+        self.timeInWhichViChanged = 0.0
+        self.cummulativeCost = 0.0
+        
+    def compute(self, curIteration):
+        displacement_person = self.getInputSignal(curIteration, "InXPerson").value
+        velocity_train = self.getInputSignal(curIteration, "InVTrain").value
+        
+        if abs(displacement_person) > 0.4 or velocity_train<0.0:
+            raise StopSimulationException()
+        
+        currentVi = self.getInputSignal(curIteration, "InVi").value
+        currentTime = self.getClock().getTime()
+        lastVi = self.getInputSignal(curIteration-1, "InVi").value
+        if lastVi != currentVi:
+            self.viChanged = True
+            self.timeInWhichViChanged = currentTime
+            self.attainedVelocity = False
+        else:
+            self.viChanged = False
+        
+        lastVTrain = self.getInputSignal(curIteration-1, "InVTrain").value
+        currentVTrain = self.getInputSignal(curIteration, "InVTrain").value
+        if ((lastVTrain-currentVi)*(currentVTrain-currentVi) <= 0):
+            self.attainedVelocity = True;
+        
+        if (not self.attainedVelocity):
+            instantCostTime = currentTime - self.timeInWhichViChanged
+            assert instantCostTime >= 0
+            delta_t = self.getInputSignal(curIteration, "InDelta").value
+            self.cummulativeCost = self.cummulativeCost + instantCostTime*delta_t
+        
+        self.appendToSignal(self.cummulativeCost, name_output="OutCost")
+
+
+
+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
+        
+
+
+
+
+
+
+
+

+ 0 - 0
materials/lib/CBDSimulatorInterpreter/cbd/models/__init__.py


+ 149 - 0
materials/lib/CBDSimulatorInterpreter/cbd/models/power_window.py

@@ -0,0 +1,149 @@
+from bokeh.plotting import output_file, figure, show
+
+from cbd.src.CBD import ConstantBlock, NegatorBlock, \
+    IntegratorBlock, CBD, ProductBlock, AdderBlock, InverterBlock, DecisionBlock
+from cbd.src.CBDDraw import draw
+
+
+DELTA = 0.01
+
+class PowerWindowUp(CBD):
+    def __init__(self, blockName, delta_t = DELTA):
+        CBD.__init__(self,blockName, input_ports=[], output_ports=["out_w0","out_v0", "out_Fo100","out_Fo","out_acceleration","out_acceleration_w"])
+        
+        self.addBlock(ConstantBlock("delta_t", value=delta_t))
+        self.addBlock(ConstantBlock("torque", value=2.0))
+        self.addBlock(ConstantBlock("1", value=1.0))
+        self.addBlock(ConstantBlock("0.4", value=0.4))
+        self.addBlock(ConstantBlock("force_threshold", value=-100))
+        
+        self.addBlock(ConstantBlock("in_w0", value=0.0))
+        self.addBlock(ConstantBlock("in_v0", value=0.0))
+        
+        self.addBlock(AdderBlock("compare_force"))
+        
+        self.addBlock(PowerWindowPlant("plant"))
+        
+        self.addConnection("delta_t", "plant", input_port_name="delta_t")
+        self.addConnection("torque", "plant", input_port_name="motor")
+        self.addConnection("1", "plant", input_port_name="object_detect")
+        self.addConnection("0.4", "plant", input_port_name="object_position")
+        self.addConnection("force_threshold", "compare_force")
+        
+        self.addConnection("in_w0", "plant", input_port_name="init_position")
+        self.addConnection("in_v0", "plant", input_port_name="init_velocity")
+        
+        self.addConnection("compare_force", "out_Fo100")
+        
+        self.addConnection("plant", "out_w0", output_port_name="position_out")
+        self.addConnection("plant", "out_v0", output_port_name="velocity_out")
+        self.addConnection("plant", "compare_force", output_port_name="force_out")
+        self.addConnection("plant", "out_Fo", output_port_name="force_out")
+        self.addConnection("plant", "out_acceleration", output_port_name="acceleration_out")
+        self.addConnection("plant", "out_acceleration_w", output_port_name="acceleration_w_out")
+        
+        
+class PowerWindowPlant(CBD):
+    def __init__(self, blockName, delta_t = 0.01):
+        CBD.__init__(self,blockName, input_ports=[
+                                    "object_detect",
+                                    "object_position",
+                                    "motor", 
+                                    "init_position",
+                                    "init_velocity",
+                                    "delta_t"
+                        ], output_ports=["position_out","velocity_out","force_out","acceleration_out","acceleration_w_out"])
+        
+        # See power_window_object.pdf
+        
+        self.addBlock(ConstantBlock("m", value=10.0))
+        self.addBlock(ConstantBlock("cw",value=-10.0))
+        self.addBlock(ConstantBlock("zero",value=0.0))
+        self.addBlock(ConstantBlock("k0",value=1000.0))
+        self.addBlock(ConstantBlock("c0",value=-1000.0))
+        
+        self.addBlock(InverterBlock("invert_mass"))
+        
+        self.addBlock(NegatorBlock("position_object_neg"))
+        
+        self.addBlock(ProductBlock("cw_p"))
+        self.addBlock(ProductBlock("divide_m"))
+        self.addBlock(ProductBlock("c0_p"))
+        self.addBlock(ProductBlock("k0_p"))
+        self.addBlock(ProductBlock("object_detect_enable"))
+        
+        self.addBlock(AdderBlock("torque_friction"))
+        self.addBlock(AdderBlock("total_forces"))
+        self.addBlock(AdderBlock("object_compare"))
+        self.addBlock(AdderBlock("object_compression"))
+        self.addBlock(AdderBlock("object_displacement"))
+        
+        self.addBlock(IntegratorBlock("velocity"))
+        self.addBlock(IntegratorBlock("position"))
+        
+        self.addBlock(DecisionBlock("obj_detected"))
+        
+        self.addConnection("object_detect", "object_detect_enable")
+        self.addConnection("object_position", "position_object_neg")
+        self.addConnection("motor", "torque_friction")
+        self.addConnection("init_position", "position", input_port_name="IC")
+        self.addConnection("init_velocity", "velocity", input_port_name="IC")
+        self.addConnection("delta_t", "position", input_port_name="delta_t")
+        self.addConnection("delta_t", "velocity", input_port_name="delta_t")
+        
+        self.addConnection("m", "invert_mass")
+        self.addConnection("zero", "obj_detected", input_port_name="F")
+        
+        self.addConnection("invert_mass", "divide_m")
+        
+        self.addConnection("cw", "cw_p")
+        self.addConnection("k0", "k0_p")
+        self.addConnection("c0", "c0_p")
+        self.addConnection("position_object_neg", "object_compare")
+        self.addConnection("position_object_neg", "object_displacement")
+        
+        
+        self.addConnection("cw_p", "torque_friction")
+        self.addConnection("divide_m", "velocity")
+        self.addConnection("c0_p", "object_compression")
+        self.addConnection("k0_p", "object_compression")
+        self.addConnection("object_detect_enable", "total_forces")
+        self.addConnection("object_detect_enable", "force_out")
+        
+        self.addConnection("torque_friction", "total_forces")
+        self.addConnection("torque_friction", "acceleration_w_out")
+        self.addConnection("total_forces", "divide_m")
+        self.addConnection("total_forces", "acceleration_out")
+        self.addConnection("object_compare", "obj_detected", input_port_name="C")
+        self.addConnection("object_compression", "obj_detected", input_port_name="T")
+        self.addConnection("object_displacement", "k0_p")
+        
+        self.addConnection("velocity", "position")
+        self.addConnection("velocity", "cw_p")
+        self.addConnection("velocity", "c0_p")
+        self.addConnection("velocity", "velocity_out")
+        self.addConnection("position", "object_displacement")
+        self.addConnection("position", "position_out")
+        self.addConnection("position", "object_compare")
+        
+        self.addConnection("obj_detected", "object_detect_enable")
+        
+
+cbd = PowerWindowUp("powerwindow")
+plantDot = draw(cbd.getBlockByName("plant"))
+plantDot.render('plant.pdf')
+
+cbd.run(int(6.0 / DELTA))
+
+times = []
+output = []
+
+for timeValuePair in cbd.getSignal("out_w0"):
+    times.append(timeValuePair.time)
+    output.append(timeValuePair.value)
+            
+#Plot
+output_file("./results.html", title="Even Numbers")
+p = figure(title="Plot", x_axis_label='time', y_axis_label='N')
+p.circle(x=times, y=output, legend="out_w0")
+show(p)

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1182 - 0
materials/lib/CBDSimulatorInterpreter/cbd/src/CBD.py


+ 42 - 0
materials/lib/CBDSimulatorInterpreter/cbd/src/CBDDraw.py

@@ -0,0 +1,42 @@
+from graphviz import Digraph
+
+from cbd.src.CBD import ConstantBlock, CBD
+
+
+def draw(cbd):
+	'''
+	Output CBD as a dot digraph
+
+	:param cbd: the model
+	:return: a dot digraph
+	'''
+
+	dot = Digraph(comment='The model')
+
+	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="Msquare"
+
+		dot.node(block.getBlockName(), label, {'shape': shape})
+
+
+	for block in cbd.getBlocks():
+		writeBlock(block)
+		for (name, other) in  block.getLinksIn().items():
+			label = ""
+
+			if not name.startswith("IN"):
+				label = name
+
+			if not other.output_port.startswith("OUT"):
+				label = label + " / " + other.output_port
+
+			dot.edge(other.block.getBlockName(), block.getBlockName(), label)
+
+	return dot

+ 0 - 0
materials/lib/CBDSimulatorInterpreter/cbd/src/__init__.py


+ 129 - 0
materials/lib/CBDSimulatorInterpreter/cbd/src/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
materials/lib/CBDSimulatorInterpreter/cbd/src/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()

+ 44 - 0
materials/lib/CBDSimulatorInterpreter/cbd/test/TestCounter.py

@@ -0,0 +1,44 @@
+from cbd.test.testBasicCBD import BasicCBDTestCase
+
+import unittest
+from cbd.src.CBD import *
+
+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)
+        self.assertEqual(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
materials/lib/CBDSimulatorInterpreter/cbd/test/__init__.py


+ 551 - 0
materials/lib/CBDSimulatorInterpreter/cbd/test/testBasicCBD.py

@@ -0,0 +1,551 @@
+#!/usr/bin/env python
+#
+# Unit tests for all the basic CBD blocks, discrete-time CBD. 
+
+import unittest
+
+from cbd.src.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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(self._getSignal("i1"), [0.2] * NUM_DISCR_TIME_STEPS)
+    self.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(self._getSignal("prev"), [5, 2, 12, 22, 23, 32, 11])
+          
+  def testTimeBlock(self):
+    self.CBD.addBlock(TimeBlock(block_name="t"))
+    self._run(4)
+    self.assertEqual(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.assertEqual(self._getSignal("lt1"), [0.0])
+    self.assertEqual(self._getSignal("lt2"), [0.0])
+    self.assertEqual(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.assertEqual(self._getSignal("eq1"), [1.0])
+    self.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(self._getSignal("OrBlock1"), [0])
+    self.assertEqual(self._getSignal("OrBlock2"), [1])
+    self.assertEqual(self._getSignal("OrBlock3"), [1])
+    self.assertEqual(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.assertEqual(self._getSignal("AndBlock1"), [0])
+    self.assertEqual(self._getSignal("AndBlock2"), [0])
+    self.assertEqual(self._getSignal("AndBlock3"), [1])
+    self.assertEqual(self._getSignal("AndBlock4"), [0])
+    self.assertEqual(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.assertEqual(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.assertEqual(self._getSignal("a1"), [-5.5]*5)
+    self.assertEqual(self._getSignal("a2"), [5.0]*5)
+    self.assertEqual(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.assertEqual(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.assertEqual(self._getSignal("a"), [-0.75]*5)
+    self.assertEqual(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.assertEqual(self._getSignal("a1"), [6.5]*5)
+    self.assertEqual(self._getSignal("a2"), [1.5]*5)
+    self.assertEqual(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.assertEqual(self._getSignal("a1"), [-2.0]*5)
+    self.assertEqual(self._getSignal("a2"), [-3.0]*5)
+    self.assertEqual(self._getSignal("a3"), [-5.0]*5)
+    self.assertEqual(self._getSignal("a4"), [4.25]*5)
+    self.assertEqual(self._getSignal("a5"), [-3.25]*5)
+    self.assertEqual(self._getSignal("p"), [-7.5]*5)
+    self.assertEqual(self._getSignal("n1"), [7.5]*5)
+    self.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(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
materials/lib/CBDSimulatorInterpreter/cbd/test/testFlattenCBD.py

@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+#
+# Unit tests for the flatten function on the CBD
+
+import unittest
+from cbd.src.CBD import *
+from cbd.test.testBasicCBD 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.assertEqual(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.assertEqual(self._getSignal("adderCBD.outAdd"), [-0.75]*5)
+		self.assertEqual(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.assertEqual(self._getSignal("adder1CBD.outAdd1"), [6.5]*5)
+		self.assertEqual(self._getSignal("adder2CBD.outAdd2"), [1.5]*5)
+		self.assertEqual(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.assertEqual(self._getSignal("first_child.p"), [14.0]*5)
+		self.assertEqual(self._getSignal("first_child.first_child_of_first_child.n"), [-14.0]*5)
+		self.assertEqual(self._getSignal("first_child.in1CBD1"), [2.0]*5)
+		self.assertEqual(self._getSignal("first_child.a"), [-12.0]*5)
+		self.assertEqual(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()
+
+	
+	
+	
+	
+	
+	
+	
+	

+ 202 - 0
materials/lib/CBDSimulatorInterpreter/cbd/test/testHierarchyCBD.py

@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+#
+# Unit tests for the hierarchy functionality of the CBD
+
+import unittest
+from cbd.src.CBD import *
+from cbd.test.testBasicCBD 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.assertEqual(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.assertEqual(self._getSignal("adderCBD", output_port = "outAdd"), [-0.75]*5)
+		self.assertEqual(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.assertEqual(self._getSignal("adder1CBD", output_port = "outAdd1"), [6.5]*5)
+		self.assertEqual(self._getSignal("adder2CBD", output_port = "outAdd2"), [1.5]*5)
+		self.assertEqual(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.assertEqual(self._getSignal("first_child", output_port = "p"), [14.0]*5)
+		self.assertEqual(self._getSignal("first_child", output_port = "in1CBD1"), [2.0]*5)
+		self.assertEqual(self._getSignal("first_child", output_port = "a"), [-12.0]*5)
+		self.assertEqual(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()
+
+	
+	
+	
+	
+	
+	
+	
+	

+ 164 - 0
materials/lib/CBDSimulatorInterpreter/cbd/test/testSortedGraphCBD.py

@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+#
+# Unit tests for the sorting of a CBD.
+
+import unittest
+from cbd.src.CBD import *
+from cbd.test.testBasicCBD 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.assertEqual(len(sortedGraph), 5)
+		self.assertEqual(sortedGraph[0][0], const)
+		self.assertEqual(sortedGraph[2][0], negCbd)
+		self.assertEqual(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.assertEqual(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.assertEqual(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.assertEqual(len(sortedGraph), 5)
+		self.assertEqual(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.assertEqual(len(sortedGraph), 5)
+		self.assertEqual(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()

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 1
materials/notes.drawio