Rolf Egert 5 سال پیش
والد
کامیت
d66cc2d0fd
1فایلهای تغییر یافته به همراه812 افزوده شده و 810 حذف شده
  1. 812 810
      src/psoAlgoCode/SimulateSimulator.java

+ 812 - 810
src/psoAlgoCode/SimulateSimulator.java

@@ -1,810 +1,812 @@
-package psoAlgoCode;
-
-import classes.*;
-import classes.comparator.EnergyMinToMaxComparator;
-import classes.comparator.MinEnergyComparator;
-import classes.comparator.WeakestBattery;
-import ui.model.Model;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-
-/**
- * Controller for Simulation.
- *
- * @author Gruppe14
- */
-public class SimulateSimulator {
-	int global = 0;
-	private Model model;
-	private ArrayList<AbstractCpsObject> objectsToHandle;
-	private ArrayList<SubNet> subNets;
-	private ArrayList<CpsEdge> brokenEdges;
-	private int timeStep;
-	private HashMap<Integer, Float> tagTable = new HashMap<>();
-
-	private HashMap<HolonElement, Float> flexDevicesTurnedOnThisTurn = new HashMap<>();
-
-	/**
-	 * One Element of each HolonObject will be powered first, starting with the
-	 * smallest Demand. If ale HolonObjects have an active Element, the simulation
-	 * will try to fully supply as many HolonObjects as possible.
-	 */
-	public static final short fairnessMininumDemandFirst = 0;
-
-	/**
-	 * All HolonObjects will receive the same amount of energy.
-	 */
-	public static final short fairnessAllEqual = 1;
-
-	/**
-	 * Constructor.
-	 *
-	 * @param m
-	 *            Model
-	 */
-	SimulateSimulator(Model m) {
-		model = m;
-		subNets = new ArrayList<>();
-		brokenEdges = new ArrayList<>();
-	}
-
-	/**
-	 * calculates the flow of the edges and the supply for objects.
-	 *
-	 * @param x
-	 *            current Iteration
-	 */
-	void calculateStateForTimeStep(int x) {
-		reset();
-		timeStep = x;
-		searchForSubNets();
-		
-		/**
-		 * Some state reset stuff, seems to be very unnecessary....
-		 */
-		for (SubNet singleSubNet : subNets) {
-			if (singleSubNet.getObjects().size() == 0) {
-				resetConnections(singleSubNet.getBatteries().get(0), new ArrayList<>(), new ArrayList<>());
-			} else {
-				resetConnections(singleSubNet.getObjects().get(0), new ArrayList<>(), new ArrayList<>());
-			}
-
-		}
-		for (SubNet singleSubNet : subNets) {
-			float production = calculateEnergyWithoutFlexDevices("prod", singleSubNet, timeStep);
-			float consumption = calculateEnergyWithoutFlexDevices("cons", singleSubNet, timeStep);
-			// surplus of energy is computed by sum, since consumption is a
-			// negative value
-			float energySurplus = production + consumption;
-
-			// --------------- use flexible devices ---------------
-			if (energySurplus != 0 && model.useFlexibleDevices()) {
-				turnOnFlexibleDevices(singleSubNet, energySurplus, x);
-
-				// recompute after having examined/turned on all flexible
-				// devices
-				production = calculateEnergyWithFlexDevices("prod", singleSubNet, timeStep);
-				consumption = calculateEnergyWithFlexDevices("cons", singleSubNet, timeStep);
-				energySurplus = production + consumption;
-			}
-
-			// --------------- set flow simulation ---------------
-			setFlowSimulation(singleSubNet);
-
-			// --------------- visualise graph ---------------
-
-			/**
-			 * production of subnets, that might be partially turned on/off
-			 */
-			float currentProduction = production;
-
-			/**
-			 * energy each HolonObject receives in AlleEqualModus
-			 */
-
-			if (energySurplus >= 0) {
-				// Supply all consumer
-				for (HolonObject hO : singleSubNet.getObjects()) {
-					float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
-					if (neededEnergy < 0) {
-						hO.setCurrentSupply(-neededEnergy);
-						currentProduction -= -neededEnergy; // Subtract the Energy from the Production
-					}
-				}
-				// Supply all Batterys with the left currentProduction
-				singleSubNet.getBatteries().sort(new WeakestBattery(x));// Sort all batteries by the Value of ther
-																		// StateOfCharge/Capasity
-				for (HolonBattery hB : singleSubNet.getBatteries()) {
-					float energyToCollect = hB.getInAtTimeStep(x - 1);
-					if (currentProduction >= energyToCollect) {
-						// change StateofCharge soc = soc + energyToCollect
-						hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) + energyToCollect, x);
-						currentProduction -= energyToCollect;
-					} else {
-						// change StateofCharge soc = soc + currentProduction
-						hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) + currentProduction, x);
-						currentProduction = 0;
-						// no break must be calculatet for all break; //because no more energy
-					}
-				}
-				// Over_Supply all consumer equal
-				long nOConsumer = singleSubNet.getObjects().stream()
-						.filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
-				if (nOConsumer != 0) {
-					// energy to seperated equal
-					float EnergyOverSupplyPerHolonObject = currentProduction / nOConsumer;
-					for (HolonObject hO : singleSubNet.getObjects()) {
-						float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
-						if (neededEnergy < 0) {
-							hO.setCurrentSupply(hO.getCurrentSupply() + EnergyOverSupplyPerHolonObject);
-						}
-					}
-					currentProduction = 0;
-				}
-			} else {
-				// Check all Battries what they can provide
-				if (energySurplus + GetOutAllBatteries(singleSubNet.getBatteries(), x) >= 0) {
-					singleSubNet.getBatteries().sort(new WeakestBattery(x));// .reverse();
-					Collections.reverse(singleSubNet.getBatteries()); // most supplyed first
-					// Get the NEEDED energy
-					for (HolonBattery hB : singleSubNet.getBatteries()) {
-						float neededEnergyFromBattery = currentProduction + consumption; // Energy is negativ
-						float maxEnergyAvailable = hB.getOutAtTimeStep(x - 1); // energy is positiv
-						if (maxEnergyAvailable >= -neededEnergyFromBattery) {
-							// change StateofCharge soc = soc - -neededEnergyFromBattery
-							hB.setStateOfChargeAtTimeStep(
-									hB.getStateOfChargeAtTimeStep(x - 1) - -neededEnergyFromBattery, x);
-							currentProduction += -neededEnergyFromBattery;
-							// no break must be calculatet for all beabreak; //When a energy can supply the
-							// last needed energy break;
-						} else {
-							// change StateofCharge soc = soc - maxEnergyAvailable
-							hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) - maxEnergyAvailable, x);
-							currentProduction += maxEnergyAvailable;
-						}
-					}
-					// Supply all consumer all ar in state Supplied no one is oversupplied because
-					// just the energy that is needed is gained from the batteries
-					for (HolonObject hO : singleSubNet.getObjects()) {
-						float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
-						if (neededEnergy < 0) {
-							hO.setCurrentSupply(-neededEnergy);
-							currentProduction -= -neededEnergy; // Subtract the Energy from the Production
-						}
-					}
-				} else // Objects have to be partially supplied
-				{
-					// Get all Energy out of battries as possible
-					for (HolonBattery hB : singleSubNet.getBatteries()) {
-						float maxEnergyAvailable = hB.getOutAtTimeStep(x - 1); // energy is positiv
-						// change StateofCharge soc = soc - maxEnergyAvailable
-						hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) - maxEnergyAvailable, x);
-						currentProduction += maxEnergyAvailable;
-					}
-					// Calc
-					singleSubNet.getObjects().stream().forEach(hl -> hl.setCurrentSupply(0));
-					if (model.getFairnessModel() == fairnessAllEqual) {
-						long nOConsumer = singleSubNet.getObjects().stream()
-								.filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
-						float energyPerHolonObject = 0;
-						if (nOConsumer != 0)
-							energyPerHolonObject = currentProduction / nOConsumer;
-						for (HolonObject hO : singleSubNet.getObjects()) {
-							if (hO.getCurrentEnergyAtTimeStep(x) < 0) // Just Consumer need Energy
-							{
-								hO.setCurrentSupply(energyPerHolonObject);
-								currentProduction -= energyPerHolonObject; // Subtract the Energy from the Production
-							}
-						}
-					} else // (model.getFairnessModel() == fairnessMininumDemandFirst)
-					{
-						singleSubNet.getObjects().sort(new MinEnergyComparator(x));
-						// SupplyAllMinimumEnergy
-						for (HolonObject hO : singleSubNet.getObjects()) {
-							if (hO.checkIfPartiallySupplied(x))
-								continue;
-							if (hO.getCurrentEnergyAtTimeStep(x) > 0)
-								continue;
-							float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x); // Energy from getMinEnergy is negative -> convert to
-																	// positive
-							if (minEnergy <= currentProduction) {
-								hO.setCurrentSupply(minEnergy);
-								currentProduction -= minEnergy;
-							} else {
-								hO.setCurrentSupply(currentProduction);
-								currentProduction = 0;
-								break;
-							}
-						}
-						singleSubNet.getObjects().sort(new EnergyMinToMaxComparator(x));
-						// supplyFullytillEnd ... because its cant be fully supplied
-						for (HolonObject hO : singleSubNet.getObjects()) {
-
-							float actualSupplyEnergy = hO.getCurrentSupply();
-							float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x) - actualSupplyEnergy;
-							if (neededEnergy <= 0)
-								continue; // Producer or No EnergyNeeded
-							if (neededEnergy <= currentProduction) {
-								hO.setCurrentSupply(neededEnergy + actualSupplyEnergy);
-								currentProduction -= neededEnergy;
-							} else {
-								hO.setCurrentSupply(currentProduction + actualSupplyEnergy);
-								currentProduction = 0;
-								break;
-							}
-						}
-
-					}
-				}
-
-			}
-			// Visualize the Color
-			for (HolonObject hO : singleSubNet.getObjects()) {
-				float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x); // convert negative energy in positive for
-																		// calculations
-				if (neededEnergy < 0) {
-					hO.setState(HolonObject.PRODUCER);
-				} else if (neededEnergy > 0) {
-					float currentSupply = hO.getCurrentSupply();
-					if (currentSupply > neededEnergy) {
-						hO.setState(HolonObject.OVER_SUPPLIED);
-					} else if (currentSupply == neededEnergy) {
-						hO.setState(HolonObject.SUPPLIED);
-					} else if (currentSupply < neededEnergy) {
-						float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x);
-						if (currentSupply >= minEnergy || hO.getSelfMadeEnergy(x) >= minEnergy) {
-							hO.setState(HolonObject.PARTIALLY_SUPPLIED);
-						} else {
-							hO.setState(HolonObject.NOT_SUPPLIED);
-						}
-					}
-				} else if (neededEnergy == 0) {
-					hO.setState(HolonObject.NO_ENERGY);
-				}
-			}
-		}
-	}
-
-	/**
-	 * add all battries.getOut() from a list of battries and return them
-	 * 
-	 * @param aL
-	 *            a List of HolonBattries likely from subnet.getBatteries()
-	 * @param x
-	 *            TimeStep
-	 * @return
-	 * 
-	 */
-	private float GetOutAllBatteries(ArrayList<HolonBattery> aL, int x) {
-		float OutEnergy = 0;
-		for (HolonBattery hB : aL) {
-			OutEnergy += hB.getOutAtTimeStep(x - 1);
-		}
-		return OutEnergy;
-	}
-
-	/**
-	 * search for all flexible devices in the network and turn them on, until energy
-	 * surplus = 0 or all devices have been examined.
-	 *
-	 * This code could be compressed (cases inside over- and underproduction are the
-	 * same), but we decided that it is better readable this way
-	 *
-	 * @param subNet
-	 *            the subnet
-	 * @param energySurplus
-	 *            the current surplus of energy
-	 */
-	private void turnOnFlexibleDevices(SubNet subNet, float energySurplus, int timestep) {
-		for (HolonObject holonOb : subNet.getObjects()) {
-			for (HolonElement holonEl : holonOb.getElements()) {
-
-				// if this element is flexible and active (can be considered for
-				// calculations)
-				if (holonEl.isFlexible() && holonEl.isActive()) {
-					float energyAvailableSingle = holonEl.getAvailableEnergyAt(timestep);
-					float energyAvailableMultiple = energyAvailableSingle * holonEl.getAmount();
-
-					// ------------- flexible consumer / OVERPRODUCTION
-					// -------------
-					if (energyAvailableMultiple < 0 && energySurplus > 0) {
-
-						// if there is more wasted energy than energy that this
-						// device can give, give all energy available
-						if (Math.abs(energyAvailableMultiple) <= Math.abs(energySurplus)) {
-							energySurplus += energyAvailableMultiple;
-							// set the new energy consumption to the maximum
-							holonEl.setEnergyPerElement(energyAvailableSingle);
-							flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple);
-						}
-						// else: we just need to turn on part of the flexible
-						// energy available
-						else {
-							float energyNeeded = -energySurplus;
-							energySurplus += energyNeeded; // should give 0, but
-															// was kept this was
-															// for consistency
-							// the energy needed divided through the amount of
-							// elements
-							holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount());
-							flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded);
-						}
-					}
-
-					// ------------- flexible producer / UNDERPRODUCTION
-					// -------------
-					else if (energyAvailableMultiple > 0 && energySurplus < 0) {
-
-						// if there is more energy needed than this device can
-						// give, give all the energy available
-						if (Math.abs(energyAvailableMultiple) <= Math.abs(energySurplus)) {
-							energySurplus += energyAvailableMultiple;
-							// set the new energy consumption to the maximum
-							holonEl.setEnergyPerElement(energyAvailableSingle);
-							flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple);
-						}
-						// else: we just need to turn on part of the flexible
-						// energy available
-						else {
-							float energyNeeded = -energySurplus;
-							int i = 0;
-							energySurplus += energyNeeded; // should give 0, but
-															// was kept this was
-															// for consistency
-							// the energy needed divided through the amount of
-							// elements
-							holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount());
-							flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded);
-						}
-
-					}
-				}
-
-				if (energySurplus == 0) {
-					break;
-				}
-			}
-
-			if (energySurplus == 0) {
-				break;
-			}
-		}
-	}
-
-	/**
-	 * Set Flow Simulation.
-	 *
-	 * @param sN
-	 *            Subnet
-	 */
-	private void setFlowSimulation(SubNet sN) {
-		ArrayList<AbstractCpsObject> producers = new ArrayList<>();
-		AbstractCpsObject tmp = null;
-		tagTable = new HashMap<>();
-		// traverse all objects in this subnet
-		for (HolonObject hl : sN.getObjects()) {
-			float energy = hl.getCurrentEnergyAtTimeStep(timeStep);
-			// if their production is higher than their consumption
-			if (energy > 0) {
-				tagTable.put(hl.getId(), energy);
-				hl.addTag(hl.getId());
-				for (CpsEdge edge : hl.getConnections()) {
-					if (edge.isWorking()) {
-						// set other end of edge as tmp-object
-						// and add this end to the other end's tag-list
-						AbstractCpsObject a = edge.getA();
-						AbstractCpsObject b = edge.getB();
-						if (a.getId() == hl.getId()) {
-							b.addTag(hl.getId());
-							tmp = b;
-						}
-						if (b.getId() == hl.getId()) {
-							a.addTag(hl.getId());
-							tmp = a;
-						}
-
-						edge.setFlow(edge.getFlow() + energy);
-						edge.calculateState();
-						edge.addTag(hl.getId());
-						if (edge.isWorking() && !producers.contains(tmp)) {
-							if (tmp instanceof HolonSwitch) {
-								if (((HolonSwitch) tmp).getState(timeStep)) {
-									producers.add(tmp);
-								}
-							} else if (!(tmp instanceof CpsUpperNode)) {
-								producers.add(tmp);
-							}
-						}
-					}
-				}
-			}
-		}
-		setFlowSimRec(producers, 0);
-	}
-
-	/**
-	 * Set Flow Simulation Rec.
-	 *
-	 * @param nodes
-	 *            the nodes
-	 * @param iter
-	 *            the Iteration
-	 */
-	private void setFlowSimRec(ArrayList<AbstractCpsObject> nodes, int iter) {
-		ArrayList<AbstractCpsObject> newNodes = new ArrayList<>();
-		ArrayList<CpsEdge> changedEdges = new ArrayList<>();
-		AbstractCpsObject tmp;
-		if (nodes.size() != 0) {
-			for (AbstractCpsObject cps : nodes) {
-				// check whether the cps is in a legit state if it is a switch
-				if (legitState(cps)) {
-					for (CpsEdge edge : cps.getConnections()) {
-						// is edge working
-						// and does the edge's tag-list not (yet) contain all
-						// tags of the cps
-						if (edge.isWorking() && (!(edge.containsTags(edge.getTags(), cps.getTag())))) {
-							if (edge.getA().getId() == cps.getId()) {
-								tmp = edge.getB();
-							} else {
-								tmp = edge.getA();
-							}
-							for (Integer tag : cps.getTag()) {
-								if (!(edge.getTags().contains(tag)) && !(edge.getPseudoTags().contains(tag))) {
-									edge.setFlow(edge.getFlow() + tagTable.get(tag));
-									edge.addTag(tag);
-								}
-							}
-							// uppernodes do not spread energy
-							if (!(tmp instanceof CpsUpperNode)) {
-								for (Integer tag : tmp.getTag()) {
-									if (!(edge.getTags().contains(tag)) && tagTable.get(tag) != null
-											&& !(edge.getPseudoTags().contains(tag))) {
-										edge.setFlow(edge.getFlow() + tagTable.get(tag));
-										edge.addPseudoTag(tag);
-										changedEdges.add(edge);
-									}
-								}
-							}
-							edge.calculateState();
-							if (edge.isWorking() && !(tmp instanceof CpsUpperNode)) {
-								tmp.addAllPseudoTags(cps.getTag());
-								if (!newNodes.contains(tmp)) {
-									newNodes.add(tmp);
-								}
-							}
-						}
-					}
-				}
-			}
-			setPseudoTags(newNodes, changedEdges);
-			setFlowSimRec(newNodes, iter + 1);
-		}
-	}
-
-	/**
-	 * Set the Pseudo Tags.
-	 *
-	 * @param nodes
-	 *            Array of AbstractCpsObjects
-	 */
-	private void setPseudoTags(ArrayList<AbstractCpsObject> nodes, ArrayList<CpsEdge> edges) {
-		for (AbstractCpsObject node : nodes) {
-			node.recalculateTags();
-			node.setPseudoTags(new ArrayList<>());
-		}
-		for (CpsEdge edge : edges) {
-			edge.recalculateTags();
-			edge.setPseudoTag(new ArrayList<>());
-		}
-	}
-
-	/**
-	 * Reset the Connection.
-	 *
-	 * @param cps
-	 *            CpsObject
-	 * @param visitedObj
-	 *            the visited Objects
-	 * @param visitedEdges
-	 *            the visited Edges
-	 */
-	private void resetConnections(AbstractCpsObject cps, ArrayList<Integer> visitedObj,
-			ArrayList<CpsEdge> visitedEdges) {
-		visitedObj.add(cps.getId());
-		cps.resetTags();
-		for (CpsEdge e : cps.getConnections()) {
-			if (!(visitedEdges.contains(e))) {
-				e.setFlow(0);
-				e.calculateState();
-				e.setTags(new ArrayList<>());
-				visitedEdges.add(e);
-				if (!(visitedObj.contains(e.getA().getId()))) {
-					resetConnections(e.getA(), visitedObj, visitedEdges);
-					e.getA().resetTags();
-				}
-				if (!(visitedObj.contains(e.getB().getId()))) {
-					resetConnections(e.getB(), visitedObj, visitedEdges);
-					e.getB().resetTags();
-				}
-			}
-		}
-	}
-
-	/**
-	 * calculates the energy of either all producers or consumers. Flexible devices
-	 * are filtered out
-	 *
-	 * @param type
-	 *            Type
-	 * @param sN
-	 *            Subnet
-	 * @param x
-	 *            Integer
-	 * @return The Energy
-	 */
-	private float calculateEnergyWithoutFlexDevices(String type, SubNet sN, int x) {
-		float energy = 0;
-		for (HolonObject hl : sN.getObjects()) {
-			float currentEnergyWithoutFlexibles = hl.getCurrentEnergyAtTimeStepWithoutFlexiblesAndResetFlexibles(x);
-
-			if (type.equals("prod")) {
-				if (currentEnergyWithoutFlexibles > 0) {
-					energy += currentEnergyWithoutFlexibles;
-					hl.setState(HolonObject.PRODUCER);
-				}
-			}
-			if (type.equals("cons")) {
-				if (currentEnergyWithoutFlexibles < 0) {
-					energy += currentEnergyWithoutFlexibles;
-					hl.setState(HolonObject.NOT_SUPPLIED);
-				}
-			}
-			if (currentEnergyWithoutFlexibles == 0) {
-				hl.setState(HolonObject.NO_ENERGY);
-			}
-		}
-		return energy;
-	}
-
-	/**
-	 * calculates the energy of either all producers or consumers. Flexible devices
-	 * are filtered out
-	 *
-	 * @param type
-	 *            Type
-	 * @param sN
-	 *            Subnet
-	 * @param x
-	 *            Integer
-	 * @return The Energy
-	 */
-	private float calculateEnergyWithFlexDevices(String type, SubNet sN, int x) {
-		float energy = 0;
-		for (HolonObject hl : sN.getObjects()) {
-			float currentEnergy = hl.getCurrentEnergyAtTimeStep(x);
-
-			if (type.equals("prod")) {
-				if (currentEnergy > 0) {
-					energy += currentEnergy;
-					hl.setState(HolonObject.PRODUCER);
-				}
-			}
-			if (type.equals("cons")) {
-				if (currentEnergy < 0) {
-					energy = energy + currentEnergy;
-					hl.setState(HolonObject.NOT_SUPPLIED);
-				}
-			}
-			if (currentEnergy == 0) {
-				hl.setState(HolonObject.NO_ENERGY);
-			}
-		}
-		return energy;
-	}
-
-	/**
-	 * generates all subNets from all objectsToHandle.
-	 */
-	private void searchForSubNets() {
-		subNets = new ArrayList<>();
-		brokenEdges.clear();
-		boolean end = false;
-		int i = 0;
-		AbstractCpsObject cps;
-		if (objectsToHandle.size() > 0) {
-			while (!end) {
-				cps = objectsToHandle.get(i);
-				SubNet singleSubNet = new SubNet(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(),
-						new ArrayList<>());
-				singleSubNet = buildSubNet(cps, new ArrayList<>(), singleSubNet);
-				if (singleSubNet.getObjects().size() + singleSubNet.getBatteries().size() != 0) {
-					subNets.add(singleSubNet);
-				}
-				if (0 == objectsToHandle.size()) {
-					end = true;
-				}
-			}
-		}
-	}
-
-	/**
-	 * recursivly generates a subnet of all objects, that one specific object is
-	 * connected to.
-	 *
-	 * @param cps
-	 *            AbstractCpsObject
-	 * @param visited
-	 *            visited Array of Integer
-	 * @param sN
-	 *            Subnets
-	 * @return Subnet
-	 */
-	private SubNet buildSubNet(AbstractCpsObject cps, ArrayList<Integer> visited, SubNet sN) {
-		visited.add(cps.getId());
-		if (cps instanceof HolonObject) {
-			sN.getObjects().add((HolonObject) cps);
-		}
-		if (cps instanceof HolonSwitch) {
-			sN.getSwitches().add((HolonSwitch) cps);
-		}
-		if (cps instanceof HolonBattery) {
-			sN.getBatteries().add((HolonBattery) cps);
-		}
-		removeFromToHandle(cps.getId());
-		AbstractCpsObject a;
-		AbstractCpsObject b;
-		for (CpsEdge edge : cps.getConnections()) {
-			if (edge.isWorking()) {
-				a = edge.getA();
-				b = edge.getB();
-				if (!(cps instanceof HolonSwitch)) {
-					if (!(sN.getEdges().contains(edge))) {
-						sN.getEdges().add(edge);
-					}
-				}
-				if (cps instanceof HolonSwitch && ((HolonSwitch) cps).getState(timeStep)) {
-					if (!(sN.getEdges().contains(edge))) {
-						sN.getEdges().add(edge);
-					}
-				}
-				if (!visited.contains(a.getId()) && legitState(cps) && !(a instanceof CpsUpperNode)) {
-					sN = buildSubNet(a, visited, sN);
-				}
-				if (!visited.contains(b.getId()) && legitState(cps) && !(b instanceof CpsUpperNode)) {
-					sN = buildSubNet(b, visited, sN);
-				}
-				if (a instanceof CpsUpperNode && a.getId() != cps.getId()) {
-					edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
-					checkForConnectedStates(b, (CpsUpperNode) a, edge);
-				}
-				if (b instanceof CpsUpperNode && b.getId() != cps.getId()) {
-					edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
-					checkForConnectedStates(a, (CpsUpperNode) b, edge);
-				}
-			} else {
-				brokenEdges.add(edge);
-			}
-		}
-		return sN;
-	}
-
-	/**
-	 * is the Switch in a legitimate State.
-	 *
-	 * @param current
-	 *            AbstractCpsObject
-	 * @return boolean
-	 */
-	private boolean legitState(AbstractCpsObject current) {
-		return !(current instanceof HolonSwitch) || ((HolonSwitch) current).getState(timeStep);
-	}
-
-	// /**
-	// * ensures that objectsToHandle only contains HolonObjects.
-	// */
-	// public void cleanObjectsToHandle() {
-	// for (int i = 0; i < objectsToHandle.size(); i++) {
-	// if (!(objectsToHandle.get(i) instanceof HolonObject)) {
-	// objectsToHandle.remove(i);
-	// }
-	// }
-	// }
-
-	/**
-	 * removes an Object that already has been handled.
-	 *
-	 * @param id
-	 *            the Object ID
-	 */
-	private void removeFromToHandle(int id) {
-		for (int i = 0; i < objectsToHandle.size(); i++) {
-			if (objectsToHandle.get(i).getId() == id) {
-				objectsToHandle.remove(i);
-			}
-		}
-	}
-
-	/**
-	 * copies the data of an array of Objects.
-	 *
-	 * @param toCopy
-	 *            the ArrayList of CpsObjects co Copy
-	 */
-	private void copyObjects(ArrayList<AbstractCpsObject> toCopy) {
-		for (AbstractCpsObject cps : toCopy) {
-			if (cps instanceof CpsUpperNode) {
-				copyObjects(((CpsUpperNode) cps).getNodes());
-			} else {
-				objectsToHandle.add(cps);
-			}
-		}
-	}
-
-	/**
-	 * Reset all Data to the current state of the Model.
-	 */
-	public void reset() {
-		objectsToHandle = new ArrayList<>();
-		copyObjects(model.getObjectsOnCanvas());
-		flexDevicesTurnedOnThisTurn = new HashMap<>();
-	}
-
-	/**
-	 * Resets the State of all Edges
-	 */
-	private void resetEdges() {
-		for (CpsEdge e : brokenEdges) {
-			e.setWorkingState(true);
-		}
-	}
-
-	/**
-	 * Resets the State for the whole Simulation Model
-	 */
-	void resetSimulation() {
-		reset();
-		resetEdges();
-	}
-
-	/**
-	 * Get all Subnets.
-	 *
-	 * @return all Subnets
-	 */
-	public ArrayList<SubNet> getSubNets() {
-		return subNets;
-	}
-
-	/**
-	 * Get broken Edges
-	 */
-	// public ArrayList<CpsEdge> getBrokenEdges() {
-	// return brokenEdges;
-	// }
-
-	/**
-	 * checks whether a given object is connected to an object inside the upperNode.
-	 * if yes, the state for the edge is changed in "connected" or "not connected"
-	 */
-	private void checkForConnectedStates(AbstractCpsObject cps, CpsUpperNode cUNode, CpsEdge theEdge) {
-		AbstractCpsObject tmp;
-		for (CpsEdge edge : cps.getConnections()) {
-			if (edge.getA().getId() == cps.getId()) {
-				tmp = edge.getB();
-			} else {
-				tmp = edge.getA();
-			}
-			if (cUNode.getNodes().contains(tmp)) {
-				if (tmp instanceof CpsUpperNode) {
-					checkForConnectedStates(cps, (CpsUpperNode) tmp, theEdge);
-				} else {
-					theEdge.setConnected(CpsEdge.CON_UPPER_NODE_AND_INSIDE);
-					break;
-				}
-			}
-		}
-	}
-
-}
+package psoAlgoCode;
+
+import classes.*;
+import classes.comparator.EnergyMinToMaxComparator;
+import classes.comparator.MinEnergyComparator;
+import classes.comparator.WeakestBattery;
+import ui.model.Model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+
+/**
+ * Controller for Simulation.
+ *
+ * @author Gruppe14
+ */
+public class SimulateSimulator {
+	int global = 0;
+	private Model model;
+	private ArrayList<AbstractCpsObject> objectsToHandle;
+	private ArrayList<SubNet> subNets;
+	private ArrayList<CpsEdge> brokenEdges;
+	private int timeStep;
+	private HashMap<Integer, Float> tagTable = new HashMap<>();
+
+	private HashMap<HolonElement, Float> flexDevicesTurnedOnThisTurn = new HashMap<>();
+
+	/**
+	 * One Element of each HolonObject will be powered first, starting with the
+	 * smallest Demand. If ale HolonObjects have an active Element, the simulation
+	 * will try to fully supply as many HolonObjects as possible.
+	 */
+	public static final short fairnessMininumDemandFirst = 0;
+
+	/**
+	 * All HolonObjects will receive the same amount of energy.
+	 */
+	public static final short fairnessAllEqual = 1;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param m
+	 *            Model
+	 */
+	SimulateSimulator(Model m) {
+		model = m;
+		subNets = new ArrayList<>();
+		brokenEdges = new ArrayList<>();
+	}
+
+	/**
+	 * calculates the flow of the edges and the supply for objects.
+	 *
+	 * @param x
+	 *            current Iteration
+	 */
+	void calculateStateForTimeStep(int x) {
+		reset();
+		timeStep = x;
+		searchForSubNets();
+		
+		/**
+		 * Some state reset stuff, seems to be very unnecessary.... COMMENT THIS IN IF STRANGE CALCULATION STUFF HAPPENS
+		 */
+		/*for (SubNet singleSubNet : subNets) {
+			if (singleSubNet.getObjects().size() == 0) {
+				resetConnections(singleSubNet.getBatteries().get(0), new ArrayList<>(), new ArrayList<>());
+			} else {
+				resetConnections(singleSubNet.getObjects().get(0), new ArrayList<>(), new ArrayList<>());
+			}
+
+		}*/
+		for (SubNet singleSubNet : subNets) {
+			float production = calculateEnergyWithoutFlexDevices("prod", singleSubNet, timeStep);
+			float consumption = calculateEnergyWithoutFlexDevices("cons", singleSubNet, timeStep);
+			// surplus of energy is computed by sum, since consumption is a
+			// negative value
+			float energySurplus = production + consumption;
+
+			// --------------- use flexible devices ---------------
+			/*if (energySurplus != 0 && model.useFlexibleDevices()) {
+				turnOnFlexibleDevices(singleSubNet, energySurplus, x);
+
+				// recompute after having examined/turned on all flexible
+				// devices
+				production = calculateEnergyWithFlexDevices("prod", singleSubNet, timeStep);
+				consumption = calculateEnergyWithFlexDevices("cons", singleSubNet, timeStep);
+				energySurplus = production + consumption;
+			}*/
+
+			// --------------- set flow simulation ---------------
+			setFlowSimulation(singleSubNet);
+
+			// --------------- visualise graph ---------------
+
+			/**
+			 * production of subnets, that might be partially turned on/off
+			 */
+			float currentProduction = production;
+
+			/**
+			 * energy each HolonObject receives in AlleEqualModus
+			 */
+
+			if (energySurplus >= 0) {
+				// Supply all consumer
+				for (HolonObject hO : singleSubNet.getObjects()) {
+					float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
+					if (neededEnergy < 0) {
+						hO.setCurrentSupply(-neededEnergy);
+						currentProduction -= -neededEnergy; // Subtract the Energy from the Production
+					}
+				}
+				// Supply all Batterys with the left currentProduction
+				singleSubNet.getBatteries().sort(new WeakestBattery(x));// Sort all batteries by the Value of ther
+																		// StateOfCharge/Capasity
+				for (HolonBattery hB : singleSubNet.getBatteries()) {
+					float energyToCollect = hB.getInAtTimeStep(x - 1);
+					if (currentProduction >= energyToCollect) {
+						// change StateofCharge soc = soc + energyToCollect
+						hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) + energyToCollect, x);
+						currentProduction -= energyToCollect;
+					} else {
+						// change StateofCharge soc = soc + currentProduction
+						hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) + currentProduction, x);
+						currentProduction = 0;
+						// no break must be calculatet for all break; //because no more energy
+					}
+				}
+				// Over_Supply all consumer equal
+				long nOConsumer = singleSubNet.getObjects().stream()
+						.filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
+				if (nOConsumer != 0) {
+					// energy to seperated equal
+					float EnergyOverSupplyPerHolonObject = currentProduction / nOConsumer;
+					for (HolonObject hO : singleSubNet.getObjects()) {
+						float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
+						if (neededEnergy < 0) {
+							hO.setCurrentSupply(hO.getCurrentSupply() + EnergyOverSupplyPerHolonObject);
+						}
+					}
+					currentProduction = 0;
+				}
+			} else {
+				// Check all Battries what they can provide
+				if (energySurplus + GetOutAllBatteries(singleSubNet.getBatteries(), x) >= 0) {
+					singleSubNet.getBatteries().sort(new WeakestBattery(x));// .reverse();
+					Collections.reverse(singleSubNet.getBatteries()); // most supplyed first
+					// Get the NEEDED energy
+					for (HolonBattery hB : singleSubNet.getBatteries()) {
+						float neededEnergyFromBattery = currentProduction + consumption; // Energy is negativ
+						float maxEnergyAvailable = hB.getOutAtTimeStep(x - 1); // energy is positiv
+						if (maxEnergyAvailable >= -neededEnergyFromBattery) {
+							// change StateofCharge soc = soc - -neededEnergyFromBattery
+							hB.setStateOfChargeAtTimeStep(
+									hB.getStateOfChargeAtTimeStep(x - 1) - -neededEnergyFromBattery, x);
+							currentProduction += -neededEnergyFromBattery;
+							// no break must be calculatet for all beabreak; //When a energy can supply the
+							// last needed energy break;
+						} else {
+							// change StateofCharge soc = soc - maxEnergyAvailable
+							hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) - maxEnergyAvailable, x);
+							currentProduction += maxEnergyAvailable;
+						}
+					}
+					// Supply all consumer all ar in state Supplied no one is oversupplied because
+					// just the energy that is needed is gained from the batteries
+					for (HolonObject hO : singleSubNet.getObjects()) {
+						float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
+						if (neededEnergy < 0) {
+							hO.setCurrentSupply(-neededEnergy);
+							currentProduction -= -neededEnergy; // Subtract the Energy from the Production
+						}
+					}
+				} else // Objects have to be partially supplied
+				{
+					// Get all Energy out of battries as possible
+					for (HolonBattery hB : singleSubNet.getBatteries()) {
+						float maxEnergyAvailable = hB.getOutAtTimeStep(x - 1); // energy is positiv
+						// change StateofCharge soc = soc - maxEnergyAvailable
+						hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x - 1) - maxEnergyAvailable, x);
+						currentProduction += maxEnergyAvailable;
+					}
+					// Calc
+					singleSubNet.getObjects().stream().forEach(hl -> hl.setCurrentSupply(0));
+					if (model.getFairnessModel() == fairnessAllEqual) {
+						long nOConsumer = singleSubNet.getObjects().stream()
+								.filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
+						float energyPerHolonObject = 0;
+						if (nOConsumer != 0)
+							energyPerHolonObject = currentProduction / nOConsumer;
+						for (HolonObject hO : singleSubNet.getObjects()) {
+							if (hO.getCurrentEnergyAtTimeStep(x) < 0) // Just Consumer need Energy
+							{
+								hO.setCurrentSupply(energyPerHolonObject);
+								currentProduction -= energyPerHolonObject; // Subtract the Energy from the Production
+							}
+						}
+					} else // (model.getFairnessModel() == fairnessMininumDemandFirst)
+					{
+						singleSubNet.getObjects().sort(new MinEnergyComparator(x));
+						// SupplyAllMinimumEnergy
+						for (HolonObject hO : singleSubNet.getObjects()) {
+							if (hO.checkIfPartiallySupplied(x))
+								continue;
+							if (hO.getCurrentEnergyAtTimeStep(x) > 0)
+								continue;
+							float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x); // Energy from getMinEnergy is negative -> convert to
+																	// positive
+							if (minEnergy <= currentProduction) {
+								hO.setCurrentSupply(minEnergy);
+								currentProduction -= minEnergy;
+							} else {
+								hO.setCurrentSupply(currentProduction);
+								currentProduction = 0;
+								break;
+							}
+						}
+						singleSubNet.getObjects().sort(new EnergyMinToMaxComparator(x));
+						// supplyFullytillEnd ... because its cant be fully supplied
+						for (HolonObject hO : singleSubNet.getObjects()) {
+
+							float actualSupplyEnergy = hO.getCurrentSupply();
+							float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x) - actualSupplyEnergy;
+							if (neededEnergy <= 0)
+								continue; // Producer or No EnergyNeeded
+							if (neededEnergy <= currentProduction) {
+								hO.setCurrentSupply(neededEnergy + actualSupplyEnergy);
+								currentProduction -= neededEnergy;
+							} else {
+								hO.setCurrentSupply(currentProduction + actualSupplyEnergy);
+								currentProduction = 0;
+								break;
+							}
+						}
+
+					}
+				}
+
+			}
+			// Visualize the Color
+			for (HolonObject hO : singleSubNet.getObjects()) {
+				float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x); // convert negative energy in positive for
+																		// calculations
+				if (neededEnergy < 0) {
+					hO.setState(HolonObject.PRODUCER);
+				} else if (neededEnergy > 0) {
+					float currentSupply = hO.getCurrentSupply();
+					if (currentSupply > neededEnergy) {
+						hO.setState(HolonObject.OVER_SUPPLIED);
+					} else if (currentSupply == neededEnergy) {
+						hO.setState(HolonObject.SUPPLIED);
+					} else if (currentSupply < neededEnergy) {
+						float minEnergy = -hO.getMinEnergyNecessaryAtTimestep(x);
+						if (currentSupply >= minEnergy || hO.getSelfMadeEnergy(x) >= minEnergy) {
+							hO.setState(HolonObject.PARTIALLY_SUPPLIED);
+						} else {
+							hO.setState(HolonObject.NOT_SUPPLIED);
+						}
+					}
+				} else if (neededEnergy == 0) {
+					hO.setState(HolonObject.NO_ENERGY);
+				}
+			}
+		}
+	}
+
+	/**
+	 * add all battries.getOut() from a list of battries and return them
+	 * 
+	 * @param aL
+	 *            a List of HolonBattries likely from subnet.getBatteries()
+	 * @param x
+	 *            TimeStep
+	 * @return
+	 * 
+	 */
+	private float GetOutAllBatteries(ArrayList<HolonBattery> aL, int x) {
+		float OutEnergy = 0;
+		for (HolonBattery hB : aL) {
+			OutEnergy += hB.getOutAtTimeStep(x - 1);
+		}
+		return OutEnergy;
+	}
+
+	/**
+	 * search for all flexible devices in the network and turn them on, until energy
+	 * surplus = 0 or all devices have been examined.
+	 *
+	 * This code could be compressed (cases inside over- and underproduction are the
+	 * same), but we decided that it is better readable this way
+	 *
+	 * @param subNet
+	 *            the subnet
+	 * @param energySurplus
+	 *            the current surplus of energy
+	 */
+	private void turnOnFlexibleDevices(SubNet subNet, float energySurplus, int timestep) {
+		for (HolonObject holonOb : subNet.getObjects()) {
+			for (HolonElement holonEl : holonOb.getElements()) {
+
+				// if this element is flexible and active (can be considered for
+				// calculations)
+				if (holonEl.isFlexible() && holonEl.isActive()) {
+					float energyAvailableSingle = holonEl.getAvailableEnergyAt(timestep);
+					float energyAvailableMultiple = energyAvailableSingle * holonEl.getAmount();
+
+					// ------------- flexible consumer / OVERPRODUCTION
+					// -------------
+					if (energyAvailableMultiple < 0 && energySurplus > 0) {
+
+						// if there is more wasted energy than energy that this
+						// device can give, give all energy available
+						if (Math.abs(energyAvailableMultiple) <= Math.abs(energySurplus)) {
+							energySurplus += energyAvailableMultiple;
+							// set the new energy consumption to the maximum
+							holonEl.setEnergyPerElement(energyAvailableSingle);
+							flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple);
+						}
+						// else: we just need to turn on part of the flexible
+						// energy available
+						else {
+							float energyNeeded = -energySurplus;
+							energySurplus += energyNeeded; // should give 0, but
+															// was kept this was
+															// for consistency
+							// the energy needed divided through the amount of
+							// elements
+							holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount());
+							flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded);
+						}
+					}
+
+					// ------------- flexible producer / UNDERPRODUCTION
+					// -------------
+					else if (energyAvailableMultiple > 0 && energySurplus < 0) {
+
+						// if there is more energy needed than this device can
+						// give, give all the energy available
+						if (Math.abs(energyAvailableMultiple) <= Math.abs(energySurplus)) {
+							energySurplus += energyAvailableMultiple;
+							// set the new energy consumption to the maximum
+							holonEl.setEnergyPerElement(energyAvailableSingle);
+							flexDevicesTurnedOnThisTurn.put(holonEl, energyAvailableMultiple);
+						}
+						// else: we just need to turn on part of the flexible
+						// energy available
+						else {
+							float energyNeeded = -energySurplus;
+							int i = 0;
+							energySurplus += energyNeeded; // should give 0, but
+															// was kept this was
+															// for consistency
+							// the energy needed divided through the amount of
+							// elements
+							holonEl.setEnergyPerElement(energyNeeded / holonEl.getAmount());
+							flexDevicesTurnedOnThisTurn.put(holonEl, energyNeeded);
+						}
+
+					}
+				}
+
+				if (energySurplus == 0) {
+					break;
+				}
+			}
+
+			if (energySurplus == 0) {
+				break;
+			}
+		}
+	}
+
+	/**
+	 * Set Flow Simulation.
+	 *
+	 * @param sN
+	 *            Subnet
+	 */
+	private void setFlowSimulation(SubNet sN) {
+		ArrayList<AbstractCpsObject> producers = new ArrayList<>();
+		AbstractCpsObject tmp = null;
+		tagTable = new HashMap<>();
+		// traverse all objects in this subnet
+		for (HolonObject hl : sN.getObjects()) {
+			float energy = hl.getCurrentEnergyAtTimeStep(timeStep);
+			// if their production is higher than their consumption
+			if (energy > 0) {
+				tagTable.put(hl.getId(), energy);
+				hl.addTag(hl.getId());
+				for (CpsEdge edge : hl.getConnections()) {
+					if (edge.isWorking()) {
+						// set other end of edge as tmp-object
+						// and add this end to the other end's tag-list
+						AbstractCpsObject a = edge.getA();
+						AbstractCpsObject b = edge.getB();
+						if (a.getId() == hl.getId()) {
+							b.addTag(hl.getId());
+							tmp = b;
+						}
+						if (b.getId() == hl.getId()) {
+							a.addTag(hl.getId());
+							tmp = a;
+						}
+
+						edge.setFlow(edge.getFlow() + energy);
+						edge.calculateState();
+						edge.addTag(hl.getId());
+						if (edge.isWorking() && !producers.contains(tmp)) {
+							if (tmp instanceof HolonSwitch) {
+								if (((HolonSwitch) tmp).getState(timeStep)) {
+									producers.add(tmp);
+								}
+							} else if (!(tmp instanceof CpsUpperNode)) {
+								producers.add(tmp);
+							}
+						}
+					}
+				}
+			}
+		}
+		setFlowSimRec(producers, 0);
+	}
+
+	/**
+	 * Set Flow Simulation Rec.
+	 *
+	 * @param nodes
+	 *            the nodes
+	 * @param iter
+	 *            the Iteration
+	 */
+	private void setFlowSimRec(ArrayList<AbstractCpsObject> nodes, int iter) {
+		ArrayList<AbstractCpsObject> newNodes = new ArrayList<>();
+		ArrayList<CpsEdge> changedEdges = new ArrayList<>();
+		AbstractCpsObject tmp;
+		if (nodes.size() != 0) {
+			for (AbstractCpsObject cps : nodes) {
+				// check whether the cps is in a legit state if it is a switch
+				if (legitState(cps)) {
+					for (CpsEdge edge : cps.getConnections()) {
+						// is edge working
+						// and does the edge's tag-list not (yet) contain all
+						// tags of the cps
+						if (edge.isWorking() && (!(edge.containsTags(edge.getTags(), cps.getTag())))) {
+							if (edge.getA().getId() == cps.getId()) {
+								tmp = edge.getB();
+							} else {
+								tmp = edge.getA();
+							}
+							for (Integer tag : cps.getTag()) {
+								if (!(edge.getTags().contains(tag)) && !(edge.getPseudoTags().contains(tag))) {
+									edge.setFlow(edge.getFlow() + tagTable.get(tag));
+									edge.addTag(tag);
+								}
+							}
+							// uppernodes do not spread energy
+							if (!(tmp instanceof CpsUpperNode)) {
+								for (Integer tag : tmp.getTag()) {
+									if (!(edge.getTags().contains(tag)) && tagTable.get(tag) != null
+											&& !(edge.getPseudoTags().contains(tag))) {
+										edge.setFlow(edge.getFlow() + tagTable.get(tag));
+										edge.addPseudoTag(tag);
+										changedEdges.add(edge);
+									}
+								}
+							}
+							edge.calculateState();
+							if (edge.isWorking() && !(tmp instanceof CpsUpperNode)) {
+								tmp.addAllPseudoTags(cps.getTag());
+								if (!newNodes.contains(tmp)) {
+									newNodes.add(tmp);
+								}
+							}
+						}
+					}
+				}
+			}
+			setPseudoTags(newNodes, changedEdges);
+			setFlowSimRec(newNodes, iter + 1);
+		}
+	}
+
+	/**
+	 * Set the Pseudo Tags.
+	 *
+	 * @param nodes
+	 *            Array of AbstractCpsObjects
+	 */
+	private void setPseudoTags(ArrayList<AbstractCpsObject> nodes, ArrayList<CpsEdge> edges) {
+		for (AbstractCpsObject node : nodes) {
+			node.recalculateTags();
+			node.setPseudoTags(new ArrayList<>());
+		}
+		for (CpsEdge edge : edges) {
+			edge.recalculateTags();
+			edge.setPseudoTag(new ArrayList<>());
+		}
+	}
+
+	/**
+	 * Reset the Connection.
+	 *
+	 * @param cps
+	 *            CpsObject
+	 * @param visitedObj
+	 *            the visited Objects
+	 * @param visitedEdges
+	 *            the visited Edges
+	 */
+	private void resetConnections(AbstractCpsObject cps, ArrayList<Integer> visitedObj,
+			ArrayList<CpsEdge> visitedEdges) {
+		visitedObj.add(cps.getId());
+		cps.resetTags();
+		for (CpsEdge e : cps.getConnections()) {
+			if (!(visitedEdges.contains(e))) {
+				e.setFlow(0);
+				e.calculateState();
+				e.setTags(new ArrayList<>());
+				visitedEdges.add(e);
+				if (!(visitedObj.contains(e.getA().getId()))) {
+					resetConnections(e.getA(), visitedObj, visitedEdges);
+					e.getA().resetTags();
+				}
+				if (!(visitedObj.contains(e.getB().getId()))) {
+					resetConnections(e.getB(), visitedObj, visitedEdges);
+					e.getB().resetTags();
+				}
+			}
+		}
+	}
+
+	/**
+	 * calculates the energy of either all producers or consumers. Flexible devices
+	 * are filtered out
+	 *
+	 * @param type
+	 *            Type
+	 * @param sN
+	 *            Subnet
+	 * @param x
+	 *            Integer
+	 * @return The Energy
+	 */
+	private float calculateEnergyWithoutFlexDevices(String type, SubNet sN, int x) {
+		float energy = 0;
+		for (HolonObject hl : sN.getObjects()) {
+			float currentEnergyWithoutFlexibles = hl.getCurrentEnergyAtTimeStepWithoutFlexiblesAndResetFlexibles(x);
+
+			if (type.equals("prod")) {
+				if (currentEnergyWithoutFlexibles > 0) {
+					energy += currentEnergyWithoutFlexibles;
+					hl.setState(HolonObject.PRODUCER);
+				}
+			}
+			if (type.equals("cons")) {
+				if (currentEnergyWithoutFlexibles < 0) {
+					energy += currentEnergyWithoutFlexibles;
+					hl.setState(HolonObject.NOT_SUPPLIED);
+				}
+			}
+			if (currentEnergyWithoutFlexibles == 0) {
+				hl.setState(HolonObject.NO_ENERGY);
+			}
+		}
+		return energy;
+	}
+
+	/**
+	 * calculates the energy of either all producers or consumers. Flexible devices
+	 * are filtered out
+	 *
+	 * @param type
+	 *            Type
+	 * @param sN
+	 *            Subnet
+	 * @param x
+	 *            Integer
+	 * @return The Energy
+	 */
+	private float calculateEnergyWithFlexDevices(String type, SubNet sN, int x) {
+		float energy = 0;
+		for (HolonObject hl : sN.getObjects()) {
+			float currentEnergy = hl.getCurrentEnergyAtTimeStep(x);
+
+			if (type.equals("prod")) {
+				if (currentEnergy > 0) {
+					energy += currentEnergy;
+					hl.setState(HolonObject.PRODUCER);
+				}
+			}
+			if (type.equals("cons")) {
+				if (currentEnergy < 0) {
+					energy = energy + currentEnergy;
+					hl.setState(HolonObject.NOT_SUPPLIED);
+				}
+			}
+			if (currentEnergy == 0) {
+				hl.setState(HolonObject.NO_ENERGY);
+			}
+		}
+		return energy;
+	}
+
+	/**
+	 * generates all subNets from all objectsToHandle.
+	 */
+	private void searchForSubNets() {
+		subNets = new ArrayList<>();
+		brokenEdges.clear();
+		boolean end = false;
+		int i = 0;
+		AbstractCpsObject cps;
+		if (objectsToHandle.size() > 0) {
+			while (!end) {
+				cps = objectsToHandle.get(i);
+				//SubNet singleSubNet = new SubNet(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(),
+					//	new ArrayList<>());
+				SubNet singleSubNet = buildSubNet(cps, new ArrayList<>());
+				if (singleSubNet.getObjects().size() + singleSubNet.getBatteries().size() != 0) {
+					subNets.add(singleSubNet);
+				}
+				if (0 == objectsToHandle.size()) {
+					end = true;
+				}
+			}
+		}
+	}
+
+	/**
+	 * recursivly generates a subnet of all objects, that one specific object is
+	 * connected to.
+	 *
+	 * @param cps
+	 *            AbstractCpsObject
+	 * @param visited
+	 *            visited Array of Integer
+	 * @param sN
+	 *            Subnets
+	 * @return Subnet
+	 */
+	private SubNet buildSubNet(AbstractCpsObject cps, ArrayList<Integer> visited) {
+		SubNet sN = new SubNet(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(),	new ArrayList<>());
+		
+		visited.add(cps.getId());
+		if (cps instanceof HolonObject) {
+			sN.getObjects().add((HolonObject) cps);
+		}
+		if (cps instanceof HolonSwitch) {
+			sN.getSwitches().add((HolonSwitch) cps);
+		}
+		if (cps instanceof HolonBattery) {
+			sN.getBatteries().add((HolonBattery) cps);
+		}
+		removeFromToHandle(cps.getId());
+		AbstractCpsObject a;
+		AbstractCpsObject b;
+		for (CpsEdge edge : cps.getConnections()) {
+			if (edge.isWorking()) {
+				a = edge.getA();
+				b = edge.getB();
+				if (!(cps instanceof HolonSwitch)) {
+					if (!(sN.getEdges().contains(edge))) {
+						sN.getEdges().add(edge);
+					}
+				}
+				if (cps instanceof HolonSwitch && ((HolonSwitch) cps).getState(timeStep)) {
+					if (!(sN.getEdges().contains(edge))) {
+						sN.getEdges().add(edge);
+					}
+				}
+				if (!visited.contains(a.getId()) && legitState(cps) && !(a instanceof CpsUpperNode)) {
+					sN = buildSubNet(a, visited);
+				}
+				if (!visited.contains(b.getId()) && legitState(cps) && !(b instanceof CpsUpperNode)) {
+					sN = buildSubNet(b, visited);
+				}
+				if (a instanceof CpsUpperNode && a.getId() != cps.getId()) {
+					edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
+					checkForConnectedStates(b, (CpsUpperNode) a, edge);
+				}
+				if (b instanceof CpsUpperNode && b.getId() != cps.getId()) {
+					edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
+					checkForConnectedStates(a, (CpsUpperNode) b, edge);
+				}
+			} else {
+				brokenEdges.add(edge);
+			}
+		}
+		return sN;
+	}
+
+	/**
+	 * is the Switch in a legitimate State.
+	 *
+	 * @param current
+	 *            AbstractCpsObject
+	 * @return boolean
+	 */
+	private boolean legitState(AbstractCpsObject current) {
+		return !(current instanceof HolonSwitch) || ((HolonSwitch) current).getState(timeStep);
+	}
+
+	// /**
+	// * ensures that objectsToHandle only contains HolonObjects.
+	// */
+	// public void cleanObjectsToHandle() {
+	// for (int i = 0; i < objectsToHandle.size(); i++) {
+	// if (!(objectsToHandle.get(i) instanceof HolonObject)) {
+	// objectsToHandle.remove(i);
+	// }
+	// }
+	// }
+
+	/**
+	 * removes an Object that already has been handled.
+	 *
+	 * @param id
+	 *            the Object ID
+	 */
+	private void removeFromToHandle(int id) {
+		for (int i = 0; i < objectsToHandle.size(); i++) {
+			if (objectsToHandle.get(i).getId() == id) {
+				objectsToHandle.remove(i);
+			}
+		}
+	}
+
+	/**
+	 * copies the data of an array of Objects.
+	 *
+	 * @param toCopy
+	 *            the ArrayList of CpsObjects co Copy
+	 */
+	private void copyObjects(ArrayList<AbstractCpsObject> toCopy) {
+		for (AbstractCpsObject cps : toCopy) {
+			if (cps instanceof CpsUpperNode) {
+				copyObjects(((CpsUpperNode) cps).getNodes());
+			} else {
+				objectsToHandle.add(cps);
+			}
+		}
+	}
+
+	/**
+	 * Reset all Data to the current state of the Model.
+	 */
+	public void reset() {
+		objectsToHandle = new ArrayList<>();
+		copyObjects(model.getObjectsOnCanvas());
+		flexDevicesTurnedOnThisTurn = new HashMap<>();
+	}
+
+	/**
+	 * Resets the State of all Edges
+	 */
+	private void resetEdges() {
+		for (CpsEdge e : brokenEdges) {
+			e.setWorkingState(true);
+		}
+	}
+
+	/**
+	 * Resets the State for the whole Simulation Model
+	 */
+	void resetSimulation() {
+		reset();
+		resetEdges();
+	}
+
+	/**
+	 * Get all Subnets.
+	 *
+	 * @return all Subnets
+	 */
+	public ArrayList<SubNet> getSubNets() {
+		return subNets;
+	}
+
+	/**
+	 * Get broken Edges
+	 */
+	// public ArrayList<CpsEdge> getBrokenEdges() {
+	// return brokenEdges;
+	// }
+
+	/**
+	 * checks whether a given object is connected to an object inside the upperNode.
+	 * if yes, the state for the edge is changed in "connected" or "not connected"
+	 */
+	private void checkForConnectedStates(AbstractCpsObject cps, CpsUpperNode cUNode, CpsEdge theEdge) {
+		AbstractCpsObject tmp;
+		for (CpsEdge edge : cps.getConnections()) {
+			if (edge.getA().getId() == cps.getId()) {
+				tmp = edge.getB();
+			} else {
+				tmp = edge.getA();
+			}
+			if (cUNode.getNodes().contains(tmp)) {
+				if (tmp instanceof CpsUpperNode) {
+					checkForConnectedStates(cps, (CpsUpperNode) tmp, theEdge);
+				} else {
+					theEdge.setConnected(CpsEdge.CON_UPPER_NODE_AND_INSIDE);
+					break;
+				}
+			}
+		}
+	}
+
+}