package exampleAlgorithms; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.image.BufferedImage; 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.NumberFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; 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.JFileChooser; 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.filechooser.FileNameExtensionFilter; 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.Model; import ui.model.DecoratedHolonObject.HolonObjectState; import ui.model.DecoratedGroupNode; 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 = 0.01; private double dependency = 2.07; private int rounds = 20; //Settings For GroupNode using and plotting private boolean append = false; private boolean useGroupNode = false; private DecoratedGroupNode dGroupNode = null; //Parameter defined by Algo private HashMap access; private List initialState; private double c1, c2, w; private RunDataBase db; //Parameter for Plotting (Default Directory in Constructor) private JFileChooser fileChooser = new JFileChooser(); //Gui Part: private Control control; private JTextArea textArea; private JPanel content = new JPanel(); //ProgressBar private JProgressBar progressBar = new JProgressBar(); private int progressBarCount = 0; private long startTime; public static void main(String[] args) { JFrame newFrame = new JFrame("exampleWindow"); PSOAlgotihm instance = new PSOAlgotihm(); newFrame.setContentPane(instance.getAlgorithmPanel()); newFrame.pack(); newFrame.setVisible(true); newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public PSOAlgotihm() { content.setLayout(new BorderLayout()); textArea = new JTextArea(); textArea.setEditable(false); JScrollPane scrollPane = new JScrollPane(textArea); JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createOptionPanel() , scrollPane); splitPane.setResizeWeight(0.0); content.add(splitPane, BorderLayout.CENTER); 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()); 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 info = new JLabel("Tune the variables of the PSO algorithm in order to reach better results."); info.setBounds(10, 10, 480, 15); parameterPanel.add(info); JLabel swarmSizeLabel = new JLabel("Swarm Size:"); swarmSizeLabel.setBounds(20, 60, 100, 20); parameterPanel.add(swarmSizeLabel); JLabel maxIterLabel = new JLabel("Max. Iterations:"); maxIterLabel.setBounds(20, 85, 100, 20); parameterPanel.add(maxIterLabel); JLabel limitLabel = new JLabel("Limit:"); limitLabel.setBounds(20, 110, 100, 20); parameterPanel.add(limitLabel); JLabel dependecyLabel = new JLabel("Dependency:"); dependecyLabel.setBounds(20, 135, 100, 20); parameterPanel.add(dependecyLabel); JLabel roundsLabel = new JLabel("Round:"); roundsLabel.setBounds(20, 160, 100, 20); parameterPanel.add(roundsLabel); JLabel cautionLabel = new JLabel( "Caution: High values in the fields of 'Swarm Size' and 'Max. Iteration' may take some time to calculate."); cautionLabel.setFont(new Font("Serif", Font.ITALIC, 12)); JLabel showDiagnosticsLabel = new JLabel("Append Plott on existing File:"); showDiagnosticsLabel.setBounds(200, 60, 170, 20); parameterPanel.add(showDiagnosticsLabel); JPanel borderPanel = new JPanel(null); borderPanel.setBounds(200, 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); JLabel progressLabel = new JLabel("Progress:"); progressLabel.setBounds(200, 135, 170, 20); parameterPanel.add(progressLabel); progressBar.setBounds(200, 155, 185, 20); progressBar.setStringPainted(true); parameterPanel.add(progressBar); cautionLabel.setBounds(10, 210, 500, 15); parameterPanel.add(cautionLabel); JCheckBox diagnosticsCheckBox = new JCheckBox(); diagnosticsCheckBox.setSelected(false); diagnosticsCheckBox.setBounds(370, 60, 25, 20); diagnosticsCheckBox.addActionListener(actionEvent -> append = diagnosticsCheckBox.isSelected()); parameterPanel.add(diagnosticsCheckBox); //Integer formatter NumberFormat format = NumberFormat.getIntegerInstance(); format.setGroupingUsed(false); format.setParseIntegerOnly(true); NumberFormatter integerFormatter = new NumberFormatter(format); integerFormatter.setMinimum(0); integerFormatter.setCommitsOnValidEdit(true); JFormattedTextField swarmSizeTextField = new JFormattedTextField(integerFormatter); swarmSizeTextField.setValue(swarmSize); swarmSizeTextField.setToolTipText("Only positive Integer."); swarmSizeTextField.addPropertyChangeListener(actionEvent -> swarmSize = Integer.parseInt(swarmSizeTextField.getValue().toString())); swarmSizeTextField.setBounds(125, 60, 50, 20); parameterPanel.add(swarmSizeTextField); JFormattedTextField maxIterTextField = new JFormattedTextField(integerFormatter); maxIterTextField.setValue(maxIterations); maxIterTextField.setToolTipText("Only positive Integer."); maxIterTextField.addPropertyChangeListener(propertyChange -> maxIterations = Integer.parseInt(maxIterTextField.getValue().toString())); maxIterTextField.setBounds(125, 85, 50, 20); parameterPanel.add(maxIterTextField); //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 limitTextField = new JFormattedTextField(limitFormatter); limitTextField.setValue(limit); limitTextField.setToolTipText("Only Double in range [0.0, 1.0] with DecimalSeperator Point('.')."); limitTextField.addPropertyChangeListener(propertyChange -> limit = Double.parseDouble(limitTextField.getValue().toString())); limitTextField.setBounds(125, 110, 50, 20); parameterPanel.add(limitTextField); //Limit Formatter: NumberFormatter dependencyFormatter = new NumberFormatter(doubleFormat); dependencyFormatter.setMinimum(2.001); dependencyFormatter.setMaximum(2.4); JFormattedTextField dependencyTextField = new JFormattedTextField(dependencyFormatter); dependencyTextField.setValue(dependency); dependencyTextField.setToolTipText("Only Double in range [2.001, 2.4] with DecimalSeperator Point('.')."); dependencyTextField.addPropertyChangeListener(propertyChange -> dependency = Double.parseDouble(dependencyTextField.getValue().toString())); 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() { JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); 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 fitnessButton = new JButton("Actual Fitness"); fitnessButton.addActionListener(actionEvent -> fitness()); buttonPanel.add(fitnessButton); 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 -> { Runnable task = () -> { startTimer(); executePsoAlgoWithCurrentParameters(); printElapsedTime(); }; Thread thread = new Thread(task); thread.start(); }); buttonPanel.add(runButton); return buttonPanel; } private void fitness() { initDependentParameter(); double currentFitness = evaluatePosition(extractPositionAndAccess(control.getModel())); println("Actual Fitnessvalue: " + currentFitness); } 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 + ", Rounds:" + rounds +", DependentParameter: w:"+ w + ", c1:" + c1 + ", c2:" + c2 ); } @Override public JPanel getAlgorithmPanel() { return content; } @Override public void setController(Control control) { this.control = control; } private void clear() { textArea.setText(""); } private void print(String message) { textArea.append(message); } private void println(String message) { textArea.append(message + "\n"); } private void selectGroupNode() { Object[] possibilities = control.getSimManager().getActualVisualRepresentationalState().getCreatedGroupNodes().values().stream().map(aCps -> new Handle(aCps)).toArray(); @SuppressWarnings("unchecked") Handle selected = (Handle) 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 = swarmSize * (maxIterations + 1)* rounds + 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); } //Algo Part: /** * The Execution of the Algo its initialize the missing parameter and execute single Algo runs successively. */ private void executePsoAlgoWithCurrentParameters() { initDependentParameter(); calculateProgressBarParameter(); printParameter(); Best runBest = new Best(); runBest.value = Double.MAX_VALUE; db = new RunDataBase(); for(int r = 0; r < rounds; r++) { List 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; } /** *

