GaAlgorithm.java 32 KB

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