SimulationManager.java 21 KB

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