Algo from Paper:

	 *  
	 *  Begin
	 *  	t = 0; {t: generation index}
	 *  	initialize particles xp,i,j(t);
	 *  	evaluation xp,i,j(t);
	 *  	while (termination condition ≠ true) do
	 *  		vi,j(t) = update vi,j(t); {by Eq. (6)}
	 *  		xg,i,j(t) = update xg,i,j(t); {by Eq. (7)}
	 *  		xg,i,j(t) = mutation xg,i,j(t); {by Eq. (11)}
	 *  		xp,i,j(t) = decode xg,i,j(t); {by Eqs. (8) and (9)}
	 *  		evaluate xp,i,j(t);
	 *  		t = t + 1;
	 *  	end while
	 *  End
*

with:

* * xg,i,j: genotype ->genetic information -> in continuous space
* xp,i,j: phenotype -> observable characteristics-> in binary space
* Xg,max: is the Maximum here set to 4.
* Eq. (6):vi,j(t + 1) = wvi,j+c1R1(Pbest,i,j-xp,i,j(t))+c2R2(gbest,i,j-xp,i,j(t))
* Eq. (7):xg,i,j(t + 1) = xg,i,j(t) + vi,j(t + 1)
* Eq. (11):if(rand()<rmu)then xg,i,j(t + 1) = -xg,i,j(t + 1)
* Eq. (8):xp,i,j(t + 1) = (rand() < S(xg,i,j(t + 1))) ? 1 : 0
* Eq. (9) Sigmoid:S(xg,i,j(t + 1)) := 1/(1 + e-xg,i,j(t + 1))
*

Parameter:

