SimulationManager.java 22 KB

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