SimulationManager.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. package ui.controller;
  2. import classes.*;
  3. import classes.comparator.EnergyMinToMaxComparator;
  4. import classes.comparator.MinEnergyComparator;
  5. import classes.comparator.TotalEnergyComparator;
  6. import ui.model.Model;
  7. import ui.view.FlexiblePane;
  8. import ui.view.MyCanvas;
  9. import java.util.ArrayList;
  10. import java.util.HashMap;
  11. /**
  12. * Controller for Simulation.
  13. *
  14. * @author Gruppe14
  15. */
  16. public class SimulationManager {
  17. int global = 0;
  18. private Model model;
  19. private ArrayList<AbstractCpsObject> objectsToHandle;
  20. // private ArrayList<CpsEdge> allConnections;
  21. private ArrayList<SubNet> subNets;
  22. private ArrayList<CpsEdge> brokenEdges;
  23. private MyCanvas canvas;
  24. private int timeStep;
  25. private HashMap<Integer, Float> tagTable = new HashMap<>();
  26. private FlexiblePane flexPane;
  27. private HashMap<HolonElement, Float> flexDevicesTurnedOnThisTurn = new HashMap<>();
  28. /**
  29. * One Element of each HolonObject will be powered first, starting with the
  30. * smallest Demand. If ale HolonObjects have an active Element, the
  31. * simulation will try to fully supply as many HolonObjects as possible.
  32. */
  33. public static final short fairnessMininumDemandFirst = 0;
  34. /**
  35. * All HolonObjects will receive the same amount of energy.
  36. */
  37. public static final short fairnessAllEqual = 1;
  38. /**
  39. * Constructor.
  40. *
  41. * @param m
  42. * Model
  43. */
  44. SimulationManager(Model m) {
  45. canvas = null;
  46. model = m;
  47. subNets = new ArrayList<>();
  48. brokenEdges = new ArrayList<>();
  49. }
  50. /**
  51. * calculates the flow of the edges and the supply for objects.
  52. *
  53. * @param x
  54. * current Iteration
  55. */
  56. void calculateStateForTimeStep(int x) {
  57. reset();
  58. timeStep = x;
  59. searchForSubNets();
  60. for (SubNet singleSubNet : subNets) {
  61. resetConnections(singleSubNet.getObjects().get(0),
  62. new ArrayList<>(), new ArrayList<>());
  63. }
  64. for (SubNet singleSubNet : subNets) {
  65. float production = calculateEnergyWithoutFlexDevices("prod",
  66. singleSubNet, timeStep);
  67. float consumption = calculateEnergyWithoutFlexDevices("cons",
  68. singleSubNet, timeStep);
  69. // surplus of energy is computed by sum, since consumption is a
  70. // negative value
  71. float energySurplus = production + consumption;
  72. //float minConsumption = calculateMinimumEnergy(singleSubNet, timeStep);
  73. // --------------- use flexible devices ---------------
  74. if (energySurplus != 0 && model.useFlexibleDevices()) {
  75. turnOnFlexibleDevices(singleSubNet, energySurplus, x);
  76. // if (!flexDevicesTurnedOnThisTurn.isEmpty()) {
  77. // System.out.println("The following devices were turned on in this turn: ");
  78. // System.out.println(flexDevicesTurnedOnThisTurn.toString());
  79. // }
  80. // recompute after having examined/turned on all flexible
  81. // devices
  82. production = calculateEnergyWithFlexDevices("prod",
  83. singleSubNet, timeStep);
  84. consumption = calculateEnergyWithFlexDevices("cons",
  85. singleSubNet, timeStep);
  86. energySurplus = production + consumption;
  87. }
  88. // --------------- set flow simulation ---------------
  89. setFlowSimulation(singleSubNet);
  90. // --------------- visualise graph ---------------
  91. /**
  92. * production of subnets, that might be partially turned on/off
  93. */
  94. float currentProduction = production;
  95. /**
  96. * HolonObjects that can be partially Supplied but might be fully
  97. * Supplied
  98. */
  99. ArrayList<HolonObject> partiallySuppliedList = new ArrayList<HolonObject>();
  100. /**
  101. * HolonObjects that can get the spare energy
  102. */
  103. ArrayList<HolonObject> notSuppliedList = new ArrayList<HolonObject>();
  104. /**
  105. * Number of HolonObjects that need to be supplied
  106. */
  107. long numberOfConsumers = singleSubNet.getObjects().stream()
  108. .filter(hl -> (hl.getState() != HolonObject.NO_ENERGY
  109. && hl.getState() != HolonObject.PRODUCER && hl
  110. .getConnectedTo().stream()
  111. .filter(e -> (e.getFlow() > 0)).count() > 0))
  112. .count();
  113. /**
  114. * energy each HolonObject receives in AlleEqualModus
  115. */
  116. float energyPerHolonObject = 0;
  117. if (model.getFairnessModel() == fairnessMininumDemandFirst) {
  118. /**
  119. * supply Buildings with minimal Energy first, if conflicts
  120. * happen
  121. */
  122. singleSubNet.getObjects().sort(new MinEnergyComparator(x));
  123. } else if (model.getFairnessModel() == fairnessAllEqual) {
  124. /*
  125. * give every building (just consumer) the same energy
  126. */
  127. if (numberOfConsumers != 0)
  128. energyPerHolonObject = production / numberOfConsumers;
  129. }
  130. for (HolonObject hl : singleSubNet.getObjects()) {
  131. hl.setCurrentSupply(0);
  132. if (hl.getState() != HolonObject.NO_ENERGY
  133. && hl.getState() != HolonObject.PRODUCER) {
  134. for (int i = 0; i < hl.getConnections().size(); i++) {
  135. CpsEdge edge = hl.getConnectedTo().get(i);
  136. if (edge.isWorking()
  137. && edge.getFlow() > 0
  138. || edge.getCapacity() == CpsEdge.CAPACITY_INFINITE) {
  139. if (model.getFairnessModel() == fairnessAllEqual) {
  140. /* fairness: everyone receives the Same Energy */
  141. float neededEnergy = hl
  142. .getCurrentEnergyAtTimeStep(x);
  143. if (neededEnergy > 0) {
  144. hl.setState(HolonObject.PRODUCER);
  145. } else if (energyPerHolonObject > -neededEnergy) {
  146. hl.setState(HolonObject.OVER_SUPPLIED);
  147. } else if (energyPerHolonObject == -neededEnergy) {
  148. hl.setState(HolonObject.SUPPLIED);
  149. } else if (energyPerHolonObject >= -hl
  150. .getMinEnergy(x)) {
  151. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  152. } else {
  153. hl.setState(HolonObject.NOT_SUPPLIED);
  154. }
  155. hl.setCurrentSupply(energyPerHolonObject);
  156. } else if (model.getFairnessModel() == fairnessMininumDemandFirst) {
  157. /* fairness: minimum demand gets Energy first */
  158. if ((production + consumption) >= 0) {
  159. if (energySurplus > 0) {
  160. hl.setState(HolonObject.OVER_SUPPLIED);
  161. hl.setCurrentSupply(-hl.getCurrentEnergyAtTimeStep(x)
  162. + energySurplus/numberOfConsumers);
  163. } else {
  164. hl.setState(HolonObject.SUPPLIED);
  165. hl.setCurrentSupply(-hl
  166. .getCurrentEnergyAtTimeStep(x));
  167. }
  168. } else {
  169. float minEnergy = hl.getMinEnergy(x);
  170. if (hl.checkIfPartiallySupplied(timeStep)) {
  171. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  172. currentProduction += minEnergy;
  173. hl.setCurrentSupply(-minEnergy);
  174. partiallySuppliedList.add(hl);
  175. } else {
  176. /**
  177. * Case that only some HolonObjects can
  178. * be supplied
  179. */
  180. if (-hl.getCurrentEnergyAtTimeStep(x) <= currentProduction) {
  181. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  182. currentProduction += minEnergy;
  183. hl.setCurrentSupply(-minEnergy);
  184. partiallySuppliedList.add(hl);
  185. } else if (-hl.getMinEnergy(x) <= currentProduction) {
  186. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  187. currentProduction += minEnergy;
  188. hl.setCurrentSupply(-minEnergy);
  189. partiallySuppliedList.add(hl);
  190. } else {
  191. hl.setState(HolonObject.NOT_SUPPLIED);
  192. hl.setCurrentSupply(0.0f);
  193. notSuppliedList.add(hl);
  194. // currentProduction +=
  195. // hl.getCurrentEnergyAtTimeStep(x);
  196. }
  197. }
  198. }
  199. }
  200. hl.getCurrentEnergyAtTimeStep(x);
  201. break;
  202. }
  203. }
  204. /**
  205. * check if some object cn self supply itself
  206. */
  207. if (hl.checkIfPartiallySupplied(timeStep)
  208. && hl.getState() != HolonObject.SUPPLIED
  209. && hl.getState() != HolonObject.OVER_SUPPLIED) {
  210. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  211. }
  212. }
  213. }
  214. if (model.getFairnessModel() == fairnessMininumDemandFirst) {
  215. /**
  216. * check if some partially supplied building might be fully
  217. * supplied.
  218. */
  219. partiallySuppliedList.sort(new EnergyMinToMaxComparator(x));
  220. for (HolonObject hl : partiallySuppliedList) {
  221. float minEnergy = hl.getMinEnergy(x);
  222. currentProduction -= minEnergy;
  223. /*
  224. * if possible, supply fully
  225. */
  226. float currentEnergyAtTimeStep = hl
  227. .getCurrentEnergyAtTimeStep(x);
  228. if (-currentEnergyAtTimeStep <= currentProduction) {
  229. hl.setState(HolonObject.SUPPLIED);
  230. currentProduction += currentEnergyAtTimeStep;
  231. hl.setCurrentSupply(-currentEnergyAtTimeStep);
  232. hl.getCurrentEnergyAtTimeStep(x);
  233. } else {
  234. currentProduction += minEnergy;
  235. notSuppliedList.add(hl);
  236. }
  237. }
  238. if (!notSuppliedList.isEmpty() && currentProduction > 0) {
  239. float energyPerHolon = currentProduction
  240. / notSuppliedList.size();
  241. for (HolonObject hl : notSuppliedList) {
  242. hl.setCurrentSupply(hl.getCurrentSupply()
  243. + energyPerHolon);
  244. hl.getCurrentEnergyAtTimeStep(x);
  245. }
  246. }
  247. }
  248. }
  249. canvas.repaint();
  250. flexPane.recalculate();
  251. }
  252. /**
  253. * search for all flexible devices in the network and turn them on, until
  254. * energy surplus = 0 or all devices have been examined.
  255. *
  256. * This code could be compressed (cases inside over- and underproduction are
  257. * the same), but we decided that it is better readable this way
  258. *
  259. * @param subNet
  260. * the subnet
  261. * @param energySurplus
  262. * the current surplus of energy
  263. */
  264. private void turnOnFlexibleDevices(SubNet subNet, float energySurplus,
  265. int timestep) {
  266. for (HolonObject holonOb : subNet.getObjects()) {
  267. for (HolonElement holonEl : holonOb.getElements()) {
  268. // if this element is flexible and active (can be considered for
  269. // calculations)
  270. if (holonEl.isFlexible() && holonEl.isActive()) {
  271. float energyAvailableSingle = holonEl
  272. .getAvailableEnergyAt(timestep);
  273. float energyAvailableMultiple = energyAvailableSingle
  274. * holonEl.getAmount();
  275. // ------------- flexible consumer / OVERPRODUCTION
  276. // -------------
  277. if (energyAvailableMultiple < 0 && energySurplus > 0) {
  278. // if there is more wasted energy than energy that this
  279. // device can give, give all energy available
  280. if (Math.abs(energyAvailableMultiple) <= Math
  281. .abs(energySurplus)) {
  282. energySurplus += energyAvailableMultiple;
  283. // set the new energy consumption to the maximum
  284. holonEl.setEnergyPerElement(energyAvailableSingle);
  285. flexDevicesTurnedOnThisTurn.put(holonEl,
  286. energyAvailableMultiple);
  287. }
  288. // else: we just need to turn on part of the flexible
  289. // energy available
  290. else {
  291. float energyNeeded = -energySurplus;
  292. energySurplus += energyNeeded; // should give 0, but
  293. // was kept this was
  294. // for consistency
  295. // the energy needed divided through the amount of
  296. // elements
  297. holonEl.setEnergyPerElement(energyNeeded
  298. / holonEl.getAmount());
  299. flexDevicesTurnedOnThisTurn.put(holonEl,
  300. energyNeeded);
  301. }
  302. }
  303. // ------------- flexible producer / UNDERPRODUCTION
  304. // -------------
  305. else if (energyAvailableMultiple > 0 && energySurplus < 0) {
  306. // if there is more energy needed than this device can
  307. // give, give all the energy available
  308. if (Math.abs(energyAvailableMultiple) <= Math
  309. .abs(energySurplus)) {
  310. energySurplus += energyAvailableMultiple;
  311. // set the new energy consumption to the maximum
  312. holonEl.setEnergyPerElement(energyAvailableSingle);
  313. flexDevicesTurnedOnThisTurn.put(holonEl,
  314. energyAvailableMultiple);
  315. }
  316. // else: we just need to turn on part of the flexible
  317. // energy available
  318. else {
  319. float energyNeeded = -energySurplus;
  320. int i = 0;
  321. energySurplus += energyNeeded; // should give 0, but
  322. // was kept this was
  323. // for consistency
  324. // the energy needed divided through the amount of
  325. // elements
  326. holonEl.setEnergyPerElement(energyNeeded
  327. / holonEl.getAmount());
  328. flexDevicesTurnedOnThisTurn.put(holonEl,
  329. energyNeeded);
  330. }
  331. }
  332. }
  333. if (energySurplus == 0) {
  334. break;
  335. }
  336. }
  337. if (energySurplus == 0) {
  338. break;
  339. }
  340. }
  341. }
  342. /**
  343. * Set Flow Simulation.
  344. *
  345. * @param sN
  346. * Subnet
  347. */
  348. private void setFlowSimulation(SubNet sN) {
  349. ArrayList<AbstractCpsObject> producers = new ArrayList<>();
  350. AbstractCpsObject tmp = null;
  351. tagTable = new HashMap<>();
  352. // traverse all objects in this subnet
  353. for (HolonObject hl : sN.getObjects()) {
  354. float energy = hl.getCurrentEnergyAtTimeStep(timeStep);
  355. // if their production is higher than their consumption
  356. if (energy > 0) {
  357. tagTable.put(hl.getId(), energy);
  358. hl.addTag(hl.getId());
  359. for (CpsEdge edge : hl.getConnections()) {
  360. if (edge.isWorking()) {
  361. // set other end of edge as tmp-object
  362. // and add this end to the other end's tag-list
  363. AbstractCpsObject a = edge.getA();
  364. AbstractCpsObject b = edge.getB();
  365. if (a.getId() == hl.getId()) {
  366. b.addTag(hl.getId());
  367. tmp = b;
  368. }
  369. if (b.getId() == hl.getId()) {
  370. a.addTag(hl.getId());
  371. tmp = a;
  372. }
  373. edge.setFlow(edge.getFlow() + energy);
  374. edge.calculateState();
  375. edge.addTag(hl.getId());
  376. if (edge.isWorking() && !producers.contains(tmp)) {
  377. if (tmp instanceof HolonSwitch) {
  378. if (((HolonSwitch) tmp).getState(timeStep)) {
  379. producers.add(tmp);
  380. }
  381. } else if (!(tmp instanceof CpsUpperNode)) {
  382. producers.add(tmp);
  383. }
  384. }
  385. }
  386. }
  387. }
  388. }
  389. setFlowSimRec(producers, 0);
  390. }
  391. /**
  392. * Set Flow Simulation Rec.
  393. *
  394. * @param nodes
  395. * the nodes
  396. * @param iter
  397. * the Iteration
  398. */
  399. private void setFlowSimRec(ArrayList<AbstractCpsObject> nodes, int iter) {
  400. ArrayList<AbstractCpsObject> newNodes = new ArrayList<>();
  401. ArrayList<CpsEdge> changedEdges = new ArrayList<>();
  402. AbstractCpsObject tmp;
  403. if (nodes.size() != 0) {
  404. for (AbstractCpsObject cps : nodes) {
  405. // check whether the cps is in a legit state if it is a switch
  406. if (legitState(cps)) {
  407. for (CpsEdge edge : cps.getConnections()) {
  408. // is edge working
  409. // and does the edge's tag-list not (yet) contain all
  410. // tags of the cps
  411. if (edge.isWorking()
  412. && (!(edge.containsTags(edge.getTags(),
  413. cps.getTag())))) {
  414. if (edge.getA().getId() == cps.getId()) {
  415. tmp = edge.getB();
  416. } else {
  417. tmp = edge.getA();
  418. }
  419. for (Integer tag : cps.getTag()) {
  420. if (!(edge.getTags().contains(tag))
  421. && !(edge.getPseudoTags().contains(tag))) {
  422. edge.setFlow(edge.getFlow()
  423. + tagTable.get(tag));
  424. edge.addTag(tag);
  425. }
  426. }
  427. // uppernodes do not spread energy
  428. if (!(tmp instanceof CpsUpperNode)) {
  429. for (Integer tag : tmp.getTag()) {
  430. if (!(edge.getTags().contains(tag))
  431. && tagTable.get(tag) != null
  432. && !(edge.getPseudoTags()
  433. .contains(tag))) {
  434. edge.setFlow(edge.getFlow()
  435. + tagTable.get(tag));
  436. edge.addPseudoTag(tag);
  437. changedEdges.add(edge);
  438. }
  439. }
  440. }
  441. edge.calculateState();
  442. if (edge.isWorking()
  443. && !(tmp instanceof CpsUpperNode)) {
  444. tmp.addAllPseudoTags(cps.getTag());
  445. if (!newNodes.contains(tmp)) {
  446. newNodes.add(tmp);
  447. }
  448. }
  449. }
  450. }
  451. }
  452. }
  453. setPseudoTags(newNodes, changedEdges);
  454. setFlowSimRec(newNodes, iter + 1);
  455. }
  456. }
  457. /**
  458. * Set the Pseudo Tags.
  459. *
  460. * @param nodes
  461. * Array of AbstractCpsObjects
  462. */
  463. private void setPseudoTags(ArrayList<AbstractCpsObject> nodes,
  464. ArrayList<CpsEdge> edges) {
  465. for (AbstractCpsObject node : nodes) {
  466. node.recalculateTags();
  467. node.setPseudoTags(new ArrayList<>());
  468. }
  469. for (CpsEdge edge : edges) {
  470. edge.recalculateTags();
  471. edge.setPseudoTag(new ArrayList<>());
  472. }
  473. }
  474. /**
  475. * Reset the Connection.
  476. *
  477. * @param cps
  478. * CpsObject
  479. * @param visitedObj
  480. * the visited Objects
  481. * @param visitedEdges
  482. * the visited Edges
  483. */
  484. private void resetConnections(AbstractCpsObject cps,
  485. ArrayList<Integer> visitedObj, ArrayList<CpsEdge> visitedEdges) {
  486. visitedObj.add(cps.getId());
  487. cps.resetTags();
  488. for (CpsEdge e : cps.getConnections()) {
  489. if (!(visitedEdges.contains(e))) {
  490. e.setFlow(0);
  491. e.calculateState();
  492. e.setTags(new ArrayList<>());
  493. visitedEdges.add(e);
  494. if (!(visitedObj.contains(e.getA().getId()))) {
  495. resetConnections(e.getA(), visitedObj, visitedEdges);
  496. e.getA().resetTags();
  497. }
  498. if (!(visitedObj.contains(e.getB().getId()))) {
  499. resetConnections(e.getB(), visitedObj, visitedEdges);
  500. e.getB().resetTags();
  501. }
  502. }
  503. }
  504. }
  505. /**
  506. * calculates the energy of either all producers or consumers. Flexible
  507. * devices are filtered out
  508. *
  509. * @param type
  510. * Type
  511. * @param sN
  512. * Subnet
  513. * @param x
  514. * Integer
  515. * @return The Energy
  516. */
  517. private float calculateEnergyWithoutFlexDevices(String type, SubNet sN,
  518. int x) {
  519. float energy = 0;
  520. for (HolonObject hl : sN.getObjects()) {
  521. float currentEnergyWithoutFlexibles = hl
  522. .getCurrentEnergyAtTimeStepWithoutFlexiblesAndResetFlexibles(x);
  523. if (type.equals("prod")) {
  524. if (currentEnergyWithoutFlexibles > 0) {
  525. energy += currentEnergyWithoutFlexibles;
  526. hl.setState(HolonObject.PRODUCER);
  527. }
  528. }
  529. if (type.equals("cons")) {
  530. if (currentEnergyWithoutFlexibles < 0) {
  531. energy = energy + currentEnergyWithoutFlexibles;
  532. hl.setState(HolonObject.NOT_SUPPLIED);
  533. }
  534. }
  535. if (currentEnergyWithoutFlexibles == 0) {
  536. hl.setState(HolonObject.NO_ENERGY);
  537. }
  538. }
  539. return energy;
  540. }
  541. /**
  542. * calculates the energy of either all producers or consumers. Flexible
  543. * devices are filtered out
  544. *
  545. * @param type
  546. * Type
  547. * @param sN
  548. * Subnet
  549. * @param x
  550. * Integer
  551. * @return The Energy
  552. */
  553. private float calculateEnergyWithFlexDevices(String type, SubNet sN, int x) {
  554. float energy = 0;
  555. for (HolonObject hl : sN.getObjects()) {
  556. float currentEnergy = hl.getCurrentEnergyAtTimeStep(x);
  557. if (type.equals("prod")) {
  558. if (currentEnergy > 0) {
  559. energy += currentEnergy;
  560. hl.setState(HolonObject.PRODUCER);
  561. }
  562. }
  563. if (type.equals("cons")) {
  564. if (currentEnergy < 0) {
  565. energy = energy + currentEnergy;
  566. hl.setState(HolonObject.NOT_SUPPLIED);
  567. }
  568. }
  569. if (currentEnergy == 0) {
  570. hl.setState(HolonObject.NO_ENERGY);
  571. }
  572. }
  573. return energy;
  574. }
  575. /**
  576. * Calculate the Minimum Energy of a Subnet.
  577. *
  578. * @param sN
  579. * Subnet
  580. * @param x
  581. * Integer
  582. * @return the Calculated minimum Energy of a Subnet
  583. */
  584. private float calculateMinimumEnergy(SubNet sN, int x) {
  585. float minimummConsumptionSubnet = 0;
  586. for (HolonObject hl : sN.getObjects()) {
  587. float minElement = 0;
  588. // Search for a activ element
  589. for (HolonElement he : hl.getElements()) {
  590. if (he.isActive()) {
  591. float overallEnergy = he.getOverallEnergyAtTimeStep(x);
  592. if (overallEnergy < 0) {
  593. // Is a consumer
  594. minElement = overallEnergy;
  595. }
  596. }
  597. }
  598. for (HolonElement he : hl.getElements()) {
  599. if (he.isActive()) {
  600. float overallEnergy = he.getOverallEnergyAtTimeStep(x);
  601. if (minElement < overallEnergy && overallEnergy < 0) {
  602. // is a smaller consumer
  603. minElement = overallEnergy;
  604. }
  605. }
  606. }
  607. minimummConsumptionSubnet += minElement;
  608. }
  609. System.out.println("MinimumEnergy = "+ minimummConsumptionSubnet);
  610. return minimummConsumptionSubnet;
  611. }
  612. /**
  613. * generates all subNets from all objectsToHandle.
  614. */
  615. private void searchForSubNets() {
  616. subNets = new ArrayList<>();
  617. brokenEdges.clear();
  618. boolean end = false;
  619. int i = 0;
  620. AbstractCpsObject cps;
  621. if (objectsToHandle.size() > 0) {
  622. while (!end) {
  623. cps = objectsToHandle.get(i);
  624. SubNet singleSubNet = new SubNet(new ArrayList<>(),
  625. new ArrayList<>(), new ArrayList<>());
  626. singleSubNet = buildSubNet(cps, new ArrayList<>(), singleSubNet);
  627. if (singleSubNet.getObjects().size() != 0) {
  628. subNets.add(singleSubNet);
  629. }
  630. if (0 == objectsToHandle.size()) {
  631. end = true;
  632. }
  633. }
  634. }
  635. }
  636. /**
  637. * recursivly generates a subnet of all objects, that one specific object is
  638. * connected to.
  639. *
  640. * @param cps
  641. * AbstractCpsObject
  642. * @param visited
  643. * visited Array of Integer
  644. * @param sN
  645. * Subnets
  646. * @return Subnet
  647. */
  648. private SubNet buildSubNet(AbstractCpsObject cps,
  649. ArrayList<Integer> visited, SubNet sN) {
  650. visited.add(cps.getId());
  651. if (cps instanceof HolonObject) {
  652. sN.getObjects().add((HolonObject) cps);
  653. }
  654. if (cps instanceof HolonSwitch) {
  655. sN.getSwitches().add((HolonSwitch) cps);
  656. }
  657. removeFromToHandle(cps.getId());
  658. AbstractCpsObject a;
  659. AbstractCpsObject b;
  660. for (CpsEdge edge : cps.getConnections()) {
  661. if (edge.isWorking()) {
  662. a = edge.getA();
  663. b = edge.getB();
  664. if (!(cps instanceof HolonSwitch)) {
  665. if (!(sN.getEdges().contains(edge))) {
  666. sN.getEdges().add(edge);
  667. }
  668. }
  669. if (cps instanceof HolonSwitch
  670. && ((HolonSwitch) cps).getState(timeStep)) {
  671. if (!(sN.getEdges().contains(edge))) {
  672. sN.getEdges().add(edge);
  673. }
  674. }
  675. if (!visited.contains(a.getId()) && legitState(cps)
  676. && !(a instanceof CpsUpperNode)) {
  677. sN = buildSubNet(a, visited, sN);
  678. }
  679. if (!visited.contains(b.getId()) && legitState(cps)
  680. && !(b instanceof CpsUpperNode)) {
  681. sN = buildSubNet(b, visited, sN);
  682. }
  683. if (a instanceof CpsUpperNode && a.getId() != cps.getId()) {
  684. edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
  685. checkForConnectedStates(b, (CpsUpperNode) a, edge);
  686. }
  687. if (b instanceof CpsUpperNode && b.getId() != cps.getId()) {
  688. edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
  689. checkForConnectedStates(a, (CpsUpperNode) b, edge);
  690. }
  691. } else {
  692. brokenEdges.add(edge);
  693. }
  694. }
  695. return sN;
  696. }
  697. /**
  698. * is the Switch in a legitimate State.
  699. *
  700. * @param current
  701. * AbstractCpsObject
  702. * @return boolean
  703. */
  704. private boolean legitState(AbstractCpsObject current) {
  705. return !(current instanceof HolonSwitch)
  706. || ((HolonSwitch) current).getState(timeStep);
  707. }
  708. // /**
  709. // * ensures that objectsToHandle only contains HolonObjects.
  710. // */
  711. // public void cleanObjectsToHandle() {
  712. // for (int i = 0; i < objectsToHandle.size(); i++) {
  713. // if (!(objectsToHandle.get(i) instanceof HolonObject)) {
  714. // objectsToHandle.remove(i);
  715. // }
  716. // }
  717. // }
  718. /**
  719. * removes an Object that already has been handled.
  720. *
  721. * @param id
  722. * the Object ID
  723. */
  724. private void removeFromToHandle(int id) {
  725. for (int i = 0; i < objectsToHandle.size(); i++) {
  726. if (objectsToHandle.get(i).getId() == id) {
  727. objectsToHandle.remove(i);
  728. }
  729. }
  730. }
  731. /**
  732. * copies the data of an array of Objects.
  733. *
  734. * @param toCopy
  735. * the ArrayList of CpsObjects co Copy
  736. */
  737. private void copyObjects(ArrayList<AbstractCpsObject> toCopy) {
  738. for (AbstractCpsObject cps : toCopy) {
  739. if (cps instanceof CpsUpperNode) {
  740. copyObjects(((CpsUpperNode) cps).getNodes());
  741. } else {
  742. objectsToHandle.add(cps);
  743. }
  744. }
  745. }
  746. /**
  747. * Prints the Components auf all subnets.
  748. */
  749. private void printNetsToConsole() {
  750. for (int i = 0; i < subNets.size(); i++) {
  751. SubNet subNet = subNets.get(i);
  752. System.out.println("SUBNET NR:" + i);
  753. subNet.toString(timeStep);
  754. }
  755. }
  756. /**
  757. * Set the Canvas.
  758. *
  759. * @param can
  760. * the Canvas
  761. */
  762. public void setCanvas(MyCanvas can) {
  763. canvas = can;
  764. }
  765. /**
  766. * Reset all Data to the current state of the Model.
  767. */
  768. public void reset() {
  769. objectsToHandle = new ArrayList<>();
  770. copyObjects(model.getObjectsOnCanvas());
  771. flexDevicesTurnedOnThisTurn = new HashMap<>();
  772. }
  773. /**
  774. * Resets the State of all Edges
  775. */
  776. private void resetEdges() {
  777. for (CpsEdge e : brokenEdges) {
  778. e.setWorkingState(true);
  779. }
  780. }
  781. /**
  782. * Resets the State for the whole Simulation Model
  783. */
  784. void resetSimulation() {
  785. reset();
  786. resetEdges();
  787. }
  788. /**
  789. * Get all Subnets.
  790. *
  791. * @return all Subnets
  792. */
  793. public ArrayList<SubNet> getSubNets() {
  794. return subNets;
  795. }
  796. /**
  797. * Get broken Edges
  798. */
  799. // public ArrayList<CpsEdge> getBrokenEdges() {
  800. // return brokenEdges;
  801. // }
  802. /**
  803. * checks whether a given object is connected to an object inside the
  804. * upperNode. if yes, the state for the edge is changed in "connected" or
  805. * "not connected"
  806. */
  807. private void checkForConnectedStates(AbstractCpsObject cps,
  808. CpsUpperNode cUNode, CpsEdge theEdge) {
  809. AbstractCpsObject tmp;
  810. for (CpsEdge edge : cps.getConnections()) {
  811. if (edge.getA().getId() == cps.getId()) {
  812. tmp = edge.getB();
  813. } else {
  814. tmp = edge.getA();
  815. }
  816. if (cUNode.getNodes().contains(tmp)) {
  817. if (tmp instanceof CpsUpperNode) {
  818. checkForConnectedStates(cps, (CpsUpperNode) tmp, theEdge);
  819. } else {
  820. theEdge.setConnected(CpsEdge.CON_UPPER_NODE_AND_INSIDE);
  821. break;
  822. }
  823. }
  824. }
  825. }
  826. public FlexiblePane getFlexiblePane() {
  827. return flexPane;
  828. }
  829. void setFlexiblePane(FlexiblePane fp) {
  830. flexPane = fp;
  831. }
  832. }