* w inertia, calculated from phi(Variable:{@link #dependency})
* c1: influence, calculated from phi(Variable:{@link #dependency})
* c2: influence, calculated from phi(Variable:{@link #dependency})
* rmu: probability that the proposed operation is conducted defined by limit(Variable:{@link #limit})
* * */ private Best executePSOoneTime(List 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 swarm= initializeParticles(dimensions); runList.add(globalBest.value); evaluation(globalBest, swarm); runList.add(globalBest.value); for (int iteration = 0; iteration < maxIterations ; iteration++) { 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); } } evaluation(globalBest, swarm); runList.add(globalBest.value); } println(" End Value:" + globalBest.value); return globalBest; } /** * Eq. (6):vi,j(t + 1) = wvi,j+c1R1(Pbest,i,j-xp,i,j(t))+c2R2(gbest,i,j-xp,i,j(t))
* @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):xg,i,j(t + 1) = xg,i,j(t) + vi,j(t + 1)
* @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):if(rand()<rmu)then xg,i,j(t + 1) = -xg,i,j(t + 1)
* @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):xp,i,j(t + 1) = (rand() < S(xg,i,j(t + 1))) ? 1 : 0
* @param particle * @param index */ private void decode(Particle particle, int index) { particle.xPhenotype.set(index, Random.nextDouble() < Sigmoid(particle.xGenotype.get(index))); } /** * Eq. (9) Sigmoid:S(xg,i,j(t + 1)) := 1/(1 + e-xg,i,j(t + 1))
* @param value * @return */ private double Sigmoid(double value) { return 1.0 / (1.0 + Math.exp(-value)); } /** * To clamp Xg,j,i and vi,j in Range [-Xg,max|+Xg,max] with {Xg,max= 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 initializeParticles(int j) { List swarm = new ArrayList(); //Create The Particle for (int particleNumber = 0; particleNumber < swarmSize; particleNumber++){ //Create a Random position List aRandomPosition = new ArrayList(); for (int index = 0; index < j; index++){ aRandomPosition.add(Random.nextBoolean()); } swarm.add(new Particle(aRandomPosition)); } return swarm; } /** * Evaluate each particle and update the global Best position; * @param globalBest * @param swarm */ private void evaluation(Best globalBest, List 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 position) { setState(position); progressBarStep(); control.calculateStateForCurrentTimeStep(); 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.getConsumerList().stream().map(con -> StateToDouble(con.getState())).reduce(0.0, (a,b) -> (a+b)); //System.out.println("objectfitness for statestuff: " + 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; } /** * 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(); //result = (float) Math.pow((maxElements -activeElements),2)*10; result = (float) Math.pow(5, 4* ( (float) maxElements - (float) activeElements)/ (float) maxElements) - 1; //System.out.println("max: " + maxElements + " active: " + activeElements + " results in penalty: " + result); return result; } /** * Untouched: * Calculates a penalty value based on the HOs current supply percentage * @param supplyPercentage * @return */ private double holonObjectSupplyPenaltyFunction(float supplyPercentage) { double 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; */ if(supplyPercentage <= 1.0) { result = Math.pow(5,((100 - (supplyPercentage*100))/50 + 2)) - Math.pow(5, 2); } else { result = Math.pow(6,((100 - (supplyPercentage*100))/50 + 2)) - Math.pow(6, 2); } 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 300.0; case NO_ENERGY: return 100.0; case OVER_SUPPLIED: return 200.0; case PARTIALLY_SUPPLIED: return 100.0; case PRODUCER: return 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 extractPositionAndAccess(Model model) { initialState = new ArrayList(); access= new HashMap(); rollOutNodes((useGroupNode && (dGroupNode != null))? dGroupNode.getModel().getNodes() :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 nodes, List 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)); } } else if (aCps instanceof HolonSwitch) { HolonSwitch sw = (HolonSwitch) aCps; positionToInit.add(sw.getState(timeStep)); access.put(positionToInit.size() - 1 , new AccessWrapper(sw)); } else if(aCps instanceof CpsUpperNode) { rollOutNodes(((CpsUpperNode)aCps).getNodes(), positionToInit ,timeStep ); } } } /** * 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 position) { for(int i = 0;iBest) Values in a execution of a the Algo. For Easy Printing. */ private class RunDataBase { List> allRuns; RunDataBase(){ allRuns = new ArrayList>(); } /** * 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 { try { out.write(maxIterations + 2 + "," + allRuns.size() + "," + swarmSize); out.newLine(); } catch(IOException e) { println(e.getMessage()); } 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 calculateAverageRun(){ int amountOfRuns = allRuns.size(); List newAverageRun = new ArrayList(); 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 insertNewRun(){ List newRun = new ArrayList(); allRuns.add(newRun); return newRun; } } /** * To give the Local Best of a Partice(PBest) or the Global Best(GBest) a Wrapper to have Position And Evaluation Value in one Place. */ private class Best{ public double value; public List 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; 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); } } /** * Class to represent a Particle. */ private class Particle{ /** * The velocity of a particle. */ public List velocity; /** * The positions genotype. */ public List xGenotype; /** * The positions phenotype. Alias the current position. */ public List xPhenotype; public Best localBest; Particle(List 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 String listToString(List 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(); } } private class Handle{ public T object; Handle(T object){ this.object = object; } public String toString() { return object.toString(); } } }