Browse Source

Aco Algorithm

username 5 years ago
parent
commit
05463ddce4
3 changed files with 802 additions and 15 deletions
  1. 762 0
      src/exampleAlgorithms/AcoAlgorithm.java
  2. 8 0
      src/exampleAlgorithms/GaAlgorithm.java
  3. 32 15
      src/ui/view/Main.java

+ 762 - 0
src/exampleAlgorithms/AcoAlgorithm.java

@@ -0,0 +1,762 @@
+package exampleAlgorithms;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.image.BufferedImage;
+import java.math.RoundingMode;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JFormattedTextField;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTextArea;
+import javax.swing.text.NumberFormatter;
+
+import api.Algorithm;
+import classes.AbstractCpsObject;
+import classes.CpsUpperNode;
+import classes.HolonElement;
+import classes.HolonObject;
+import classes.HolonSwitch;
+import ui.controller.Control;
+import ui.model.DecoratedGroupNode;
+import ui.model.DecoratedState;
+import ui.model.Model;
+import ui.view.Console;
+import ui.model.DecoratedHolonObject.HolonObjectState;
+
+public class AcoAlgorithm implements Algorithm {
+
+		//Parameter for Algo with default Values:
+		/**
+		 * Should be even.
+		 */
+		private int popsize = 20;
+		private int maxGenerations = 200;
+		/**
+		 * The vaporization factor;
+		 */
+		private double p = 0.3;
+		private double convergenceFactorReset = 0.99;
+		private int rounds = 3;
+		
+		private int resetCount = 0;
+		
+		
+		//Settings For GroupNode using and cancel
+		private boolean useGroupNode = false;
+		private DecoratedGroupNode dGroupNode = null;
+		private boolean cancel = false;
+		
+		
+
+		//Parameter defined by Algo
+		private HashMap<Integer, AccessWrapper> access;
+		LinkedList<List<Boolean>> resetChain = new LinkedList<List<Boolean>>();
+		private List<Boolean> initialState;
+		private List<HolonSwitch> switchList;
+		private List<HolonObject> objectList;
+		
+		//Gui Part:
+		private Control  control;
+		private Console console = new Console();
+		private JPanel content = new JPanel();
+		//ProgressBar
+		private JProgressBar progressBar = new JProgressBar();
+		private int progressBarCount = 0;
+		private long startTime;
+		private Thread runThread;
+
+
+
+
+
+		
+		
+		
+		
+		
+		
+		
+		public static void main(String[] args)
+		{
+		      JFrame newFrame = new JFrame("exampleWindow");
+		      AcoAlgorithm instance = new AcoAlgorithm();
+		      newFrame.setContentPane(instance.getAlgorithmPanel());
+		      newFrame.pack();
+		      newFrame.setVisible(true);
+		      newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		}
+		public AcoAlgorithm() {
+			content.setLayout(new BorderLayout());
+			JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+					createOptionPanel() , console);
+			splitPane.setResizeWeight(0.0);
+			content.add(splitPane, BorderLayout.CENTER);
+			content.setPreferredSize(new Dimension(800,800));	
+		}
+		public JPanel createOptionPanel() {
+			JPanel optionPanel = new JPanel(new BorderLayout());
+			JScrollPane scrollPane = new JScrollPane(createParameterPanel());
+			scrollPane.setBorder(BorderFactory.createTitledBorder("Parameter"));
+			optionPanel.add(scrollPane,  BorderLayout.CENTER);
+			optionPanel.add(createButtonPanel(), BorderLayout.PAGE_END);
+			return optionPanel;
+		}
+		
+		private Component createParameterPanel() {
+			JPanel parameterPanel = new JPanel(null);
+			parameterPanel.setPreferredSize(new Dimension(510,300));
+			
+			
+				
+			JLabel maxGenerationsLabel = new JLabel("Max. Generations:");
+			maxGenerationsLabel.setBounds(20, 60, 150, 20);
+			parameterPanel.add(maxGenerationsLabel);
+			
+			JLabel populationLabel = new JLabel("Population Size:");
+			populationLabel.setBounds(20, 85, 150, 20);
+			parameterPanel.add(populationLabel);
+			
+			JLabel roundLabel = new JLabel("Rounds:");
+			roundLabel.setBounds(20, 110, 150, 20);
+			parameterPanel.add(roundLabel);
+			
+			JLabel vaporizationLabel = new JLabel("Vaporization:");
+			vaporizationLabel.setBounds(20, 135, 150, 20);
+			parameterPanel.add(vaporizationLabel);
+			
+		
+			JLabel resetLabel = new JLabel("Reset Trigger:");
+			resetLabel.setBounds(20, 160, 150, 20);
+			parameterPanel.add(resetLabel);
+			
+			
+			JLabel progressLabel = new JLabel("Progress:");
+			progressLabel.setBounds(350, 135, 170, 20);
+			parameterPanel.add(progressLabel);	
+			
+			progressBar.setBounds(350, 155, 185, 20);
+			progressBar.setStringPainted(true);
+			parameterPanel.add(progressBar);
+			
+			JPanel borderPanel = new JPanel(null);
+			borderPanel.setBounds(350, 85, 185, 50);
+			borderPanel.setBorder(BorderFactory.createTitledBorder(""));
+			parameterPanel.add(borderPanel);	
+			
+			JLabel showGroupNodeLabel = new JLabel("Use Group Node:");
+			showGroupNodeLabel.setBounds(10, 1, 170, 20);
+			borderPanel.add(showGroupNodeLabel);	
+			
+			JButton selectGroupNodeButton = new JButton("Select GroupNode");
+			selectGroupNodeButton.setEnabled(false);
+			selectGroupNodeButton.setBounds(10, 25, 165, 20);
+			selectGroupNodeButton.addActionListener(actionEvent -> selectGroupNode());
+			borderPanel.add(selectGroupNodeButton);	
+			
+			JCheckBox useGroupNodeCheckBox = new JCheckBox();
+			useGroupNodeCheckBox.setSelected(false);
+			useGroupNodeCheckBox.setBounds(155, 1, 25, 20);
+			useGroupNodeCheckBox.addActionListener(actionEvent -> {
+				useGroupNode = useGroupNodeCheckBox.isSelected();
+				selectGroupNodeButton.setEnabled(useGroupNode);
+			});
+			borderPanel.add(useGroupNodeCheckBox);
+			
+	
+			//Integer formatter
+			NumberFormat format = NumberFormat.getIntegerInstance();
+			format.setGroupingUsed(false);
+			format.setParseIntegerOnly(true);
+			NumberFormatter integerFormatter = new NumberFormatter(format);
+			integerFormatter.setMinimum(1);
+			integerFormatter.setCommitsOnValidEdit(true);
+			
+			
+			JFormattedTextField maxGenerationsTextField = new  JFormattedTextField(integerFormatter);
+			maxGenerationsTextField.setValue(this.maxGenerations);
+			maxGenerationsTextField.setToolTipText("Only positive Integer.");
+			maxGenerationsTextField.addPropertyChangeListener(actionEvent -> this.maxGenerations = Integer.parseInt(maxGenerationsTextField.getValue().toString()));
+			maxGenerationsTextField.setBounds(160, 60, 50, 20);
+			parameterPanel.add(maxGenerationsTextField);
+			
+			JFormattedTextField popSizeTextField = new JFormattedTextField(integerFormatter);
+			popSizeTextField.setValue(this.popsize);
+			popSizeTextField.setToolTipText("Only positive Integer.");
+			popSizeTextField.addPropertyChangeListener(propertyChange -> this.popsize = Integer.parseInt(popSizeTextField.getValue().toString()));
+			popSizeTextField.setBounds(160, 85, 50, 20);
+			parameterPanel.add(popSizeTextField);
+			
+			
+			JFormattedTextField roundsTextField = new JFormattedTextField(integerFormatter);
+			roundsTextField.setValue(this.rounds);
+			roundsTextField.setToolTipText("Only positive Integer.");
+			roundsTextField.addPropertyChangeListener(propertyChange -> this.rounds = Integer.parseInt(roundsTextField.getValue().toString()));
+			roundsTextField.setBounds(160, 110, 50, 20);
+			parameterPanel.add(roundsTextField);
+			
+			
+			//Double Format:
+			NumberFormat doubleFormat = NumberFormat.getNumberInstance(Locale.US);
+			doubleFormat.setMinimumFractionDigits(1);
+			doubleFormat.setMaximumFractionDigits(3);
+			doubleFormat.setRoundingMode(RoundingMode.HALF_UP);
+
+			//Limit Formatter:
+			NumberFormatter limitFormatter = new NumberFormatter(doubleFormat);
+			limitFormatter.setMinimum(0.0);
+			limitFormatter.setMaximum(1.0);
+			
+			JFormattedTextField vaporizationField = new JFormattedTextField(limitFormatter);
+			vaporizationField.setValue(this.p);
+			vaporizationField.setToolTipText("Only Double in range [0.0, 1.0] with DecimalSeperator Point('.').");
+			vaporizationField.addPropertyChangeListener(propertyChange -> p = Double.parseDouble(vaporizationField.getValue().toString()));
+			vaporizationField.setBounds(160, 135, 50, 20);
+			parameterPanel.add(vaporizationField);
+			
+			
+			
+			JFormattedTextField resetFactorField = new JFormattedTextField(limitFormatter);
+			resetFactorField.setValue(this.convergenceFactorReset);
+			resetFactorField.setToolTipText("Only Double in range [0.0, 1.0] with DecimalSeperator Point('.').");
+			resetFactorField.addPropertyChangeListener(propertyChange -> this.convergenceFactorReset = Double.parseDouble(resetFactorField.getValue().toString()));
+			resetFactorField.setBounds(160, 160, 50, 20);
+			parameterPanel.add(resetFactorField);
+			
+			
+			
+			return parameterPanel;
+		}
+		public JPanel createButtonPanel() {
+			JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+			JButton resetButton =  new JButton("ResetAll");
+			resetButton.setToolTipText("Resets the State to before the Algorithm has runed.");
+			resetButton.addActionListener(actionEvent -> resetAll());
+			buttonPanel.add(resetButton);
+			JButton cancelButton =  new JButton("Cancel Run");
+			cancelButton.addActionListener(actionEvent -> cancel());
+			buttonPanel.add(cancelButton);
+			JButton undoButton =  new JButton("Undo");
+			undoButton.setToolTipText("One Algo Step Back.");
+			undoButton.addActionListener(actionEvent -> resetLast());
+			buttonPanel.add(undoButton);
+			JButton runButton =  new JButton("Run");
+			runButton.addActionListener(actionEvent -> {
+				Runnable task = () -> run();
+				runThread = new Thread(task);
+				runThread.start();
+			});
+			buttonPanel.add(runButton);
+			return buttonPanel;
+		}
+		private void cancel() {
+			if(runThread.isAlive()) {
+				println("");
+				println("Cancel run.");
+				cancel = true;
+				progressBar.setValue(0);
+			} else {
+				println("Nothing to cancel.");
+			}
+		}
+		
+		private void run() {
+			cancel = false;
+			disableGuiInput(true);
+			executeAlgoWithParameter();
+			updateVisual();
+			disableGuiInput(false);
+		}
+		
+		private void resetLast() {
+			if(runThread.isAlive()) {
+				println("Run have to be cancelled First.");
+				return;
+			}
+			if(!resetChain.isEmpty()) {
+				println("Resetting..");
+				resetState();
+				resetChain.removeLast();
+				control.resetSimulation();
+				updateVisual();
+			}else {
+				println("No run inistialized.");
+			}
+		}
+		
+		private void resetAll() {
+			if(runThread.isAlive()) {
+				println("Run have to be cancelled First.");
+				return;
+			}
+			if(!resetChain.isEmpty()) {
+				println("Resetting..");
+				setState(resetChain.getFirst());
+				resetChain.clear();
+				control.resetSimulation();
+				control.setCurIteration(0);
+				updateVisual();
+			}else {
+				println("No run inistialized.");
+			}
+		}
+		
+		
+		
+		private void disableGuiInput(boolean bool) {
+			control.guiDiable(bool);
+		}
+		
+		
+
+		
+		
+		@Override
+		public JPanel getAlgorithmPanel() {
+			return content;
+		}
+		@Override
+		public void setController(Control control) {
+			this.control = control;
+			
+		}
+		private void println(String message) {
+			console.println(message);
+		}
+		private void selectGroupNode() {
+			Object[] possibilities = control.getSimManager().getActualVisualRepresentationalState().getCreatedGroupNodes().values().stream().map(aCps -> new Handle<DecoratedGroupNode>(aCps)).toArray();
+			@SuppressWarnings("unchecked")
+			Handle<DecoratedGroupNode> selected = (Handle<DecoratedGroupNode>) JOptionPane.showInputDialog(content, "Select GroupNode:", "GroupNode?",  JOptionPane.OK_OPTION,new ImageIcon(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)) , possibilities, "");
+			if(selected != null) {
+				println("Selected: " + selected);
+				dGroupNode = selected.object;
+			}
+		}
+		private void progressBarStep(){
+			progressBar.setValue(++progressBarCount);
+		}
+		private void calculateProgressBarParameter() {
+			int max = this.maxGenerations * this.popsize * this.rounds;
+			progressBarCount = 0;
+			progressBar.setValue(0);
+			progressBar.setMaximum(max);
+		}
+		
+		private void startTimer(){
+			startTime = System.currentTimeMillis();
+		}
+		private void printElapsedTime(){
+			long elapsedMilliSeconds = System.currentTimeMillis() - startTime;
+			println("Execution Time of Algo in Milliseconds:" + elapsedMilliSeconds);
+		}
+		
+		
+		
+		
+		private void executeAlgoWithParameter(){
+			
+			
+			
+			int actualIteration = control.getModel().getCurIteration();
+			println("TimeStep:" + actualIteration);
+			calculateProgressBarParameter();
+			println("Algo Parameter: p="+ p + " cfreset=" + convergenceFactorReset);
+			resetCount = 0;
+			startTimer();
+			Individual runBest = new Individual();
+			runBest.fitness = Double.MAX_VALUE;
+			for(int r = 0; r < rounds; r++)
+			{		
+			  Individual  roundBest = executeAcoAlgo();
+			  if(cancel)return;
+			  resetState();
+			  if(roundBest.fitness < runBest.fitness) runBest = roundBest;
+			}
+			printElapsedTime();
+			setState(runBest.position);
+			updateVisual();
+			println("ResetsCount:"+resetCount);
+			println("AlgoResult:" + runBest.fitness);
+			
+			
+		}
+		
+		
+		
+		
+		//Algo Part:
+		/** 	
+		 * 	Algorithm 20 !! Fitness is better when smaller.: 
+		 *  PseudoCode:
+		 *  Best <- actual;
+		 *  pheromones = initPheromons();
+		 * 	for(maxGeneration times){
+		 * 		population = createSolutionsBiasedBy(pheromones);
+		 * 		for(each Individual i from population){
+		 * 			fitness <- evaluatePosition(i);
+		 * 			if(fitness < best.fitnessValue) Best <- i;
+		 * 		}
+		 * 		vaporizeIntensifiePheromons(pheromones);
+		 * 	}
+		 * @return 
+		 */
+		private Individual executeAcoAlgo() {
+			Individual best = new Individual();
+			best.position = extractPositionAndAccess();
+			println("Bit-Array_length: " + best.position.size());
+			best.fitness = evaluatePosition(best.position, false);
+			println("Start with Fitness: " + best.fitness);
+			int problemSize = best.position.size();
+			if(problemSize == 0) return best;
+			List<Double> pheromones = initPheromones(problemSize);
+			List<Individual> population = new ArrayList<Individual>();
+			println("Size To Test:" + population.size());
+			for(int generation = 0; generation< maxGenerations; generation++) {
+				population.clear();
+				population = constructSolutionsBiasedBy(pheromones);
+				println("Generation" + generation + " start with Fitness: " + best.fitness);
+				for(Individual i : population) {
+					i.fitness = evaluatePosition(i.position, true);
+					println("Fitness" + i.fitness);
+					if(i.fitness < best.fitness) best = i;	
+				}
+				println("________________");
+				vaporizeIntensifiePheromons(pheromones, best.position, problemSize);
+				double cf = calculateConvergenceFactor(pheromones, problemSize);
+				println("ConvergenceFactor = " + cf);
+				if(cf > this.convergenceFactorReset) {
+					pheromones = initPheromones(problemSize);
+					resetCount++;
+				}
+			}
+			
+			
+			println("RoundResult:" + best.fitness);
+			return best;
+			
+		}
+		
+		
+		/**
+		 * tj1 is the pheromon level in the j position
+		 * cf is the convergence factor cf e [0;1]
+		 * difference = | tj1 - tj0 | = | tj1 - (1 - tj1) |
+		 * 
+		 * 
+		 * 
+		 * @param pheromones
+		 * @return cf
+		 */
+		private double calculateConvergenceFactor(List<Double> pheromones,int problemSize) {
+			double sumOfDifference = pheromones.stream().map(tj1 -> Math.abs(tj1 - (1.0 - tj1))).reduce(0.0, Double::sum);
+			double cf = sumOfDifference / (double)problemSize;
+			return cf;
+		}
+		/**
+		 * pheromone <- (1-p) * pheromone;
+		 * if(best is true at this position) pheromone <- pheromone + p;
+		 * @param pheromones
+		 * @param position
+		 */
+		private void vaporizeIntensifiePheromons(List<Double> pheromones, List<Boolean> position, int problemSize) {
+			ListIterator<Double> iterPheromone = pheromones.listIterator();
+			ListIterator<Boolean> iterBest = position.listIterator();
+			for(int i = 0; i < problemSize; i++) {
+				double pheromone = iterPheromone.next();
+				boolean bestDecision = iterBest.next();
+				iterPheromone.set((1.0 - p) * pheromone + (bestDecision?p:0.0));
+			}
+		}
+		/**
+		 * 
+		 * @param pheromones
+		 * @return
+		 */
+		private List<Individual> constructSolutionsBiasedBy(List<Double> pheromones) {
+			List<Individual> population =  new ArrayList<Individual>();
+			for(int i = 0; i < popsize; i++) {
+				population.add(constructASolutionBiasedBy(pheromones));
+			}
+			return population;
+		}
+		
+		
+		/**
+		 * Walks the path with a ant and decide by pheromones if should take true or false;
+		 * A pheromone have a level of 0 < pheromone < 1.
+		 * A Pheromone is  equal to the probability.
+		 * @param pheromones
+		 * @return
+		 */
+		private Individual constructASolutionBiasedBy(List<Double> pheromones) {
+			Individual result = new Individual();
+			result.position = new ArrayList<Boolean>();
+			for(double pheromone : pheromones) {
+				result.position.add((Random.nextDouble() < pheromone));
+			}
+			return result;
+		}
+		/**
+		 * Initialize Pheromons with 0.5
+		 */
+		private List<Double> initPheromones(int problemSize) {
+			List<Double> result = new ArrayList<Double>();
+			for(int i = 0; i < problemSize;i++) {
+				result.add(0.5);
+			}
+			return result;
+		}
+		
+		
+		
+		/**
+		 * 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 = control.getModel();
+			switchList = new ArrayList<HolonSwitch>();
+			objectList = new ArrayList<HolonObject>();
+			initialState = new ArrayList<Boolean>();
+			access= new HashMap<Integer, AccessWrapper>();
+			rollOutNodes((useGroupNode && (dGroupNode != null))? dGroupNode.getModel().getNodes() :model.getObjectsOnCanvas(), initialState, model.getCurIteration());			
+			resetChain.add(initialState); 
+			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()) {
+						positionToInit.add(hE.isActive());
+						access.put(positionToInit.size() - 1 , new AccessWrapper(hE));
+					}
+					objectList.add((HolonObject) aCps);
+				}
+				else if (aCps instanceof HolonSwitch) {
+					HolonSwitch sw = (HolonSwitch) aCps;
+					positionToInit.add(sw.getState(timeStep));
+					switchList.add(sw);
+					access.put(positionToInit.size() - 1 , new AccessWrapper(sw));
+				}
+				else if(aCps instanceof CpsUpperNode) {
+					rollOutNodes(((CpsUpperNode)aCps).getNodes(), positionToInit ,timeStep );
+				}
+			}
+		}
+		
+		
+		
+		private double evaluatePosition(List<Boolean> position, boolean doIncreaseCounter) {
+			setState(position);
+			if(doIncreaseCounter)progressBarStep();
+			control.calculateStateOnlyForCurrentTimeStep();
+			DecoratedState actualstate = control.getSimManager().getActualDecorState();		
+			return PSOAlgorithm.getFitnessValueForState(actualstate);
+		}
+		
+		
+		
+		/**
+		 * To let the User See the current state without touching the Canvas.
+		 */
+		private void updateVisual() {
+			control.calculateStateAndVisualForCurrentTimeStep();
+			//control.updateCanvas();
+			//control.getGui().triggerUpdateController(null);
+		}
+		/**
+		 * Sets the Model back to its original State before the LAST run.
+		 */
+		private void resetState() {
+			setState(resetChain.getLast());
+		}
+		
+		/**
+		 * 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));
+			}
+		}
+		
+		private class Individual {
+			public double fitness;
+			public  List<Boolean> position;
+			
+			Individual(){};
+			/**
+			 *  Copy Constructor
+			 */
+			Individual(Individual c){
+				position = c.position.stream().collect(Collectors.toList());
+				fitness = c.fitness;
+			}
+		}
+		
+		
+		
+		
+		
+		
+		
+		/**
+		 * 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;
+			private HolonSwitch hSwitch;
+			private HolonElement hElement;
+			public AccessWrapper(HolonSwitch hSwitch){
+				type = SWITCH;
+				this.hSwitch = hSwitch;
+			}
+			public AccessWrapper(HolonElement hElement){
+				type = HOLONELEMENT;
+				this.hElement = hElement;
+			}
+			public void setState(boolean state) {
+				if(type == HOLONELEMENT) {
+					hElement.setActive(state);
+				}else{//is switch
+					hSwitch.setManualMode(true);
+					hSwitch.setManualState(state);
+				}
+					
+			}
+			public boolean getState(int timeStep) {
+				return (type == HOLONELEMENT)?hElement.isActive():hSwitch.getState(timeStep);
+			}
+			public int getType() {
+				return type;
+			}
+		}
+		
+		
+		private class RunResult {
+			public int activatedFlex = 0;
+			public int deactivatedElements = 0;
+			public float totalCost = 0;
+			public LinkedList<TimeStepStateResult> timeStepList = new LinkedList<TimeStepStateResult>();
+			
+			
+			public TimeStepStateResult addTimeStepStateResult(){
+				TimeStepStateResult aResult = new TimeStepStateResult();
+				timeStepList.add(aResult);
+				return aResult;
+			}
+			
+			
+			public class TimeStepStateResult{
+				public int amountOfProducer = 0;
+				public int amountOfConsumer = 0;
+				public int amountOfPassiv = 0;
+				public int amountOfConsumerOverSupplied = 0;
+				public int amountOfConsumerSupplied = 0;
+				public int amountOfConsumerPartiallySupplied = 0;
+				public int amountOfConsumerUnSupplied= 0;
+				
+				public float getProportionWithState(HolonObjectState state) {
+					float amountOfObjects = amountOfProducer + amountOfConsumer + amountOfPassiv;
+					switch(state) {
+					case NOT_SUPPLIED:
+						return (float) amountOfConsumerUnSupplied / amountOfObjects;
+					case NO_ENERGY:
+						return (float) amountOfPassiv / amountOfObjects;
+					case OVER_SUPPLIED:
+						return (float) amountOfConsumerOverSupplied / amountOfObjects;
+					case PARTIALLY_SUPPLIED:
+						return (float) amountOfConsumerPartiallySupplied / amountOfObjects;
+					case PRODUCER:
+						return (float) amountOfProducer / amountOfObjects;
+					case SUPPLIED:
+						return (float) amountOfConsumerSupplied / amountOfObjects;
+					default:
+						return 0.f;
+					}
+				}
+			}
+			public float getAvergaeProportionWithState(HolonObjectState state) {
+				return timeStepList.stream().map(step -> step.getProportionWithState(state)).reduce((a,b) -> (a + b)).orElse(0.f) / (float) 100;
+			}
+		}
+		
+
+		/**
+		* To create Random and maybe switch the random generation in the future.
+		*/
+		private static class Random{
+			
+				
+				private static java.util.Random random = new java.util.Random();
+			
+				/**
+				 * True or false
+				 * @return the random boolean.
+				 */
+				public static boolean nextBoolean(){
+					return random.nextBoolean();
+				}
+				/**
+				 * Between 0.0(inclusive) and 1.0 (exclusive)
+				 * @return the random double.
+				 */
+				public static double nextDouble() {
+					return random.nextDouble();
+				}
+				
+				/**
+				 * Random Int in Range [min;max[ with UniformDistirbution
+				 * @param min
+				 * @param max
+				 * @return
+				 */
+				public static int nextIntegerInRange(int min, int max) {
+					return min + random.nextInt(max - min);
+				}
+			}
+		
+		
+		
+		
+		private   class  Handle<T>{
+			public T object;
+			Handle(T object){
+				this.object = object;
+			}
+			public String toString() {
+				return object.toString();
+			}
+		}
+
+}

