GaAlgorithm.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. package exampleAlgorithms;
  2. import java.awt.BorderLayout;
  3. import java.awt.Component;
  4. import java.awt.Dimension;
  5. import java.awt.FlowLayout;
  6. import java.awt.image.BufferedImage;
  7. import java.math.RoundingMode;
  8. import java.text.NumberFormat;
  9. import java.util.ArrayList;
  10. import java.util.HashMap;
  11. import java.util.LinkedList;
  12. import java.util.List;
  13. import java.util.ListIterator;
  14. import java.util.Locale;
  15. import java.util.stream.Collectors;
  16. import javax.swing.BorderFactory;
  17. import javax.swing.ImageIcon;
  18. import javax.swing.JButton;
  19. import javax.swing.JCheckBox;
  20. import javax.swing.JFormattedTextField;
  21. import javax.swing.JFrame;
  22. import javax.swing.JLabel;
  23. import javax.swing.JOptionPane;
  24. import javax.swing.JPanel;
  25. import javax.swing.JProgressBar;
  26. import javax.swing.JScrollPane;
  27. import javax.swing.JSplitPane;
  28. import javax.swing.JTextArea;
  29. import javax.swing.text.NumberFormatter;
  30. import api.Algorithm;
  31. import classes.AbstractCpsObject;
  32. import classes.CpsUpperNode;
  33. import classes.HolonElement;
  34. import classes.HolonObject;
  35. import classes.HolonSwitch;
  36. import ui.controller.Control;
  37. import ui.model.DecoratedGroupNode;
  38. import ui.model.DecoratedState;
  39. import ui.model.Model;
  40. import ui.view.Console;
  41. import ui.model.DecoratedHolonObject.HolonObjectState;
  42. public class GaAlgorithm implements Algorithm {
  43. //Parameter for Algo with default Values:
  44. /**
  45. * Should be even.
  46. */
  47. private int popsize = 20;
  48. private int maxGenerations = 100;
  49. private double tournamentSize = 2.1;
  50. private double fixedSwapProbability = 0.02;
  51. private boolean useFixedSpawProbability = false;
  52. private double fixedMutateProbability = 0.02;
  53. private boolean useFixedMutateProbability = false;
  54. private int rounds = 2;
  55. //Settings For GroupNode using and cancel
  56. private boolean useGroupNode = false;
  57. private DecoratedGroupNode dGroupNode = null;
  58. private boolean cancel = false;
  59. //Parameter defined by Algo
  60. private HashMap<Integer, AccessWrapper> access;
  61. LinkedList<List<Boolean>> resetChain = new LinkedList<List<Boolean>>();
  62. private List<Boolean> initialState;
  63. private List<HolonSwitch> switchList;
  64. private List<HolonObject> objectList;
  65. //Gui Part:
  66. private Control control;
  67. private Console console = new Console();
  68. private JPanel content = new JPanel();
  69. //ProgressBar
  70. private JProgressBar progressBar = new JProgressBar();
  71. private int progressBarCount = 0;
  72. private long startTime;
  73. private Thread runThread;
  74. public static void main(String[] args)
  75. {
  76. JFrame newFrame = new JFrame("exampleWindow");
  77. GaAlgorithm instance = new GaAlgorithm();
  78. newFrame.setContentPane(instance.getAlgorithmPanel());
  79. newFrame.pack();
  80. newFrame.setVisible(true);
  81. newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  82. }
  83. public GaAlgorithm() {
  84. content.setLayout(new BorderLayout());
  85. JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
  86. createOptionPanel() , console);
  87. splitPane.setResizeWeight(0.0);
  88. content.add(splitPane, BorderLayout.CENTER);
  89. content.setPreferredSize(new Dimension(800,800));
  90. }
  91. public JPanel createOptionPanel() {
  92. JPanel optionPanel = new JPanel(new BorderLayout());
  93. JScrollPane scrollPane = new JScrollPane(createParameterPanel());
  94. scrollPane.setBorder(BorderFactory.createTitledBorder("Parameter"));
  95. optionPanel.add(scrollPane, BorderLayout.CENTER);
  96. optionPanel.add(createButtonPanel(), BorderLayout.PAGE_END);
  97. return optionPanel;
  98. }
  99. private Component createParameterPanel() {
  100. JPanel parameterPanel = new JPanel(null);
  101. parameterPanel.setPreferredSize(new Dimension(510,300));
  102. JLabel maxGenerationsLabel = new JLabel("Max. Generations:");
  103. maxGenerationsLabel.setBounds(20, 60, 150, 20);
  104. parameterPanel.add(maxGenerationsLabel);
  105. JLabel populationLabel = new JLabel("Population Size:");
  106. populationLabel.setBounds(20, 85, 150, 20);
  107. parameterPanel.add(populationLabel);
  108. JLabel roundLabel = new JLabel("Rounds:");
  109. roundLabel.setBounds(20, 110, 150, 20);
  110. parameterPanel.add(roundLabel);
  111. JLabel mutationLabel = new JLabel("FixedMutation:");
  112. mutationLabel.setBounds(50, 135, 150, 20);
  113. mutationLabel.setEnabled(useFixedMutateProbability);
  114. parameterPanel.add(mutationLabel);
  115. JLabel swapLabel = new JLabel("FixedSwap:");
  116. swapLabel.setBounds(50, 160, 150, 20);
  117. swapLabel.setEnabled(this.useFixedSpawProbability);
  118. parameterPanel.add(swapLabel);
  119. JLabel tournamentLabel = new JLabel("TournamentSize:");
  120. tournamentLabel.setBounds(20, 185, 150, 20);
  121. parameterPanel.add(tournamentLabel);
  122. JLabel progressLabel = new JLabel("Progress:");
  123. progressLabel.setBounds(350, 135, 170, 20);
  124. parameterPanel.add(progressLabel);
  125. progressBar.setBounds(350, 155, 185, 20);
  126. progressBar.setStringPainted(true);
  127. parameterPanel.add(progressBar);
  128. JPanel borderPanel = new JPanel(null);
  129. borderPanel.setBounds(350, 85, 185, 50);
  130. borderPanel.setBorder(BorderFactory.createTitledBorder(""));
  131. parameterPanel.add(borderPanel);
  132. JLabel showGroupNodeLabel = new JLabel("Use Group Node:");
  133. showGroupNodeLabel.setBounds(10, 1, 170, 20);
  134. borderPanel.add(showGroupNodeLabel);
  135. JButton selectGroupNodeButton = new JButton("Select GroupNode");
  136. selectGroupNodeButton.setEnabled(false);
  137. selectGroupNodeButton.setBounds(10, 25, 165, 20);
  138. selectGroupNodeButton.addActionListener(actionEvent -> selectGroupNode());
  139. borderPanel.add(selectGroupNodeButton);
  140. JCheckBox useGroupNodeCheckBox = new JCheckBox();
  141. useGroupNodeCheckBox.setSelected(false);
  142. useGroupNodeCheckBox.setBounds(155, 1, 25, 20);
  143. useGroupNodeCheckBox.addActionListener(actionEvent -> {
  144. useGroupNode = useGroupNodeCheckBox.isSelected();
  145. selectGroupNodeButton.setEnabled(useGroupNode);
  146. });
  147. borderPanel.add(useGroupNodeCheckBox);
  148. //Integer formatter
  149. NumberFormat format = NumberFormat.getIntegerInstance();
  150. format.setGroupingUsed(false);
  151. format.setParseIntegerOnly(true);
  152. NumberFormatter integerFormatter = new NumberFormatter(format);
  153. integerFormatter.setMinimum(1);
  154. integerFormatter.setCommitsOnValidEdit(true);
  155. JFormattedTextField maxGenerationsTextField = new JFormattedTextField(integerFormatter);
  156. maxGenerationsTextField.setValue(this.maxGenerations);
  157. maxGenerationsTextField.setToolTipText("Only positive Integer.");
  158. maxGenerationsTextField.addPropertyChangeListener(actionEvent -> this.maxGenerations = Integer.parseInt(maxGenerationsTextField.getValue().toString()));
  159. maxGenerationsTextField.setBounds(160, 60, 50, 20);
  160. parameterPanel.add(maxGenerationsTextField);
  161. JFormattedTextField popSizeTextField = new JFormattedTextField(integerFormatter);
  162. popSizeTextField.setValue(this.popsize);
  163. popSizeTextField.setToolTipText("Only positive Integer.");
  164. popSizeTextField.addPropertyChangeListener(propertyChange -> this.popsize = Integer.parseInt(popSizeTextField.getValue().toString()));
  165. popSizeTextField.setBounds(160, 85, 50, 20);
  166. parameterPanel.add(popSizeTextField);
  167. JFormattedTextField roundsTextField = new JFormattedTextField(integerFormatter);
  168. roundsTextField.setValue(this.rounds);
  169. roundsTextField.setToolTipText("Only positive Integer.");
  170. roundsTextField.addPropertyChangeListener(propertyChange -> this.rounds = Integer.parseInt(roundsTextField.getValue().toString()));
  171. roundsTextField.setBounds(160, 110, 50, 20);
  172. parameterPanel.add(roundsTextField);
  173. //Double Format:
  174. NumberFormat doubleFormat = NumberFormat.getNumberInstance(Locale.US);
  175. doubleFormat.setMinimumFractionDigits(1);
  176. doubleFormat.setMaximumFractionDigits(3);
  177. doubleFormat.setRoundingMode(RoundingMode.HALF_UP);
  178. //Limit Formatter:
  179. NumberFormatter limitFormatter = new NumberFormatter(doubleFormat);
  180. limitFormatter.setMinimum(0.0);
  181. limitFormatter.setMaximum(1.0);
  182. JFormattedTextField mutateTextField = new JFormattedTextField(limitFormatter);
  183. mutateTextField.setValue(this.fixedMutateProbability);
  184. mutateTextField.setEnabled(this.useFixedMutateProbability);
  185. mutateTextField.setToolTipText("Only Double in range [0.0, 1.0] with DecimalSeperator Point('.').");
  186. mutateTextField.addPropertyChangeListener(propertyChange -> fixedMutateProbability = Double.parseDouble(mutateTextField.getValue().toString()));
  187. mutateTextField.setBounds(160, 135, 50, 20);
  188. parameterPanel.add(mutateTextField);
  189. JCheckBox useFixMutateCheckBox = new JCheckBox();
  190. useFixMutateCheckBox.setSelected(this.useFixedMutateProbability);
  191. useFixMutateCheckBox.setToolTipText("If not checked its 1/ProblemSize");
  192. useFixMutateCheckBox.setBounds(20, 135, 25, 20);
  193. useFixMutateCheckBox.addActionListener(actionEvent -> {
  194. boolean state = useFixMutateCheckBox.isSelected();
  195. this.useFixedMutateProbability = state;
  196. mutateTextField.setEnabled(state);
  197. mutationLabel.setEnabled(state);
  198. });
  199. parameterPanel.add(useFixMutateCheckBox);
  200. JFormattedTextField swapTextField = new JFormattedTextField(limitFormatter);
  201. swapTextField.setValue(this.fixedSwapProbability);
  202. swapTextField.setEnabled(this.useFixedMutateProbability);
  203. swapTextField.setToolTipText("Only Double in range [0.0, 1.0] with DecimalSeperator Point('.').");
  204. swapTextField.addPropertyChangeListener(propertyChange -> this.fixedSwapProbability = Double.parseDouble(swapTextField.getValue().toString()));
  205. swapTextField.setBounds(160, 160, 50, 20);
  206. parameterPanel.add(swapTextField);
  207. JCheckBox useFixSwapCheckBox = new JCheckBox();
  208. useFixSwapCheckBox.setSelected(this.useFixedSpawProbability);
  209. useFixSwapCheckBox.setToolTipText("If not checked its 1/ProblemSize");
  210. useFixSwapCheckBox.setBounds(20, 160, 25, 20);
  211. useFixSwapCheckBox.addActionListener(actionEvent -> {
  212. boolean state = useFixSwapCheckBox.isSelected();
  213. this.useFixedSpawProbability = state;
  214. swapTextField.setEnabled(state);
  215. swapLabel.setEnabled(state);
  216. });
  217. parameterPanel.add(useFixSwapCheckBox);
  218. NumberFormatter tournamentFormatter = new NumberFormatter(doubleFormat);
  219. tournamentFormatter.setMinimum(1.0);
  220. JFormattedTextField tournamentSizeTextField = new JFormattedTextField(tournamentFormatter);
  221. tournamentSizeTextField.setValue(this.tournamentSize);
  222. tournamentSizeTextField.setToolTipText("Only Double bigger or equal then 1.");
  223. tournamentSizeTextField.addPropertyChangeListener(propertyChange -> this.tournamentSize = Double.parseDouble(tournamentSizeTextField.getValue().toString()));
  224. tournamentSizeTextField.setBounds(160, 185, 50, 20);
  225. parameterPanel.add(tournamentSizeTextField);
  226. return parameterPanel;
  227. }
  228. public JPanel createButtonPanel() {
  229. JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
  230. JButton resetButton = new JButton("ResetAll");
  231. resetButton.setToolTipText("Resets the State to before the Algorithm has runed.");
  232. resetButton.addActionListener(actionEvent -> resetAll());
  233. buttonPanel.add(resetButton);
  234. JButton cancelButton = new JButton("Cancel Run");
  235. cancelButton.addActionListener(actionEvent -> cancel());
  236. buttonPanel.add(cancelButton);
  237. JButton undoButton = new JButton("Undo");
  238. undoButton.setToolTipText("One Algo Step Back.");
  239. undoButton.addActionListener(actionEvent -> resetLast());
  240. buttonPanel.add(undoButton);
  241. JButton runButton = new JButton("Run");
  242. runButton.addActionListener(actionEvent -> {
  243. Runnable task = () -> run();
  244. runThread = new Thread(task);
  245. runThread.start();
  246. });
  247. buttonPanel.add(runButton);
  248. return buttonPanel;
  249. }
  250. private void cancel() {
  251. if(runThread.isAlive()) {
  252. println("");
  253. println("Cancel run.");
  254. cancel = true;
  255. progressBar.setValue(0);
  256. } else {
  257. println("Nothing to cancel.");
  258. }
  259. }
  260. private void run() {
  261. cancel = false;
  262. disableGuiInput(true);
  263. executeAlgoWithParameter();
  264. updateVisual();
  265. disableGuiInput(false);
  266. }
  267. private void resetLast() {
  268. if(runThread.isAlive()) {
  269. println("Run have to be cancelled First.");
  270. return;
  271. }
  272. if(!resetChain.isEmpty()) {
  273. println("Resetting..");
  274. resetState();
  275. resetChain.removeLast();
  276. control.resetSimulation();
  277. updateVisual();
  278. }else {
  279. println("No run inistialized.");
  280. }
  281. }
  282. private void resetAll() {
  283. if(runThread.isAlive()) {
  284. println("Run have to be cancelled First.");
  285. return;
  286. }
  287. if(!resetChain.isEmpty()) {
  288. println("Resetting..");
  289. setState(resetChain.getFirst());
  290. resetChain.clear();
  291. control.resetSimulation();
  292. control.setCurIteration(0);
  293. updateVisual();
  294. }else {
  295. println("No run inistialized.");
  296. }
  297. }
  298. private void disableGuiInput(boolean bool) {
  299. control.guiDiable(bool);
  300. }
  301. @Override
  302. public JPanel getAlgorithmPanel() {
  303. return content;
  304. }
  305. @Override
  306. public void setController(Control control) {
  307. this.control = control;
  308. }
  309. private void clear() {
  310. console.clear();
  311. }
  312. private void println(String message) {
  313. console.println(message);
  314. }
  315. private void selectGroupNode() {
  316. Object[] possibilities = control.getSimManager().getActualVisualRepresentationalState().getCreatedGroupNodes().values().stream().map(aCps -> new Handle<DecoratedGroupNode>(aCps)).toArray();
  317. @SuppressWarnings("unchecked")
  318. 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, "");
  319. if(selected != null) {
  320. println("Selected: " + selected);
  321. dGroupNode = selected.object;
  322. }
  323. }
  324. private void progressBarStep(){
  325. progressBar.setValue(++progressBarCount);
  326. }
  327. private void calculateProgressBarParameter() {
  328. int max = this.maxGenerations * this.popsize * this.rounds;
  329. progressBarCount = 0;
  330. progressBar.setValue(0);
  331. progressBar.setMaximum(max);
  332. }
  333. private void startTimer(){
  334. startTime = System.currentTimeMillis();
  335. }
  336. private void printElapsedTime(){
  337. long elapsedMilliSeconds = System.currentTimeMillis() - startTime;
  338. println("Execution Time of Algo in Milliseconds:" + elapsedMilliSeconds);
  339. }
  340. private void executeAlgoWithParameter(){
  341. int actualIteration = control.getModel().getCurIteration();
  342. println("TimeStep:" + actualIteration);
  343. calculateProgressBarParameter();
  344. startTimer();
  345. Individual runBest = new Individual();
  346. runBest.fitness = Double.MAX_VALUE;
  347. for(int r = 0; r < rounds; r++)
  348. {
  349. Individual roundBest = executeGaAlgo();
  350. if(cancel)return;
  351. resetState();
  352. if(roundBest.fitness < runBest.fitness) runBest = roundBest;
  353. }
  354. printElapsedTime();
  355. setState(runBest.position);
  356. updateVisual();
  357. println("AlgoResult:" + runBest.fitness);
  358. }
  359. //Algo Part:
  360. /**
  361. * Algorithm 20 !! Fitness is better when smaller.:
  362. * PseudoCode:
  363. * Best <- actual;
  364. * population = initPopulationRandom();
  365. * for(maxGeneration times){
  366. * for(each Individual i from population){
  367. * fitness <- evaluatePosition(i);
  368. * if(fitness < best.fitnessValue) Best <- i;
  369. * }
  370. * childList <- {};
  371. * for(popsize/2 times){
  372. * parentA <- selectAParent(population);
  373. * parentB <- selectAParent(population);
  374. * childA,childB <- crossover(Copy(parentA ), Copy(parentB));
  375. * mutate(childA);
  376. * mutate(childB);
  377. * childList.add(childA);
  378. * childList.add(childB);
  379. * }
  380. * population = childList;
  381. *
  382. * }
  383. * @return
  384. */
  385. private Individual executeGaAlgo() {
  386. Individual best = new Individual();
  387. best.position = extractPositionAndAccess();
  388. println("Bit-Array_length: " + best.position.size());
  389. best.fitness = evaluatePosition(best.position, false);
  390. println("Start with Fitness: " + best.fitness);
  391. int problemSize = best.position.size();
  392. List<Individual> population = initPopuluationRandom(problemSize, best);
  393. println("Size To Test:" + population.size());
  394. for(int generation = 0; generation< maxGenerations; generation++) {
  395. println("Generation" + generation + " start with Fitness: " + best.fitness);
  396. for(Individual i : population) {
  397. i.fitness = evaluatePosition(i.position, true);
  398. println("Fitness" + i.fitness);
  399. if(i.fitness < best.fitness) best = i;
  400. }
  401. List<Individual> childList = new ArrayList<Individual>();
  402. for(int k = 0; k<popsize/2; k++) {
  403. Individual parentA = selectAParent(population, popsize);
  404. Individual parentB = selectAParent(population, popsize);
  405. Individual childA = new Individual(parentA);
  406. Individual childB = new Individual(parentB);
  407. crossover(childA, childB, problemSize);
  408. mutate(childA, problemSize);
  409. mutate(childB, problemSize);
  410. childList.add(childA);
  411. childList.add(childB);
  412. }
  413. population = childList;
  414. println("________________");
  415. }
  416. println("RoundResult:" + best.fitness);
  417. return best;
  418. }
  419. /**
  420. * Algorithm 22 Bit-Flip Mutation.
  421. *
  422. */
  423. private void mutate(Individual child, int problemSize) {
  424. double probability = (this.useFixedMutateProbability) ? this.fixedMutateProbability : 1.0/(double)problemSize;
  425. ListIterator<Boolean> iter = child.position.listIterator();
  426. while(iter.hasNext()) {
  427. boolean boolValue = iter.next();
  428. if(Random.nextDouble() <= probability) {
  429. iter.set(!boolValue);
  430. }
  431. }
  432. }
  433. /**
  434. * Algorithm 25 Uniform Crossover.
  435. * Probability is set to 1/Problemsize when not changed.
  436. */
  437. private void crossover(Individual childA, Individual childB, int problemSize) {
  438. double probability = (this.useFixedSpawProbability) ? this.fixedSwapProbability : 1.0/(double)problemSize;
  439. ListIterator<Boolean> iterA = childA.position.listIterator();
  440. ListIterator<Boolean> iterB = childB.position.listIterator();
  441. for(int i= 0; i < problemSize; i++) {
  442. boolean boolA = iterA.next();
  443. boolean boolB = iterB.next();
  444. if(Random.nextDouble() <= probability ) {
  445. //Swap
  446. iterA.set(boolB);
  447. iterB.set(boolA);
  448. }
  449. }
  450. }
  451. /**
  452. * Algorithm 32 Tournament Selection.
  453. * The fitnessValues are calculated for the Population List.
  454. * PseudoCode
  455. */
  456. private Individual selectAParent(List<Individual> population,int popsize) {
  457. Individual tournamentBest = population.get(Random.nextIntegerInRange(0, popsize));
  458. double participants;
  459. for(participants = tournamentSize ; participants >= 2; participants -= 1.0) {
  460. Individual next = population.get(Random.nextIntegerInRange(0, popsize));
  461. if(next.fitness < tournamentBest.fitness) tournamentBest = next;
  462. }
  463. //if tournament size is not a whole number like 2.5 or 3.6
  464. //the remaining part is the chance to fight another time; 2.7 -> 70% chance to fight a second time
  465. if( participants > 1) {
  466. if(Random.nextDouble() < participants - 1.0) {
  467. println("Chance to find a match");
  468. Individual next = population.get(Random.nextIntegerInRange(0, popsize));
  469. if(next.fitness < tournamentBest.fitness) tournamentBest = next;
  470. }
  471. }
  472. return tournamentBest;
  473. }
  474. /**
  475. * Initialize the Population with Individuals that have a random Position.
  476. */
  477. private List<Individual> initPopuluationRandom(int problemSize, Individual startIndidual){
  478. List<Individual> population = new ArrayList<Individual>();
  479. for(int i = 0; i < popsize -1; i++) {
  480. population.add(createRandomIndividualWithoutFitness(problemSize));
  481. }
  482. //Add Start Position
  483. population.add(new Individual(startIndidual));
  484. return population;
  485. }
  486. /**
  487. * Algorithm 21 The BooleanVeator initialization.
  488. * @param problemSize
  489. * @return
  490. */
  491. private Individual createRandomIndividualWithoutFitness(int problemSize) {
  492. //create Random Individual Without Fitness
  493. Individual result = new Individual();
  494. result.position = new ArrayList<Boolean>();
  495. for (int index = 0; index < problemSize; index++){
  496. result.position.add(Random.nextBoolean());
  497. }
  498. return result;
  499. }
  500. /**
  501. * Method to get the current Position alias a ListOf Booleans for aktive settings on the Objects on the Canvas.
  502. * Also initialize the Access Hashmap to swap faster positions.
  503. * @param model
  504. * @return
  505. */
  506. private List<Boolean> extractPositionAndAccess() {
  507. Model model = control.getModel();
  508. switchList = new ArrayList<HolonSwitch>();
  509. objectList = new ArrayList<HolonObject>();
  510. initialState = new ArrayList<Boolean>();
  511. access= new HashMap<Integer, AccessWrapper>();
  512. rollOutNodes((useGroupNode && (dGroupNode != null))? dGroupNode.getModel().getNodes() :model.getObjectsOnCanvas(), initialState, model.getCurIteration());
  513. resetChain.add(initialState);
  514. return initialState;
  515. }
  516. /**
  517. * Method to extract the Informations recursively out of the Model.
  518. * @param nodes
  519. * @param positionToInit
  520. * @param timeStep
  521. */
  522. private void rollOutNodes(List<AbstractCpsObject> nodes, List<Boolean> positionToInit, int timeStep) {
  523. for(AbstractCpsObject aCps : nodes) {
  524. if (aCps instanceof HolonObject) {
  525. for (HolonElement hE : ((HolonObject) aCps).getElements()) {
  526. positionToInit.add(hE.isActive());
  527. access.put(positionToInit.size() - 1 , new AccessWrapper(hE));
  528. }
  529. objectList.add((HolonObject) aCps);
  530. }
  531. else if (aCps instanceof HolonSwitch) {
  532. HolonSwitch sw = (HolonSwitch) aCps;
  533. positionToInit.add(sw.getState(timeStep));
  534. switchList.add(sw);
  535. access.put(positionToInit.size() - 1 , new AccessWrapper(sw));
  536. }
  537. else if(aCps instanceof CpsUpperNode) {
  538. rollOutNodes(((CpsUpperNode)aCps).getNodes(), positionToInit ,timeStep );
  539. }
  540. }
  541. }
  542. private double evaluatePosition(List<Boolean> position, boolean doIncreaseCounter) {
  543. setState(position);
  544. if(doIncreaseCounter)progressBarStep();
  545. control.calculateStateOnlyForCurrentTimeStep();
  546. DecoratedState actualstate = control.getSimManager().getActualDecorState();
  547. return PSOAlgorithm.getFitnessValueForState(actualstate);
  548. }
  549. /**
  550. * To let the User See the current state without touching the Canvas.
  551. */
  552. private void updateVisual() {
  553. control.calculateStateAndVisualForCurrentTimeStep();
  554. //control.updateCanvas();
  555. //control.getGui().triggerUpdateController(null);
  556. }
  557. /**
  558. * Sets the Model back to its original State before the LAST run.
  559. */
  560. private void resetState() {
  561. setState(resetChain.getLast());
  562. }
  563. /**
  564. * Sets the State out of the given position for calculation or to show the user.
  565. * @param position
  566. */
  567. private void setState(List<Boolean> position) {
  568. for(int i = 0;i<position.size();i++) {
  569. access.get(i).setState(position.get(i));
  570. }
  571. }
  572. private class Individual {
  573. public double fitness;
  574. public List<Boolean> position;
  575. Individual(){};
  576. /**
  577. * Copy Constructor
  578. */
  579. Individual(Individual c){
  580. position = c.position.stream().collect(Collectors.toList());
  581. fitness = c.fitness;
  582. }
  583. }
  584. /**
  585. * A Wrapper Class for Access HolonElement and HolonSwitch in one Element and not have to split the List.
  586. */
  587. private class AccessWrapper {
  588. public static final int HOLONELEMENT = 0;
  589. public static final int SWITCH = 1;
  590. private int type;
  591. private HolonSwitch hSwitch;
  592. private HolonElement hElement;
  593. public AccessWrapper(HolonSwitch hSwitch){
  594. type = SWITCH;
  595. this.hSwitch = hSwitch;
  596. }
  597. public AccessWrapper(HolonElement hElement){
  598. type = HOLONELEMENT;
  599. this.hElement = hElement;
  600. }
  601. public void setState(boolean state) {
  602. if(type == HOLONELEMENT) {
  603. hElement.setActive(state);
  604. }else{//is switch
  605. hSwitch.setManualMode(true);
  606. hSwitch.setManualState(state);
  607. }
  608. }
  609. public boolean getState(int timeStep) {
  610. return (type == HOLONELEMENT)?hElement.isActive():hSwitch.getState(timeStep);
  611. }
  612. public int getType() {
  613. return type;
  614. }
  615. }
  616. private class RunResult {
  617. public int activatedFlex = 0;
  618. public int deactivatedElements = 0;
  619. public float totalCost = 0;
  620. public LinkedList<TimeStepStateResult> timeStepList = new LinkedList<TimeStepStateResult>();
  621. public TimeStepStateResult addTimeStepStateResult(){
  622. TimeStepStateResult aResult = new TimeStepStateResult();
  623. timeStepList.add(aResult);
  624. return aResult;
  625. }
  626. public class TimeStepStateResult{
  627. public int amountOfProducer = 0;
  628. public int amountOfConsumer = 0;
  629. public int amountOfPassiv = 0;
  630. public int amountOfConsumerOverSupplied = 0;
  631. public int amountOfConsumerSupplied = 0;
  632. public int amountOfConsumerPartiallySupplied = 0;
  633. public int amountOfConsumerUnSupplied= 0;
  634. public float getProportionWithState(HolonObjectState state) {
  635. float amountOfObjects = amountOfProducer + amountOfConsumer + amountOfPassiv;
  636. switch(state) {
  637. case NOT_SUPPLIED:
  638. return (float) amountOfConsumerUnSupplied / amountOfObjects;
  639. case NO_ENERGY:
  640. return (float) amountOfPassiv / amountOfObjects;
  641. case OVER_SUPPLIED:
  642. return (float) amountOfConsumerOverSupplied / amountOfObjects;
  643. case PARTIALLY_SUPPLIED:
  644. return (float) amountOfConsumerPartiallySupplied / amountOfObjects;
  645. case PRODUCER:
  646. return (float) amountOfProducer / amountOfObjects;
  647. case SUPPLIED:
  648. return (float) amountOfConsumerSupplied / amountOfObjects;
  649. default:
  650. return 0.f;
  651. }
  652. }
  653. }
  654. public float getAvergaeProportionWithState(HolonObjectState state) {
  655. return timeStepList.stream().map(step -> step.getProportionWithState(state)).reduce((a,b) -> (a + b)).orElse(0.f) / (float) 100;
  656. }
  657. }
  658. /**
  659. * To create Random and maybe switch the random generation in the future.
  660. */
  661. private static class Random{
  662. private static java.util.Random random = new java.util.Random();
  663. /**
  664. * True or false
  665. * @return the random boolean.
  666. */
  667. public static boolean nextBoolean(){
  668. return random.nextBoolean();
  669. }
  670. /**
  671. * Between 0.0(inclusive) and 1.0 (exclusive)
  672. * @return the random double.
  673. */
  674. public static double nextDouble() {
  675. return random.nextDouble();
  676. }
  677. /**
  678. * Random Int in Range [min;max[ with UniformDistirbution
  679. * @param min
  680. * @param max
  681. * @return
  682. */
  683. public static int nextIntegerInRange(int min, int max) {
  684. return min + random.nextInt(max - min);
  685. }
  686. }
  687. private class Handle<T>{
  688. public T object;
  689. Handle(T object){
  690. this.object = object;
  691. }
  692. public String toString() {
  693. return object.toString();
  694. }
  695. }
  696. }