|
@@ -0,0 +1,797 @@
|
|
|
|
+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.model.DecoratedHolonObject.HolonObjectState;
|
|
|
|
+
|
|
|
|
+public class GaAlgorithm implements Algorithm {
|
|
|
|
+
|
|
|
|
+ //Parameter for Algo with default Values:
|
|
|
|
+ /**
|
|
|
|
+ * Should be even.
|
|
|
|
+ */
|
|
|
|
+ private int popsize = 20;
|
|
|
|
+ private int maxGenerations = 100;
|
|
|
|
+ private int tournamentSize = 2;
|
|
|
|
+ private double fixedSwapProbability = 0.02;
|
|
|
|
+ private boolean useFixedSpawProbability = false;
|
|
|
|
+ private double fixedMutateProbability = 0.02;
|
|
|
|
+ private boolean useFixedMutateProbability = false;
|
|
|
|
+ private int rounds = 2;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //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 JTextArea textArea;
|
|
|
|
+ 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");
|
|
|
|
+ GaAlgorithm instance = new GaAlgorithm();
|
|
|
|
+ newFrame.setContentPane(instance.getAlgorithmPanel());
|
|
|
|
+ newFrame.pack();
|
|
|
|
+ newFrame.setVisible(true);
|
|
|
|
+ newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
|
|
+ }
|
|
|
|
+ public GaAlgorithm() {
|
|
|
|
+ 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));
|
|
|
|
+ }
|
|
|
|
+ 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 mutationLabel = new JLabel("FixedMutation:");
|
|
|
|
+ mutationLabel.setBounds(50, 135, 150, 20);
|
|
|
|
+ mutationLabel.setEnabled(useFixedMutateProbability);
|
|
|
|
+ parameterPanel.add(mutationLabel);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ JLabel swapLabel = new JLabel("FixedSwap:");
|
|
|
|
+ swapLabel.setBounds(50, 160, 150, 20);
|
|
|
|
+ swapLabel.setEnabled(this.useFixedSpawProbability);
|
|
|
|
+ parameterPanel.add(swapLabel);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ 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 mutateTextField = new JFormattedTextField(limitFormatter);
|
|
|
|
+ mutateTextField.setValue(this.fixedMutateProbability);
|
|
|
|
+ mutateTextField.setEnabled(this.useFixedMutateProbability);
|
|
|
|
+ mutateTextField.setToolTipText("Only Double in range [0.0, 1.0] with DecimalSeperator Point('.').");
|
|
|
|
+ mutateTextField.addPropertyChangeListener(propertyChange -> fixedMutateProbability = Double.parseDouble(mutateTextField.getValue().toString()));
|
|
|
|
+ mutateTextField.setBounds(160, 135, 50, 20);
|
|
|
|
+ parameterPanel.add(mutateTextField);
|
|
|
|
+
|
|
|
|
+ JCheckBox useFixMutateCheckBox = new JCheckBox();
|
|
|
|
+ useFixMutateCheckBox.setSelected(this.useFixedMutateProbability);
|
|
|
|
+ useFixMutateCheckBox.setToolTipText("If not checked its 1/ProblemSize");
|
|
|
|
+ useFixMutateCheckBox.setBounds(20, 135, 25, 20);
|
|
|
|
+ useFixMutateCheckBox.addActionListener(actionEvent -> {
|
|
|
|
+ boolean state = useFixMutateCheckBox.isSelected();
|
|
|
|
+ this.useFixedMutateProbability = state;
|
|
|
|
+ mutateTextField.setEnabled(state);
|
|
|
|
+ mutationLabel.setEnabled(state);
|
|
|
|
+ });
|
|
|
|
+ parameterPanel.add(useFixMutateCheckBox);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ JFormattedTextField swapTextField = new JFormattedTextField(limitFormatter);
|
|
|
|
+ swapTextField.setValue(this.fixedSwapProbability);
|
|
|
|
+ swapTextField.setEnabled(this.useFixedMutateProbability);
|
|
|
|
+ swapTextField.setToolTipText("Only Double in range [0.0, 1.0] with DecimalSeperator Point('.').");
|
|
|
|
+ swapTextField.addPropertyChangeListener(propertyChange -> this.fixedSwapProbability = Double.parseDouble(swapTextField.getValue().toString()));
|
|
|
|
+ swapTextField.setBounds(160, 160, 50, 20);
|
|
|
|
+ parameterPanel.add(swapTextField);
|
|
|
|
+
|
|
|
|
+ JCheckBox useFixSwapCheckBox = new JCheckBox();
|
|
|
|
+ useFixSwapCheckBox.setSelected(this.useFixedSpawProbability);
|
|
|
|
+ useFixSwapCheckBox.setToolTipText("If not checked its 1/ProblemSize");
|
|
|
|
+ useFixSwapCheckBox.setBounds(20, 160, 25, 20);
|
|
|
|
+ useFixSwapCheckBox.addActionListener(actionEvent -> {
|
|
|
|
+ boolean state = useFixSwapCheckBox.isSelected();
|
|
|
|
+ this.useFixedSpawProbability = state;
|
|
|
|
+ swapTextField.setEnabled(state);
|
|
|
|
+ swapLabel.setEnabled(state);
|
|
|
|
+ });
|
|
|
|
+ parameterPanel.add(useFixSwapCheckBox);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ 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 clearButton = new JButton("Clear Console");
|
|
|
|
+ clearButton.addActionListener(actionEvent -> clear());
|
|
|
|
+ buttonPanel.add(clearButton);
|
|
|
|
+ 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(!resetChain.isEmpty()) {
|
|
|
|
+ println("Resetting..");
|
|
|
|
+ resetState();
|
|
|
|
+ resetChain.removeLast();
|
|
|
|
+ control.resetSimulation();
|
|
|
|
+ updateVisual();
|
|
|
|
+ }else {
|
|
|
|
+ println("No run inistialized.");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void resetAll() {
|
|
|
|
+ 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 clear() {
|
|
|
|
+ textArea.setText("");
|
|
|
|
+ }
|
|
|
|
+ private void println(String message) {
|
|
|
|
+ textArea.append(message + "\n");
|
|
|
|
+ }
|
|
|
|
+ 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();
|
|
|
|
+
|
|
|
|
+ startTimer();
|
|
|
|
+ Individual runBest = new Individual();
|
|
|
|
+ runBest.fitness = Double.MAX_VALUE;
|
|
|
|
+ for(int r = 0; r < rounds; r++)
|
|
|
|
+ {
|
|
|
|
+ Individual roundBest = executeGaAlgo();
|
|
|
|
+ if(cancel)return;
|
|
|
|
+ resetState();
|
|
|
|
+ if(roundBest.fitness < runBest.fitness) runBest = roundBest;
|
|
|
|
+ }
|
|
|
|
+ printElapsedTime();
|
|
|
|
+ setState(runBest.position);
|
|
|
|
+ updateVisual();
|
|
|
|
+ println("AlgoResult:" + runBest.fitness);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //Algo Part:
|
|
|
|
+ /**
|
|
|
|
+ * Algorithm 20 !! Fitness is better when smaller.:
|
|
|
|
+ * PseudoCode:
|
|
|
|
+ * Best <- actual;
|
|
|
|
+ * population = initPopulationRandom();
|
|
|
|
+ * for(maxGeneration times){
|
|
|
|
+ * for(each Individual i from population){
|
|
|
|
+ * fitness <- evaluatePosition(i);
|
|
|
|
+ * if(fitness < best.fitnessValue) Best <- i;
|
|
|
|
+ * }
|
|
|
|
+ * childList <- {};
|
|
|
|
+ * for(popsize/2 times){
|
|
|
|
+ * parentA <- selectAParent(population);
|
|
|
|
+ * parentB <- selectAParent(population);
|
|
|
|
+ * childA,childB <- crossover(Copy(parentA ), Copy(parentB));
|
|
|
|
+ * mutate(childA);
|
|
|
|
+ * mutate(childB);
|
|
|
|
+ * childList.add(childA);
|
|
|
|
+ * childList.add(childB);
|
|
|
|
+ * }
|
|
|
|
+ * population = childList;
|
|
|
|
+ *
|
|
|
|
+ * }
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private Individual executeGaAlgo() {
|
|
|
|
+ Individual best = new Individual();
|
|
|
|
+ best.position = extractPositionAndAccess();
|
|
|
|
+ best.fitness = evaluatePosition(best.position, false);
|
|
|
|
+ println("Start with Fitness: " + best.fitness);
|
|
|
|
+ int problemSize = best.position.size();
|
|
|
|
+ List<Individual> population = initPopuluationRandom(problemSize);
|
|
|
|
+ println("Size To Test:" + population.size());
|
|
|
|
+ for(int generation = 0; generation< maxGenerations; generation++) {
|
|
|
|
+ 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;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ List<Individual> childList = new ArrayList<Individual>();
|
|
|
|
+ for(int k = 0; k<popsize/2; k++) {
|
|
|
|
+ Individual parentA = selectAParent(population, popsize);
|
|
|
|
+ Individual parentB = selectAParent(population, popsize);
|
|
|
|
+ Individual childA = new Individual(parentA);
|
|
|
|
+ Individual childB = new Individual(parentB);
|
|
|
|
+ crossover(childA, childB, problemSize);
|
|
|
|
+ mutate(childA, problemSize);
|
|
|
|
+ mutate(childB, problemSize);
|
|
|
|
+ childList.add(childA);
|
|
|
|
+ childList.add(childB);
|
|
|
|
+ }
|
|
|
|
+ population = childList;
|
|
|
|
+ println("________________");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ println("RoundResult:" + best.fitness);
|
|
|
|
+ return best;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Algorithm 22 Bit-Flip Mutation.
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+ private void mutate(Individual child, int problemSize) {
|
|
|
|
+ double probability = (this.useFixedMutateProbability) ? this.fixedMutateProbability : 1.0/(double)problemSize;
|
|
|
|
+ ListIterator<Boolean> iter = child.position.listIterator();
|
|
|
|
+ while(iter.hasNext()) {
|
|
|
|
+ boolean boolValue = iter.next();
|
|
|
|
+ if(Random.nextDouble() <= probability) {
|
|
|
|
+ iter.set(!boolValue);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * Algorithm 25 Uniform Crossover.
|
|
|
|
+ * Probability is set to 1/Problemsize when not changed.
|
|
|
|
+ */
|
|
|
|
+ private void crossover(Individual childA, Individual childB, int problemSize) {
|
|
|
|
+ double probability = (this.useFixedSpawProbability) ? this.fixedSwapProbability : 1.0/(double)problemSize;
|
|
|
|
+ ListIterator<Boolean> iterA = childA.position.listIterator();
|
|
|
|
+ ListIterator<Boolean> iterB = childB.position.listIterator();
|
|
|
|
+ for(int i= 0; i < problemSize; i++) {
|
|
|
|
+ boolean boolA = iterA.next();
|
|
|
|
+ boolean boolB = iterB.next();
|
|
|
|
+ if(Random.nextDouble() <= probability ) {
|
|
|
|
+ //Swap
|
|
|
|
+ iterA.set(boolB);
|
|
|
|
+ iterB.set(boolA);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * Algorithm 32 Tournament Selection.
|
|
|
|
+ * The fitnessValues are calculated for the Population List.
|
|
|
|
+ * PseudoCode
|
|
|
|
+ */
|
|
|
|
+ private Individual selectAParent(List<Individual> population,int popsize) {
|
|
|
|
+ Individual tournamentBest = population.get(Random.nextIntegerInRange(0, popsize));
|
|
|
|
+ for(int i = 2 ; i <= tournamentSize; i++) {
|
|
|
|
+ Individual next = population.get(Random.nextIntegerInRange(0, popsize));
|
|
|
|
+ if(next.fitness < tournamentBest.fitness) tournamentBest = next;
|
|
|
|
+ }
|
|
|
|
+ return tournamentBest;
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * Initialize the Population with Individuals that have a random Position.
|
|
|
|
+ */
|
|
|
|
+ private List<Individual> initPopuluationRandom(int problemSize){
|
|
|
|
+ List<Individual> population = new ArrayList<Individual>();
|
|
|
|
+ for(int i = 0; i < popsize; i++) {
|
|
|
|
+ population.add(createRandomIndividualWithoutFitness(problemSize));
|
|
|
|
+ }
|
|
|
|
+ return population;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Algorithm 21 The BooleanVeator initialization.
|
|
|
|
+ * @param problemSize
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private Individual createRandomIndividualWithoutFitness(int problemSize) {
|
|
|
|
+ //create Random Individual Without Fitness
|
|
|
|
+ Individual result = new Individual();
|
|
|
|
+ result.position = new ArrayList<Boolean>();
|
|
|
|
+ for (int index = 0; index < problemSize; index++){
|
|
|
|
+ result.position.add(Random.nextBoolean());
|
|
|
|
+ }
|
|
|
|
+ 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();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|