+ 8 - 0
src/exampleAlgorithms/GaAlgorithm.java

@@ -313,6 +313,10 @@ public class GaAlgorithm implements Algorithm {
 		}
 		
 		private void resetLast() {
+			if(runThread.isAlive()) {
+				println("Run have to be cancelled First.");
+				return;
+			}
 			if(!resetChain.isEmpty()) {
 				println("Resetting..");
 				resetState();
@@ -325,6 +329,10 @@ public class GaAlgorithm implements Algorithm {
 		}
 		
 		private void resetAll() {
+			if(runThread.isAlive()) {
+				println("Run have to be cancelled First.");
+				return;
+			}
 			if(!resetChain.isEmpty()) {
 				println("Resetting..");
 				setState(resetChain.getFirst());

+ 32 - 15
src/ui/view/Main.java

@@ -22,21 +22,30 @@ public class Main {
 	 *            standard
 	 */
 	public static void main(String[] args) {
-
-		if (!System.getProperty("os.name").startsWith("Linux"))
-			// *Design
-			try {
-			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
-			} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
-			e.printStackTrace();
-			}
-		else
-			try {
-				UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
-			} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
-					| UnsupportedLookAndFeelException e) {
-				e.printStackTrace();
-			}
+		//System.out.println(System.getProperty("os.name"));
+//		if (!System.getProperty("os.name").startsWith("Linux")) {
+//			// *Design
+//			try {
+//			
+//			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+//			} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
+//			e.printStackTrace();
+//			}
+//		}else {
+////			try {
+////				UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
+////			} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
+////					| UnsupportedLookAndFeelException e) {
+////				e.printStackTrace();
+////			}
+//		}
+		
+		if (System.getProperty("os.name").startsWith("Linux")) {
+			
+		}else {
+			loadNotLinuxLookAndFeel();	
+		}
+			
 
         EventQueue.invokeLater(() -> {
             try {
@@ -53,4 +62,12 @@ public class Main {
         });
     }
 
+	private static void loadNotLinuxLookAndFeel() {
+		try {
+		UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
+		e.printStackTrace();
+		}
+	}
+
 }