PSOAlgotihm.java 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. package exampleAlgorithms;
  2. import java.awt.BorderLayout;
  3. import java.awt.Component;
  4. import java.awt.Cursor;
  5. import java.awt.Dimension;
  6. import java.awt.FlowLayout;
  7. import java.awt.Font;
  8. import java.awt.image.BufferedImage;
  9. import java.io.BufferedWriter;
  10. import java.io.File;
  11. import java.io.FileOutputStream;
  12. import java.io.IOException;
  13. import java.io.OutputStreamWriter;
  14. import java.math.RoundingMode;
  15. import java.text.NumberFormat;
  16. import java.util.ArrayList;
  17. import java.util.HashMap;
  18. import java.util.List;
  19. import java.util.Locale;
  20. import java.util.stream.Collectors;
  21. import javax.swing.BorderFactory;
  22. import javax.swing.ImageIcon;
  23. import javax.swing.JButton;
  24. import javax.swing.JCheckBox;
  25. import javax.swing.JFileChooser;
  26. import javax.swing.JFormattedTextField;
  27. import javax.swing.JFrame;
  28. import javax.swing.JLabel;
  29. import javax.swing.JOptionPane;
  30. import javax.swing.JPanel;
  31. import javax.swing.JProgressBar;
  32. import javax.swing.JScrollPane;
  33. import javax.swing.JSplitPane;
  34. import javax.swing.JTextArea;
  35. import javax.swing.filechooser.FileNameExtensionFilter;
  36. import javax.swing.text.NumberFormatter;
  37. import api.Algorithm;
  38. import classes.AbstractCpsObject;
  39. import classes.CpsUpperNode;
  40. import classes.HolonElement;
  41. import classes.HolonObject;
  42. import classes.HolonSwitch;
  43. import ui.controller.Control;
  44. import ui.model.Model;
  45. import ui.model.DecoratedHolonObject.HolonObjectState;
  46. import ui.model.DecoratedGroupNode;
  47. import ui.model.DecoratedNetwork;
  48. import ui.model.DecoratedState;
  49. public class PSOAlgotihm implements Algorithm {
  50. //Parameter for Algo with default Values:
  51. private int swarmSize = 20;
  52. private int maxIterations = 100;
  53. private double limit = 0.01;
  54. private double dependency = 2.07;
  55. private int rounds = 20;
  56. private int mutationInterval = 0;
  57. //Settings For GroupNode using and plotting
  58. private boolean append = false;
  59. private boolean useGroupNode = false;
  60. private DecoratedGroupNode dGroupNode = null;
  61. //Parameter defined by Algo
  62. private HashMap<Integer, AccessWrapper> access;
  63. private List<Boolean> initialState;
  64. private double c1, c2, w;
  65. private RunDataBase db;
  66. //Parameter for Plotting (Default Directory in Constructor)
  67. private JFileChooser fileChooser = new JFileChooser();
  68. //Gui Part:
  69. private Control control;
  70. private JTextArea textArea;
  71. private JPanel content = new JPanel();
  72. //ProgressBar
  73. private JProgressBar progressBar = new JProgressBar();
  74. private int progressBarCount = 0;
  75. private long startTime;
  76. private Thread runThread;
  77. private boolean cancel = false;
  78. public static void main(String[] args)
  79. {
  80. JFrame newFrame = new JFrame("exampleWindow");
  81. PSOAlgotihm instance = new PSOAlgotihm();
  82. newFrame.setContentPane(instance.getAlgorithmPanel());
  83. newFrame.pack();
  84. newFrame.setVisible(true);
  85. newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  86. }
  87. public PSOAlgotihm() {
  88. content.setLayout(new BorderLayout());
  89. textArea = new JTextArea();
  90. textArea.setEditable(false);
  91. JScrollPane scrollPane = new JScrollPane(textArea);
  92. JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
  93. createOptionPanel() , scrollPane);
  94. splitPane.setResizeWeight(0.0);
  95. content.add(splitPane, BorderLayout.CENTER);
  96. content.setPreferredSize(new Dimension(800,800));
  97. //Default Directory
  98. fileChooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
  99. fileChooser.setSelectedFile(new File("plott.txt"));
  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 info = new JLabel("Tune the variables of the PSO algorithm in order to reach better results.");
  113. info.setBounds(10, 10, 480, 15);
  114. parameterPanel.add(info);
  115. JLabel swarmSizeLabel = new JLabel("Swarm Size:");
  116. swarmSizeLabel.setBounds(20, 60, 100, 20);
  117. parameterPanel.add(swarmSizeLabel);
  118. JLabel maxIterLabel = new JLabel("Max. Iterations:");
  119. maxIterLabel.setBounds(20, 85, 100, 20);
  120. parameterPanel.add(maxIterLabel);
  121. JLabel limitLabel = new JLabel("Limit:");
  122. limitLabel.setBounds(20, 110, 100, 20);
  123. parameterPanel.add(limitLabel);
  124. JLabel dependecyLabel = new JLabel("Dependency:");
  125. dependecyLabel.setBounds(20, 135, 100, 20);
  126. parameterPanel.add(dependecyLabel);
  127. JLabel roundsLabel = new JLabel("Round:");
  128. roundsLabel.setBounds(20, 160, 100, 20);
  129. parameterPanel.add(roundsLabel);
  130. JLabel mutationIntervalLabel = new JLabel("Mutation Interval");
  131. mutationIntervalLabel.setBounds(20, 185, 100, 20);
  132. parameterPanel.add(mutationIntervalLabel);
  133. JLabel cautionLabel = new JLabel(
  134. "Caution: High values in the fields of 'Swarm Size' and 'Max. Iteration' may take some time to calculate.");
  135. cautionLabel.setFont(new Font("Serif", Font.ITALIC, 12));
  136. JLabel showDiagnosticsLabel = new JLabel("Append Plott on existing File:");
  137. showDiagnosticsLabel.setBounds(200, 60, 170, 20);
  138. parameterPanel.add(showDiagnosticsLabel);
  139. JPanel borderPanel = new JPanel(null);
  140. borderPanel.setBounds(200, 85, 185, 50);
  141. borderPanel.setBorder(BorderFactory.createTitledBorder(""));
  142. parameterPanel.add(borderPanel);
  143. JLabel showGroupNodeLabel = new JLabel("Use Group Node:");
  144. showGroupNodeLabel.setBounds(10, 1, 170, 20);
  145. borderPanel.add(showGroupNodeLabel);
  146. JButton selectGroupNodeButton = new JButton("Select GroupNode");
  147. selectGroupNodeButton.setEnabled(false);
  148. selectGroupNodeButton.setBounds(10, 25, 165, 20);
  149. selectGroupNodeButton.addActionListener(actionEvent -> selectGroupNode());
  150. borderPanel.add(selectGroupNodeButton);
  151. JCheckBox useGroupNodeCheckBox = new JCheckBox();
  152. useGroupNodeCheckBox.setSelected(false);
  153. useGroupNodeCheckBox.setBounds(155, 1, 25, 20);
  154. useGroupNodeCheckBox.addActionListener(actionEvent -> {
  155. useGroupNode = useGroupNodeCheckBox.isSelected();
  156. selectGroupNodeButton.setEnabled(useGroupNode);
  157. });
  158. borderPanel.add(useGroupNodeCheckBox);
  159. JLabel progressLabel = new JLabel("Progress:");
  160. progressLabel.setBounds(200, 135, 170, 20);
  161. parameterPanel.add(progressLabel);
  162. progressBar.setBounds(200, 155, 185, 20);
  163. progressBar.setStringPainted(true);
  164. parameterPanel.add(progressBar);
  165. cautionLabel.setBounds(10, 210, 500, 15);
  166. parameterPanel.add(cautionLabel);
  167. JCheckBox diagnosticsCheckBox = new JCheckBox();
  168. diagnosticsCheckBox.setSelected(false);
  169. diagnosticsCheckBox.setBounds(370, 60, 25, 20);
  170. diagnosticsCheckBox.addActionListener(actionEvent -> append = diagnosticsCheckBox.isSelected());
  171. parameterPanel.add(diagnosticsCheckBox);
  172. //Integer formatter
  173. NumberFormat format = NumberFormat.getIntegerInstance();
  174. format.setGroupingUsed(false);
  175. format.setParseIntegerOnly(true);
  176. NumberFormatter integerFormatter = new NumberFormatter(format);
  177. integerFormatter.setMinimum(0);
  178. integerFormatter.setCommitsOnValidEdit(true);
  179. JFormattedTextField swarmSizeTextField = new JFormattedTextField(integerFormatter);
  180. swarmSizeTextField.setValue(swarmSize);
  181. swarmSizeTextField.setToolTipText("Only positive Integer.");
  182. swarmSizeTextField.addPropertyChangeListener(actionEvent -> swarmSize = Integer.parseInt(swarmSizeTextField.getValue().toString()));
  183. swarmSizeTextField.setBounds(125, 60, 50, 20);
  184. parameterPanel.add(swarmSizeTextField);
  185. JFormattedTextField maxIterTextField = new JFormattedTextField(integerFormatter);
  186. maxIterTextField.setValue(maxIterations);
  187. maxIterTextField.setToolTipText("Only positive Integer.");
  188. maxIterTextField.addPropertyChangeListener(propertyChange -> maxIterations = Integer.parseInt(maxIterTextField.getValue().toString()));
  189. maxIterTextField.setBounds(125, 85, 50, 20);
  190. parameterPanel.add(maxIterTextField);
  191. //Double Format:
  192. NumberFormat doubleFormat = NumberFormat.getNumberInstance(Locale.US);
  193. doubleFormat.setMinimumFractionDigits(1);
  194. doubleFormat.setMaximumFractionDigits(3);
  195. doubleFormat.setRoundingMode(RoundingMode.HALF_UP);
  196. //Limit Formatter:
  197. NumberFormatter limitFormatter = new NumberFormatter(doubleFormat);
  198. limitFormatter.setMinimum(0.0);
  199. limitFormatter.setMaximum(1.0);
  200. JFormattedTextField limitTextField = new JFormattedTextField(limitFormatter);
  201. limitTextField.setValue(limit);
  202. limitTextField.setToolTipText("Only Double in range [0.0, 1.0] with DecimalSeperator Point('.').");
  203. limitTextField.addPropertyChangeListener(propertyChange -> limit = Double.parseDouble(limitTextField.getValue().toString()));
  204. limitTextField.setBounds(125, 110, 50, 20);
  205. parameterPanel.add(limitTextField);
  206. //Limit Formatter:
  207. NumberFormatter dependencyFormatter = new NumberFormatter(doubleFormat);
  208. dependencyFormatter.setMinimum(2.001);
  209. dependencyFormatter.setMaximum(2.4);
  210. JFormattedTextField dependencyTextField = new JFormattedTextField(dependencyFormatter);
  211. dependencyTextField.setValue(dependency);
  212. dependencyTextField.setToolTipText("Only Double in range [2.001, 2.4] with DecimalSeperator Point('.').");
  213. dependencyTextField.addPropertyChangeListener(propertyChange -> dependency = Double.parseDouble(dependencyTextField.getValue().toString()));
  214. dependencyTextField.setBounds(125, 135, 50, 20);
  215. parameterPanel.add(dependencyTextField);
  216. NumberFormatter roundsFormatter = new NumberFormatter(format);
  217. roundsFormatter.setMinimum(1);
  218. roundsFormatter.setCommitsOnValidEdit(true);
  219. JFormattedTextField roundsTextField = new JFormattedTextField(roundsFormatter);
  220. roundsTextField.setValue(rounds);
  221. roundsTextField.setToolTipText("Number of algorithm repetitions for the same starting situation ");
  222. roundsTextField.addPropertyChangeListener(propertyChange -> rounds = Integer.parseInt((roundsTextField.getValue().toString())));
  223. roundsTextField.setBounds(125, 160, 50, 20);
  224. parameterPanel.add(roundsTextField);
  225. //--- subsequently Rolf Did stuff ------------------------------------------------------------------------------------------
  226. /*NumberFormatter mutationIntervalFormatter = new NumberFormatter(inte);
  227. mutationIntervalFormatter.setMinimum(0);
  228. mutationIntervalFormatter.setMaximum(maxIterations);
  229. mutationIntervalFormatter.setCommitsOnValidEdit(true);*/
  230. JFormattedTextField mutationIntervalTextfield = new JFormattedTextField(integerFormatter);
  231. mutationIntervalTextfield.setValue(mutationInterval);
  232. mutationIntervalTextfield.setToolTipText("The number of Iterations after which one mutation iteration is conducted");
  233. mutationIntervalTextfield.addPropertyChangeListener(propertyChange -> mutationInterval = Integer.parseInt((mutationIntervalTextfield.getValue().toString())));
  234. mutationIntervalTextfield.setBounds(125, 185, 50, 20);
  235. parameterPanel.add(mutationIntervalTextfield);
  236. //--- previously Rolf Did stuff ------------------------------------------------------------------------------------------
  237. return parameterPanel;
  238. }
  239. public JPanel createButtonPanel() {
  240. JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
  241. JButton cancelButton = new JButton("Cancel Run");
  242. cancelButton.addActionListener(actionEvent -> cancel());
  243. buttonPanel.add(cancelButton);
  244. JButton clearButton = new JButton("Clear Console");
  245. clearButton.addActionListener(actionEvent -> clear());
  246. buttonPanel.add(clearButton);
  247. JButton folderButton = new JButton("Change Plott-File");
  248. folderButton.addActionListener(actionEvent -> setSaveFile());
  249. buttonPanel.add(folderButton);
  250. JButton fitnessButton = new JButton("Actual Fitness");
  251. fitnessButton.addActionListener(actionEvent -> fitness());
  252. buttonPanel.add(fitnessButton);
  253. JButton plottButton = new JButton("Plott");
  254. plottButton.addActionListener(actionEvent -> plott());
  255. buttonPanel.add(plottButton);
  256. JButton resetButton = new JButton("Reset");
  257. resetButton.setToolTipText("Resets the State to before the Algorithm has runed.");
  258. resetButton.addActionListener(actionEvent -> reset());
  259. buttonPanel.add(resetButton);
  260. JButton runButton = new JButton("Run");
  261. runButton.addActionListener(actionEvent -> {
  262. Runnable task = () -> run();
  263. runThread = new Thread(task);
  264. runThread.start();
  265. });
  266. buttonPanel.add(runButton);
  267. return buttonPanel;
  268. }
  269. private void run() {
  270. cancel = false;
  271. disableGuiInput(true);
  272. startTimer();
  273. executePsoAlgoWithCurrentParameters();
  274. if(cancel) {
  275. reset();
  276. disableGuiInput(false);
  277. return;
  278. }
  279. printElapsedTime();
  280. disableGuiInput(false);
  281. }
  282. private void disableGuiInput(boolean bool) {
  283. control.guiDiable(bool);
  284. }
  285. private void cancel() {
  286. if(runThread.isAlive()) {
  287. println("");
  288. println("Cancel run.");
  289. cancel = true;
  290. progressBar.setValue(0);
  291. } else {
  292. println("Nothing to cancel.");
  293. }
  294. }
  295. private void fitness() {
  296. initDependentParameter();
  297. double currentFitness = evaluatePosition(extractPositionAndAccess(control.getModel()), false);
  298. println("Actual Fitnessvalue: " + currentFitness);
  299. }
  300. private void setSaveFile() {
  301. fileChooser.setFileFilter(new FileNameExtensionFilter("File", "txt"));
  302. fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
  303. int result = fileChooser.showSaveDialog(content);
  304. if(result == JFileChooser.APPROVE_OPTION) {
  305. println("Set save File to:" + fileChooser.getSelectedFile().getAbsolutePath());
  306. }
  307. }
  308. private void plott() {
  309. if(db!=null) {
  310. println("Plott..");
  311. db.initFileStream();
  312. }else {
  313. println("No run inistialized.");
  314. }
  315. }
  316. private void reset() {
  317. if(initialState != null) {
  318. println("Resetting..");
  319. resetState();
  320. updateVisual();
  321. }else {
  322. println("No run inistialized.");
  323. }
  324. }
  325. private void printParameter() {
  326. println("SwarmSize:" + swarmSize + ", MaxIter:" + maxIterations + ", Limit:" + limit + ", Dependency:" + dependency + ", Rounds:" + rounds +", DependentParameter: w:"+ w + ", c1:" + c1 + ", c2:" + c2 );
  327. }
  328. @Override
  329. public JPanel getAlgorithmPanel() {
  330. return content;
  331. }
  332. @Override
  333. public void setController(Control control) {
  334. this.control = control;
  335. }
  336. private void clear() {
  337. textArea.setText("");
  338. }
  339. private void print(String message) {
  340. textArea.append(message);
  341. }
  342. private void println(String message) {
  343. textArea.append(message + "\n");
  344. }
  345. private void selectGroupNode() {
  346. Object[] possibilities = control.getSimManager().getActualVisualRepresentationalState().getCreatedGroupNodes().values().stream().map(aCps -> new Handle<DecoratedGroupNode>(aCps)).toArray();
  347. @SuppressWarnings("unchecked")
  348. 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, "");
  349. if(selected != null) {
  350. println("Selected: " + selected);
  351. dGroupNode = selected.object;
  352. }
  353. }
  354. private void progressBarStep(){
  355. progressBar.setValue(++progressBarCount);
  356. }
  357. private void calculateProgressBarParameter() {
  358. int max = swarmSize * (maxIterations + 1)* rounds + rounds;
  359. progressBarCount = 0;
  360. progressBar.setValue(0);
  361. progressBar.setMaximum(max);
  362. }
  363. private void startTimer(){
  364. startTime = System.currentTimeMillis();
  365. }
  366. private void printElapsedTime(){
  367. long elapsedMilliSeconds = System.currentTimeMillis() - startTime;
  368. println("Execution Time of Algo in Milliseconds:" + elapsedMilliSeconds);
  369. }
  370. //Algo Part:
  371. /**
  372. * The Execution of the Algo its initialize the missing parameter and execute single Algo runs successively.
  373. */
  374. private void executePsoAlgoWithCurrentParameters() {
  375. initDependentParameter();
  376. calculateProgressBarParameter();
  377. printParameter();
  378. Best runBest = new Best();
  379. runBest.value = Double.MAX_VALUE;
  380. db = new RunDataBase();
  381. for(int r = 0; r < rounds; r++)
  382. {
  383. List<Double> runList = db.insertNewRun();
  384. Best lastRunBest = executePSOoneTime(runList);
  385. if(cancel)return;
  386. resetState();
  387. if(lastRunBest.value < runBest.value) runBest = lastRunBest;
  388. }
  389. println("AlgoResult:" + runBest.value);
  390. //println("[" + lastRunBest.position.stream().map(Object::toString).collect(Collectors.joining(", ")) + "]");
  391. setState(runBest.position);
  392. updateVisual();
  393. }
  394. /**
  395. * Calculate w, c1, c2
  396. */
  397. private void initDependentParameter() {
  398. w = 1.0 / (dependency - 1 + Math.sqrt(dependency * dependency - 2 * dependency));
  399. c1 = c2 = dependency * w;
  400. }
  401. /**
  402. * <p>Algo from Paper:</p><font size="3"><pre>
  403. *
  404. * Begin
  405. * t = 0; {t: generation index}
  406. * initialize particles x<sub>p,i,j</sub>(t);
  407. * evaluation x<sub>p,i,j</sub>(t);
  408. * while (termination condition &ne; true) do
  409. * v<sub>i,j</sub>(t) = update v<sub>i,j</sub>(t); {by Eq. (6)}
  410. * x<sub>g,i,j</sub>(t) = update x<sub>g,i,j</sub>(t); {by Eq. (7)}
  411. * x<sub>g,i,j</sub>(t) = mutation x<sub>g,i,j</sub>(t); {by Eq. (11)}
  412. * x<sub>p,i,j</sub>(t) = decode x<sub>g,i,j</sub>(t); {by Eqs. (8) and (9)}
  413. * evaluate x<sub>p,i,j</sub>(t);
  414. * t = t + 1;
  415. * end while
  416. * End</pre></font>
  417. * <p>with:</p><font size="3">
  418. *
  419. * x<sub>g,i,j</sub>: genotype ->genetic information -> in continuous space<br>
  420. * x<sub>p,i,j</sub>: phenotype -> observable characteristics-> in binary space<br>
  421. * X<sub>g,max</sub>: is the Maximum here set to 4.<br>
  422. * Eq. (6):v<sub>i,j</sub>(t + 1) = wv<sub>i,j</sub>+c<sub>1</sub>R<sub>1</sub>(P<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))+c<sub>2</sub>R<sub>2</sub>(g<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))<br>
  423. * Eq. (7):x<sub>g,i,j</sub>(t + 1) = x<sub>g,i,j</sub>(t) + v<sub>i,j</sub>(t + 1)<br>
  424. * Eq. (11):<b>if(</b>rand()&lt;r<sub>mu</sub><b>)then</b> x<sub>g,i,j</sub>(t + 1) = -x<sub>g,i,j</sub>(t + 1)<br>
  425. * Eq. (8):x<sub>p,i,j</sub>(t + 1) = <b>(</b>rand() &lt; S(x<sub>g,i,j</sub>(t + 1))<b>) ?</b> 1 <b>:</b> 0<br>
  426. * Eq. (9) Sigmoid:S(x<sub>g,i,j</sub>(t + 1)) := 1/(1 + e<sup>-x<sub>g,i,j</sub>(t + 1)</sup>)<br></font>
  427. * <p>Parameter:</p>
  428. * w inertia, calculated from phi(Variable:{@link #dependency})<br>
  429. * c1: influence, calculated from phi(Variable:{@link #dependency}) <br>
  430. * c2: influence, calculated from phi(Variable:{@link #dependency})<br>
  431. * r<sub>mu</sub>: probability that the proposed operation is conducted defined by limit(Variable:{@link #limit})<br>
  432. *
  433. *
  434. */
  435. private Best executePSOoneTime(List<Double> runList) {
  436. Best globalBest = new Best();
  437. globalBest.position = extractPositionAndAccess(control.getModel());
  438. globalBest.value = evaluatePosition(globalBest.position, true);
  439. print("Start Value:" + globalBest.value);
  440. int dimensions = globalBest.position.size();
  441. List<Particle> swarm= initializeParticles(dimensions);
  442. runList.add(globalBest.value);
  443. evaluation(globalBest, swarm);
  444. runList.add(globalBest.value);
  445. for (int iteration = 0; iteration < maxIterations ; iteration++) {
  446. int mutationAllowed = iteration % mutationInterval;
  447. for (int particleNumber = 0; particleNumber < swarmSize; particleNumber++) {
  448. Particle particle = swarm.get(particleNumber);
  449. for(int index = 0; index < dimensions; index++) {
  450. updateVelocity(particle, index, globalBest);
  451. updateGenotype(particle, index);
  452. //-------Rolf changes below------------------------
  453. if(mutationAllowed == 0 && iteration != 0)
  454. mutation(particle, index);
  455. decode(particle, index);
  456. }
  457. }
  458. if(cancel)return null;
  459. evaluation(globalBest, swarm);
  460. runList.add(globalBest.value);
  461. }
  462. println(" End Value:" + globalBest.value);
  463. return globalBest;
  464. }
  465. /**
  466. * Eq. (6):v<sub>i,j</sub>(t + 1) = wv<sub>i,j</sub>+c<sub>1</sub>R<sub>1</sub>(P<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))+c<sub>2</sub>R<sub>2</sub>(g<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))<br>
  467. * @param particle
  468. * @param index
  469. * @param globalBest
  470. */
  471. private void updateVelocity(Particle particle, int index, Best globalBest) {
  472. double r1 = Random.nextDouble();
  473. double r2 = Random.nextDouble();
  474. double posValue = particle.xPhenotype.get(index)?1.0:0.0;
  475. particle.velocity.set(index, clamp(w*particle.velocity.get(index) + c1*r1*((particle.localBest.position.get(index)?1.0:0.0) - posValue) + c2*r2*((globalBest.position.get(index)?1.0:0.0)- posValue)) );
  476. }
  477. /**
  478. * Eq. (7):x<sub>g,i,j</sub>(t + 1) = x<sub>g,i,j</sub>(t) + v<sub>i,j</sub>(t + 1)<br>
  479. * @param particle
  480. * @param index
  481. */
  482. private void updateGenotype(Particle particle, int index) {
  483. particle.xGenotype.set(index, clamp(particle.xGenotype.get(index) + particle.velocity.get(index)));
  484. }
  485. /**
  486. * Eq. (11):<b>if(</b>rand()&lt;r<sub>mu</sub><b>)then</b> x<sub>g,i,j</sub>(t + 1) = -x<sub>g,i,j</sub>(t + 1)<br>
  487. * @param particle
  488. * @param index
  489. */
  490. private void mutation(Particle particle, int index) {
  491. if(Random.nextDouble() < limit) particle.xGenotype.set(index, -particle.xGenotype.get(index));
  492. }
  493. /**
  494. * Eq. (8):x<sub>p,i,j</sub>(t + 1) = <b>(</b>rand() &lt; S(x<sub>g,i,j</sub>(t + 1))<b>) ?</b> 1 <b>:</b> 0<br>
  495. * @param particle
  496. * @param index
  497. */
  498. private void decode(Particle particle, int index) {
  499. particle.xPhenotype.set(index, Random.nextDouble() < Sigmoid(particle.xGenotype.get(index)));
  500. }
  501. /**
  502. * Eq. (9) Sigmoid:S(x<sub>g,i,j</sub>(t + 1)) := 1/(1 + e<sup>-x<sub>g,i,j</sub>(t + 1)</sup>)<br></font>
  503. * @param value
  504. * @return
  505. */
  506. private double Sigmoid(double value) {
  507. return 1.0 / (1.0 + Math.exp(-value));
  508. }
  509. /**
  510. * To clamp X<sub>g,j,i</sub> and v<sub>i,j</sub> in Range [-X<sub>g,max</sub>|+X<sub>g,max</sub>] with {X<sub>g,max</sub>= 4}
  511. * @param value
  512. * @return
  513. */
  514. private double clamp(double value) {
  515. return Math.max(-4.0, Math.min(4.0, value));
  516. }
  517. /**
  518. *
  519. * @param j maximum index of position in the particle
  520. * @return
  521. */
  522. private List<Particle> initializeParticles(int j) {
  523. List<Particle> swarm = new ArrayList<Particle>();
  524. //Create The Particle
  525. for (int particleNumber = 0; particleNumber < swarmSize; particleNumber++){
  526. //Create a Random position
  527. List<Boolean> aRandomPosition = new ArrayList<Boolean>();
  528. for (int index = 0; index < j; index++){
  529. aRandomPosition.add(Random.nextBoolean());
  530. }
  531. swarm.add(new Particle(aRandomPosition));
  532. }
  533. return swarm;
  534. }
  535. /**
  536. * Evaluate each particle and update the global Best position;
  537. * @param globalBest
  538. * @param swarm
  539. */
  540. private void evaluation(Best globalBest, List<Particle> swarm) {
  541. for(Particle p: swarm) {
  542. double localEvaluationValue = evaluatePosition(p.xPhenotype, true);
  543. p.checkNewEvaluationValue(localEvaluationValue);
  544. if(localEvaluationValue < globalBest.value) {
  545. globalBest.value = localEvaluationValue;
  546. globalBest.position = p.localBest.position;
  547. }
  548. }
  549. }
  550. /**
  551. * Evaluate a position.
  552. * @param position
  553. * @return
  554. */
  555. private double evaluatePosition(List<Boolean> position, boolean doIncreaseCounter) {
  556. setState(position);
  557. if(doIncreaseCounter)progressBarStep();
  558. control.calculateStateOnlyForCurrentTimeStep();
  559. DecoratedState actualstate = control.getSimManager().getActualDecorState();
  560. return getFitnessValueForState(actualstate);
  561. }
  562. /**
  563. * Calculate the Fitness(Penelty) Value for a state (alias the calculated Position).
  564. * TODO: Make me better Rolf.
  565. * @param state
  566. * @return
  567. */
  568. private double getFitnessValueForState(DecoratedState state) {
  569. double fitness = 0.0;
  570. double nw_fitness =0.0;
  571. double object_fitness = 0.0;
  572. // calculate network_fitness
  573. for(DecoratedNetwork net : state.getNetworkList()) {
  574. float production = net.getSupplierList().stream().map(supplier -> supplier.getEnergyToSupplyNetwork()).reduce(0.0f, (a, b) -> a + b);
  575. float consumption = net.getConsumerList().stream().map(con -> con.getEnergyNeededFromNetwork()).reduce(0.0f, (a, b) -> a + b);
  576. nw_fitness += Math.abs((production - consumption)/100); //Energy is now everywhere positive
  577. }
  578. // calculate object_fitness
  579. for(DecoratedNetwork net : state.getNetworkList()) {
  580. object_fitness += net.getConsumerList().stream().map(con -> holonObjectSupplyPenaltyFunction(con.getSupplyBarPercentage()) + inactiveHolonElementPenalty(con.getModel())).reduce(0.0, (a, b) -> (a + b));
  581. //warum war das im network fitness und nicht hier im Object fitness??
  582. object_fitness += net.getConsumerList().stream().map(con -> StateToDouble(con.getState())).reduce(0.0, (a,b) -> (a+b));
  583. //System.out.println("objectfitness for statestuff: " + object_fitness);
  584. //object_fitness += net.getPassivNoEnergyList().stream().map(con -> 1000.0).reduce(0.0, (a, b) -> (a + b));
  585. object_fitness += net.getPassivNoEnergyList().stream().map(sup -> inactiveHolonElementPenalty(sup.getModel())).reduce(0.0, (a, b) -> (a + b));
  586. object_fitness += net.getSupplierList().stream().map(sup -> inactiveHolonElementPenalty(sup.getModel())).reduce(0.0, (a, b) -> (a + b));
  587. object_fitness += net.getConsumerSelfSuppliedList().stream().map(con -> inactiveHolonElementPenalty(con.getModel())).reduce(0.0, (a, b) -> (a + b));
  588. }
  589. fitness = nw_fitness + object_fitness;
  590. return fitness;
  591. }
  592. /**
  593. * Untouched:
  594. * Function that returns the fitness depending on the number of elements deactivated in a single holon object
  595. * @param obj Holon Object that contains Holon Elements
  596. * @return fitness value for that object depending on the number of deactivated holon elements
  597. */
  598. private double inactiveHolonElementPenalty(HolonObject obj) {
  599. float result = 0;
  600. int activeElements = obj.getNumberOfActiveElements();
  601. int maxElements = obj.getElements().size();
  602. //result = (float) Math.pow((maxElements -activeElements),2)*10;
  603. result = (float) Math.pow(5, 4* ( (float) maxElements - (float) activeElements)/ (float) maxElements) - 1;
  604. //System.out.println("max: " + maxElements + " active: " + activeElements + " results in penalty: " + result);
  605. return result;
  606. }
  607. /**
  608. * Untouched:
  609. * Calculates a penalty value based on the HOs current supply percentage
  610. * @param supplyPercentage
  611. * @return
  612. */
  613. private double holonObjectSupplyPenaltyFunction(float supplyPercentage) {
  614. double result = 0;
  615. /*if(supplyPercentage == 1)
  616. return result;
  617. else if(supplyPercentage < 1 && supplyPercentage >= 0.25) // undersupplied inbetween 25% and 100%
  618. result = (float) Math.pow(1/supplyPercentage, 2);
  619. else if (supplyPercentage < 0.25) //undersupplied with less than 25%
  620. result = (float) Math.pow(1/supplyPercentage,2);
  621. else if (supplyPercentage < 1.25) //Oversupplied less than 25%
  622. result = (float) Math.pow(supplyPercentage,3) ;
  623. else result = (float) Math.pow(supplyPercentage,4); //Oversupplied more than 25%
  624. if(Float.isInfinite(result) || Float.isNaN(result))
  625. result = 1000;
  626. */
  627. if(supplyPercentage <= 1.0) {
  628. result = Math.pow(5,((100 - (supplyPercentage*100))/50 + 2)) - Math.pow(5, 2);
  629. }
  630. else {
  631. result = Math.pow(6,((100 - (supplyPercentage*100))/50 + 2)) - Math.pow(6, 2);
  632. }
  633. return result;
  634. }
  635. /**
  636. * If you want to get in touch with a reliable state? Working function not in use currently.
  637. * @param state
  638. * @return
  639. */
  640. private double StateToDouble(HolonObjectState state) {
  641. switch (state) {
  642. case NOT_SUPPLIED:
  643. return 150.0;
  644. case NO_ENERGY:
  645. return 150.0;
  646. case OVER_SUPPLIED:
  647. return 100.0;
  648. case PARTIALLY_SUPPLIED:
  649. return 100.0;
  650. case PRODUCER:
  651. return 0;
  652. case SUPPLIED:
  653. return 0;
  654. default:
  655. return 0;
  656. }
  657. }
  658. /**
  659. * Method to get the current Position alias a ListOf Booleans for aktive settings on the Objects on the Canvas.
  660. * Also initialize the Access Hashmap to swap faster positions.
  661. * @param model
  662. * @return
  663. */
  664. private List<Boolean> extractPositionAndAccess(Model model) {
  665. initialState = new ArrayList<Boolean>();
  666. access= new HashMap<Integer, AccessWrapper>();
  667. rollOutNodes((useGroupNode && (dGroupNode != null))? dGroupNode.getModel().getNodes() :model.getObjectsOnCanvas(), initialState, model.getCurIteration());
  668. return initialState;
  669. }
  670. /**
  671. * Method to extract the Informations recursively out of the Model.
  672. * @param nodes
  673. * @param positionToInit
  674. * @param timeStep
  675. */
  676. private void rollOutNodes(List<AbstractCpsObject> nodes, List<Boolean> positionToInit, int timeStep) {
  677. for(AbstractCpsObject aCps : nodes) {
  678. if (aCps instanceof HolonObject) {
  679. for (HolonElement hE : ((HolonObject) aCps).getElements()) {
  680. positionToInit.add(hE.isActive());
  681. access.put(positionToInit.size() - 1 , new AccessWrapper(hE));
  682. }
  683. }
  684. else if (aCps instanceof HolonSwitch) {
  685. HolonSwitch sw = (HolonSwitch) aCps;
  686. positionToInit.add(sw.getState(timeStep));
  687. access.put(positionToInit.size() - 1 , new AccessWrapper(sw));
  688. }
  689. else if(aCps instanceof CpsUpperNode) {
  690. rollOutNodes(((CpsUpperNode)aCps).getNodes(), positionToInit ,timeStep );
  691. }
  692. }
  693. }
  694. /**
  695. * To let the User See the current state without touching the Canvas.
  696. */
  697. private void updateVisual() {
  698. control.calculateStateAndVisualForCurrentTimeStep();
  699. control.updateCanvas();
  700. }
  701. /**
  702. * Sets the Model back to its original State before the LAST run.
  703. */
  704. private void resetState() {
  705. setState(initialState);
  706. }
  707. /**
  708. * Sets the State out of the given position for calculation or to show the user.
  709. * @param position
  710. */
  711. private void setState(List<Boolean> position) {
  712. for(int i = 0;i<position.size();i++) {
  713. access.get(i).setState(position.get(i));
  714. }
  715. }
  716. /**
  717. * A Database for all Global Best(G<sub>Best</sub>) Values in a execution of a the Algo. For Easy Printing.
  718. */
  719. private class RunDataBase {
  720. List<List<Double>> allRuns;
  721. RunDataBase(){
  722. allRuns = new ArrayList<List<Double>>();
  723. }
  724. /**
  725. * Initialize The Stream before you can write to a File.
  726. */
  727. public void initFileStream() {
  728. File file = fileChooser.getSelectedFile();
  729. try {
  730. file.createNewFile();
  731. BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
  732. new FileOutputStream(file, append), "UTF-8"));
  733. printToStream(out);
  734. out.close();
  735. } catch (IOException e) {
  736. println(e.getMessage());
  737. }
  738. }
  739. /**
  740. *
  741. * TODO: Rolf Change this method to suit your Python script respectively.
  742. * A run have maxIterations + 2 values. As described: First is the InitialState Value,
  743. * Second is The best Value after the swarm is Initialized not have moved jet, and then comes the Iterations that described
  744. * each step of movement from the swarm.
  745. */
  746. public void printToStream(BufferedWriter out) throws IOException {
  747. try {
  748. out.write(maxIterations + 2 + "," + allRuns.size() + "," + swarmSize);
  749. out.newLine();
  750. }
  751. catch(IOException e) {
  752. println(e.getMessage());
  753. }
  754. allRuns.forEach(run -> {
  755. try {
  756. out.write( run.stream().map(Object::toString).collect(Collectors.joining(", ")));
  757. out.newLine();
  758. } catch (IOException e) {
  759. println(e.getMessage());
  760. }
  761. } );
  762. /* out.write("AverageRun:");
  763. out.newLine();
  764. out.write(calculateAverageRun().stream().map(Object::toString).collect(Collectors.joining(", ")));
  765. out.newLine();
  766. */
  767. }
  768. private List<Double> calculateAverageRun(){
  769. int amountOfRuns = allRuns.size();
  770. List<Double> newAverageRun = new ArrayList<Double>();
  771. for(int iteration = 0; iteration < maxIterations + 2; iteration++) {
  772. final int currentIter = iteration;
  773. double sum = 0.0;
  774. sum = allRuns.stream().map(run -> run.get(currentIter)).reduce(0.0, (a, b) -> a + b);
  775. newAverageRun.add(sum / amountOfRuns);
  776. }
  777. return newAverageRun;
  778. }
  779. public List<Double> insertNewRun(){
  780. List<Double> newRun = new ArrayList<Double>();
  781. allRuns.add(newRun);
  782. return newRun;
  783. }
  784. }
  785. /**
  786. * To give the Local Best of a Partice(P<sub>Best</sub>) or the Global Best(G<sub>Best</sub>) a Wrapper to have Position And Evaluation Value in one Place.
  787. */
  788. private class Best{
  789. public double value;
  790. public List<Boolean> position;
  791. public Best(){
  792. }
  793. }
  794. /**
  795. * A Wrapper Class for Access HolonElement and HolonSwitch in one Element and not have to split the List.
  796. */
  797. private class AccessWrapper {
  798. public static final int HOLONELEMENT = 0;
  799. public static final int SWITCH = 1;
  800. private int type;
  801. private HolonSwitch hSwitch;
  802. private HolonElement hElement;
  803. public AccessWrapper(HolonSwitch hSwitch){
  804. type = SWITCH;
  805. this.hSwitch = hSwitch;
  806. }
  807. public AccessWrapper(HolonElement hElement){
  808. type = HOLONELEMENT;
  809. this.hElement = hElement;
  810. }
  811. public void setState(boolean state) {
  812. if(type == HOLONELEMENT) {
  813. hElement.setActive(state);
  814. }else{//is switch
  815. hSwitch.setManualMode(true);
  816. hSwitch.setManualState(state);
  817. }
  818. }
  819. public boolean getState(int timeStep) {
  820. return (type == HOLONELEMENT)?hElement.isActive():hSwitch.getState(timeStep);
  821. }
  822. }
  823. /**
  824. * Class to represent a Particle.
  825. */
  826. private class Particle{
  827. /**
  828. * The velocity of a particle.
  829. */
  830. public List<Double> velocity;
  831. /**
  832. * The positions genotype.
  833. */
  834. public List<Double> xGenotype;
  835. /**
  836. * The positions phenotype. Alias the current position.
  837. */
  838. public List<Boolean> xPhenotype;
  839. public Best localBest;
  840. Particle(List<Boolean> position){
  841. this.xPhenotype = position;
  842. //Init velocity, xGenotype with 0.0 values.
  843. this.velocity = position.stream().map(bool -> 0.0).collect(Collectors.toList());
  844. this.xGenotype = position.stream().map(bool -> 0.0).collect(Collectors.toList());
  845. localBest = new Best();
  846. localBest.value = Double.MAX_VALUE;
  847. }
  848. public void checkNewEvaluationValue(double newEvaluationValue) {
  849. if(newEvaluationValue < localBest.value) {
  850. localBest.value = newEvaluationValue;
  851. localBest.position = xPhenotype.stream().map(bool -> bool).collect(Collectors.toList());
  852. }
  853. }
  854. public String toString() {
  855. return "Particle with xPhenotype(Position), xGenotype, velocity:["
  856. + listToString(xPhenotype) + "],[" + listToString(xGenotype) + "],["
  857. + listToString(velocity) + "]";
  858. }
  859. private <Type> String listToString(List<Type> list) {
  860. return list.stream().map(Object::toString).collect(Collectors.joining(", "));
  861. }
  862. }
  863. /**
  864. * To create Random and maybe switch the random generation in the future.
  865. */
  866. private static class Random{
  867. /**
  868. * True or false
  869. * @return the random boolean.
  870. */
  871. public static boolean nextBoolean(){
  872. return (Math.random() < 0.5);
  873. }
  874. /**
  875. * Between 0.0 and 1.0
  876. * @return the random double.
  877. */
  878. public static double nextDouble(){
  879. return Math.random();
  880. }
  881. }
  882. private class Handle<T>{
  883. public T object;
  884. Handle(T object){
  885. this.object = object;
  886. }
  887. public String toString() {
  888. return object.toString();
  889. }
  890. }
  891. }