Browse Source

merge and split holons

DESKTOP-L7IQHES\Jonas 2 years ago
parent
commit
20dac307a0
31 changed files with 1040 additions and 190 deletions
  1. BIN
      exampleNetworks/MyExamples/example01.holon
  2. BIN
      exampleNetworks/MyExamples/t2.holon
  3. BIN
      exampleNetworks/MyExamples/t21.holon
  4. 36 0
      src/classes/AbstractCanvasObject.java
  5. 279 21
      src/classes/Holon.java
  6. 56 0
      src/classes/HolonSwitch.java
  7. 12 10
      src/classes/holonControlUnit/CommunicationModule.java
  8. 77 21
      src/classes/holonControlUnit/HierarchyControlUnit.java
  9. 2 10
      src/classes/holonControlUnit/HolonControlUnit.java
  10. 19 0
      src/classes/holonControlUnit/OptimizationManager.java
  11. 94 0
      src/classes/holonControlUnit/StateEstimator.java
  12. 6 0
      src/classes/holonControlUnit/TargetStateAssembler.java
  13. 6 4
      src/classes/holonControlUnit/messages/Message.java
  14. 21 0
      src/classes/holonControlUnit/messages/StateMsg.java
  15. 21 0
      src/classes/holonControlUnit/messages/StateRequestMsg.java
  16. 7 8
      src/ui/controller/CanvasController.java
  17. 4 0
      src/ui/controller/Control.java
  18. 3 2
      src/ui/controller/LoadController.java
  19. 46 45
      src/ui/controller/SimulationManager.java
  20. 1 1
      src/ui/model/DecoratedCable.java
  21. 10 2
      src/ui/model/IntermediateCableWithState.java
  22. 18 1
      src/ui/model/MinimumModel.java
  23. 182 0
      src/ui/model/Model.java
  24. 22 1
      src/ui/view/GUI.java
  25. 4 0
      src/ui/view/MyCanvas.java
  26. 72 46
      src/ui/view/holarchy/HolarchyPanel.java
  27. 2 2
      src/ui/view/holarchy/HolarchyTreePanel.java
  28. 9 0
      src/ui/view/holarchy/HolarchyWindow.java
  29. 20 9
      src/ui/view/holarchy/HolonInfoPanel.java
  30. 6 7
      src/ui/view/outliner/HolonView.java
  31. 5 0
      src/ui/view/outliner/Outliner.java

BIN
exampleNetworks/MyExamples/example01.holon


BIN
exampleNetworks/MyExamples/t2.holon


BIN
exampleNetworks/MyExamples/t21.holon


+ 36 - 0
src/classes/AbstractCanvasObject.java

