Browse Source

Working PSO

Tom Troppmann 5 years ago
parent
commit
386ae75040

+ 4 - 0
src/classes/HolonObject.java

@@ -361,4 +361,8 @@ public class HolonObject extends AbstractCpsObject {
         return sb.toString();
     }
 
+	public int getNumberOfActiveElements() {
+		return (int) elements.stream().filter(ele -> ele.isActive()).count();
+	}
+
 }

+ 6 - 6
src/exampleAlgorithms/ExampleFitnessFunction.java

@@ -95,17 +95,17 @@ public class ExampleFitnessFunction implements Algorithm {
 	private float StateToFloat(HolonObjectState state) {
 		switch (state) {
 		case NOT_SUPPLIED:
-			return -5f;
+			return 10f;
 		case NO_ENERGY:
-			return 0f;
+			return 15f;
 		case OVER_SUPPLIED:
-			return -2f;
+			return 5f;
 		case PARTIALLY_SUPPLIED:
-			return -1f;
+			return 3f;
 		case PRODUCER:
-			return 0f;
+			return 2f;
 		case SUPPLIED:
-			return 1f;
+			return 0f;
 		default:
 			return 0f;
 		}

+ 551 - 64
src/exampleAlgorithms/PSOAlgotihm.java

@@ -5,21 +5,23 @@ import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.Font;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
 import java.math.RoundingMode;
-import java.text.DecimalFormat;
 import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
-import java.util.ListIterator;
 import java.util.Locale;
 import java.util.stream.Collectors;
 
 import javax.swing.BorderFactory;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
+import javax.swing.JFileChooser;
 import javax.swing.JFormattedTextField;
 import javax.swing.JFrame;
 import javax.swing.JLabel;
@@ -27,28 +29,40 @@ import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.JSplitPane;
 import javax.swing.JTextArea;
-import javax.swing.JTextField;
+import javax.swing.filechooser.FileNameExtensionFilter;
 import javax.swing.text.NumberFormatter;
 
 import api.Algorithm;
 import classes.AbstractCpsObject;
-import classes.CpsEdge;
-import classes.CpsNode;
 import classes.CpsUpperNode;
 import classes.HolonElement;
 import classes.HolonObject;
 import classes.HolonSwitch;
+
 import ui.controller.Control;
-import ui.model.IntermediateCableWithState;
 import ui.model.Model;
-import ui.model.DecoratedCable.CableState;
+import ui.model.DecoratedHolonObject.HolonObjectState;
+import ui.model.DecoratedNetwork;
+import ui.model.DecoratedState;
 
 public class PSOAlgotihm implements Algorithm {
 	//Parameter for Algo with default Values:
 	private int swarmSize = 20; 
 	private int maxIterations = 100; 
-	private double limit = 1.0; 
-	private double dependency = 2.01; 
+	private double limit = 0.3; 
+	private double dependency = 2.07; 
+	private int rounds = 20; 
+	private boolean append = false;
+	
+	//Parameter defined by Algo
+	private HashMap<Integer, AccessWrapper> access;
+	private List<Boolean> initialState;
+	private double c1, c2, w;
+	private RunDataBase db;
+	
+	//Parameter for Plotting (Default Directory in Constructor)
+	private JFileChooser fileChooser = new JFileChooser();
+
 	
 	
 	//Gui Part:
@@ -72,9 +86,12 @@ public class PSOAlgotihm implements Algorithm {
 		JScrollPane scrollPane = new JScrollPane(textArea);
 		JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
 				createOptionPanel() , scrollPane);
-		splitPane.setResizeWeight(0.9);
+		splitPane.setResizeWeight(0.0);
 		content.add(splitPane, BorderLayout.CENTER);
-		content.setPreferredSize(new Dimension(800,800));
+		content.setPreferredSize(new Dimension(800,800));	
+		//Default Directory
+		fileChooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
+		fileChooser.setSelectedFile(new File("plott.txt"));
 	}
 	public JPanel createOptionPanel() {
 		JPanel optionPanel = new JPanel(new BorderLayout());
@@ -97,8 +114,8 @@ public class PSOAlgotihm implements Algorithm {
 		swarmSizeLabel.setBounds(20, 60, 100, 20);
 		parameterPanel.add(swarmSizeLabel);
 		
-		JLabel showDiagnosticsLabel = new JLabel("Show Diagnostic:");
-		showDiagnosticsLabel.setBounds(200, 60, 110, 20);
+		JLabel showDiagnosticsLabel = new JLabel("Append Plott on existing File:");
+		showDiagnosticsLabel.setBounds(200, 60, 170, 20);
 		parameterPanel.add(showDiagnosticsLabel);
 		
 		JLabel cautionLabel = new JLabel(
@@ -119,9 +136,15 @@ public class PSOAlgotihm implements Algorithm {
 		dependecyLabel.setBounds(20, 135, 100, 20);
 		parameterPanel.add(dependecyLabel);
 			
+		JLabel roundsLabel = new JLabel("Round:");
+		roundsLabel.setBounds(20, 160, 100, 20);
+		parameterPanel.add(roundsLabel);
+		
+		
 		JCheckBox diagnosticsCheckBox = new JCheckBox();
-		diagnosticsCheckBox.setSelected(true);
-		diagnosticsCheckBox.setBounds(320, 60, 25, 20);
+		diagnosticsCheckBox.setSelected(false);
+		diagnosticsCheckBox.setBounds(370, 60, 25, 20);
+		diagnosticsCheckBox.addPropertyChangeListener(propertyChange -> append = diagnosticsCheckBox.isSelected());
 		parameterPanel.add(diagnosticsCheckBox);
 		
 		//Integer formatter
@@ -178,6 +201,16 @@ public class PSOAlgotihm implements Algorithm {
 		dependencyTextField.setBounds(125, 135, 50, 20);
 		parameterPanel.add(dependencyTextField);
 		
+		NumberFormatter roundsFormatter = new NumberFormatter(format);
+		roundsFormatter.setMinimum(1);
+		roundsFormatter.setCommitsOnValidEdit(true);
+		
+		JFormattedTextField roundsTextField = new JFormattedTextField(roundsFormatter);
+		roundsTextField.setValue(rounds);
+		roundsTextField.setToolTipText("Amount of rounds to be runed with the same starting ");
+		roundsTextField.addPropertyChangeListener(propertyChange -> rounds = Integer.parseInt((roundsTextField.getValue().toString())));
+		roundsTextField.setBounds(125, 160, 50, 20);
+		parameterPanel.add(roundsTextField);
 		return parameterPanel;
 	}
 	public JPanel createButtonPanel() {
@@ -185,16 +218,50 @@ public class PSOAlgotihm implements Algorithm {
 		JButton clearButton =  new JButton("Clear Console");
 		clearButton.addActionListener(actionEvent -> clear());
 		buttonPanel.add(clearButton);
+		JButton folderButton =  new JButton("Change Plott-File");
+		folderButton.addActionListener(actionEvent -> setSaveFile());
+		buttonPanel.add(folderButton);
 		JButton plottButton =  new JButton("Plott");
+		plottButton.addActionListener(actionEvent -> plott());
 		buttonPanel.add(plottButton);
+		JButton resetButton =  new JButton("Reset");
+		resetButton.setToolTipText("Resets the State to before the Algorithm has runed.");
+		resetButton.addActionListener(actionEvent -> reset());
+		buttonPanel.add(resetButton);
 		JButton runButton =  new JButton("Run");
 		runButton.addActionListener(actionEvent -> executePsoAlgoWithCurrentParameters());
 		buttonPanel.add(runButton);
 		return buttonPanel;
 	}
 	
+	private void setSaveFile() {
+		fileChooser.setFileFilter(new FileNameExtensionFilter("File", "txt"));
+		fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+		int result = fileChooser.showSaveDialog(content);
+		if(result == JFileChooser.APPROVE_OPTION) {
+			println("Set save File to:" + fileChooser.getSelectedFile().getAbsolutePath());
+		}
+		
+	}
+	private void plott() {
+		if(db!=null) {
+			println("Plott..");
+			db.initFileStream();
+		}else {
+			println("No run inistialized.");
+		}
+	}
+	private void reset() {
+		if(initialState != null) {
+			println("Resetting..");
+			resetState();
+			updateVisual();
+		}else {
+			println("No run inistialized.");
+		}
+	}
 	private void printParameter() {
-		println("SwarmSize:" + swarmSize + ", MaxIter:" + maxIterations + ", Limit:" + limit + ", Dependency:" + dependency);
+		println("SwarmSize:" + swarmSize + ", MaxIter:" + maxIterations + ", Limit:" + limit + ", Dependency:" + dependency + ", Rounds:" + rounds +", DependentParameter: w:"+ w + ", c1:" + c1 + ", c2:" + c2 );
 	}
 	@Override
 	public JPanel getAlgorithmPanel() {
@@ -212,61 +279,321 @@ public class PSOAlgotihm implements Algorithm {
 		textArea.append(message);
 	}
 	private void println(String message) {
-		textArea.append(message + "\n");
+		textArea.append(message  + "\n");
 	}
 	
+	
+	
+	
+	
+	
+	
+	
 	//Algo Part:
+	/**
+	 * The Execution of the Algo its initialize the missing parameter and execute single Algo runs successively.
+	 */
 	private void executePsoAlgoWithCurrentParameters() {
-		println("SwarmSize:" + swarmSize + ", MaxIter:" + maxIterations + ", Limit:" + limit + ", Dependency:" + dependency);//maybe local parameter to not get override by runnign
-		extractPosition(control.getModel());
-//		initSwarm(startPos);
-//		runFunction(model, control);
-//		evaluate();
-		
+		initDependentParameter();
+		printParameter();
+		Best runBest = new Best();
+		runBest.value = Double.MAX_VALUE;
+		db = new RunDataBase();
+		for(int r = 0; r < rounds; r++)
+		{		
+          
+		  List<Double> runList = db.insertNewRun();
+		  Best lastRunBest = executePSOoneTime(runList);
+		  resetState();
+		  if(lastRunBest.value < runBest.value) runBest = lastRunBest;
+		}
+		println("AlgoResult:" + runBest.value);
+		//println("[" + lastRunBest.position.stream().map(Object::toString).collect(Collectors.joining(", ")) + "]");
+		setState(runBest.position);
+		updateVisual();
+	}
+	/**
+	 * Calculate w, c1, c2
+	 */
+	private void initDependentParameter() {
+		w = 1.0 / (dependency - 1 + Math.sqrt(dependency * dependency - 2 * dependency));
+		c1 = c2 = dependency * w;
+	}
+	/**
+	 *  <p>Algo from Paper:</p><font size="3"><pre>
+	 *  
+	 *  Begin
+	 *  	t = 0; {t: generation index}
+	 *  	initialize particles x<sub>p,i,j</sub>(t);
+	 *  	evaluation x<sub>p,i,j</sub>(t);
+	 *  	while (termination condition &ne; true) do
+	 *  		v<sub>i,j</sub>(t) = update v<sub>i,j</sub>(t); {by Eq. (6)}
+	 *  		x<sub>g,i,j</sub>(t) = update x<sub>g,i,j</sub>(t); {by Eq. (7)}
+	 *  		x<sub>g,i,j</sub>(t) = mutation x<sub>g,i,j</sub>(t); {by Eq. (11)}
+	 *  		x<sub>p,i,j</sub>(t) = decode x<sub>g,i,j</sub>(t); {by Eqs. (8) and (9)}
+	 *  		evaluate x<sub>p,i,j</sub>(t);
+	 *  		t = t + 1;
+	 *  	end while
+	 *  End</pre></font>
+	 *  <p>with:</p><font size="3">
+	 *  
+	 *  x<sub>g,i,j</sub>: genotype ->genetic information -> in continuous space<br>
+	 *  x<sub>p,i,j</sub>: phenotype -> observable characteristics-> in binary space<br>
+	 *  X<sub>g,max</sub>: is the Maximum here set to 4.<br>
+	 *  Eq. (6):v<sub>i,j</sub>(t + 1) = wv<sub>i,j</sub>+c<sub>1</sub>R<sub>1</sub>(P<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))+c<sub>2</sub>R<sub>2</sub>(g<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))<br>
+	 *  Eq. (7):x<sub>g,i,j</sub>(t + 1) = x<sub>g,i,j</sub>(t) + v<sub>i,j</sub>(t + 1)<br>
+	 *  Eq. (11):<b>if(</b>rand()&lt;r<sub>mu</sub><b>)then</b> x<sub>g,i,j</sub>(t + 1) = -x<sub>g,i,j</sub>(t + 1)<br>
+	 *  Eq. (8):x<sub>p,i,j</sub>(t + 1) = <b>(</b>rand() &lt; S(x<sub>g,i,j</sub>(t + 1))<b>) ?</b> 1 <b>:</b> 0<br>
+	 *  Eq. (9) Sigmoid:S(x<sub>g,i,j</sub>(t + 1)) := 1/(1 + e<sup>-x<sub>g,i,j</sub>(t + 1)</sup>)<br></font>
+	 *  <p>Parameter:</p>
+	 *  w inertia, calculated from phi(Variable:{@link #dependency})<br>
+	 *  c1:	influence, calculated from phi(Variable:{@link #dependency}) <br>
+	 *  c2:	influence, calculated from phi(Variable:{@link #dependency})<br>
+	 *  r<sub>mu</sub>: probability that the proposed operation is conducted defined by limit(Variable:{@link #limit})<br>
+	 *  
+	 *  
+	 */
+	private Best executePSOoneTime(List<Double> runList) {
+		Best globalBest = new Best();
+		globalBest.position = extractPositionAndAccess(control.getModel());
+		globalBest.value = evaluatePosition(globalBest.position);
+		print("Start Value:" + globalBest.value);
+		int dimensions = globalBest.position.size();
+		List<Particle> swarm= initializeParticles(dimensions);
+		runList.add(globalBest.value);
+		evaluation(globalBest, swarm);
+		runList.add(globalBest.value);
 		for (int iteration = 0; iteration < maxIterations ; iteration++) {
-			for (int i = 0; i < swarmSize; i++) {
-//				Particle temp = swarm.getSwarm().get(i);
-				
-				// Binary PSO 2 (S. Lee)
-				// Update Velocity
-//				temp.setVelocityAdv(updateNewVelAdv(temp.getVelocityAdv(), temp.getPositionAdv(),
-//						temp.getBestLocalPosAdv(), iterations));
-				// Update Position
-//				temp.setPositionAdv(updateNewPosAdv(temp.getVelocityAdv(), temp.getPositionAdv()));
-				// Mutation Position
-//				temp.setPositionAdv(mutatePos(temp.getPositionAdv()));
-				// Decode Position
-//				temp.setPositionAdv(decodePos(temp.getPositionAdv()));
+			for (int particleNumber = 0; particleNumber < swarmSize; particleNumber++) {
+				Particle particle = swarm.get(particleNumber);				
+				for(int index = 0; index < dimensions; index++) {
+					updateVelocity(particle, index, globalBest);
+					updateGenotype(particle, index);
+					mutation(particle, index);
+					decode(particle, index);
+				}
 			}
-//			plotSwarm();
-//			runFunction(model, control);
-//			evaluate();
+			evaluation(globalBest, swarm);
+			runList.add(globalBest.value);
 		}
+		println(" End Value:" + globalBest.value);
+		return globalBest;
+	}
+	/**
+	 * 	Eq. (6):v<sub>i,j</sub>(t + 1) = wv<sub>i,j</sub>+c<sub>1</sub>R<sub>1</sub>(P<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))+c<sub>2</sub>R<sub>2</sub>(g<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))<br>
+	 * @param particle
+	 * @param index
+	 * @param globalBest
+	 */
+	private void updateVelocity(Particle particle, int index, Best globalBest) {
+		double r1 = Random.nextDouble();
+		double r2 =	Random.nextDouble();
+		double posValue = particle.xPhenotype.get(index)?1.0:0.0;
+		particle.velocity.set(index, clamp(w*particle.velocity.get(index) + c1*r1*((particle.localBest.position.get(index)?1.0:0.0)  - posValue) + c2*r2*((globalBest.position.get(index)?1.0:0.0)- posValue)) );
+	}
+	/**
+	 * Eq. (7):x<sub>g,i,j</sub>(t + 1) = x<sub>g,i,j</sub>(t) + v<sub>i,j</sub>(t + 1)<br>
+	 * @param particle
+	 * @param index
+	 */
+	private void updateGenotype(Particle particle, int index) {
+		particle.xGenotype.set(index, clamp(particle.xGenotype.get(index) + particle.velocity.get(index)));
+	}
+	/**
+	 * Eq. (11):<b>if(</b>rand()&lt;r<sub>mu</sub><b>)then</b> x<sub>g,i,j</sub>(t + 1) = -x<sub>g,i,j</sub>(t + 1)<br>
+	 * @param particle
+	 * @param index
+	 */
+	private void mutation(Particle particle, int index) {
+		if(Random.nextDouble() < limit) particle.xGenotype.set(index, -particle.xGenotype.get(index));
+	}
+	/**
+	 * Eq. (8):x<sub>p,i,j</sub>(t + 1) = <b>(</b>rand() &lt; S(x<sub>g,i,j</sub>(t + 1))<b>) ?</b> 1 <b>:</b> 0<br>
+	 * @param particle
+	 * @param index
+	 */
+	private void decode(Particle particle, int index) {
+		particle.xPhenotype.set(index, Random.nextDouble() < Sigmoid(particle.xGenotype.get(index)));
 	}
-	private List<Boolean> extractPosition(Model model) {
-		println("Start extracting");
-		List<Boolean> position = new ArrayList<Boolean>(); 
-		HashMap<Integer, AccessWrapper> access= new HashMap<Integer, AccessWrapper>();
-		rollOutNodes(model.getObjectsOnCanvas(), position, access, model.getCurIteration());
-		println("[" + position.stream().map(Object::toString).collect(Collectors.joining(", ")) + "]");
-		ListIterator<Boolean> i = position.listIterator();
-		while(i.hasNext()) {
-			boolean actual = i.next();
-			double randomDouble = Math.random();
-			if (randomDouble < limit) {
-				  i.set(!actual);  
-			}   
+	/**
+	 * Eq. (9) Sigmoid:S(x<sub>g,i,j</sub>(t + 1)) := 1/(1 + e<sup>-x<sub>g,i,j</sub>(t + 1)</sup>)<br></font>
+	 * @param value
+	 * @return
+	 */
+	private double Sigmoid(double value) {
+		return 1.0 / (1.0 + Math.exp(-value));
+	}
+
+	/**
+	 * To clamp X<sub>g,j,i</sub> and v<sub>i,j</sub> in Range [-X<sub>g,max</sub>|+X<sub>g,max</sub>] with {X<sub>g,max</sub>= 4}
+	 * @param value
+	 * @return
+	 */
+	private double clamp(double value) {
+		return Math.max(-4.0, Math.min(4.0, value));
+	}
+	/**
+	 * 
+	 * @param j maximum index of position in the particle
+	 * @return
+	 */
+	private List<Particle> initializeParticles(int j) {
+		List<Particle> swarm = new ArrayList<Particle>();
+		//Create The Particle
+		for (int particleNumber = 0; particleNumber < swarmSize; particleNumber++){
+			//Create a Random position
+			List<Boolean> aRandomPosition = new ArrayList<Boolean>();
+			for (int index = 0; index < j; index++){
+				aRandomPosition.add(Random.nextBoolean());
+			}
+			swarm.add(new Particle(aRandomPosition));
 		}
-		println("[" + position.stream().map(Object::toString).collect(Collectors.joining(", ")) + "]");
-		setState(position, access);
-		updateVisual();
-		return null;
+		return swarm;
 	}
-	private void updateVisual() {
+	/**
+	 * Evaluate each particle and update the global Best position;
+	 * @param globalBest
+	 * @param swarm
+	 */
+	private void evaluation(Best globalBest, List<Particle> swarm) {
+		for(Particle p: swarm) {
+			double localEvaluationValue = evaluatePosition(p.xPhenotype);
+			p.checkNewEvaluationValue(localEvaluationValue);
+			if(localEvaluationValue < globalBest.value) {
+				globalBest.value = localEvaluationValue;
+				globalBest.position = p.localBest.position;
+			}
+		}
+	}
+	/**
+	 * Evaluate a position.
+	 * @param position
+	 * @return
+	 */
+	private double evaluatePosition(List<Boolean> position) {
+		setState(position);
 		control.calculateStateForCurrentTimeStep();
-		control.updateCanvas();
+		DecoratedState actualstate = control.getSimManager().getActualDecorState();		
+		return getFitnessValueForState(actualstate);
+	}
+	/**
+	 * Calculate the Fitness(Penelty) Value for a state (alias the calculated Position).
+	 * TODO: Make me better Rolf.
+	 * @param state
+	 * @return
+	 */
+	private double getFitnessValueForState(DecoratedState state) {
+		double fitness = 0.0;
+		double nw_fitness =0.0;
+		double object_fitness = 0.0;
+		
+		// calculate network_fitness
+		for(DecoratedNetwork net : state.getNetworkList()) {
+			float production = net.getSupplierList().stream().map(supplier -> supplier.getEnergyToSupplyNetwork()).reduce(0.0f, (a, b) -> a + b);
+			float consumption = net.getConsumerList().stream().map(con -> con.getEnergyNeededFromNetwork()).reduce(0.0f, (a, b) -> a + b);
+			nw_fitness += Math.abs(production - consumption); //Energy is now everywhere positive
+		}
+		
+		// calculate object_fitness
+		for(DecoratedNetwork net : state.getNetworkList()) {
+			object_fitness += net.getConsumerList().stream().map(con -> holonObjectSupplyPenaltyFunction(con.getSupplyBarPercentage()) + inactiveHolonElementPenalty(con.getModel())).reduce(0.0, (a, b) -> (a + b));
+			//warum war das im network fitness und nicht hier im Object fitness??
+			object_fitness += net.getPassivNoEnergyList().stream().map(con -> 1000.0).reduce(0.0, (a, b) -> (a + b));
+			object_fitness += net.getSupplierList().stream().map(sup -> inactiveHolonElementPenalty(sup.getModel())).reduce(0.0, (a, b) -> (a + b));
+			object_fitness += net.getConsumerSelfSuppliedList().stream().map(con -> inactiveHolonElementPenalty(con.getModel())).reduce(0.0, (a, b) -> (a + b));
+		}
+		fitness = nw_fitness + object_fitness;
+		return fitness;
 	}
-	private void rollOutNodes(List<AbstractCpsObject> nodes, List<Boolean> positionToInit, HashMap<Integer, AccessWrapper> access, int timeStep) {
+
+	
+	/**
+	 * Untouched:
+	 * Function that returns the fitness depending on the number of elements deactivated in a single holon object
+	 * @param obj Holon Object that contains Holon Elements
+	 * @return fitness value for that object depending on the number of deactivated holon elements
+	 */
+	private double inactiveHolonElementPenalty(HolonObject obj) {
+		float result = 0;
+		int activeElements = obj.getNumberOfActiveElements();
+		int maxElements = obj.getElements().size();
+		
+		if(activeElements == maxElements)
+			result =0;
+		else result = (float) Math.pow((maxElements -activeElements),2)*100;
+		
+		
+	return result;
+		
+	}
+	/**
+	 * Untouched:
+	 * Calculates a penalty value based on the HOs current supply percentage
+	 * @param supplyPercentage
+	 * @return
+	 */
+	private double holonObjectSupplyPenaltyFunction(float supplyPercentage) {
+		float result = 0;
+		if(supplyPercentage == 1)
+			return result;
+		else if(supplyPercentage < 1 && supplyPercentage >= 0.25) // undersupplied inbetween 25% and 100%
+			result = (float) Math.pow(1/supplyPercentage, 2);
+		else if (supplyPercentage < 0.25) //undersupplied with less than 25%
+			result = (float) Math.pow(1/supplyPercentage,2);
+		else if (supplyPercentage < 1.25)  //Oversupplied less than 25%
+			result = (float) Math.pow(supplyPercentage,3) ;
+		else result = (float) Math.pow(supplyPercentage,4); //Oversupplied more than 25%
+		
+		
+		if(Float.isInfinite(result) || Float.isNaN(result))
+			result = 1000;
+	
+		return result;
+	}
+	/**
+	 * If you want to get in touch with a reliable state? Working function not in use currently.
+	 * @param state
+	 * @return
+	 */
+	private double StateToDouble(HolonObjectState state) {
+		switch (state) {
+		case NOT_SUPPLIED:
+			return 10.0;
+		case NO_ENERGY:
+			return 15.0;
+		case OVER_SUPPLIED:
+			return 5.0;
+		case PARTIALLY_SUPPLIED:
+			return 3.0;
+		case PRODUCER:
+			return 2.0;
+		case SUPPLIED:
+			return 0;
+		default:
+			return 0;
+		}
+	}
+	
+
+	/**
+	 * Method to get the current Position alias a ListOf Booleans for aktive settings on the Objects on the Canvas.
+	 * Also initialize the Access Hashmap to swap faster positions.
+	 * @param model
+	 * @return
+	 */
+	private List<Boolean> extractPositionAndAccess(Model model) {
+		initialState = new ArrayList<Boolean>(); 
+		access= new HashMap<Integer, AccessWrapper>();
+		rollOutNodes(model.getObjectsOnCanvas(), initialState, model.getCurIteration());
+		return initialState;
+	}
+	/**
+	 * Method to extract the Informations recursively out of the Model.
+	 * @param nodes
+	 * @param positionToInit
+	 * @param timeStep
+	 */
+	private void rollOutNodes(List<AbstractCpsObject> nodes, List<Boolean> positionToInit, int timeStep) {
 		for(AbstractCpsObject aCps : nodes) {
 			if (aCps instanceof HolonObject) {
 				for (HolonElement hE : ((HolonObject) aCps).getElements()) {
@@ -280,17 +607,113 @@ public class PSOAlgotihm implements Algorithm {
 				access.put(positionToInit.size() - 1 , new AccessWrapper(sw));
 			}
 			else if(aCps instanceof CpsUpperNode) {
-				rollOutNodes(((CpsUpperNode)aCps).getNodes(), positionToInit, access ,timeStep );
+				rollOutNodes(((CpsUpperNode)aCps).getNodes(), positionToInit ,timeStep );
 			}
 		}
 	}
-	private void setState(List<Boolean> position, HashMap<Integer, AccessWrapper> access) {
+	/**
+	 * To let the User See the current state without touching the Canvas.
+	 */
+	private void updateVisual() {
+		control.calculateStateForCurrentTimeStep();
+		control.updateCanvas();
+	}
+	/**
+	 * Sets the Model back to its original State before the LAST run.
+	 */
+	private void resetState() {
+		setState(initialState);
+	}
+	
+	/**
+	 * Sets the State out of the given position for calculation or to show the user.
+	 * @param position
+	 */
+	private void setState(List<Boolean> position) {
 		for(int i = 0;i<position.size();i++) {
 			access.get(i).setState(position.get(i));
 		}
 	}
 	
-	public class AccessWrapper {
+	/**
+	 * A Database for all Global Best(G<sub>Best</sub>) Values in a execution of a the Algo. For Easy Printing.
+	 */
+	private class RunDataBase {
+		List<List<Double>> allRuns;
+		RunDataBase(){
+			allRuns = new ArrayList<List<Double>>();
+		}
+		
+		
+		/**
+		 * Initialize The Stream before you can write to a File.
+		 */
+		public void initFileStream() {
+			File file = fileChooser.getSelectedFile();
+			try {
+				file.createNewFile();
+				BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
+					    new FileOutputStream(file, append), "UTF-8"));
+				printToStream(out);
+				out.close();
+			} catch (IOException e) {
+				println(e.getMessage());
+			}
+		}
+		
+		/**
+		 * 
+		 * TODO: Rolf Change this method to suit your Python script respectively. 
+		 * A run have maxIterations + 2 values. As described: First is the InitialState Value, 
+		 * Second is The best Value after the swarm is Initialized not have moved jet, and then comes the Iterations that described 
+		 * each step of movement from the swarm.
+		 */
+		public void printToStream(BufferedWriter out) throws IOException {
+			allRuns.forEach(run -> {
+				try {
+					out.write( run.stream().map(Object::toString).collect(Collectors.joining(", ")));
+					out.newLine();
+				} catch (IOException e) {
+					println(e.getMessage());
+				}
+			} );
+			out.write("AverageRun:");
+			out.newLine();
+			out.write(calculateAverageRun().stream().map(Object::toString).collect(Collectors.joining(", ")));
+			out.newLine();
+		}
+		private List<Double> calculateAverageRun(){
+			int amountOfRuns = allRuns.size();
+			List<Double> newAverageRun = new ArrayList<Double>();
+			for(int iteration = 0; iteration < maxIterations + 2; iteration++) {
+				final int  currentIter = iteration;
+				double sum = 0.0;
+				sum = allRuns.stream().map(run -> run.get(currentIter)).reduce(0.0, (a, b) -> a + b);
+				newAverageRun.add(sum / amountOfRuns);
+			}
+			return newAverageRun;
+		}
+		public List<Double> insertNewRun(){
+			List<Double> newRun = new ArrayList<Double>();
+			allRuns.add(newRun);
+			return newRun;
+		}
+	}
+	
+	
+	/**
+	 * To give the Local Best of a Partice(P<sub>Best</sub>) or the Global Best(G<sub>Best</sub>) a Wrapper to have Position And Evaluation Value in one Place.
+	 */
+	private class Best{
+		public double value;
+		public  List<Boolean> position;
+		public Best(){
+		}
+	}
+	/**
+	 * A Wrapper Class for Access HolonElement and HolonSwitch in one Element and not have to split the List.
+	 */
+	private class AccessWrapper {
 		public static final int HOLONELEMENT = 0;
 		public static final int SWITCH = 1;
 		private int type;
@@ -317,4 +740,68 @@ public class PSOAlgotihm implements Algorithm {
 			return (type == HOLONELEMENT)?hElement.isActive():hSwitch.getState(timeStep);
 		}
 	}
+	/**
+	 * Class to represent a Particle.
+	 */
+	private class Particle{
+		/**
+		 * The velocity of a particle.
+		 */
+		public List<Double> velocity;
+		/**
+		 * The positions genotype.
+		 */
+		public List<Double> xGenotype;
+		/**
+		 * The positions phenotype. Alias the current position.
+		 */
+		public List<Boolean> xPhenotype;
+		
+		public Best localBest;
+		
+		Particle(List<Boolean> position){
+			this.xPhenotype = position;
+			//Init velocity, xGenotype with 0.0 values.
+			this.velocity = position.stream().map(bool -> 0.0).collect(Collectors.toList());
+			this.xGenotype = position.stream().map(bool -> 0.0).collect(Collectors.toList());
+			localBest = new Best();
+			localBest.value = Double.MAX_VALUE;
+		}
+		public void checkNewEvaluationValue(double newEvaluationValue) {
+			if(newEvaluationValue < localBest.value) {
+				localBest.value = newEvaluationValue;
+				localBest.position = xPhenotype.stream().map(bool -> bool).collect(Collectors.toList());
+			}
+		}
+		public String toString() {
+			return "Particle with xPhenotype(Position), xGenotype, velocity:[" 
+					+ listToString(xPhenotype) + "],[" + listToString(xGenotype) + "],[" 
+					+ listToString(velocity) + "]";
+		}
+		private <Type> String listToString(List<Type> list) {
+			return list.stream().map(Object::toString).collect(Collectors.joining(", "));
+		}
+		
+	}
+	
+	/**
+	* To create Random and maybe switch the random generation in the future.
+	*/
+	private static class Random{
+			/**
+			 * True or false
+			 * @return the random boolean.
+			 */
+			public static boolean nextBoolean(){
+				return (Math.random() < 0.5);
+			}
+			/**
+			 * Between 0.0 and 1.0
+			 * @return the random double.
+			 */
+			public static double nextDouble(){
+				return Math.random();
+			}
+		}
+	
 }