SimulationManager.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. package ui.controller;
  2. import classes.*;
  3. import ui.model.Model;
  4. import ui.view.FlexiblePane;
  5. import ui.view.MyCanvas;
  6. import java.util.ArrayList;
  7. import java.util.HashMap;
  8. /**
  9. * Controller for Simulation.
  10. *
  11. * @author Gruppe14
  12. */
  13. public class SimulationManager {
  14. private Model model;
  15. private ArrayList<AbstractCpsObject> objectsToHandle;
  16. // private ArrayList<CpsEdge> allConnections;
  17. private ArrayList<SubNet> subNets;
  18. private ArrayList<CpsEdge> brokenEdges;
  19. private MyCanvas canvas;
  20. private int timeStep;
  21. private HashMap<Integer, Float> tagTable = new HashMap<>();
  22. private FlexiblePane flexPane;
  23. /**
  24. * Constructor.
  25. *
  26. * @param m Model
  27. */
  28. SimulationManager(Model m) {
  29. canvas = null;
  30. model = m;
  31. subNets = new ArrayList<>();
  32. brokenEdges = new ArrayList<>();
  33. }
  34. /**
  35. * calculates the flow of the edges and the supply for objects.
  36. *
  37. * @param x current Iteration
  38. */
  39. void calculateStateForTimeStep(int x) {
  40. reset();
  41. timeStep = x;
  42. searchForSubNets();
  43. for (SubNet singleSubNet : subNets) {
  44. resetConnections(singleSubNet.getObjects().get(0), new ArrayList<>(), new ArrayList<>());
  45. }
  46. for (SubNet singleSubNet : subNets) {
  47. float production = calculateEnergy("prod", singleSubNet, timeStep);
  48. float consumption = calculateEnergy("cons", singleSubNet, timeStep);
  49. // wasted energy is computed by sum, since consumption is a negative value
  50. float wastedEnergy = production + consumption;
  51. float minConsumption = calculateMinimumEnergy(singleSubNet, timeStep);
  52. // --------------- use flexible devices ---------------
  53. // TODO: add global setting, whether the grid should react with flexible devices or whether it should not
  54. if (wastedEnergy > 0) {
  55. turnOnFlexibleDevices(singleSubNet, wastedEnergy);
  56. // recompute after having examined all flexible devices
  57. production = calculateEnergy("prod", singleSubNet, timeStep);
  58. consumption = calculateEnergy("cons", singleSubNet, timeStep);
  59. wastedEnergy = production + consumption;
  60. }
  61. // --------------- set flow simulation ---------------
  62. setFlowSimulation(singleSubNet);
  63. // --------------- visualise graph ---------------
  64. for (HolonObject hl : singleSubNet.getObjects()) {
  65. if (hl.getState() != HolonObject.NO_ENERGY
  66. && hl.getState() != HolonObject.PRODUCER) {
  67. for (int i = 0; i < hl.getConnections().size(); i++) {
  68. CpsEdge edge = hl.getConnectedTo().get(i);
  69. if (edge.isWorking() && edge.getFlow() > 0
  70. || edge.getCapacity() == CpsEdge.CAPACITY_INFINITE) {
  71. if ((production + consumption) >= 0) {
  72. if (wastedEnergy > 0) {
  73. hl.setState(HolonObject.OVER_SUPPLIED);
  74. } else {
  75. hl.setState(HolonObject.SUPPLIED);
  76. }
  77. } else {
  78. if ((production + minConsumption) >= 0) {
  79. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  80. } else if (hl.checkIfPartiallySupplied(timeStep)) {
  81. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  82. } else {
  83. hl.setState(HolonObject.NOT_SUPPLIED);
  84. }
  85. }
  86. break;
  87. }
  88. }
  89. if (hl.checkIfPartiallySupplied(timeStep)
  90. && hl.getState() != HolonObject.SUPPLIED
  91. && hl.getState() != HolonObject.OVER_SUPPLIED) {
  92. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  93. }
  94. }
  95. }
  96. }
  97. canvas.repaint();
  98. flexPane.recalculate();
  99. }
  100. /**
  101. * search for all flexible devices in the network and turn them on, until wasted energy = 0
  102. * or all devices have been examined
  103. *
  104. * @param sN the subnet
  105. * @param wastedEnergy the currently wasted energy
  106. */
  107. void turnOnFlexibleDevices(SubNet sN, float wastedEnergy) {
  108. }
  109. /**
  110. * Set Flow Simulation.
  111. *
  112. * @param sN Subnet
  113. */
  114. private void setFlowSimulation(SubNet sN) {
  115. ArrayList<AbstractCpsObject> producers = new ArrayList<>();
  116. AbstractCpsObject tmp = null;
  117. tagTable = new HashMap<>();
  118. // traverse all objects in this subnet
  119. for (HolonObject hl : sN.getObjects()) {
  120. float energy = hl.getCurrentEnergyAtTimeStep(timeStep);
  121. // if their production is higher than their consumption
  122. if (energy > 0) {
  123. tagTable.put(hl.getId(), energy);
  124. hl.addTag(hl.getId());
  125. for (CpsEdge edge : hl.getConnections()) {
  126. if (edge.isWorking()) {
  127. // set other end of edge as tmp-object
  128. // and add this end to the other end's tag-list
  129. AbstractCpsObject a = edge.getA();
  130. AbstractCpsObject b = edge.getB();
  131. if (a.getId() == hl.getId()) {
  132. b.addTag(hl.getId());
  133. tmp = b;
  134. }
  135. if (b.getId() == hl.getId()) {
  136. a.addTag(hl.getId());
  137. tmp = a;
  138. }
  139. edge.setFlow(edge.getFlow() + energy);
  140. edge.calculateState();
  141. edge.addTag(hl.getId());
  142. if (edge.isWorking() && !producers.contains(tmp)) {
  143. if (tmp instanceof HolonSwitch) {
  144. if (((HolonSwitch) tmp).getState(timeStep)) {
  145. producers.add(tmp);
  146. }
  147. } else if (!(tmp instanceof CpsUpperNode)) {
  148. producers.add(tmp);
  149. }
  150. }
  151. }
  152. }
  153. }
  154. }
  155. setFlowSimRec(producers, 0);
  156. }
  157. /**
  158. * Set Flow Simulation Rec.
  159. *
  160. * @param nodes the nodes
  161. * @param iter the Iteration
  162. */
  163. private void setFlowSimRec(ArrayList<AbstractCpsObject> nodes, int iter) {
  164. ArrayList<AbstractCpsObject> newNodes = new ArrayList<>();
  165. ArrayList<CpsEdge> changedEdges = new ArrayList<>();
  166. AbstractCpsObject tmp;
  167. if (nodes.size() != 0) {
  168. for (AbstractCpsObject cps : nodes) {
  169. // check whether the cps is in a legit state if it is a switch
  170. if (legitState(cps)) {
  171. for (CpsEdge edge : cps.getConnections()) {
  172. // is edge working
  173. // and does the edge's tag-list not (yet) contain all tags of the cps
  174. if (edge.isWorking()
  175. && (!(edge.containsTags(edge.getTags(), cps.getTag())))) {
  176. if (edge.getA().getId() == cps.getId()) {
  177. tmp = edge.getB();
  178. } else {
  179. tmp = edge.getA();
  180. }
  181. for (Integer tag : cps.getTag()) {
  182. if (!(edge.getTags().contains(tag))
  183. && !(edge.getPseudoTags().contains(tag))) {
  184. edge.setFlow(edge.getFlow() + tagTable.get(tag));
  185. edge.addTag(tag);
  186. }
  187. }
  188. // uppernodes do not spread energy
  189. if (!(tmp instanceof CpsUpperNode)) {
  190. for (Integer tag : tmp.getTag()) {
  191. if (!(edge.getTags().contains(tag))
  192. && tagTable.get(tag) != null
  193. && !(edge.getPseudoTags().contains(tag))) {
  194. edge.setFlow(edge.getFlow() + tagTable.get(tag));
  195. edge.addPseudoTag(tag);
  196. changedEdges.add(edge);
  197. }
  198. }
  199. }
  200. edge.calculateState();
  201. if (edge.isWorking()
  202. && !(tmp instanceof CpsUpperNode)) {
  203. tmp.addAllPseudoTags(cps.getTag());
  204. if (!newNodes.contains(tmp)) {
  205. newNodes.add(tmp);
  206. }
  207. }
  208. }
  209. }
  210. }
  211. }
  212. setPseudoTags(newNodes, changedEdges);
  213. setFlowSimRec(newNodes, iter + 1);
  214. }
  215. }
  216. /**
  217. * Set the Pseudo Tags.
  218. *
  219. * @param nodes Array of AbstractCpsObjects
  220. */
  221. private void setPseudoTags(ArrayList<AbstractCpsObject> nodes, ArrayList<CpsEdge> edges) {
  222. for (AbstractCpsObject node : nodes) {
  223. node.recalculateTags();
  224. node.setPseudoTags(new ArrayList<>());
  225. }
  226. for (CpsEdge edge : edges) {
  227. edge.recalculateTags();
  228. edge.setPseudoTag(new ArrayList<>());
  229. }
  230. }
  231. // /**
  232. // * Print the nodes.
  233. // *
  234. // * @param nodes
  235. // * Array of AbstractCpsObject
  236. // */
  237. // public void printNodes(ArrayList<AbstractCpsObject> nodes) {
  238. // for (AbstractCpsObject node : nodes) {
  239. // System.out.println(node.getId());
  240. // }
  241. // }
  242. // /**
  243. // * Get String.
  244. // *
  245. // * @param tags
  246. // * the tags
  247. // * @return the String
  248. // */
  249. // public String getString(ArrayList<Integer> tags) {
  250. // String result = "";
  251. // for (Integer i : tags) {
  252. // result = result + ", " + i;
  253. // }
  254. // return result;
  255. // }
  256. // /**
  257. // * Merge the Lists.
  258. // *
  259. // * @param a
  260. // * first liust
  261. // * @param b
  262. // * second list
  263. // * @return the Result
  264. // */
  265. // public ArrayList<Integer> mergeLists(ArrayList<Integer> a, ArrayList<Integer> b) {
  266. // ArrayList<Integer> result = new ArrayList<>();
  267. // for (Integer i : a) {
  268. // if (!(result.contains(i))) {
  269. // result.add(i);
  270. // }
  271. // }
  272. // for (Integer j : b) {
  273. // if (!(result.contains(j))) {
  274. // result.add(j);
  275. // }
  276. // }
  277. // return result;
  278. // }
  279. /**
  280. * Reset the Connection.
  281. *
  282. * @param cps CpsObject
  283. * @param visitedObj the visited Objects
  284. * @param visitedEdges the visited Edges
  285. */
  286. private void resetConnections(AbstractCpsObject cps, ArrayList<Integer> visitedObj,
  287. ArrayList<CpsEdge> visitedEdges) {
  288. visitedObj.add(cps.getId());
  289. cps.resetTags();
  290. for (CpsEdge e : cps.getConnections()) {
  291. if (!(visitedEdges.contains(e))) {
  292. e.setFlow(0);
  293. e.calculateState();
  294. e.setTags(new ArrayList<>());
  295. visitedEdges.add(e);
  296. if (!(visitedObj.contains(e.getA().getId()))) {
  297. resetConnections(e.getA(), visitedObj, visitedEdges);
  298. e.getA().resetTags();
  299. }
  300. if (!(visitedObj.contains(e.getB().getId()))) {
  301. resetConnections(e.getB(), visitedObj, visitedEdges);
  302. e.getB().resetTags();
  303. }
  304. }
  305. }
  306. }
  307. /**
  308. * calculates the energy of either all producers or consumers.
  309. *
  310. * @param type Type
  311. * @param sN Subnet
  312. * @param x Integer
  313. * @return The Energy
  314. */
  315. private float calculateEnergy(String type, SubNet sN, int x) {
  316. float energy = 0;
  317. for (HolonObject hl : sN.getObjects()) {
  318. if (type.equals("prod")) {
  319. if (hl.getCurrentEnergyAtTimeStep(x) > 0) {
  320. energy = energy + hl.getCurrentEnergyAtTimeStep(x);
  321. hl.setState(HolonObject.PRODUCER);
  322. }
  323. }
  324. if (type.equals("cons")) {
  325. if (hl.getCurrentEnergyAtTimeStep(x) < 0) {
  326. energy = energy + hl.getCurrentEnergyAtTimeStep(x);
  327. hl.setState(HolonObject.NOT_SUPPLIED);
  328. }
  329. }
  330. if (hl.getCurrentEnergyAtTimeStep(x) == 0) {
  331. hl.setState(HolonObject.NO_ENERGY);
  332. }
  333. }
  334. return energy;
  335. }
  336. /**
  337. * Calculate the Minimum Energy.
  338. *
  339. * @param sN Subnet
  340. * @param x Integer
  341. * @return the Calculated minimum Energy
  342. */
  343. private float calculateMinimumEnergy(SubNet sN, int x) {
  344. float min = 0;
  345. float minElement = 0;
  346. for (HolonObject hl : sN.getObjects()) {
  347. if (hl.getElements().size() > 0 && hl.getElements().get(0).getTotalEnergyAtTimeStep(x) < 0) {
  348. minElement = hl.getElements().get(0).getTotalEnergyAtTimeStep(x);
  349. }
  350. for (HolonElement he : hl.getElements()) {
  351. if (minElement < he.getTotalEnergyAtTimeStep(x) && he.getTotalEnergyAtTimeStep(x) < 0) {
  352. minElement = he.getTotalEnergyAtTimeStep(x);
  353. }
  354. }
  355. min = min + minElement;
  356. }
  357. return min;
  358. }
  359. /**
  360. * generates all subNets from all objectsToHandle.
  361. */
  362. private void searchForSubNets() {
  363. subNets = new ArrayList<>();
  364. brokenEdges.clear();
  365. boolean end = false;
  366. int i = 0;
  367. AbstractCpsObject cps;
  368. if (objectsToHandle.size() > 0) {
  369. while (!end) {
  370. cps = objectsToHandle.get(i);
  371. SubNet singleSubNet = new SubNet(new ArrayList<>(), new ArrayList<>(),
  372. new ArrayList<>());
  373. singleSubNet = buildSubNet(cps, new ArrayList<>(), singleSubNet);
  374. if (singleSubNet.getObjects().size() != 0) {
  375. subNets.add(singleSubNet);
  376. }
  377. if (0 == objectsToHandle.size()) {
  378. end = true;
  379. }
  380. }
  381. }
  382. }
  383. /**
  384. * recursivly generates a subnet of all objects, that one specific object is
  385. * connected to.
  386. *
  387. * @param cps AbstractCpsObject
  388. * @param visited visited Array of Integer
  389. * @param sN Subnets
  390. * @return Subnet
  391. */
  392. private SubNet buildSubNet(AbstractCpsObject cps, ArrayList<Integer> visited, SubNet sN) {
  393. visited.add(cps.getId());
  394. if (cps instanceof HolonObject) {
  395. sN.getObjects().add((HolonObject) cps);
  396. }
  397. if (cps instanceof HolonSwitch) {
  398. sN.getSwitches().add((HolonSwitch) cps);
  399. }
  400. removeFromToHandle(cps.getId());
  401. AbstractCpsObject a;
  402. AbstractCpsObject b;
  403. for (CpsEdge edge : cps.getConnections()) {
  404. if (edge.isWorking()) {
  405. a = edge.getA();
  406. b = edge.getB();
  407. if (!(cps instanceof HolonSwitch)) {
  408. if (!(sN.getEdges().contains(edge))) {
  409. sN.getEdges().add(edge);
  410. }
  411. }
  412. if (cps instanceof HolonSwitch && ((HolonSwitch) cps).getState(timeStep)) {
  413. if (!(sN.getEdges().contains(edge))) {
  414. sN.getEdges().add(edge);
  415. }
  416. }
  417. if (!visited.contains(a.getId()) && legitState(cps) && !(a instanceof CpsUpperNode)) {
  418. sN = buildSubNet(a, visited, sN);
  419. }
  420. if (!visited.contains(b.getId()) && legitState(cps) && !(b instanceof CpsUpperNode)) {
  421. sN = buildSubNet(b, visited, sN);
  422. }
  423. if (a instanceof CpsUpperNode && a.getId() != cps.getId()) {
  424. edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
  425. checkForConnectedStates(b, (CpsUpperNode) a, edge);
  426. }
  427. if (b instanceof CpsUpperNode && b.getId() != cps.getId()) {
  428. edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
  429. checkForConnectedStates(a, (CpsUpperNode) b, edge);
  430. }
  431. } else {
  432. brokenEdges.add(edge);
  433. }
  434. }
  435. return sN;
  436. }
  437. /**
  438. * is the Switch in a legitimate State.
  439. *
  440. * @param current AbstractCpsObject
  441. * @return boolean
  442. */
  443. private boolean legitState(AbstractCpsObject current) {
  444. return !(current instanceof HolonSwitch)
  445. || ((HolonSwitch) current).getState(timeStep);
  446. }
  447. /**
  448. * removes an Object that already has been handled.
  449. *
  450. * @param id the Object ID
  451. */
  452. private void removeFromToHandle(int id) {
  453. for (int i = 0; i < objectsToHandle.size(); i++) {
  454. if (objectsToHandle.get(i).getId() == id) {
  455. objectsToHandle.remove(i);
  456. }
  457. }
  458. }
  459. // /**
  460. // * ensures that objectsToHandle only contains HolonObjects.
  461. // */
  462. // public void cleanObjectsToHandle() {
  463. // for (int i = 0; i < objectsToHandle.size(); i++) {
  464. // if (!(objectsToHandle.get(i) instanceof HolonObject)) {
  465. // objectsToHandle.remove(i);
  466. // }
  467. // }
  468. // }
  469. /**
  470. * copies the data of an array of Objects.
  471. *
  472. * @param toCopy the ArrayList of CpsObjects co Copy
  473. */
  474. private void copyObjects(ArrayList<AbstractCpsObject> toCopy) {
  475. for (AbstractCpsObject cps : toCopy) {
  476. if (cps instanceof CpsUpperNode) {
  477. copyObjects(((CpsUpperNode) cps).getNodes());
  478. } else {
  479. objectsToHandle.add(cps);
  480. }
  481. }
  482. }
  483. /**
  484. * Prints the Components auf all subnets.
  485. */
  486. public void printNetsToConsole() {
  487. for (int i = 0; i < subNets.size(); i++) {
  488. System.out.println("SUBNET NR:" + i);
  489. System.out.println(" Objects:");
  490. for (int j = 0; j < subNets.get(i).getObjects().size(); j++) {
  491. HolonObject hl = subNets.get(i).getObjects().get(j);
  492. System.out.println(" " + hl.getName() + " " + hl.getId());
  493. }
  494. System.out.println(" Edges:");
  495. for (int j = 0; j < subNets.get(i).getEdges().size(); j++) {
  496. CpsEdge edge = subNets.get(i).getEdges().get(j);
  497. System.out.println(" " + edge.getA().getName() + " connected To " + edge.getB().getName());
  498. }
  499. System.out.println(" Switches:");
  500. for (int j = 0; j < subNets.get(i).getSwitches().size(); j++) {
  501. HolonSwitch sw = subNets.get(i).getSwitches().get(j);
  502. System.out.println(" " + sw.getName() + " " + sw.getId() + " State:" + sw.getActiveAt()[timeStep]);
  503. }
  504. }
  505. }
  506. /**
  507. * Set the Canvas.
  508. *
  509. * @param can the Canvas
  510. */
  511. public void setCanvas(MyCanvas can) {
  512. canvas = can;
  513. }
  514. /**
  515. * Reset all Data to the current state of the Model.
  516. */
  517. public void reset() {
  518. objectsToHandle = new ArrayList<>();
  519. copyObjects(model.getObjectsOnCanvas());
  520. }
  521. /**
  522. * Resets the State of all Edges
  523. */
  524. private void resetEdges() {
  525. for (CpsEdge e : brokenEdges) {
  526. e.setWorkingState(true);
  527. }
  528. }
  529. /**
  530. * Resets the State for the whole Simulation Model
  531. */
  532. void resetSimulation() {
  533. reset();
  534. resetEdges();
  535. }
  536. /**
  537. * Get all Subnets.
  538. *
  539. * @return all Subnets
  540. */
  541. public ArrayList<SubNet> getSubNets() {
  542. return subNets;
  543. }
  544. /**
  545. * Get broken Edges
  546. */
  547. // public ArrayList<CpsEdge> getBrokenEdges() {
  548. // return brokenEdges;
  549. // }
  550. /**
  551. * checks whether a given object is connected to an object inside the upperNode.
  552. * if yes, the state for the edge is changed in "connected" or "not connected"
  553. */
  554. private void checkForConnectedStates(AbstractCpsObject cps, CpsUpperNode cUNode, CpsEdge theEdge) {
  555. AbstractCpsObject tmp;
  556. for (CpsEdge edge : cps.getConnections()) {
  557. if (edge.getA().getId() == cps.getId()) {
  558. tmp = edge.getB();
  559. } else {
  560. tmp = edge.getA();
  561. }
  562. if (cUNode.getNodes().contains(tmp)) {
  563. if (tmp instanceof CpsUpperNode) {
  564. checkForConnectedStates(cps, (CpsUpperNode) tmp, theEdge);
  565. } else {
  566. theEdge.setConnected(CpsEdge.CON_UPPER_NODE_AND_INSIDE);
  567. break;
  568. }
  569. }
  570. }
  571. }
  572. public FlexiblePane getFlexiblePane() {
  573. return flexPane;
  574. }
  575. void setFlexiblePane(FlexiblePane fp) {
  576. flexPane = fp;
  577. }
  578. }