@@ -174,6 +174,22 @@ public abstract class AbstractCanvasObject {
 	public ArrayList<Edge> getConnectedTo() {
 		return connections;
 	}
+	
+	public ArrayList<AbstractCanvasObject> getConnectedObjects(){
+		ArrayList<AbstractCanvasObject> connected = new ArrayList<AbstractCanvasObject>();
+		
+		for(Edge e : this.connections) {
+			AbstractCanvasObject a = e.getA();
+			AbstractCanvasObject b = e.getB();
+			if(a.equals(this)) {
+				connected.add(b);
+			} else {
+				connected.add(a);
+			}
+		}
+		
+		return connected;
+	}
 
 	/**
 	 * Add a new connection to the selected Object.
@@ -182,8 +198,28 @@ public abstract class AbstractCanvasObject {
 	 *            Edge
 	 */
 	public void addConnection(Edge toConnect) {
+		AbstractCanvasObject a = toConnect.getA();
+		AbstractCanvasObject b = toConnect.getB();
+		if(a instanceof HolonObject && ((HolonObject)a).holon != null) {
+			((HolonObject) a).holon.holonControlUnit.getHierarchyController().addEdgeTo(b);
+		}
+		if(b instanceof HolonObject && ((HolonObject)b).holon != null) {
+			((HolonObject) b).holon.holonControlUnit.getHierarchyController().addEdgeTo(a);
+		}
 		connections.add(toConnect);
 	}
+	
+	public void removeConnection(Edge edge) {
+		AbstractCanvasObject a = edge.getA();
+		AbstractCanvasObject b = edge.getB();
+		if(a instanceof HolonObject) {
+			((HolonObject) a).holon.holonControlUnit.getHierarchyController().removeEdgeTo(b);
+		}
+		if(b instanceof HolonObject) {
+			((HolonObject) b).holon.holonControlUnit.getHierarchyController().removeEdgeTo(a);
+		}
+		connections.remove(edge);
+	}
 
 	/**
 	 * Set the position of the Object in the canvas.

+ 279 - 21
src/classes/Holon.java

@@ -9,6 +9,8 @@ import java.util.UUID;
 import classes.holonControlUnit.HolonControlUnit;
 import ui.controller.Control;
 import ui.model.DecoratedNetwork;
+import ui.model.IntermediateCableWithState;
+import ui.model.MinimumModel;
 import ui.model.Model;
 
 public class Holon {
@@ -22,22 +24,27 @@ public class Holon {
 	public HolonControlUnit holonControlUnit;
 	private String uniqueID;
 	public Model model;
+	private MinimumModel minModel;
+	/** stores whether the part between this holon and the child is occupied by the superholon */
+	private boolean canRunIndependentFromParent;
 	
 	public Holon(String name, Model model) {
 		this.name = name;
+		this.parent = parent;
 		this.holonObject = null;
 		isPhysical = false;
-		this.holonControlUnit = new HolonControlUnit(this);
 		this.uniqueID = UUID.randomUUID().toString();
 		this.model = model;
-//		System.out.println("Created new Holon "+name+"   "+this.uniqueID);
+		this.holonControlUnit = new HolonControlUnit(this);
+		this.minModel = new MinimumModel(new ArrayList<AbstractCanvasObject>(), new ArrayList<Edge>());
+		this.canRunIndependentFromParent = true;
 	}
 	
 	public Holon(HolonObject object, Model model) {
 		holonObject = object;
 		object.holon = this;
+		this.parent = parent;
 		name = object.getName();
-		this.holonControlUnit = new HolonControlUnit(this);
 		elements.addAll(object.getElements());
 		for(HolonElement ele : elements) {
 			ele.holon = this;
@@ -45,7 +52,11 @@ public class Holon {
 		isPhysical = true;
 		this.uniqueID = UUID.randomUUID().toString();
 		this.model = model;
-//		System.out.println("Created new Holon "+name+"   "+this.uniqueID);
+		this.holonControlUnit = new HolonControlUnit(this);
+		ArrayList<AbstractCanvasObject> list = new ArrayList<AbstractCanvasObject>();
+		list.add(object);
+		this.minModel = new MinimumModel(list, new ArrayList<Edge>());
+		this.canRunIndependentFromParent = true;
 	}
 	
 	
@@ -62,31 +73,33 @@ public class Holon {
 	}
 	
 	public void addChild(Holon child) {
-		if(!this.model.getHolonsByID().containsKey(child.getUniqueID()))
-			return;
-		child.parent = this;
-		childHolons.add(child);
+		if(!this.childHolons.contains(child)) {
+			child.parent = this;
+			this.childHolons.add(child);
+		}
 		this.holonControlUnit.addSubHolon(child);
-//		System.out.println("Holon "+this.name+" added new child holon "+child.name);
 	}
 	
 	public void addChildHolon(Holon child, int index) {
-		child.parent = this;
-		childHolons.add(index, child);
+		if(!this.childHolons.contains(child)) {
+			child.parent = this;
+			childHolons.add(index, child);
+		}
 		this.holonControlUnit.addSubHolon(child);
-//		System.out.println("Holon "+this.name+" added new child holon "+child.name);
 	}
 	
 	public void removeChildHolon(Holon child) {
 		child.parent = null;
 		childHolons.remove(child);
 		this.holonControlUnit.getHierarchyController().removeSubHolon(child.getUniqueID());
+		revalidateMinModel();
 	}
 	
 	public void removeFromParent() {
 		if(parent != null) {
 			parent.removeChildHolon(this);
 		}
+		parent = model.getStateHolon();
 	}
 	
 	
@@ -99,9 +112,8 @@ public class Holon {
 	}
 	
 	public void setParent(Holon parent) {
-//		System.out.println("Holon "+this.name+" replaced parent "+this.parent.name+" with "+parent.name);
 		this.parent = parent;
-		this.holonControlUnit.setSuperHolon(parent);
+		this.holonControlUnit.getHierarchyController().setSuperHolon(parent.getUniqueID());
 	}
 	
 	public HolonObject getHolonObject() {
@@ -125,7 +137,7 @@ public class Holon {
 
 	public void reassignAllChildren(Holon other) {
 		for(Holon child: this.childHolons) {
-			other.addChild(child);
+			other.merge(child);
 		}
 		childHolons.clear();
 	}
@@ -195,21 +207,20 @@ public class Holon {
 			if(isPureAbstract) {
 				continue;
 			}
-			boolean isPhysicalConnected = table.get(first) == table.get(otherHolonObject);
+			boolean isPhysicalConnected = model.checkHolonObjectsAreConnected(this, other);
 			if(!isPhysicalConnected) {
 				removeList.add(other);
 			}
 		}
 		//Remove holons
 		for(Holon holon : removeList) {
-			holon.removeFromParent();
-			stateHolon.addChild(holon);
+			holon.split(stateHolon);
 		}
 		
 	}
 	
 	public void addNewVirtualNeighbor(String virtualNeighbor) {
-		if(!this.equals(virtualNeighbor)) {
+		if(!this.uniqueID.equals(virtualNeighbor)) {
 			this.holonControlUnit.addNewVirtualNeighbor(virtualNeighbor);
 		}
 	}
@@ -218,6 +229,253 @@ public class Holon {
 		return uniqueID;
 	}
 	
-}
-
+	public ArrayList<HolonObject> getAllHolonObjects() {
+		ArrayList<HolonObject> list = new ArrayList<HolonObject>();
+		for(Holon h : this.childHolons) {
+			list.addAll(h.getAllHolonObjects());
+		}
+		if(this.holonObject != null) {
+			list.add(this.holonObject);
+		}
+		return list;
+	}
+	
+	public MinimumModel getMinimumModel() {
+		return this.minModel;
+	}
+	
+	public void merge(Holon child) {
+		if(!this.model.getHolonsByID().containsKey(child.getUniqueID())) {
+			System.err.println("could not find: "+child.getHolonObject());
+			return;
+		}
+		
+		if(this.childHolons.contains(child)) {
+			return;
+		}
+		
+		if(this.getLayer() == 0) {
+			this.addChild(child);
+			return;
+		}
+		
+		//check if path between this holon and child holon is already occupied
+		ArrayList<HolonObject> holarchy = getAllHolonObjects();
+		holarchy.addAll(child.getAllHolonObjects());
+		HashMap<Float, ArrayList<Edge>> paths = this.model.getShortestPathToHolarchy(this.minModel, child.getMinimumModel(), holarchy);
+		HashMap<Float, ArrayList<Edge>> free_paths = new HashMap<Float, ArrayList<Edge>>();
+		HashMap<Float, ArrayList<Edge>> occ_paths = new HashMap<Float, ArrayList<Edge>>();
+		HashMap<ArrayList<Edge>, Holon> occ_by = new HashMap<ArrayList<Edge>, Holon>();
+		
+		for(Float f : paths.keySet()) {
+			ArrayList<Edge> path = paths.get(f);
+			Holon holder = isPathOccupied(path);
+			if(holder == null || holder.getLayer() == 0 || holder.equals(this.parent)) {
+				free_paths.put(f, path);
+			} else {
+				occ_paths.put(f, path);
+				occ_by.put(path, holder);
+			}
+		}
+		
+		if(free_paths.size() > 0) {
+			//there is a free path, take it and add child directly
+			this.addChild(child);
+			this.addChildToMinModel(child, free_paths.get(getShortestPath(free_paths)));
+			if(this.getLayer() > 1) {
+				this.parent.recalculateMinModel();
+			}
+			return;
+		}
+		if(occ_paths.size() < 1) {
+			System.err.println("something went wrong when looking for shortest path while merging "+this.uniqueID+" and "+child.getUniqueID());
+		}
+		ArrayList<ArrayList<Edge>> shortestPaths = sortPaths(occ_paths);
+		for(int i=0; i< shortestPaths.size(); i++) {
+			//check if holon should merge with holder of this path
+			ArrayList<Edge> path = shortestPaths.get(i);
+			Holon holder = occ_by.get(path);
+			//if true try to merge with holon which is using the path
+			if(holder != null && holder.getLayer() > 0) {
+				this.split(holder);
+				this.addChild(child);
+				this.addChildToMinModel(child, path);
+				if(this.parent != null && this.getLayer() > 1) {
+					this.parent.recalculateMinModel();
+				}
+				this.canRunIndependentFromParent = false;
+			}
+			break;
+		}
+	}
+	
+	/**
+	 * checks whether a path is occupied
+	 * if true returns the holon in which the path is located
+	 * @param path
+	 * @return
+	 */
+	private Holon isPathOccupied(ArrayList<Edge> path) {
+		Holon h = this.parent;
+		Holon r = this;
+		Holon holder = null;
+		while(h != null) {
+			holder = h.containsPath(path, r);
+			if(holder != null) {
+				//found a holon which contains the path
+				return holder;
+			}
+			r = h;
+			h = h.parent;
+		}
+		return null;
+	}
+	
+	private ArrayList<ArrayList<Edge>> sortPaths(HashMap<Float, ArrayList<Edge>> paths) {
+		ArrayList<ArrayList<Edge>> shortestPaths = new ArrayList<ArrayList<Edge>>();
+		
+		while(paths.size() > 0) {
+			shortestPaths.add(paths.remove(getShortestPath(paths)));
+		}
+		
+		return shortestPaths;
+	}
+	
+	private Float getShortestPath(HashMap<Float, ArrayList<Edge>> paths){
+		float min = Float.MAX_VALUE;
+		for(Float f : paths.keySet()) {
+			if(f < min) {
+				min = f;
+			}
+		}
+		return min;
+	}
+	
+	/**
+	 * removes this holon from current superholon and merge with new superholon
+	 */
+	public void split(Holon newParent) {
+		if(newParent == null) {
+			System.err.println("can not split without new super holon");
+			return;
+		}
+		
+		//ensure that this holarchy can run independent(path is not occupied by superholon) from the superholon
+		if(!this.canRunIndependentFromParent) {
+			return;
+		}
+		
+		if(this.parent != null) {
+			this.parent.removeChildHolon(this);
+		}
+		
+		newParent.merge(this);
+	}
+	
+	/**
+	 * recalculates the min model after a holon was added to a subholon
+	 * does NOT recalculate the shortest paths between its subholons
+	 */
+	public void recalculateMinModel() {
+		ArrayList<AbstractCanvasObject> objects = new ArrayList<AbstractCanvasObject>();
+		ArrayList<Edge> edges = new ArrayList<Edge>();
+		for(Holon child : this.childHolons) {
+			MinimumModel cmm = child.getMinimumModel();
+			objects.addAll(cmm.getHolonObjectList());
+			objects.addAll(cmm.getNodeList());
+			objects.addAll(cmm.getSwitchList());
+			for(IntermediateCableWithState icws : cmm.getEdgeList()) {
+				edges.add(icws.getModel());
+			}
+		}
+		//go through the edge list and add all edges connecting the subholons
+		for(IntermediateCableWithState icws : this.minModel.getEdgeList()) {
+			if(!edges.contains(icws.getModel())) {
+				edges.add(icws.getModel());
+			}
+		}
+		
+		this.minModel = new MinimumModel(objects, edges);
+		
+		//notify superholon to recalculate its minModel
+		if(this.parent != null && this.getLayer() > 0) {
+			this.parent.recalculateMinModel();
+		}
+	}
+	
+	/**
+	 * adds a child and its min model (incl. all its subholons) to this min model
+	 * @param child
+	 */
+	private void addChildToMinModel(Holon child, ArrayList<Edge> path) {
+		if(this.minModel.getHolonObjectList().contains(child.getHolonObject()) || getLayer() == 0)
+			return;
+		
+		ArrayList<Edge> edgeList = new ArrayList<Edge>();
+		//add all holon objects that are part of this holarchy
+		ArrayList<HolonObject> holarchy = getAllHolonObjects();
+		holarchy.addAll(child.getAllHolonObjects());
+		edgeList.addAll(path);
+		for(IntermediateCableWithState icws : this.minModel.getEdgeList()) {
+			edgeList.add(icws.getModel());
+		}
+		for(IntermediateCableWithState icws : child.minModel.getEdgeList()) {
+			edgeList.add(icws.getModel());
+		}
+		//aggregate all objects
+		ArrayList<AbstractCanvasObject> objects = new ArrayList<AbstractCanvasObject>();
+		for(Edge e : edgeList) {
+			AbstractCanvasObject a = e.getA();
+			AbstractCanvasObject b = e.getB();
+			if(!objects.contains(a)) {
+				objects.add(a);
+			}
+			if(!objects.contains(b)) {
+				objects.add(b);
+			}
+		}
+		
+		this.minModel = new MinimumModel(objects, edgeList);
+	}
+	
+	/**
+	 * revalidate this min model after a subholon was removed
+	 */
+	public void revalidateMinModel() {
+		if(getLayer() == 0)
+			return;
 
+		this.canRunIndependentFromParent = true;
+		ArrayList<AbstractCanvasObject> list = new ArrayList<AbstractCanvasObject>();
+		list.add(this.holonObject);
+		this.minModel = new MinimumModel(list, new ArrayList<Edge>());
+		for(int i=0; i< this.childHolons.size(); i++) {
+			Holon child = this.childHolons.remove(0);
+			this.merge(child);
+		}
+		
+		if(this.parent != null) {
+			this.parent.revalidateMinModel();
+		}
+	}
+	
+	/**
+	 * returns the holon which uses the specified path if it is included in min model, otherwise null
+	 */
+	public Holon containsPath(ArrayList<Edge> path, Holon requester) {
+		if(this.minModel.containsPath(path) || this.getLayer() == 0) {
+			for(Holon child : this.childHolons) {
+				if(child.equals(requester))
+					continue;
+				Holon h = child.containsPath(path, this);
+				if(h != null) {
+					return h;
+				}
+			}
+			
+			return this;
+		}
+		
+		return null;
+	}
+}

+ 56 - 0
src/classes/HolonSwitch.java

@@ -3,8 +3,10 @@ package classes;
 import java.awt.Point;
 import java.awt.geom.Point2D;
 import java.awt.geom.Point2D.Double;
+import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.ListIterator;
+import java.util.UUID;
 
 import com.google.gson.annotations.Expose;
 import interfaces.GraphEditable;
@@ -58,6 +60,8 @@ public class HolonSwitch extends AbstractCanvasObject implements LocalMode, Grap
 	boolean[] activeAt;
 	// Points on the UnitGraph
 	LinkedList<Point2D.Double> graphPoints = new LinkedList<>();
+	
+	private String uniqueID;
 
 	/**
 	 * Create a new HolonSwitch with the default name ("Switch"), a default
@@ -76,6 +80,7 @@ public class HolonSwitch extends AbstractCanvasObject implements LocalMode, Grap
 		setGraphPoints(new LinkedList<Point2D.Double>());
 		initGraphPoints();
 		sampleGraph();
+		this.uniqueID = "Switch "+UUID.randomUUID().toString();
 	}
 
 	/**
@@ -100,6 +105,7 @@ public class HolonSwitch extends AbstractCanvasObject implements LocalMode, Grap
 		}
 		sampleGraph();
 		setManualMode(copyObj.getManualMode());
+		this.uniqueID = "Switch "+UUID.randomUUID().toString();
 	}
 
 	/**
@@ -318,4 +324,54 @@ public class HolonSwitch extends AbstractCanvasObject implements LocalMode, Grap
 		return name + "[ID:" + id + "]";
 		
 	}
+	
+	public ArrayList<String> getAllConnectedHolons() {
+		ArrayList<String> conns = new ArrayList();
+		
+		//switch is open therefore it does not connect objects
+		if(!this.isClosed())
+			return conns;
+		
+		for(Edge e : this.connections) {
+			AbstractCanvasObject a = e.getA();
+			AbstractCanvasObject b = e.getB();
+			System.out.println("This: "+this.id+" A: "+e.getA().id+" B: "+e.getB().id);
+			if(b.equals(this)) {
+				if(a instanceof HolonObject) {
+					conns.add(((HolonObject) a).holon.getUniqueID());
+				} else if(a instanceof HolonSwitch) {
+					conns.addAll(((HolonSwitch)a).getAllConnectedHolons());
+				} else {
+					
+				}
+			} else {
+				if(b instanceof HolonObject) {
+					conns.add(((HolonObject) b).holon.getUniqueID());
+				} else if(b instanceof HolonSwitch) {
+					conns.addAll(((HolonSwitch)b).getAllConnectedHolons());
+				} else {
+					
+				}
+			}
+		}
+		
+		return conns;
+	}
+	
+	public String getUniqueID() {
+		if(this.uniqueID == null)
+			this.uniqueID = "Switch "+UUID.randomUUID().toString();
+		return this.uniqueID;
+	}
+	
+	/**
+	 * switch is closed is equivalent to on, therefore energy can flow through the switch 
+	 * @return
+	 */
+	public boolean isClosed() {
+		if( (this.manualMode && this.manualActive) || (!this.manualMode && this.autoActive) ) {
+			return true;
+		}
+		return false;
+	}
 }

+ 12 - 10
src/classes/holonControlUnit/CommunicationModule.java

@@ -3,6 +3,8 @@ package classes.holonControlUnit;
 import classes.Holon;
 import classes.holonControlUnit.messages.Message;
 import classes.holonControlUnit.messages.NeighborhoodMsg;
+import classes.holonControlUnit.messages.StateMsg;
+import classes.holonControlUnit.messages.StateRequestMsg;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -19,20 +21,15 @@ public class CommunicationModule {
 	
 	private HolonControlUnit hcu;
 	private Gson gson;
-
-	public enum MessageType {
-		ORDER, NEIGHBORHOOD
-	}
 	
 	public CommunicationModule(HolonControlUnit owner) {
 		this.hcu = owner;
 		this.gson = new Gson();
 	}
 
-	public void sendMsg(String receiver, MessageType type, String body) {
+	public void sendMsg(String receiver, Message.Type type, String body) {
 		//send msg to holon receiver
 		Message msg = new Message(this.hcu.getHolon().getUniqueID(), receiver, type, body);
-//		System.out.println("Holon "+hcu.getHolon().getUniqueID()+" send message: "+msg);
 		//get receiver through his uniqueID
 		Holon h = this.hcu.getHolon().model.getHolonsByID().get(receiver);
 		if(h == null) {
@@ -44,23 +41,29 @@ public class CommunicationModule {
 	
 	public void receiveMsg(String message) {
 		Message msg = this.gson.fromJson(message, Message.class);
-//		System.out.println("Holon "+hcu.getHolon().getUniqueID()+" received message: "+message);
 		
 		if(!msg.getReceiver().equals(this.hcu.getHolon().getUniqueID()))
 			throw new RuntimeException("Missleaded message:\n"+message);
 		
 		switch (msg.getType()) {
 			case ORDER:
+				
 				break;
 			case NEIGHBORHOOD:
-				receiveNewVNeighbor(msg);
+				receiveNeighborhoodMsg(msg);
+				break;
+			case STATE_REQUEST:
+				this.hcu.getStateEstimator().receiveStateRequest(msg.getSender(), this.gson.fromJson(msg.getBody(), StateRequestMsg.class));
+				break;
+			case STATE:
+				this.hcu.getStateEstimator().receiveState(msg.getSender(), this.gson.fromJson(msg.getBody(), StateMsg.class));
 				break;
 			default:
 				throw new RuntimeException("Unknown message type:\n"+message);
 		}
 	}
 	
-	private void receiveNewVNeighbor(Message msg) {
+	private void receiveNeighborhoodMsg(Message msg) {
 		NeighborhoodMsg nMsg = this.gson.fromJson(msg.getBody(), NeighborhoodMsg.class);
 		ArrayList<String> neighbors = nMsg.getNeighbors();
 		switch(nMsg.getType()) {
@@ -77,7 +80,6 @@ public class CommunicationModule {
 			default:
 				throw new RuntimeException("Unknown neighborhood type:\n"+msg);
 		}
-//		System.out.println("Holon "+hcu.getHolon().name+" received new v neighbor "+v.getNewVirtualNeighbor());
 	}
 	
 	public Gson getGson() {

+ 77 - 21
src/classes/holonControlUnit/HierarchyControlUnit.java

@@ -1,18 +1,29 @@
 package classes.holonControlUnit;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 
+import classes.AbstractCanvasObject;
+import classes.Edge;
+import classes.GroupNode;
 import classes.Holon;
+import classes.HolonObject;
+import classes.HolonSwitch;
 import classes.holonControlUnit.messages.NeighborhoodMsg;
+import classes.holonControlUnit.messages.Message;
 
 public class HierarchyControlUnit {
 
 	private HolonControlUnit hcu;
+	private String superHolon;
 	private ArrayList<String> subHolons;
 	private ArrayList<String> physicalNeighbors;
 	private ArrayList<String> virtualNeighbors;
+	private Map<String, HolonSwitch> switches;
 	
 	public HierarchyControlUnit(HolonControlUnit hcu) {
 		this.hcu = hcu;
@@ -20,13 +31,7 @@ public class HierarchyControlUnit {
 		this.physicalNeighbors = new ArrayList();
 		
 		this.virtualNeighbors = new ArrayList();
-//		if(h.getParent() != null)
-//			this.virtualNeighbors.addAll(h.getParent().childHolons);
-//		System.out.println("created hcu for holon "+h.name);
-//		System.out.println("\tsuperholon"+(h.getParent() != null ? h.getParent().name : ""));
-//		System.out.println("\tsubholons"+h.childHolons.toString());
-//		System.out.println("\tvirtual neighbors"+this.virtualNeighbors.toString());
-//		System.out.println("\tphysical neighbors"+this.physicalNeighbors.toString());
+		this.switches = new HashMap();
 	}
 	
 	public ArrayList<String> getPhysicalNeighbors() {
@@ -38,7 +43,9 @@ public class HierarchyControlUnit {
 	}
 	
 	public void addPhysicalNeighbor(String physicalNeighbor) {
-		this.physicalNeighbors.add(physicalNeighbor);
+		if(!this.physicalNeighbors.contains(physicalNeighbor)) {
+			this.physicalNeighbors.add(physicalNeighbor);
+		}
 	}
 
 	public ArrayList<String> getVirtualNeighbors() {
@@ -50,46 +57,59 @@ public class HierarchyControlUnit {
 	}
 	
 	public void addSubHolon(String subHolon) {
-//		System.out.println("Holon "+this.hcu.getHolon().getUniqueID()+" adds sub-holon "+subHolon);
+		if(this.subHolons.contains(subHolon))
+			return;
 		//propagate new virtual neighbor for all subholons
-		ArrayList<String> list = new ArrayList();
+		ArrayList<String> list = new ArrayList<String>();
 		list.add(subHolon);
 		String body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.NEW_VIRTUAL_NEIGHBOR, list));
-//		System.out.println("list: "+list.toString()+" body "+body);
 		for(String sub : this.subHolons) {
-			this.hcu.getCommunicator().sendMsg(sub, CommunicationModule.MessageType.NEIGHBORHOOD, body);
+			this.hcu.getCommunicator().sendMsg(sub, Message.Type.NEIGHBORHOOD, body);
 		}
 		if(this.subHolons.size() > 0) {
 			body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.NEW_VIRTUAL_NEIGHBOR, this.subHolons));
-			this.hcu.getCommunicator().sendMsg(subHolon, CommunicationModule.MessageType.NEIGHBORHOOD, body);
+			this.hcu.getCommunicator().sendMsg(subHolon, Message.Type.NEIGHBORHOOD, body);
 		}
-		
 		this.subHolons.add(subHolon);
 	}
 	
 	public void removeSubHolon(String subHolon) {
-		if(!this.subHolons.remove(subHolon))
+		if(!this.subHolons.remove(subHolon)) {
 			System.err.println("Could not remove sub holon "+subHolon);
+			return;
+		}
 		ArrayList<String> list = new ArrayList();
 		list.add(subHolon);
 		String body = this.hcu.getCommunicator().getGson().toJson(new NeighborhoodMsg(NeighborhoodMsg.Type.REMOVE_VIRTUAL_NEIGHBOR, list));
 		for(String sub : this.subHolons) {
-			this.hcu.getCommunicator().sendMsg(sub, CommunicationModule.MessageType.NEIGHBORHOOD, body);
+			this.hcu.getCommunicator().sendMsg(sub, Message.Type.NEIGHBORHOOD, body);
 		}
 	}
 	
+	public String getSuperHolon() {
+		return this.superHolon;
+	}
+	
+	public void setSuperHolon(String parent) {
+		this.superHolon = parent;
+	}
+	
 	public ArrayList<String> getSubHolons() {
 		return this.subHolons;
 	}
 	
 	public void addVirtualNeighbor(String virtualNeighbor) {
-		this.virtualNeighbors.add(virtualNeighbor);
-//		System.out.println("Holon "+this.hcu.getHolon().getUniqueID()+" add virtual neighbor"+virtualNeighbor);
+		if(!this.virtualNeighbors.contains(virtualNeighbor)) {
+			this.virtualNeighbors.add(virtualNeighbor);
+		}
 	}
 	
-	public void addVirtualNeighbors(ArrayList<String> virtualNeighbor) {
-		this.virtualNeighbors.addAll(virtualNeighbor);
-//		System.out.println("Holon "+this.hcu.getHolon().getUniqueID()+" add virtual neighbor"+virtualNeighbor);
+	public void addVirtualNeighbors(ArrayList<String> virtualNeighbors) {
+		for(int i=0; i<virtualNeighbors.size(); i++) {
+			String virtualNeighbor = virtualNeighbors.get(i);
+			if(!this.virtualNeighbors.contains(virtualNeighbor))
+				this.virtualNeighbors.add(virtualNeighbor);
+		}
 	}
 	
 	public void removeVirtualNeighbor(String virtualNeighbor) {
@@ -99,4 +119,40 @@ public class HierarchyControlUnit {
 	public void removeVirtualNeighbors(ArrayList<String> virtualNeighbor) {
 		this.virtualNeighbors.removeAll(virtualNeighbor);
 	}
+	
+	public void addEdgeTo(AbstractCanvasObject b) {
+		if(b instanceof HolonObject && ((HolonObject)b).holon != null) {
+			//add holon of b as physical neighbor
+			Holon ho = ((HolonObject) b).holon;
+			if(!this.physicalNeighbors.contains(ho.getUniqueID())) {
+				this.physicalNeighbors.add(ho.getUniqueID());
+			}
+		} else if(b instanceof HolonSwitch) {
+			//get edges of b and add them if switch is open
+			HolonSwitch hs = (HolonSwitch) b;
+			if(!this.physicalNeighbors.contains(hs.getUniqueID())) {
+				this.physicalNeighbors.add(hs.getUniqueID());
+				this.switches.put(hs.getUniqueID(), hs);
+			}
+		} else if (b instanceof GroupNode) {
+			//go inside groupnode and find the endpoint
+			
+		}
+	}
+	
+	public void removeEdgeTo(AbstractCanvasObject b) {
+		if(b instanceof HolonObject) {
+			//add holon of b as physical neighbor
+			Holon ho = ((HolonObject) b).holon;
+			this.physicalNeighbors.remove(ho.getUniqueID());
+		} else if(b instanceof HolonSwitch) {
+			//get edges of b and add them if switch is open
+			HolonSwitch hs = (HolonSwitch) b;
+			this.physicalNeighbors.remove(hs.getUniqueID());
+			this.switches.remove(hs.getUniqueID());
+		} else if (b instanceof GroupNode) {
+			//go inside groupnode and find the endpoint
+			
+		}
+	}
 }

+ 2 - 10
src/classes/holonControlUnit/HolonControlUnit.java

@@ -10,7 +10,7 @@ import classes.holonControlUnit.messages.NeighborhoodMsg;
 
 public class HolonControlUnit {
 	
-	private Holon holon, superHolon;
+	private Holon holon;
 	private FlexibilityManager flexMan;
 	private ForecastComputationUnit forecaster;
 	private HierarchyControlUnit hierarchyController;
@@ -25,19 +25,11 @@ public class HolonControlUnit {
 		this.flexMan = new FlexibilityManager();
 		this.forecaster = new ForecastComputationUnit();
 		this.optimizer = new OptimizationManager();
-		this.stateEstimator = new StateEstimator();
+		this.stateEstimator = new StateEstimator(this);
 		this.stateAssembler = new TargetStateAssembler();
 		this.communicator = new CommunicationModule(this);
 	}
 
-	public Holon getSuperHolon() {
-		return superHolon;
-	}
-
-	public void setSuperHolon(Holon superHolon) {
-		this.superHolon = superHolon;
-	}
-
 	public ArrayList<Holon> getSubHolon() {
 		return this.holon.childHolons;
 	}

+ 19 - 0
src/classes/holonControlUnit/OptimizationManager.java

@@ -2,4 +2,23 @@ package classes.holonControlUnit;
 
 public class OptimizationManager {
 
+	public enum OptimizationScheme {
+		COMFORT, MIN_COST, ENERGY_CONSUMPTION, STABILITY, RECOVERY
+	}
+	
+	private OptimizationScheme optimizationScheme;
+	
+	public OptimizationManager() {
+		this.optimizationScheme = OptimizationScheme.COMFORT;
+	}
+
+	public OptimizationScheme getOptimizationScheme() {
+		return optimizationScheme;
+	}
+
+	public void setOptimizationScheme(OptimizationScheme optimizationScheme) {
+		this.optimizationScheme = optimizationScheme;
+	}
+	
+	
 }

+ 94 - 0
src/classes/holonControlUnit/StateEstimator.java

@@ -1,5 +1,99 @@
 package classes.holonControlUnit;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import classes.Holon;
+import classes.HolonElement;
+import classes.holonControlUnit.messages.Message;
+import classes.holonControlUnit.messages.StateMsg;
+import classes.holonControlUnit.messages.StateRequestMsg;
+
+/**
+ * aggregates all states from sub holons and forwards the resulting own state to the state assembler
+ * @author Jonas
+ *
+ */
 public class StateEstimator {
 
+	/* indicates the current state of the holon */
+	public enum StateIndicator {
+		/* everything runs as expected, all parameters are inside their tresholds */
+		DESIRED, 
+		/* everything is still as expected except for minor deviations, parts may be endangered/dysfunctional */
+		ENDANGERED, 
+		/* stability/functionality of holon is not guaranteed */
+		DYSFUNCTIONAL
+	}
+	private final float POWER_TRESHOLD = 0.95f;
+	
+	private HolonControlUnit hcu;
+	private StateIndicator stateInd;
+	private float powerUsage;
+	private HashMap<String, StateMsg> childStates;
+	
+	public StateEstimator(HolonControlUnit hcu) {
+		this.hcu = hcu;
+		this.stateInd = StateIndicator.DESIRED;
+	}
+
+	public StateIndicator getStateIndicator() {
+		return stateInd;
+	}
+	
+	/**
+	 * Depth-first computation
+	 * aggregates childrens state first, then computes own state
+	 */
+	public void computeState(int timeStep) {
+		//request childrens state
+		this.childStates = new HashMap<String, StateMsg>();
+		ArrayList<String> children = this.hcu.getHierarchyController().getSubHolons();
+		for(String child : children) {
+			//send request to child
+			this.hcu.getCommunicator().sendMsg(child, Message.Type.STATE_REQUEST, 
+					this.hcu.getCommunicator().getGson().toJson(new StateRequestMsg(timeStep)));
+		}
+		//wait for sub holons to compute state and send it
+		if(this.childStates.size() < children.size()) {
+			System.err.println("Something went wrong while computing state of "+this.hcu.getHolon().getUniqueID());
+			System.err.println("\tchildStates "+childStates);
+			System.err.println("\tchildren "+children);
+			return;
+		}
+		//aggregate cub holons state
+		this.powerUsage = 0;
+		for(String s : this.childStates.keySet()) {
+			this.powerUsage += this.childStates.get(s).getPowerUsage();
+		}
+		//add state from holon elements
+		Holon holon = this.hcu.getHolon();
+		if(holon.isPhysical) {
+			this.powerUsage += holon.getHolonObject().getEnergyAtTimeStep(timeStep);
+		}
+		if(this.powerUsage < this.POWER_TRESHOLD * this.hcu.getStateAssembler().getDesiredPowerUsage()) {
+			this.stateInd = StateIndicator.DESIRED;
+		} else {
+			this.stateInd = StateIndicator.ENDANGERED;
+		}
+	}
+	
+	public void receiveState(String sender, StateMsg stateMsg) {
+		if(this.childStates == null)
+			return;
+		this.childStates.put(sender, stateMsg);
+	}
+	
+	public void receiveStateRequest(String sender, StateRequestMsg req) {
+		computeState(req.getTimeStep());
+		//send current state to sender/super holon
+		StateMsg stateMsg = new StateMsg(this.powerUsage);
+		String body = this.hcu.getCommunicator().getGson().toJson(stateMsg);
+		this.hcu.getCommunicator().sendMsg(sender, Message.Type.STATE, body);
+	}
+
+	public float getPowerUsage() {
+		return this.powerUsage;
+	}
+	
 }

+ 6 - 0
src/classes/holonControlUnit/TargetStateAssembler.java

@@ -1,5 +1,11 @@
 package classes.holonControlUnit;
 
 public class TargetStateAssembler {
+	
+	private float desiredPowerUsage = 100f;
+
+	public float getDesiredPowerUsage() {
+		return desiredPowerUsage;
+	}
 
 }

+ 6 - 4
src/classes/holonControlUnit/messages/Message.java

@@ -1,16 +1,18 @@
 package classes.holonControlUnit.messages;
 
 import classes.Holon;
-import classes.holonControlUnit.CommunicationModule.MessageType;
 
 public class Message {
 
+	public enum Type {
+		ORDER, NEIGHBORHOOD, STATE_REQUEST, STATE
+	}
 	private String sender;
 	private String receiver;
-	private MessageType type;
+	private Type type;
 	private String body;
 	
-	public Message(String sender, String receiver, MessageType type, String body) {
+	public Message(String sender, String receiver, Type type, String body) {
 		super();
 		this.sender = sender;
 		this.receiver = receiver;
@@ -31,7 +33,7 @@ public class Message {
 		return receiver;
 	}
 
-	public MessageType getType() {
+	public Type getType() {
 		return type;
 	}
 

+ 21 - 0
src/classes/holonControlUnit/messages/StateMsg.java

@@ -0,0 +1,21 @@
+package classes.holonControlUnit.messages;
+
+public class StateMsg {
+
+	private float powerUsage;
+
+	public StateMsg(float powerUsage) {
+		super();
+		this.powerUsage = powerUsage;
+	}
+
+	public float getPowerUsage() {
+		return powerUsage;
+	}
+
+	@Override
+	public String toString() {
+		return "StateMsg [powerUsage=" + powerUsage + "]";
+	}
+	
+}

+ 21 - 0
src/classes/holonControlUnit/messages/StateRequestMsg.java

@@ -0,0 +1,21 @@
+package classes.holonControlUnit.messages;
+
+public class StateRequestMsg {
+	
+	private int timeStep;
+
+	public StateRequestMsg(int timeStep) {
+		super();
+		this.timeStep = timeStep;
+	}
+
+	@Override
+	public String toString() {
+		return "StateRequestMsg [timeStep=" + timeStep + "]";
+	}
+
+	public int getTimeStep() {
+		return timeStep;
+	}
+
+}

+ 7 - 8
src/ui/controller/CanvasController.java

@@ -49,11 +49,6 @@ public class CanvasController {
 	public void addObject(AbstractCanvasObject object, boolean replace) {
 		model.getCvsObjIdx().put(object.getId(), model.getObjectsOnCanvas().size());
 		model.getObjectsOnCanvas().add(object);
-		if(object instanceof HolonObject) {
-			Holon holon = new Holon((HolonObject)object, model);
-//			model.getHolonsByID().put(holon.getUniqueID(), holon);
-			model.getStateHolon().addChild(holon);
-		}
 		
 		/**
 		 * check if we should drag & drop replace
@@ -146,7 +141,6 @@ public class CanvasController {
 		model.getObjectsOnCanvas().remove(obj);
 		if(obj instanceof HolonObject) {
 			HolonObject holonObject  = (HolonObject) obj;
-			model.getHolonsByID().remove(holonObject.holon.getUniqueID(), holonObject.holon);
 			removeHolon(holonObject.holon);
 			holonObject.holon = null;
 		}
@@ -158,6 +152,7 @@ public class CanvasController {
 		if(holon == null) {
 			return;
 		}
+		model.getHolonsByID().remove(holon.getUniqueID(), holon);
 		holon.reassignAllChildren(holon.getParent());
 		holon.removeFromParent();
 		holon.removeAllRefrences();
@@ -198,6 +193,8 @@ public class CanvasController {
 	 */
 	public void addEdgeOnCanvas(Edge edge) {
 		model.getEdgesOnCanvas().add(edge);
+		edge.getA().addConnection(edge);
+		edge.getB().addConnection(edge);
 	}
 
 	/**
@@ -207,8 +204,8 @@ public class CanvasController {
 	 *            the edge to remove
 	 */
 	public void removeEdgesOnCanvas(Edge edge) {
-		edge.getA().getConnections().remove(edge);
-		edge.getB().getConnections().remove(edge);
+		edge.getA().removeConnection(edge);
+		edge.getB().removeConnection(edge);
 		model.getEdgesOnCanvas().remove(edge);
 	}
 
@@ -323,6 +320,8 @@ public class CanvasController {
 		while(iter.hasNext() ) {
 			Edge edge = iter.next();
 			if(edge.getA() == obj || edge.getB() == obj) {
+				edge.getA().removeConnection(edge);
+				edge.getB().removeConnection(edge);
 				iter.remove();
 			}
 		}

+ 4 - 0
src/ui/controller/Control.java

@@ -532,6 +532,7 @@ public class Control {
         simulationManager.calculateStateForTimeStep(x, true);
         updateOutliner();
         updateFlexWindow();
+        updateHolarchyWindow();
         this.updateCanvas();
     }
 
@@ -870,6 +871,9 @@ public class Control {
 		gui.updateFlexWindows();
 	}
 	
+	public void updateHolarchyWindow() {
+		gui.updateHolarchyWindows();
+	}
 	
 	public void updateCanvas() {
 		gui.repaintCanvas();

+ 3 - 2
src/ui/controller/LoadController.java

@@ -203,7 +203,6 @@ public class LoadController {
     
 	private void deserializeHolon(Holon parent, JsonObject holonJson,
 			HashMap<Integer, AbstractCanvasObject> objDispatch) {
-		System.out.println("deserialize holon from parent"+parent.name);
 		int objId = holonJson.get("HolonObjectID").getAsInt();
 		String name = holonJson.get("Name").getAsString();
 		Holon created;
@@ -219,7 +218,7 @@ public class LoadController {
 		for(JsonElement ele : array) {
 			deserializeHolon(created, ele.getAsJsonObject() , objDispatch);
 		}
-		parent.addChild(created);
+		parent.merge(created);
 	}
 
 	/**
@@ -389,6 +388,8 @@ public class LoadController {
         temp.setA(objDispatch.get(object.get("A").getAsInt()));
         temp.setB(objDispatch.get(object.get("B").getAsInt()));
         model.getEdgesOnCanvas().add(temp);
+        temp.getA().addConnection(temp);
+        temp.getB().addConnection(temp);
     }
 
     /**

+ 46 - 45
src/ui/controller/SimulationManager.java

@@ -17,6 +17,7 @@ import ui.model.VisualRepresentationalState;
 import java.lang.ModuleLayer.Controller;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -48,51 +49,64 @@ public class SimulationManager {
 		model = m;
 	}
 	
-	
-	
-	
-	
-	
 	/**
 	 * calculates the flow of the edges and the supply for objects and consider old timesteps for burned cables.
 	 *
-	 * @param timestep
+	 * @param timeStep
 	 *            current Iteration
 	 * @param updateVisual TODO
 	 */
-	public void calculateStateForTimeStep(int timestep, boolean updateVisual) {
-		boolean doesFlexManagerExist = savesFlexManger.containsKey(timestep);
+	public void calculateStateForTimeStep(int timeStep, boolean updateVisual) {
+		this.timeStep = timeStep;
+		//compute state of each holon
+		this.model.getStateHolon().holonControlUnit.getStateEstimator().computeState(timeStep);
+		
+		boolean doesFlexManagerExist = savesFlexManger.containsKey(timeStep);
 		boolean createNew = updateVisual || !doesFlexManagerExist;
 		FlexManager newFlexManager;
 		if(createNew) {
-			newFlexManager = new FlexManager(model, timestep, savesFlexManger.get(timestep-1));
-			if(doesFlexManagerExist) newFlexManager.orderFlexFromList(savesFlexManger.get(timestep).getAllFlexesOrderedThisTimeStep());
-			savesFlexManger.put(timestep, newFlexManager);
+			newFlexManager = new FlexManager(model, timeStep, savesFlexManger.get(timeStep-1));
+			if(doesFlexManagerExist) newFlexManager.orderFlexFromList(savesFlexManger.get(timeStep).getAllFlexesOrderedThisTimeStep());
+			savesFlexManger.put(timeStep, newFlexManager);
 		}else {
-			newFlexManager = savesFlexManger.get(timestep);
+			newFlexManager = savesFlexManger.get(timeStep);
 		}
 		
-
-		
-		
-		
 		HashMap<Edge, CableState> map = new HashMap<Edge, CableState>();
-		if(timestep > 0 && saves.containsKey(timestep-1)) //if the state before exist
+		if(timeStep > 0 && saves.containsKey(timeStep-1)) //if the state before exist
 		{
 			//make cable hastmap
-			DecoratedState theStateBefore = saves.get(timestep-1);
+			DecoratedState theStateBefore = saves.get(timeStep-1);
 			//edges without HolonObjects or burned
 			for(DecoratedCable edge : theStateBefore.getLeftOverEdges())
 			{
 				map.put(edge.getModel(), edge.getState());
 			}
 		}
-		timeStep = timestep;
-		
-		
 		
 		ArrayList<MinimumNetwork> list =  new ArrayList<MinimumNetwork>();
+
 		MinimumModel minimumModel = new MinimumModel(model.getObjectsOnCanvas(), model.getEdgesOnCanvas());
+		
+		//for each holarchy get minimum model
+		ArrayList<MinimumModel> independentHolarchies = new ArrayList<MinimumModel>();
+		for(Holon h : model.getStateHolon().childHolons) {
+			independentHolarchies.add(h.getMinimumModel());
+		}
+		
+		//set all edges that are not connecting holarchies unnused
+		HashSet<Edge> e = new HashSet<Edge>();
+		for(MinimumModel minimumModel2 : independentHolarchies) {
+			for(IntermediateCableWithState i : minimumModel2.getEdgeList()) {
+				e.add(i.getModel());
+			}
+		}
+		for(IntermediateCableWithState cable : minimumModel.getEdgeList()) {
+			if(!e.contains(cable.getModel())) {
+				cable.setState(CableState.Unused);
+			}
+		}
+		
 		//set all BreakedManuel Cable Burned:
 		for(IntermediateCableWithState cable : minimumModel.getEdgeList()) {
 			if(cable.getModel().isBreakedManuel()) cable.setState(CableState.Burned);
@@ -104,50 +118,43 @@ public class SimulationManager {
 		}
 		ArrayList<IntermediateCableWithState> leftOver = new ArrayList<IntermediateCableWithState>();
 		
-		
-		
 		boolean doAnotherLoop = true;
 		while(doAnotherLoop) {
 			doAnotherLoop = false;
-			list = calculateNetworks(minimumModel, timestep, leftOver);
+			list = calculateNetworks(minimumModel, timeStep, leftOver);
 			for(MinimumNetwork net : list) {
-				float energyOnCables = net.getHolonObjectList().stream().filter(object -> object.getEnergyAtTimeStepWithFlex(timestep, newFlexManager) > 0.0f).map(object -> object.getEnergyAtTimeStepWithFlex(timestep, newFlexManager)).reduce(0.0f, ((a,b) -> a + b));
+//				float energyOnCables = net.getHolonObjectList().stream().filter(object -> object.getEnergyAtTimeStepWithFlex(timeStep, newFlexManager) > 0.0f).map(object -> object.getEnergyAtTimeStepWithFlex(timeStep, newFlexManager)).reduce(0.0f, ((a,b) -> a + b));
+				float energyOnCables = net.getHolonObjectList().stream().filter(object -> object.holon.holonControlUnit.getStateEstimator().getPowerUsage() > 0.0f).map(object -> object.getEnergyAtTimeStepWithFlex(timeStep, newFlexManager)).reduce(0.0f, ((a,b) -> a + b));
 				//find the cable with the energy supplied from his two connected objects are the biggest, from all cables that the network give more energy than the cablecapacity. 
-				IntermediateCableWithState cable = net.getEdgeList().stream().filter(aCable -> energyOnCables > aCable.getModel().getCapacity() && !aCable.getModel().isUnlimitedCapacity()).max((lhs,rhs) -> Float.compare(lhs.getEnergyFromConnetedAtTimestep(timestep, newFlexManager), rhs.getEnergyFromConnetedAtTimestep(timestep, newFlexManager))).orElse(null);
+				IntermediateCableWithState cable = net.getEdgeList().stream().filter(aCable -> energyOnCables > aCable.getModel().getCapacity() && !aCable.getModel().isUnlimitedCapacity()).max((lhs,rhs) -> Float.compare(lhs.getEnergyFromConnetedAtTimestep(timeStep, newFlexManager), rhs.getEnergyFromConnetedAtTimestep(timeStep, newFlexManager))).orElse(null);
 				if(cable != null) {
 					cable.setState(CableState.Burned);
 					doAnotherLoop = true;
 				}
 			}
 		}
-		//Create lookUpTableForHolonObjetcs
-		
-		
-		
 		
+		//Create lookUpTableForHolonObjetcs
 		HashMap<HolonObject, DecoratedNetwork> holonObjectNetworkTable = new HashMap<HolonObject, DecoratedNetwork>();
 		ArrayList<DecoratedNetwork> decorNetworks = new ArrayList<DecoratedNetwork>();
 		FairnessModel actualFairnessModel = model.getFairnessModel();
 		for (MinimumNetwork net : list) {
-			DecoratedNetwork decNetwork = new DecoratedNetwork(net, timestep, actualFairnessModel, newFlexManager);
+			DecoratedNetwork decNetwork = new DecoratedNetwork(net, timeStep, actualFairnessModel, newFlexManager);
 			decorNetworks.add(decNetwork);
 			for(HolonObject obj : net.getHolonObjectList()) {
 				holonObjectNetworkTable.put(obj, decNetwork);
 			}
 		}
-
-		
-		
 		
 		ArrayList<DecoratedCable> leftOverDecoratedCables = new ArrayList<DecoratedCable>();
 		
 		for(IntermediateCableWithState cable: leftOver) {
 			leftOverDecoratedCables.add(new DecoratedCable(cable.getModel(), cable.getState(), 0.0f));
 		}
-		ArrayList<DecoratedSwitch> listOfDecoratedSwitches = decorateSwitches(minimumModel, timestep);
-		DecoratedState stateFromThisTimestep = new DecoratedState(decorNetworks, leftOverDecoratedCables, listOfDecoratedSwitches, newFlexManager, timestep, holonObjectNetworkTable);
-		saves.put(timestep, stateFromThisTimestep);
-		if(updateVisual)savesVisual.put(timestep, new VisualRepresentationalState(stateFromThisTimestep, minimumModel));
+		ArrayList<DecoratedSwitch> listOfDecoratedSwitches = decorateSwitches(minimumModel, timeStep);
+		DecoratedState stateFromThisTimestep = new DecoratedState(decorNetworks, leftOverDecoratedCables, listOfDecoratedSwitches, newFlexManager, timeStep, holonObjectNetworkTable);
+		saves.put(timeStep, stateFromThisTimestep);
+		if(updateVisual)savesVisual.put(timeStep, new VisualRepresentationalState(stateFromThisTimestep, minimumModel));
 		//Check Holarchy and split Holons if no physical connection is present.
 		List<Holon> holonList = model.getStateHolon().childHolons;
 		for(int i = 0; i < holonList.size(); i++) {
@@ -155,11 +162,6 @@ public class SimulationManager {
 		}
 	}
 
-
-
-
-
-
 	/** 
 	 * Decorate a switch
 	 * @param minModel
@@ -173,6 +175,7 @@ public class SimulationManager {
 		}
 		return aListOfDecoratedSwitches;
 	}
+	
 	/**
 	 * SubFunction to calculate the Networks from the model.
 	 * @param minModel
@@ -283,6 +286,4 @@ public class SimulationManager {
 	public VisualRepresentationalState getVisualRepresentationalState(int timestep) {
 		return savesVisual.getOrDefault(timestep, null);
 	}
-
-
 }

+ 1 - 1
src/ui/model/DecoratedCable.java

@@ -4,7 +4,7 @@ import classes.Edge;
 
 public class DecoratedCable {
 	public enum CableState{
-		Working, Burned
+		Working, Burned, Unused
 	}
 	private Edge model;
 	private CableState state;

+ 10 - 2
src/ui/model/IntermediateCableWithState.java

@@ -30,8 +30,16 @@ public class IntermediateCableWithState {
 	//ugly
 	public float getEnergyFromConnetedAtTimestep(int iteration, FlexManager flexManager) {
 		float energy = 0.0f;
-		if(model.getA() instanceof HolonObject && ((HolonObject) model.getA()).getEnergyAtTimeStepWithFlex(iteration, flexManager) > 0) energy += ((HolonObject) model.getA()).getEnergyAtTimeStepWithFlex(iteration, flexManager);
-		if(model.getB() instanceof HolonObject && ((HolonObject) model.getB()).getEnergyAtTimeStepWithFlex(iteration, flexManager) > 0) energy += ((HolonObject) model.getB()).getEnergyAtTimeStepWithFlex(iteration, flexManager);
+//		if(model.getA() instanceof HolonObject && ((HolonObject) model.getA()).getEnergyAtTimeStepWithFlex(iteration, flexManager) > 0) energy += ((HolonObject) model.getA()).getEnergyAtTimeStepWithFlex(iteration, flexManager);
+//		if(model.getB() instanceof HolonObject && ((HolonObject) model.getB()).getEnergyAtTimeStepWithFlex(iteration, flexManager) > 0) energy += ((HolonObject) model.getB()).getEnergyAtTimeStepWithFlex(iteration, flexManager);
+		
+		if(model.getA() instanceof HolonObject && ((HolonObject)model.getA()).holon.holonControlUnit.getStateEstimator().getPowerUsage() > 0) {
+			energy += ((HolonObject)model.getA()).holon.holonControlUnit.getStateEstimator().getPowerUsage();
+		}
+		if(model.getB() instanceof HolonObject && ((HolonObject)model.getB()).holon.holonControlUnit.getStateEstimator().getPowerUsage() > 0) {
+			energy += ((HolonObject)model.getB()).holon.holonControlUnit.getStateEstimator().getPowerUsage();
+		}
+		
 		return energy;
 	}
 	

+ 18 - 1
src/ui/model/MinimumModel.java

@@ -114,5 +114,22 @@ public class MinimumModel {
 		return inGroupObjects;
 	}
 
-	
+	public boolean containsPath(ArrayList<Edge> path) {
+		for(IntermediateCableWithState icws : this.cableList) {
+			for(Edge e : path) {
+				if(e.equals(icws.getModel())) {
+					return true;
+				}
+				AbstractCanvasObject a = e.getA();
+				AbstractCanvasObject b = e.getB();
+				if( (a instanceof HolonObject && this.holonObjectList.contains(a)) || (a instanceof HolonSwitch && this.switchList.contains(a))
+						|| (a instanceof Node && this.nodeList.contains(a)) || (b instanceof HolonObject && this.holonObjectList.contains(b)) 
+						|| (b instanceof HolonSwitch && this.switchList.contains(b)) || (b instanceof Node && this.nodeList.contains(b)) ) {
+					return true;
+				}
+			}
+		}
+		
+		return false;
+	}
 }

+ 182 - 0
src/ui/model/Model.java

@@ -2,7 +2,13 @@ package ui.model;
 
 import java.awt.Color;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -883,4 +889,180 @@ public class Model {
 		return holonsByID;
 	}
 	
+	/**
+	 * get all edges that connect objects inside the holarchy
+	 * requires that all objects are connected
+	 * energy always takes the shortest path between two objects -> all shortest paths are included
+	 * all traversed objects are whether a switch or holon that is part of the holarchy
+	 * group nodes not supported
+	 * @param from
+	 * @param to
+	 * @return
+	 */
+	public ArrayList<Edge> getAllEdgesInHolarchy(ArrayList<HolonObject> holarchy){
+		if(holarchy.size() < 2) {
+			return new ArrayList<Edge>();
+		}
+		//construct subgraph that contains all objects of the holarchy and all switches from the canvas
+		ArrayList<AbstractCanvasObject> vertices = new ArrayList<AbstractCanvasObject>();
+		for(AbstractCanvasObject aco : this.objectsOnCanvas) {
+			if(aco instanceof HolonSwitch || aco instanceof Node
+					|| (aco instanceof HolonObject && holarchy.contains(aco)) ) {
+				vertices.add(aco);
+			}
+		}
+		ArrayList<Edge> edges = new ArrayList<Edge>();
+		for(Edge e : this.edgesOnCanvas) {
+			AbstractCanvasObject a = e.getA();
+			AbstractCanvasObject b = e.getB();
+			if(vertices.contains(a) && vertices.contains(b)) {
+				edges.add(e);
+			}
+		}
+		
+		//find shortest paths between the objects
+		ArrayList<Edge> es = new ArrayList<Edge>();
+		if(holarchy.size() < 2) {
+			return es;
+		}
+		
+		for(int i=0; i<holarchy.size(); i++) {
+			HolonObject a = holarchy.get(i);
+			for(int j=i+1; j<holarchy.size(); j++) {
+				es.addAll(dijkstra(a, holarchy.get(j), holarchy, vertices, edges));
+			}
+		}
+		
+		return es;
+	}
+	
+	public HashMap<Float, ArrayList<Edge>> getShortestPathToHolarchy(MinimumModel minModel, MinimumModel minModel2, ArrayList<HolonObject> holarchy){
+		ArrayList<AbstractCanvasObject> objects = new ArrayList<AbstractCanvasObject>();
+		objects.addAll(minModel.getHolonObjectList());
+		objects.addAll(minModel.getNodeList());
+		objects.addAll(minModel.getSwitchList());
+		
+		ArrayList<AbstractCanvasObject> objects2 = new ArrayList<AbstractCanvasObject>();
+		objects2.addAll(minModel2.getHolonObjectList());
+		objects2.addAll(minModel2.getNodeList());
+		objects2.addAll(minModel2.getSwitchList());
+		
+		HashMap<Float, ArrayList<Edge>> map = new HashMap<Float, ArrayList<Edge>>();
+		for(AbstractCanvasObject aco : objects) {
+			for(AbstractCanvasObject aco2 : objects2) {
+				ArrayList<Edge> edges = dijkstra(aco, aco2, holarchy, this.objectsOnCanvas, this.edgesOnCanvas);
+				float dist = 0;
+				for(Edge e : edges) {
+					dist += e.getLength();
+				}
+				map.put(dist, edges);
+			}
+		}
+		
+		return map;
+	}
+	
+	public ArrayList<Edge> dijkstra(AbstractCanvasObject a, AbstractCanvasObject b, ArrayList<HolonObject> holarchy, ArrayList<AbstractCanvasObject> vertices, ArrayList<Edge> edges) {
+		ArrayList<Edge> es = new ArrayList<Edge>();
+		
+		HashSet<AbstractCanvasObject> visited = new HashSet<AbstractCanvasObject>();
+		ArrayList<AbstractCanvasObject> unvisited = new ArrayList<AbstractCanvasObject>();
+		HashMap<AbstractCanvasObject, Float> dist = new HashMap<AbstractCanvasObject, Float>();
+		for(AbstractCanvasObject aco : vertices) {
+			unvisited.add(aco);
+			dist.put(aco, Float.MAX_VALUE);
+		}
+		dist.put(a, 0f);
+		HashMap<AbstractCanvasObject, AbstractCanvasObject> pre = new HashMap<AbstractCanvasObject, AbstractCanvasObject>();
+
+		AbstractCanvasObject current = a;
+		visited.add(a);
+		unvisited.remove(a);
+		while(!unvisited.isEmpty()) {
+			if(b.equals(current))
+				break;
+			float currDist = dist.get(current);
+			for(AbstractCanvasObject aco : current.getConnectedObjects()) {
+				if(visited.contains(aco) || (aco instanceof HolonObject && !holarchy.contains(aco))) {
+					continue;
+				}
+				float newDist = currDist + getEdgeBetweenObjects(current, aco, this.edgesOnCanvas).getLength();
+				if(newDist < dist.get(aco)) {
+					dist.put(aco, newDist);
+					pre.put(aco, current);
+				}
+			}
+			AbstractCanvasObject next = getMinInMap(dist, unvisited);
+			visited.add(current);
+			unvisited.remove(current);
+			current = next;
+		}
+		
+		//trace back path
+		current = b;
+		while(!current.equals(a)) {
+			AbstractCanvasObject next = pre.get(current);
+			es.add(getEdgeBetweenObjects(current, next, edges));
+			current = next;
+		}
+		
+		return es;
+	}
+	
+	public AbstractCanvasObject getMinInMap(HashMap<AbstractCanvasObject, Float> map, ArrayList<AbstractCanvasObject> unvisited) {
+		AbstractCanvasObject min = null;
+		float m = Float.MAX_VALUE;
+		
+		for(AbstractCanvasObject aco : map.keySet()) {
+			if(unvisited.contains(aco) && map.get(aco) < m) {
+//				System.out.println("new min "+min);
+				m = map.get(aco);
+				min = aco;
+			}
+		}
+		
+		return min;
+	}
+	
+	public Edge getEdgeBetweenObjects(AbstractCanvasObject a, AbstractCanvasObject b, ArrayList<Edge> edges) {
+		for(Edge e : edges) {
+			AbstractCanvasObject a2 = e.getA();
+			AbstractCanvasObject b2 = e.getB();
+			if( (a.equals(a2) && b.equals(b2)) || (a.equals(b2) && b.equals(a2)) ) {
+				return e;
+			}
+		}
+		return null;
+	}
+	
+	public boolean checkHolonObjectsAreConnected(Holon a, Holon b) {
+		if(a.equals(b)) {
+			return false;
+		}
+		HashSet<AbstractCanvasObject> visited = new HashSet<AbstractCanvasObject>();
+		ArrayList<AbstractCanvasObject> objects = new ArrayList<AbstractCanvasObject>();
+		objects.addAll(a.getAllHolonObjects());
+		objects.addAll(b.getAllHolonObjects());
+		
+		ArrayList<AbstractCanvasObject> toVisit = new ArrayList<AbstractCanvasObject>();
+		toVisit.add(a.getHolonObject());
+		while(!toVisit.isEmpty()) {
+			AbstractCanvasObject aco = toVisit.remove(0);
+			for(AbstractCanvasObject aco2 : aco.getConnectedObjects()) {
+				if(visited.contains(aco2) || (aco2 instanceof HolonSwitch && !((HolonSwitch)aco2).isClosed()) ) {
+					continue;
+				}
+				if(aco2 instanceof HolonObject && aco2.equals(b.getHolonObject())) {
+					return true;
+				}
+				if( aco2 instanceof HolonSwitch || aco2 instanceof Node || (aco2 instanceof HolonObject && objects.contains(aco2)) ) {
+					toVisit.add(aco2);
+				}
+			}
+			visited.add(aco);
+		}
+		
+		return false;
+	}
+	
 }

+ 22 - 1
src/ui/view/GUI.java

@@ -80,6 +80,7 @@ import classes.AbstractCanvasObject;
 import classes.Category;
 import classes.Edge;
 import classes.GroupNode;
+import classes.Holon;
 import classes.HolonElement;
 import classes.HolonObject;
 import classes.HolonSwitch;
@@ -298,6 +299,7 @@ public class GUI{
 	
 	private List<Outliner> outlinerList = new ArrayList<Outliner>();
 	private List<FlexWindow> flexList = new ArrayList<FlexWindow>();
+	private List<HolarchyWindow> holarchyList = new ArrayList<HolarchyWindow>();
 
 	private JMenuItem removeItem = new JMenuItem("Remove");
 
@@ -1540,6 +1542,8 @@ public class GUI{
 								AbstractCanvasObject h = null;
 								if (tempCps instanceof HolonObject) {
 									h = new HolonObject(tempCps);
+									((HolonObject) h).holon = new Holon((HolonObject) h, controller.getModel());
+									model.getStateHolon().addChild(((HolonObject)h).holon);
 								}
 								if (tempCps instanceof HolonSwitch) {
 									h = new HolonSwitch(tempCps);
@@ -1572,6 +1576,11 @@ public class GUI{
 							AbstractCanvasObject h = null;
 							if (tempCps instanceof HolonObject) {
 								h = new HolonObject(tempCps);
+								((HolonObject) h).holon = new Holon((HolonObject) h, controller.getModel());
+								model.getHolonsByID().put(((HolonObject) h).holon.getUniqueID(), ((HolonObject) h).holon);
+								model.getStateHolon().addChild(((HolonObject)h).holon);
+//								System.out.println("all holon "+model.getStateHolon().getUniqueID());
+//								System.out.println("added holon to canvas "+((HolonObject)h).holon.getUniqueID());
 							}
 							if (tempCps instanceof HolonSwitch) {
 								h = new HolonSwitch(tempCps);
@@ -2172,7 +2181,7 @@ public class GUI{
 		//Holarchy View
 		JMenuItem holarchyMenuItem = new JMenuItem("Open Holarchy Panel", new ImageIcon(ImageImport.loadImage("/Button_Images/holon_logic.png").getScaledInstance(20, 20, java.awt.Image.SCALE_SMOOTH)));
 		holarchyMenuItem.addActionListener(actionEvent -> {
-			new HolarchyWindow(holegJFrame, controller);
+			holarchyList.add(new HolarchyWindow(holegJFrame, controller));
 		});
 		holarchyMenuItem.setAccelerator(KeyStroke.getKeyStroke('H', Toolkit.getDefaultToolkit ().getMenuShortcutKeyMask()));
 		menuWindow.add(holarchyMenuItem);
@@ -2206,6 +2215,18 @@ public class GUI{
 		}
 	}
 	
+	public void updateHolarchyWindows() {
+		//remove closed Outliner
+		ListIterator<HolarchyWindow> iter = holarchyList.listIterator();
+		while(iter.hasNext())
+		{
+			if(iter.next().isClosed) iter.remove();
+		}
+		//update open Flex
+		for(HolarchyWindow out : holarchyList) {
+			out.update();
+		}
+	}
 	
 	
 	private void showScrollGraph() {

+ 4 - 0
src/ui/view/MyCanvas.java

@@ -371,6 +371,10 @@ public class MyCanvas extends AbstractCanvas implements MouseListener,
 			g.setColor(new Color(13, 175, 28));
 			g.setStroke(new BasicStroke(unlimited?2f:(currentEnergy / capacity * 2f) + 1));
 			break;
+		case Unused:
+			g.setColor(Color.blue);
+			g.setStroke(new BasicStroke(unlimited?2f:(currentEnergy / capacity * 2f) + 1));
+			break;
 		}
 		if(isSelected){
 			g.setColor(Color.lightGray);

+ 72 - 46
src/ui/view/holarchy/HolarchyPanel.java

@@ -1,12 +1,16 @@
 package ui.view.holarchy;
 
+import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
+import java.awt.Stroke;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.geom.Ellipse2D;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -74,17 +78,35 @@ public class HolarchyPanel extends JPanel {
 		this.sep2.setBounds(0, 235, 60, 1);
 		this.add(this.sep2);
 		
-		this.ellipses = new ArrayList();
-		this.ellipsesChild = new ArrayList();
+		this.ellipses = new ArrayList<Map<Ellipse2D, Holon>>();
+		this.ellipsesChild = new ArrayList<Map<Ellipse2D, Map<Ellipse2D, Holon>>>();
 		this.displayedLayer = 0;
-		this.layeredHolons = new ArrayList();
-		this.surroundings = new ArrayList();
-		this.coloredHolons = new HashMap();
+		this.layeredHolons = new ArrayList<ArrayList<Holon>>();
+		this.surroundings = new ArrayList<Ellipse2D>();
+		this.coloredHolons = new HashMap<Holon, Color>();
 		getAllHolons();
 		setSliderMax(this.layeredHolons.size());
 		createAllLayers();
 		generateColorSet();
 	}
+	
+	public void update() {
+		ArrayList<ArrayList<Holon>> layeredHolonsCpy = new ArrayList<ArrayList<Holon>>();
+		copyList(layeredHolonsCpy, this.layeredHolons);
+		this.layeredHolons.clear();
+		getAllHolons();
+		//the holarchy did not change
+		if(compareAllHolons(layeredHolonsCpy))
+			return;
+		this.ellipses = new ArrayList<Map<Ellipse2D, Holon>>();
+		this.ellipsesChild = new ArrayList<Map<Ellipse2D, Map<Ellipse2D, Holon>>>();
+		this.surroundings = new ArrayList<Ellipse2D>();
+		this.coloredHolons = new HashMap<Holon, Color>();
+		setSliderMax(this.layeredHolons.size());
+		createAllLayers();
+		generateColorSet();
+		repaint();
+	}
 		
 	public void paintComponent(Graphics g) {
 		super.paintComponent(g);
@@ -99,21 +121,19 @@ public class HolarchyPanel extends JPanel {
 	public void paintLayer(Graphics g, int layer) {
 		this.displayedLayer = layer;
 		Graphics2D g2 = (Graphics2D) g;
+		Stroke stroke = new BasicStroke(3f);
+		g2.setStroke(stroke);
 		
 		//resize panel
 		Ellipse2D surrounding = this.surroundings.get(this.displayedLayer);
 		if(surrounding.getWidth() > this.getWidth()) {
 			this.setSize((int) surrounding.getWidth(), this.getHeight());
-//			this.parentFrame.resizeScrollPane((int) surrounding.getWidth(), this.getHeight());
 		}
 		if(surrounding.getHeight() > this.getHeight()) {
 			this.setSize(this.getWidth(), (int) surrounding.getHeight());
-//			this.parentFrame.resizeScrollPane(this.getWidth(), (int) surrounding.getHeight());
 		}
 		
-//		System.out.println("painting layer "+layer+"#elements="+this.ellipses.get(layer).size());
 		for(Ellipse2D e : this.ellipses.get(this.displayedLayer).keySet()) {
-//			System.out.println("paint ellipse");
 			//draw ellipse
 			g2.setColor( this.coloredHolons.get(this.ellipses.get(this.displayedLayer).get(e)) );
 			g2.draw(e);
@@ -127,11 +147,9 @@ public class HolarchyPanel extends JPanel {
 	
 	public void createAllLayers() {
 		for(int layer=0; layer<this.layeredHolons.size(); layer++) {
-//			System.out.println("creating layer "+layer+" #elements="+this.layeredHolons.get(layer).size());
-			this.ellipsesChild.add(layer, new HashMap());
-//			System.out.println("creating ellipse");
+			this.ellipsesChild.add(layer, new HashMap<Ellipse2D, Map<Ellipse2D, Holon>>());
 			//estimate the required area, center if it is smaller than the panels size
-			Ellipse2D surrounding = estimateSurrounding(60, 0, layer);
+			Ellipse2D surrounding = estimateSurrounding(60, 0, layer, this.minRadius);
 			double newX = surrounding.getX(), newY = surrounding.getY();
 			if(surrounding.getWidth() <= this.getWidth()) {
 				double diff = this.getWidth() - surrounding.getWidth();
@@ -146,8 +164,6 @@ public class HolarchyPanel extends JPanel {
 			
 			//create ellipse for each holon
 			this.ellipses.add(layer, placeHolons(this.layeredHolons.get(layer), surrounding, true));
-//			System.out.println("paint surrounding width="+surrounding.getWidth()+" height="+surrounding.getHeight());
-//			System.out.println("pending holons "+this.ellipses.get(layer).size());
 			for(Ellipse2D e : this.ellipses.get(layer).keySet()) {
 				//draw child ellipses and add them to global list
 				Map<Ellipse2D, Holon> ellipses2 = placeHolons(ellipses.get(layer).get(e).childHolons, e, false);
@@ -169,7 +185,7 @@ public class HolarchyPanel extends JPanel {
 		double width = surrounding.getWidth();
 		double height = surrounding.getHeight();
 		
-		Map<Ellipse2D, Holon> shapes = new HashMap();
+		Map<Ellipse2D, Holon> shapes = new HashMap<Ellipse2D, Holon>();
 		int abord = 0;
 		int i = 0;
 		
@@ -196,13 +212,11 @@ public class HolarchyPanel extends JPanel {
 					break;
 				}
 			}
-//			System.out.println("try to add ellipse "+i+" x="+e.getX()+" y="+e.getY());
 
 			abord++;
 			//if not add the ellipse to the already existing ones
 			if(!overlap) {
 				shapes.put(e, h);
-//				System.out.println("added ellipse "+i+" at ("+e.getX()+", "+e.getY()+")");
 				i++;
 				abord = 0;
 			}
@@ -211,43 +225,35 @@ public class HolarchyPanel extends JPanel {
 		return shapes;
 	}
 	
-	public Ellipse2D estimateSurrounding(int x, int y, int layer) {
-		if(this.layeredHolons == null || this.layeredHolons.size() < layer+1)
+	public Ellipse2D estimateSurrounding(int x, int y, int layer, int radius) {
+		if(this.layeredHolons == null || this.layeredHolons.size() <= layer)
 			return new Ellipse2D.Double(x, y, Integer.MAX_VALUE, Integer.MAX_VALUE);
 
 		int w = 0;
 		for(Holon h : this.layeredHolons.get(layer)) {
-			w += this.minRadius * (h.getChildCount()+1);
+			w += radius * (h.getChildCount()+1);
 		}
 		w = w * 4 + 10;
 		
-		return new Ellipse2D.Double(x, y, w, w);
-	}
-	
-	/**
-	 * @deprecated
-	 * calculate distance between the two specified ellipses and check if they overlap
-	 * @param e1
-	 * @param e2
-	 * @return
-	 */
-	public boolean overlap(Ellipse2D e1, Ellipse2D e2) {
-		int dist = (int) Math.sqrt( Math.pow((e1.getCenterX()+e2.getCenterX()), 2) + Math.pow((e1.getCenterY()+e2.getCenterY()), 2) );
+		if(w > this.getHeight() - 50) {
+			int div = radius / (w/(this.getHeight()-50));
+			if(div == radius)
+				div--;
+			return estimateSurrounding(x, y, layer, div );
+		}
 		
-		if(dist < e1.getWidth()/2 + e2.getWidth()/2 + 10)
-			return true;
-		return false;
+		return new Ellipse2D.Double(x, y, w, w);
 	}
 	
 	public void getAllHolons() {
-		this.layeredHolons.add(this.root.childHolons);
+		this.layeredHolons.add((ArrayList<Holon>) this.root.childHolons.clone());
 		
 		//TODO: potential infinit loop
 		while(true) {
 			//new layer
-			ArrayList<Holon> children = new ArrayList();
+			ArrayList<Holon> children = new ArrayList<Holon>();
 			for(Holon h : this.layeredHolons.get(this.layeredHolons.size()-1)) {
-				children.addAll(h.childHolons);
+				children.addAll((Collection<? extends Holon>) h.childHolons.clone());
 			}
 			if(children.size() > 0) {
 				this.layeredHolons.add(children);
@@ -281,8 +287,7 @@ public class HolarchyPanel extends JPanel {
 			numColors = this.layeredHolons.get(layer).size();
 			if(numColors <= 0)
 				continue;
-//			System.out.println("generating colors for "+numColors+" holons");
-			ArrayList<Color> colors = new ArrayList();
+			ArrayList<Color> colors = new ArrayList<Color>();
 			float hue = Random.nextFloatInRange(0, 1);
 			for(float i = 0; i < 360; i += 360 / numColors) {
 			    hue += 0.618033988749895f; 
@@ -291,12 +296,36 @@ public class HolarchyPanel extends JPanel {
 			    Color c = Color.getHSBColor(hue%1, saturation, lightness);
 	
 			    colors.add(c);
-//				System.out.println("generated color "+c.toString()+" by h "+hue+" sat "+saturation+" light "+lightness);
 			}
 			
 			for(int j=0;j<this.layeredHolons.get(layer).size(); j++) {
 				this.coloredHolons.put(this.layeredHolons.get(layer).get(j), colors.get(j));
-//				System.out.println("generated color "+colors.get(j).toString()+" for holon "+this.layeredHolons.get(layer).get(j));
+			}
+		}
+	}
+	
+	/**
+	 * compares list with this.layeredHolons
+	 * @param list
+	 * @return true if list is equivalent to this.layeredHolons
+	 */
+	private boolean compareAllHolons(ArrayList<ArrayList<Holon>> list) {
+		if(this.layeredHolons.size() != list.size())
+			return false;
+		for(int i=0; i<this.layeredHolons.size(); i++) {
+			if(this.layeredHolons.get(i).size() != list.get(i).size())
+				return false;
+			if(!list.get(i).containsAll(this.layeredHolons.get(i)))
+				return false;
+		}
+		return true;
+	}
+	
+	private void copyList(ArrayList<ArrayList<Holon>> dest, ArrayList<ArrayList<Holon>> src) {
+		for(int i=0; i<src.size(); i++) {
+			dest.add(new ArrayList<Holon>());
+			for(int j=0; j<src.get(i).size(); j++) {
+				dest.get(i).add(src.get(i).get(j));
 			}
 		}
 	}
@@ -305,7 +334,6 @@ public class HolarchyPanel extends JPanel {
 
 		@Override
 		public void mouseClicked(MouseEvent arg0) {
-//			System.out.println("mouse click at ("+arg0.getX()+","+arg0.getY()+")");
 			//Get clicked Holon
 			for(Ellipse2D e : ellipses.get(displayedLayer).keySet()) {
 				if(e.contains(arg0.getX(), arg0.getY())) {
@@ -317,14 +345,12 @@ public class HolarchyPanel extends JPanel {
 							//child was clicked
 							child = true;
 							parentFrame.displayHolonInfos(ellipsesChild.get(displayedLayer).get(e).get(e2));
-//							System.out.println("child holon "+ellipsesChild.get(e).get(e2).name+" was clicked");
 							break;
 						}
 					}
 					if(!child) {
 						//no child was clicked
 						parentFrame.displayHolonInfos(ellipses.get(displayedLayer).get(e));
-//						System.out.println("holon "+ellipses.get(e).name+" was clicked");
 					}
 					break;
 				}

+ 2 - 2
src/ui/view/holarchy/HolarchyTreePanel.java

@@ -41,7 +41,7 @@ public class HolarchyTreePanel extends JPanel {
 		initilizePanel();
 	}
 
-	private void initilizePanel() {
+	public void initilizePanel() {
 		holonTree = generateTree();
 		holonTree.setCellRenderer(new HolonJtreeRenderer());
         holonTree.getSelectionModel().setSelectionMode(
@@ -108,7 +108,7 @@ public class HolarchyTreePanel extends JPanel {
 		}
 		public void AddHolon(Holon holon) {
 			holon.removeFromParent();
-			this.holon.addChild(holon);
+			this.holon.merge(holon);
 		}
 		@Override
 		public Icon getIcon() {

+ 9 - 0
src/ui/view/holarchy/HolarchyWindow.java

@@ -72,4 +72,13 @@ public class HolarchyWindow extends JFrame {
 		this.infoPanel.clearInfos();
 	}
 	
+	public void update() {
+		if(this.holarchyPanel != null)
+			this.holarchyPanel.update();
+		if(this.infoPanel != null)
+			this.infoPanel.update();
+		if(this.treePanel != null)
+			this.treePanel.initilizePanel();
+	}
+	
 }

+ 20 - 9
src/ui/view/holarchy/HolonInfoPanel.java

@@ -15,12 +15,12 @@ import ui.controller.Control;
 public class HolonInfoPanel extends JPanel {
 
 	Control control;
-	int offset;
+	int offset, offsetLabels = 110;
 	HolarchyWindow parentFrame;
 	Holon h = null;
 	//name, state, parent, children, virtualNeihgbors, physicalNeighbors
 	JPanel[] panels = { new JPanel(), new JPanel(), new JPanel()};
-	JLabel[] labels1 = {new JLabel("Name: "), new JLabel("UUID"), new JLabel("State: "), new JLabel("Parent: ")};
+	JLabel[] labels1 = {new JLabel("Name: "), new JLabel("UUID"), new JLabel("State: "), new JLabel("Optimization Scheme: "), new JLabel("Parent: ")};
 	String[] labels2 = {"Subholons", "Virtual neighbors", "Physical neighbors"};
 	Set<JLabel> toRemove = new HashSet();
 	
@@ -41,7 +41,7 @@ public class HolonInfoPanel extends JPanel {
 		}
 		for(int i=0; i<this.panels.length; i++) {
 			JPanel p = this.panels[i];
-			p.setBounds(5, 89+21*i, this.getWidth(), 20);
+			p.setBounds(5, offsetLabels+21*i, this.getWidth(), 20);
 			JLabel label = new JLabel(this.labels2[i]);
 			label.setBounds(0, 0, p.getWidth(), p.getHeight());
 			p.add(label);
@@ -54,10 +54,11 @@ public class HolonInfoPanel extends JPanel {
 		this.h = h;
 		this.labels1[0].setText("Name: "+h.name);
 		this.labels1[1].setText("UUID: "+h.getUniqueID());
-		this.labels1[2].setText("State: ");
-		this.labels1[3].setText("Superholon: "+(h.getParent() != null ? h.getParent().name : ""));
+		this.labels1[2].setText("State: "+h.holonControlUnit.getStateEstimator().getStateIndicator());
+		this.labels1[3].setText("Optimization Scheme: "+h.holonControlUnit.getOptimizer().getOptimizationScheme());
+		this.labels1[4].setText("Superholon: "+(h.getParent() != null ? h.getParent().name : ""));
 		
-		int offset = 110;
+		int offset = offsetLabels + 21;
 		for(int i=0; i<h.childHolons.size(); i++) {
 			Holon c = h.childHolons.get(i);
 			JLabel l = new JLabel(c.name+"   "+c.getUniqueID());
@@ -71,7 +72,6 @@ public class HolonInfoPanel extends JPanel {
 		this.panels[1].setLocation(5, offset);
 		offset += 21;
 		ArrayList<String> holons = h.holonControlUnit.getHierarchyController().getVirtualNeighbors();
-//		System.out.println("Holon: "+h.name+" virtual neighbors: "+holons.toString());
 		for(String s : holons) {
 //			System.out.println("id: "+s);
 			Holon c = this.control.getModel().getHolonsByID().get(s);
@@ -87,8 +87,13 @@ public class HolonInfoPanel extends JPanel {
 		offset += 21;
 		holons = h.holonControlUnit.getHierarchyController().getPhysicalNeighbors();
 		for(String s : holons) {
-			Holon c = this.control.getModel().getHolonsByID().get(s);
-			JLabel l = new JLabel(c.name+"   "+c.getUniqueID());
+			JLabel l;
+			if(s.contains("Switch")) {
+				l = new JLabel(s);
+			} else {
+				Holon c = this.control.getModel().getHolonsByID().get(s);
+				l = new JLabel(c.name+"   "+c.getUniqueID());
+			}
 			l.setBounds(5,  offset, this.getWidth(), 20);
 			this.add(l);
 			this.toRemove.add(l);
@@ -109,4 +114,10 @@ public class HolonInfoPanel extends JPanel {
 		this.repaint();
 	}
 	
+	public void update() {
+		if(this.h == null)
+			return;
+		displayInfos(this.h);
+	}
+	
 }

+ 6 - 7
src/ui/view/outliner/HolonView.java

@@ -57,7 +57,7 @@ public class HolonView extends JPanel{
 		parent.outlinerUpdate.addListener(() -> updateTreeStructure());
 	}
 
-	private void initilizePanel() {
+	public void initilizePanel() {
 		holonTree = generateTree();
 		holonTree.setCellRenderer(new HolonJtreeRenderer());
 		holonTree.setDragEnabled(true);
@@ -173,8 +173,7 @@ public class HolonView extends JPanel{
 			holon.addElement(element);
 		}
 		public void AddHolon(Holon holon) {
-			holon.removeFromParent();
-			this.holon.addChild(holon);
+			holon.split(this.holon);
 		}
 		@Override
 		public Transferable getTransferable(HolonTransferHandler handler) {
@@ -224,8 +223,8 @@ public class HolonView extends JPanel{
      	    	parent.removeChildHolon(info.holon);
      	    	Holon newHolon = new Holon("New Holon", control.getModel());
      	    	control.getModel().getHolonsByID().put(newHolon.getUniqueID(), newHolon);
-     	    	newHolon.addChild(info.holon);
-     	    	parent.addChild(newHolon);
+     	    	newHolon.merge(info.holon);
+     	    	parent.merge(newHolon);
      	    	updateTreeStructure();
  	    	});
      	   newHolonAsChildItem.addActionListener(clicked -> {
@@ -233,7 +232,7 @@ public class HolonView extends JPanel{
     	    	HolonInfo info = getInfoFromPath(path);
     	    	if(info == null) return;
     	    	Holon newHolon = new Holon("New Holon", control.getModel());
-    	    	info.holon.addChild(newHolon);
+    	    	info.holon.merge(newHolon);
      	    	control.getModel().getHolonsByID().put(newHolon.getUniqueID(), newHolon);
     	    	updateTreeStructure();
 	    	});
@@ -346,7 +345,7 @@ public class HolonView extends JPanel{
 		        try {
 		        	Holon dropHolon = ((HolonInfo) node.getUserObject()).holon;
 					Holon dragHolon = (Holon) support.getTransferable().getTransferData(holonFlavor);
-					boolean physicalConnected = dropHolon.checkHolonArePhysicalConnected(dragHolon, control);
+					boolean physicalConnected = control.getModel().checkHolonObjectsAreConnected(dragHolon, dropHolon);
 					boolean isAllStateHolon = dropHolon.getLayer() == 0;
 					return  physicalConnected || isAllStateHolon;
 				} catch (UnsupportedFlavorException | IOException e) {

+ 5 - 0
src/ui/view/outliner/Outliner.java

@@ -124,6 +124,11 @@ public class Outliner extends JFrame {
 		listPanel.revalidate();
 		statePanel.revalidate();
 		listPanel.repaint();
+		
+		if(holonView != null) {
+			holonView.revalidate();
+			holonView.repaint();
+		}
 	}