SimulationManager.java 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  1. package ui.controller;
  2. import classes.*;
  3. import classes.comparator.EnergyMinToMaxComparator;
  4. import classes.comparator.MinEnergyComparator;
  5. import classes.comparator.WeakestBattery;
  6. import ui.model.CableWithState;
  7. import ui.model.DecoratedCable;
  8. import ui.model.DecoratedCable.CableState;
  9. import ui.model.DecoratedNetwork;
  10. import ui.model.DecoratedState;
  11. import ui.model.DecoratedSwitch;
  12. import ui.model.MinimumModel;
  13. import ui.model.MinimumNetwork;
  14. import ui.model.Model;
  15. import ui.view.FlexiblePane;
  16. import ui.view.MyCanvas;
  17. import java.util.ArrayList;
  18. import java.util.Collections;
  19. import java.util.HashMap;
  20. import javax.swing.JPanel;
  21. /**
  22. * Controller for Simulation.
  23. *
  24. * @author Gruppe14
  25. */
  26. public class SimulationManager {
  27. int global = 0;
  28. private Model model;
  29. private ArrayList<AbstractCpsObject> objectsToHandle;
  30. private ArrayList<SubNet> subNets;
  31. private ArrayList<CpsEdge> brokenEdges;
  32. private HashMap<Integer, DecoratedState> saves = new HashMap<Integer, DecoratedState>();
  33. private MyCanvas canvas;
  34. private int timeStep;
  35. private HashMap<Integer, Float> tagTable = new HashMap<>();
  36. private FlexiblePane flexPane;
  37. private HashMap<HolonElement, Float> flexDevicesTurnedOnThisTurn = new HashMap<>();
  38. /**
  39. * One Element of each HolonObject will be powered first, starting with the
  40. * smallest Demand. If ale HolonObjects have an active Element, the
  41. * simulation will try to fully supply as many HolonObjects as possible.
  42. */
  43. public static final short fairnessMininumDemandFirst = 0;
  44. /**
  45. * All HolonObjects will receive the same amount of energy.
  46. */
  47. public static final short fairnessAllEqual = 1;
  48. /**
  49. * Constructor.
  50. *
  51. * @param m
  52. * Model
  53. */
  54. SimulationManager(Model m) {
  55. canvas = null;
  56. model = m;
  57. subNets = new ArrayList<>();
  58. brokenEdges = new ArrayList<>();
  59. }
  60. /**
  61. * calculates the flow of the edges and the supply for objects.
  62. *
  63. * @param timestep
  64. * current Iteration
  65. */
  66. void calculateStateForTimeStep(int timestep) {
  67. boolean theStateBeforeExist= (timestep > 0 && saves.containsKey(timestep-1));
  68. System.out.println("Calculate Timestep: " + timestep + (theStateBeforeExist ? " StateBeforeExist": ""));
  69. HashMap<CpsEdge, CableState> map = new HashMap<CpsEdge, CableState>();
  70. if(theStateBeforeExist)
  71. {
  72. //make cable hastmap
  73. DecoratedState theStateBefore = saves.get(timestep-1);
  74. for(DecoratedCable edge : theStateBefore.getLeftOverEdges())
  75. {
  76. map.put(edge.getModel(), edge.getState());
  77. }
  78. }
  79. timeStep = timestep;
  80. ArrayList<MinimumNetwork> list = new ArrayList<MinimumNetwork>();
  81. MinimumModel minimumModel = new MinimumModel(model.getObjectsOnCanvas(), model.getEdgesOnCanvas());
  82. //set all working:
  83. for(CableWithState cable : minimumModel.getEdgeList()) {
  84. if(map.containsKey(cable.getModel())) cable.setState(map.get(cable.getModel()));
  85. }
  86. ArrayList<CableWithState> leftOver = new ArrayList<CableWithState>();
  87. boolean doAnotherLoop = true;
  88. while(doAnotherLoop) {
  89. doAnotherLoop = false;
  90. list = CalculataModel.calculateNetworks(minimumModel, timestep, leftOver);
  91. for(MinimumNetwork net : list) {
  92. float energyOnCables = net.getHolonObjectList().stream().filter(object -> object.getEnergyAtTimeStep(timestep) > 0.0f).map(object -> object.getEnergyAtTimeStep(timestep)).reduce(0.0f, ((a,b) -> a + b));
  93. //find the cable with the energy supplied from his two connected objects are the biggest, from all cables that the network give more energy than the cablecapacity.
  94. CableWithState cable = net.getEdgeList().stream().filter(aCable -> energyOnCables > aCable.getModel().getCapacity()).max((lhs,rhs) -> Float.compare(lhs.getEnergyFromConnetedAtTimestep(timestep), rhs.getEnergyFromConnetedAtTimestep(timestep))).orElse(null);
  95. if(cable != null) {
  96. cable.setState(CableState.Burned);
  97. doAnotherLoop = true;
  98. }
  99. }
  100. }
  101. ArrayList<DecoratedNetwork> decorNetworks = new ArrayList<DecoratedNetwork>();
  102. for (MinimumNetwork net : list) {
  103. decorNetworks.add(new DecoratedNetwork(net, timestep));
  104. }
  105. ArrayList<DecoratedCable> leftOverDecoratedCables = new ArrayList<DecoratedCable>();
  106. for(CableWithState cable: leftOver) {
  107. leftOverDecoratedCables.add(new DecoratedCable(cable.getModel(), cable.getState(), 0.0f));
  108. }
  109. ArrayList<DecoratedSwitch> listOfDecoratedSwitches = CalculataModel.decorateSwitches(minimumModel, timestep);
  110. saves.put(timestep, new DecoratedState(decorNetworks, leftOverDecoratedCables, listOfDecoratedSwitches, minimumModel.getNodeList() , timestep));
  111. canvas.repaint();
  112. // for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
  113. // System.out.println(ste);
  114. //// }
  115. // reset();
  116. // timeStep = x;
  117. // searchForSubNets();
  118. // for (SubNet singleSubNet : subNets) {
  119. // if(singleSubNet.getObjects().size() == 0)
  120. // {
  121. // resetConnections(singleSubNet.getBatteries().get(0),
  122. // new ArrayList<>(), new ArrayList<>());
  123. // }else
  124. // {
  125. // resetConnections(singleSubNet.getObjects().get(0),
  126. // new ArrayList<>(), new ArrayList<>());
  127. // }
  128. //
  129. // }
  130. // for (SubNet singleSubNet : subNets) {
  131. // float production = calculateEnergyWithoutFlexDevices("prod",
  132. // singleSubNet, timeStep);
  133. // float consumption = calculateEnergyWithoutFlexDevices("cons",
  134. // singleSubNet, timeStep);
  135. // // surplus of energy is computed by sum, since consumption is a
  136. // // negative value
  137. // float energySurplus = production + consumption;
  138. //
  139. //
  140. // //float minConsumption = calculateMinimumEnergy(singleSubNet, timeStep);
  141. //
  142. // // --------------- use flexible devices ---------------
  143. // if (energySurplus != 0 && model.useFlexibleDevices()) {
  144. // turnOnFlexibleDevices(singleSubNet, energySurplus, x);
  145. //
  146. // // if (!flexDevicesTurnedOnThisTurn.isEmpty()) {
  147. // // System.out.println("The following devices were turned on in this turn: ");
  148. // // System.out.println(flexDevicesTurnedOnThisTurn.toString());
  149. // // }
  150. //
  151. // // recompute after having examined/turned on all flexible
  152. // // devices
  153. // production = calculateEnergyWithFlexDevices("prod",
  154. // singleSubNet, timeStep);
  155. // consumption = calculateEnergyWithFlexDevices("cons",
  156. // singleSubNet, timeStep);
  157. // energySurplus = production + consumption;
  158. // }
  159. //
  160. // // --------------- set flow simulation ---------------
  161. // setFlowSimulation(singleSubNet);
  162. //
  163. // // --------------- visualise graph ---------------
  164. //
  165. // /**
  166. // * production of subnets, that might be partially turned on/off
  167. // */
  168. // float currentProduction = production;
  169. // /**
  170. // * HolonObjects that can be partially Supplied but might be fully
  171. // * Supplied
  172. // */
  173. // /*
  174. // ArrayList<HolonObject> partiallySuppliedList = new ArrayList<HolonObject>();
  175. // /**
  176. // * HolonObjects that can get the spare energy
  177. // */
  178. ////
  179. //// ArrayList<HolonObject> notSuppliedList = new ArrayList<HolonObject>();
  180. // /**
  181. // * Number of HolonObjects that need to be supplied
  182. // */
  183. //// long numberOfConsumers = singleSubNet.getObjects().stream()
  184. //// .filter(hl -> (hl.getState() != HolonObject.NO_ENERGY
  185. //// && hl.getState() != HolonObject.PRODUCER && hl
  186. //// .getConnectedTo().stream()
  187. //// .filter(e -> (e.getFlow() > 0)).count() > 0))
  188. //// .count();
  189. // /**
  190. // * energy each HolonObject receives in AlleEqualModus
  191. // */
  192. //
  193. // if(energySurplus >= 0)
  194. // {
  195. // //Supply all consumer
  196. // for(HolonObject hO : singleSubNet.getObjects())
  197. // {
  198. // float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
  199. // if(neededEnergy < 0)
  200. // {
  201. // hO.setCurrentSupply(-neededEnergy);
  202. // currentProduction -= -neededEnergy; //Subtract the Energy from the Production
  203. // }
  204. // }
  205. // //Supply all Batterys with the left currentProduction
  206. // singleSubNet.getBatteries().sort(new WeakestBattery(x));//Sort all batteries by the Value of ther StateOfCharge/Capasity
  207. // for(HolonBattery hB : singleSubNet.getBatteries())
  208. // {
  209. // float energyToCollect = hB.getInAtTimeStep(x-1);
  210. // if(currentProduction >= energyToCollect)
  211. // {
  212. // //change StateofCharge soc = soc + energyToCollect
  213. // hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x-1) + energyToCollect, x);
  214. // currentProduction -= energyToCollect;
  215. // }else
  216. // {
  217. // //change StateofCharge soc = soc + currentProduction
  218. // hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x-1) + currentProduction, x);
  219. // currentProduction = 0;
  220. // //no break must be calculatet for all break; //because no more energy
  221. // }
  222. // }
  223. // //Over_Supply all consumer equal
  224. // long nOConsumer = singleSubNet.getObjects().stream().filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
  225. // if(nOConsumer != 0)
  226. // {
  227. // //energy to seperated equal
  228. // float EnergyOverSupplyPerHolonObject = currentProduction / nOConsumer;
  229. // for(HolonObject hO : singleSubNet.getObjects())
  230. // {
  231. // float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
  232. // if(neededEnergy < 0)
  233. // {
  234. // hO.setCurrentSupply(hO.getCurrentSupply() + EnergyOverSupplyPerHolonObject);
  235. // }
  236. // }
  237. // currentProduction = 0;
  238. // }
  239. // }
  240. // else
  241. // {
  242. // //Check all Battries what they can provide
  243. // if(energySurplus + GetOutAllBatteries(singleSubNet.getBatteries(), x) >= 0)
  244. // {
  245. // singleSubNet.getBatteries().sort(new WeakestBattery(x));//.reverse();
  246. // Collections.reverse(singleSubNet.getBatteries()); //most supplyed first
  247. // //Get the NEEDED energy
  248. // for(HolonBattery hB : singleSubNet.getBatteries())
  249. // {
  250. // float neededEnergyFromBattery = currentProduction + consumption; //Energy is negativ
  251. // float maxEnergyAvailable = hB.getOutAtTimeStep(x-1); //energy is positiv
  252. // if(maxEnergyAvailable >= -neededEnergyFromBattery)
  253. // {
  254. // //change StateofCharge soc = soc - -neededEnergyFromBattery
  255. // hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x-1) - -neededEnergyFromBattery, x);
  256. // currentProduction += -neededEnergyFromBattery;
  257. // //no break must be calculatet for all beabreak; //When a energy can supply the last needed energy break;
  258. // }
  259. // else
  260. // {
  261. // //change StateofCharge soc = soc - maxEnergyAvailable
  262. // hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x-1) - maxEnergyAvailable, x);
  263. // currentProduction += maxEnergyAvailable;
  264. // }
  265. // }
  266. // //Supply all consumer all ar in state Supplied no one is oversupplied because
  267. // // just the energy that is needed is gained from the batteries
  268. // for(HolonObject hO : singleSubNet.getObjects())
  269. // {
  270. // float neededEnergy = hO.getCurrentEnergyAtTimeStep(x);
  271. // if(neededEnergy < 0)
  272. // {
  273. // hO.setCurrentSupply(-neededEnergy);
  274. // currentProduction -= -neededEnergy; //Subtract the Energy from the Production
  275. // }
  276. // }
  277. // }
  278. // else //Objects have to be partially supplied
  279. // {
  280. // //Get all Energy out of battries as possible
  281. // for(HolonBattery hB : singleSubNet.getBatteries())
  282. // {
  283. // float maxEnergyAvailable = hB.getOutAtTimeStep(x-1); //energy is positiv
  284. // //change StateofCharge soc = soc - maxEnergyAvailable
  285. // hB.setStateOfChargeAtTimeStep(hB.getStateOfChargeAtTimeStep(x-1) - maxEnergyAvailable, x);
  286. // currentProduction += maxEnergyAvailable;
  287. // }
  288. // //Calc
  289. // singleSubNet.getObjects().stream().forEach(hl -> hl.setCurrentSupply(0));
  290. // if(model.getFairnessModel() == fairnessAllEqual)
  291. // {
  292. // long nOConsumer = singleSubNet.getObjects().stream().filter(hl -> (hl.getCurrentEnergyAtTimeStep(x) < 0)).count();
  293. // float energyPerHolonObject = 0;
  294. // if (nOConsumer != 0)
  295. // energyPerHolonObject = currentProduction / nOConsumer;
  296. // for(HolonObject hO : singleSubNet.getObjects())
  297. // {
  298. // if(hO.getCurrentEnergyAtTimeStep(x) < 0) //Just Consumer need Energy
  299. // {
  300. // hO.setCurrentSupply(energyPerHolonObject);
  301. // currentProduction -= energyPerHolonObject; //Subtract the Energy from the Production
  302. // }
  303. // }
  304. // }
  305. // else //(model.getFairnessModel() == fairnessMininumDemandFirst)
  306. // {
  307. // singleSubNet.getObjects().sort(new MinEnergyComparator(x));
  308. // //SupplyAllMinimumEnergy
  309. // for(HolonObject hO : singleSubNet.getObjects())
  310. // {
  311. // if(hO.checkIfPartiallySupplied(x))continue;
  312. // if(hO.getCurrentEnergyAtTimeStep(x) > 0)continue;
  313. // float minEnergy = -hO.getMinEnergy(x); //Energy from getMinEnergy is negative -> convert to positive
  314. // if(minEnergy <= currentProduction)
  315. // {
  316. // hO.setCurrentSupply(minEnergy);
  317. // currentProduction -= minEnergy;
  318. // }else
  319. // {
  320. // hO.setCurrentSupply(currentProduction);
  321. // currentProduction = 0;
  322. // break;
  323. // }
  324. // }
  325. // singleSubNet.getObjects().sort(new EnergyMinToMaxComparator(x));
  326. // //supplyFullytillEnd ... because its cant be fully supplied
  327. // for(HolonObject hO : singleSubNet.getObjects())
  328. // {
  329. //
  330. // float actualSupplyEnergy = hO.getCurrentSupply();
  331. // float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x) - actualSupplyEnergy;
  332. // if(neededEnergy <= 0)continue; //Producer or No EnergyNeeded
  333. // if(neededEnergy <= currentProduction)
  334. // {
  335. // hO.setCurrentSupply(neededEnergy+actualSupplyEnergy);
  336. // currentProduction -= neededEnergy;
  337. // }else
  338. // {
  339. // hO.setCurrentSupply(currentProduction+actualSupplyEnergy);
  340. // currentProduction = 0;
  341. // break;
  342. // }
  343. // }
  344. //
  345. //
  346. // }
  347. // }
  348. //
  349. // }
  350. // //Visualize the Color
  351. // for(HolonObject hO : singleSubNet.getObjects())
  352. // {
  353. // float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x); // convert negative energy in positive for calculations
  354. // if(neededEnergy < 0)
  355. // {
  356. // hO.setState(HolonObject.PRODUCER);
  357. // }
  358. // else if(neededEnergy > 0)
  359. // {
  360. // float currentSupply = hO.getCurrentSupply() ;
  361. // if(currentSupply > neededEnergy)
  362. // {
  363. // hO.setState(HolonObject.OVER_SUPPLIED);
  364. // }else if (currentSupply == neededEnergy)
  365. // {
  366. // hO.setState(HolonObject.SUPPLIED);
  367. // }else if (currentSupply < neededEnergy)
  368. // {
  369. // float minEnergy = -hO.getMinEnergy(x);
  370. // if(currentSupply >= minEnergy || hO.getSelfMadeEnergy(x) >= minEnergy )
  371. // {
  372. // hO.setState(HolonObject.PARTIALLY_SUPPLIED);
  373. // }else
  374. // {
  375. // hO.setState(HolonObject.NOT_SUPPLIED);
  376. // }
  377. // }
  378. // }
  379. // else if(neededEnergy == 0)
  380. // {
  381. // hO.setState(HolonObject.NO_ENERGY);
  382. // }
  383. // }
  384. // }
  385. // canvas.repaint();
  386. // flexPane.recalculate();
  387. }
  388. /**
  389. * add all battries.getOut() from a list of battries and return them
  390. * @param aL a List of HolonBattries likely from subnet.getBatteries()
  391. * @param x TimeStep
  392. * @return
  393. *
  394. */
  395. private float GetOutAllBatteries(ArrayList<HolonBattery> aL, int x)
  396. {
  397. float OutEnergy = 0;
  398. for(HolonBattery hB : aL)
  399. {
  400. //System.out.println("Iteration: "+ x +"OutBattery: "+ hB.getOutAtTimeStep(x-1));
  401. OutEnergy += hB.getOutAtTimeStep(x-1);
  402. }
  403. //System.out.println("Iteration: "+ x +"GetOutAllBatteries: "+ OutEnergy);
  404. return OutEnergy;
  405. }
  406. /**
  407. * search for all flexible devices in the network and turn them on, until
  408. * energy surplus = 0 or all devices have been examined.
  409. *
  410. * This code could be compressed (cases inside over- and underproduction are
  411. * the same), but we decided that it is better readable this way
  412. *
  413. * @param subNet
  414. * the subnet
  415. * @param energySurplus
  416. * the current surplus of energy
  417. */
  418. private void turnOnFlexibleDevices(SubNet subNet, float energySurplus,
  419. int timestep) {
  420. for (HolonObject holonOb : subNet.getObjects()) {
  421. for (HolonElement holonEl : holonOb.getElements()) {
  422. // if this element is flexible and active (can be considered for
  423. // calculations)
  424. if (holonEl.isFlexible() && holonEl.isActive()) {
  425. float energyAvailableSingle = holonEl
  426. .getEnergyAtTimeStep(timestep);
  427. float energyAvailableMultiple = energyAvailableSingle
  428. * holonEl.getAmount();
  429. // ------------- flexible consumer / OVERPRODUCTION
  430. // -------------
  431. if (energyAvailableMultiple < 0 && energySurplus > 0) {
  432. // if there is more wasted energy than energy that this
  433. // device can give, give all energy available
  434. if (Math.abs(energyAvailableMultiple) <= Math
  435. .abs(energySurplus)) {
  436. energySurplus += energyAvailableMultiple;
  437. // set the new energy consumption to the maximum
  438. holonEl.setEnergyPerElement(energyAvailableSingle);
  439. flexDevicesTurnedOnThisTurn.put(holonEl,
  440. energyAvailableMultiple);
  441. }
  442. // else: we just need to turn on part of the flexible
  443. // energy available
  444. else {
  445. float energyNeeded = -energySurplus;
  446. energySurplus += energyNeeded; // should give 0, but
  447. // was kept this was
  448. // for consistency
  449. // the energy needed divided through the amount of
  450. // elements
  451. holonEl.setEnergyPerElement(energyNeeded
  452. / holonEl.getAmount());
  453. flexDevicesTurnedOnThisTurn.put(holonEl,
  454. energyNeeded);
  455. }
  456. }
  457. // ------------- flexible producer / UNDERPRODUCTION
  458. // -------------
  459. else if (energyAvailableMultiple > 0 && energySurplus < 0) {
  460. // if there is more energy needed than this device can
  461. // give, give all the energy available
  462. if (Math.abs(energyAvailableMultiple) <= Math
  463. .abs(energySurplus)) {
  464. energySurplus += energyAvailableMultiple;
  465. // set the new energy consumption to the maximum
  466. holonEl.setEnergyPerElement(energyAvailableSingle);
  467. flexDevicesTurnedOnThisTurn.put(holonEl,
  468. energyAvailableMultiple);
  469. }
  470. // else: we just need to turn on part of the flexible
  471. // energy available
  472. else {
  473. float energyNeeded = -energySurplus;
  474. int i = 0;
  475. energySurplus += energyNeeded; // should give 0, but
  476. // was kept this was
  477. // for consistency
  478. // the energy needed divided through the amount of
  479. // elements
  480. holonEl.setEnergyPerElement(energyNeeded
  481. / holonEl.getAmount());
  482. flexDevicesTurnedOnThisTurn.put(holonEl,
  483. energyNeeded);
  484. }
  485. }
  486. }
  487. if (energySurplus == 0) {
  488. break;
  489. }
  490. }
  491. if (energySurplus == 0) {
  492. break;
  493. }
  494. }
  495. }
  496. /**
  497. * Set Flow Simulation.
  498. *
  499. * @param sN
  500. * Subnet
  501. */
  502. private void setFlowSimulation(SubNet sN) {
  503. ArrayList<AbstractCpsObject> producers = new ArrayList<>();
  504. AbstractCpsObject tmp = null;
  505. tagTable = new HashMap<>();
  506. // traverse all objects in this subnet
  507. for (HolonObject hl : sN.getObjects()) {
  508. float energy = hl.getCurrentEnergyAtTimeStep(timeStep);
  509. // if their production is higher than their consumption
  510. if (energy > 0) {
  511. tagTable.put(hl.getId(), energy);
  512. hl.addTag(hl.getId());
  513. for (CpsEdge edge : hl.getConnections()) {
  514. if (edge.isWorking()) {
  515. // set other end of edge as tmp-object
  516. // and add this end to the other end's tag-list
  517. AbstractCpsObject a = edge.getA();
  518. AbstractCpsObject b = edge.getB();
  519. if (a.getId() == hl.getId()) {
  520. b.addTag(hl.getId());
  521. tmp = b;
  522. }
  523. if (b.getId() == hl.getId()) {
  524. a.addTag(hl.getId());
  525. tmp = a;
  526. }
  527. edge.setFlow(edge.getFlow() + energy);
  528. edge.calculateState();
  529. edge.addTag(hl.getId());
  530. if (edge.isWorking() && !producers.contains(tmp)) {
  531. if (tmp instanceof HolonSwitch) {
  532. if (((HolonSwitch) tmp).getState(timeStep)) {
  533. producers.add(tmp);
  534. }
  535. } else if (!(tmp instanceof CpsUpperNode)) {
  536. producers.add(tmp);
  537. }
  538. }
  539. }
  540. }
  541. }
  542. }
  543. setFlowSimRec(producers, 0);
  544. }
  545. /**
  546. * Set Flow Simulation Rec.
  547. *
  548. * @param nodes
  549. * the nodes
  550. * @param iter
  551. * the Iteration
  552. */
  553. private void setFlowSimRec(ArrayList<AbstractCpsObject> nodes, int iter) {
  554. ArrayList<AbstractCpsObject> newNodes = new ArrayList<>();
  555. ArrayList<CpsEdge> changedEdges = new ArrayList<>();
  556. AbstractCpsObject tmp;
  557. if (nodes.size() != 0) {
  558. for (AbstractCpsObject cps : nodes) {
  559. // check whether the cps is in a legit state if it is a switch
  560. if (legitState(cps)) {
  561. for (CpsEdge edge : cps.getConnections()) {
  562. // is edge working
  563. // and does the edge's tag-list not (yet) contain all
  564. // tags of the cps
  565. if (edge.isWorking()
  566. && (!(edge.containsTags(edge.getTags(),
  567. cps.getTag())))) {
  568. if (edge.getA().getId() == cps.getId()) {
  569. tmp = edge.getB();
  570. } else {
  571. tmp = edge.getA();
  572. }
  573. for (Integer tag : cps.getTag()) {
  574. if (!(edge.getTags().contains(tag))
  575. && !(edge.getPseudoTags().contains(tag))) {
  576. edge.setFlow(edge.getFlow()
  577. + tagTable.get(tag));
  578. edge.addTag(tag);
  579. }
  580. }
  581. // uppernodes do not spread energy
  582. if (!(tmp instanceof CpsUpperNode)) {
  583. for (Integer tag : tmp.getTag()) {
  584. if (!(edge.getTags().contains(tag))
  585. && tagTable.get(tag) != null
  586. && !(edge.getPseudoTags()
  587. .contains(tag))) {
  588. edge.setFlow(edge.getFlow()
  589. + tagTable.get(tag));
  590. edge.addPseudoTag(tag);
  591. changedEdges.add(edge);
  592. }
  593. }
  594. }
  595. edge.calculateState();
  596. if (edge.isWorking()
  597. && !(tmp instanceof CpsUpperNode)) {
  598. tmp.addAllPseudoTags(cps.getTag());
  599. if (!newNodes.contains(tmp)) {
  600. newNodes.add(tmp);
  601. }
  602. }
  603. }
  604. }
  605. }
  606. }
  607. setPseudoTags(newNodes, changedEdges);
  608. setFlowSimRec(newNodes, iter + 1);
  609. }
  610. }
  611. /**
  612. * Set the Pseudo Tags.
  613. *
  614. * @param nodes
  615. * Array of AbstractCpsObjects
  616. */
  617. private void setPseudoTags(ArrayList<AbstractCpsObject> nodes,
  618. ArrayList<CpsEdge> edges) {
  619. for (AbstractCpsObject node : nodes) {
  620. node.recalculateTags();
  621. node.setPseudoTags(new ArrayList<>());
  622. }
  623. for (CpsEdge edge : edges) {
  624. edge.recalculateTags();
  625. edge.setPseudoTag(new ArrayList<>());
  626. }
  627. }
  628. /**
  629. * Reset the Connection.
  630. *
  631. * @param cps
  632. * CpsObject
  633. * @param visitedObj
  634. * the visited Objects
  635. * @param visitedEdges
  636. * the visited Edges
  637. */
  638. private void resetConnections(AbstractCpsObject cps,
  639. ArrayList<Integer> visitedObj, ArrayList<CpsEdge> visitedEdges) {
  640. visitedObj.add(cps.getId());
  641. cps.resetTags();
  642. for (CpsEdge e : cps.getConnections()) {
  643. if (!(visitedEdges.contains(e))) {
  644. e.setFlow(0);
  645. e.calculateState();
  646. e.setTags(new ArrayList<>());
  647. visitedEdges.add(e);
  648. if (!(visitedObj.contains(e.getA().getId()))) {
  649. resetConnections(e.getA(), visitedObj, visitedEdges);
  650. e.getA().resetTags();
  651. }
  652. if (!(visitedObj.contains(e.getB().getId()))) {
  653. resetConnections(e.getB(), visitedObj, visitedEdges);
  654. e.getB().resetTags();
  655. }
  656. }
  657. }
  658. }
  659. /**
  660. * calculates the energy of either all producers or consumers. Flexible
  661. * devices are filtered out
  662. *
  663. * @param type
  664. * Type
  665. * @param sN
  666. * Subnet
  667. * @param x
  668. * Integer
  669. * @return The Energy
  670. */
  671. private float calculateEnergyWithoutFlexDevices(String type, SubNet sN,
  672. int x) {
  673. float energy = 0;
  674. for (HolonObject hl : sN.getObjects()) {
  675. float currentEnergyWithoutFlexibles = hl
  676. .getCurrentEnergyAtTimeStepWithoutFlexiblesAndResetFlexibles(x);
  677. if (type.equals("prod")) {
  678. if (currentEnergyWithoutFlexibles > 0) {
  679. energy += currentEnergyWithoutFlexibles;
  680. hl.setState(HolonObject.PRODUCER);
  681. }
  682. }
  683. if (type.equals("cons")) {
  684. if (currentEnergyWithoutFlexibles < 0) {
  685. energy += currentEnergyWithoutFlexibles;
  686. hl.setState(HolonObject.NOT_SUPPLIED);
  687. }
  688. }
  689. if (currentEnergyWithoutFlexibles == 0) {
  690. hl.setState(HolonObject.NO_ENERGY);
  691. }
  692. }
  693. return energy;
  694. }
  695. /**
  696. * calculates the energy of either all producers or consumers. Flexible
  697. * devices are filtered out
  698. *
  699. * @param type
  700. * Type
  701. * @param sN
  702. * Subnet
  703. * @param x
  704. * Integer
  705. * @return The Energy
  706. */
  707. private float calculateEnergyWithFlexDevices(String type, SubNet sN, int x) {
  708. float energy = 0;
  709. for (HolonObject hl : sN.getObjects()) {
  710. float currentEnergy = hl.getCurrentEnergyAtTimeStep(x);
  711. if (type.equals("prod")) {
  712. if (currentEnergy > 0) {
  713. energy += currentEnergy;
  714. hl.setState(HolonObject.PRODUCER);
  715. }
  716. }
  717. if (type.equals("cons")) {
  718. if (currentEnergy < 0) {
  719. energy = energy + currentEnergy;
  720. hl.setState(HolonObject.NOT_SUPPLIED);
  721. }
  722. }
  723. if (currentEnergy == 0) {
  724. hl.setState(HolonObject.NO_ENERGY);
  725. }
  726. }
  727. return energy;
  728. }
  729. /**
  730. * Calculate the Minimum Energy of a Subnet.
  731. *
  732. * @param sN
  733. * Subnet
  734. * @param x
  735. * Integer
  736. * @return the Calculated minimum Energy of a Subnet
  737. */
  738. private float calculateMinimumEnergy(SubNet sN, int x) {
  739. float minimummConsumptionSubnet = 0;
  740. for (HolonObject hl : sN.getObjects()) {
  741. float minElement = 0;
  742. // Search for a activ element
  743. for (HolonElement he : hl.getElements()) {
  744. if (he.isActive()) {
  745. float overallEnergy = he.getOverallEnergyAtTimeStep(x);
  746. if (overallEnergy < 0) {
  747. // Is a consumer
  748. minElement = overallEnergy;
  749. }
  750. }
  751. }
  752. for (HolonElement he : hl.getElements()) {
  753. if (he.isActive()) {
  754. float overallEnergy = he.getOverallEnergyAtTimeStep(x);
  755. if (minElement < overallEnergy && overallEnergy < 0) {
  756. // is a smaller consumer
  757. minElement = overallEnergy;
  758. }
  759. }
  760. }
  761. minimummConsumptionSubnet += minElement;
  762. }
  763. System.out.println("MinimumEnergy = "+ minimummConsumptionSubnet);
  764. return minimummConsumptionSubnet;
  765. }
  766. /**
  767. * generates all subNets from all objectsToHandle.
  768. */
  769. private void searchForSubNets() {
  770. subNets = new ArrayList<>();
  771. brokenEdges.clear();
  772. boolean end = false;
  773. int i = 0;
  774. AbstractCpsObject cps;
  775. if (objectsToHandle.size() > 0) {
  776. while (!end) {
  777. cps = objectsToHandle.get(i);
  778. SubNet singleSubNet = new SubNet(new ArrayList<>(),
  779. new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
  780. singleSubNet = buildSubNet(cps, new ArrayList<>(), singleSubNet);
  781. if (singleSubNet.getObjects().size() + singleSubNet.getBatteries().size() != 0 ) {
  782. subNets.add(singleSubNet);
  783. }
  784. if (0 == objectsToHandle.size()) {
  785. end = true;
  786. }
  787. }
  788. }
  789. }
  790. /**
  791. * recursivly generates a subnet of all objects, that one specific object is
  792. * connected to.
  793. *
  794. * @param cps
  795. * AbstractCpsObject
  796. * @param visited
  797. * visited Array of Integer
  798. * @param sN
  799. * Subnets
  800. * @return Subnet
  801. */
  802. private SubNet buildSubNet(AbstractCpsObject cps,
  803. ArrayList<Integer> visited, SubNet sN) {
  804. visited.add(cps.getId());
  805. if (cps instanceof HolonObject) {
  806. sN.getObjects().add((HolonObject) cps);
  807. }
  808. if (cps instanceof HolonSwitch) {
  809. sN.getSwitches().add((HolonSwitch) cps);
  810. }
  811. if (cps instanceof HolonBattery) {
  812. sN.getBatteries().add((HolonBattery) cps);
  813. }
  814. removeFromToHandle(cps.getId());
  815. AbstractCpsObject a;
  816. AbstractCpsObject b;
  817. for (CpsEdge edge : cps.getConnections()) {
  818. if (edge.isWorking()) {
  819. a = edge.getA();
  820. b = edge.getB();
  821. if (!(cps instanceof HolonSwitch)) {
  822. if (!(sN.getEdges().contains(edge))) {
  823. sN.getEdges().add(edge);
  824. }
  825. }
  826. if (cps instanceof HolonSwitch
  827. && ((HolonSwitch) cps).getState(timeStep)) {
  828. if (!(sN.getEdges().contains(edge))) {
  829. sN.getEdges().add(edge);
  830. }
  831. }
  832. if (!visited.contains(a.getId()) && legitState(cps)
  833. && !(a instanceof CpsUpperNode)) {
  834. sN = buildSubNet(a, visited, sN);
  835. }
  836. if (!visited.contains(b.getId()) && legitState(cps)
  837. && !(b instanceof CpsUpperNode)) {
  838. sN = buildSubNet(b, visited, sN);
  839. }
  840. if (a instanceof CpsUpperNode && a.getId() != cps.getId()) {
  841. edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
  842. checkForConnectedStates(b, (CpsUpperNode) a, edge);
  843. }
  844. if (b instanceof CpsUpperNode && b.getId() != cps.getId()) {
  845. edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
  846. checkForConnectedStates(a, (CpsUpperNode) b, edge);
  847. }
  848. } else {
  849. brokenEdges.add(edge);
  850. }
  851. }
  852. return sN;
  853. }
  854. /**
  855. * is the Switch in a legitimate State.
  856. *
  857. * @param current
  858. * AbstractCpsObject
  859. * @return boolean
  860. */
  861. private boolean legitState(AbstractCpsObject current) {
  862. return !(current instanceof HolonSwitch)
  863. || ((HolonSwitch) current).getState(timeStep);
  864. }
  865. // /**
  866. // * ensures that objectsToHandle only contains HolonObjects.
  867. // */
  868. // public void cleanObjectsToHandle() {
  869. // for (int i = 0; i < objectsToHandle.size(); i++) {
  870. // if (!(objectsToHandle.get(i) instanceof HolonObject)) {
  871. // objectsToHandle.remove(i);
  872. // }
  873. // }
  874. // }
  875. /**
  876. * removes an Object that already has been handled.
  877. *
  878. * @param id
  879. * the Object ID
  880. */
  881. private void removeFromToHandle(int id) {
  882. for (int i = 0; i < objectsToHandle.size(); i++) {
  883. if (objectsToHandle.get(i).getId() == id) {
  884. objectsToHandle.remove(i);
  885. }
  886. }
  887. }
  888. /**
  889. * copies the data of an array of Objects.
  890. *
  891. * @param toCopy
  892. * the ArrayList of CpsObjects co Copy
  893. */
  894. private void copyObjects(ArrayList<AbstractCpsObject> toCopy) {
  895. for (AbstractCpsObject cps : toCopy) {
  896. if (cps instanceof CpsUpperNode) {
  897. copyObjects(((CpsUpperNode) cps).getNodes());
  898. } else {
  899. objectsToHandle.add(cps);
  900. }
  901. }
  902. }
  903. /**
  904. * Prints the Components auf all subnets.
  905. */
  906. private void printNetsToConsole() {
  907. for (int i = 0; i < subNets.size(); i++) {
  908. SubNet subNet = subNets.get(i);
  909. System.out.println("SUBNET NR:" + i);
  910. subNet.toString(timeStep);
  911. }
  912. }
  913. /**
  914. * Set the Canvas.
  915. *
  916. * @param can
  917. * the Canvas
  918. */
  919. public void setCanvas(MyCanvas can) {
  920. canvas = can;
  921. }
  922. /**
  923. * Reset all Data to the current state of the Model.
  924. */
  925. public void reset() {
  926. objectsToHandle = new ArrayList<>();
  927. copyObjects(model.getObjectsOnCanvas());
  928. flexDevicesTurnedOnThisTurn = new HashMap<>();
  929. }
  930. /**
  931. * Resets the State of all Edges
  932. */
  933. private void resetEdges() {
  934. for (CpsEdge e : brokenEdges) {
  935. e.setWorkingState(true);
  936. }
  937. }
  938. /**
  939. * Resets the State for the whole Simulation Model
  940. */
  941. void resetSimulation() {
  942. reset();
  943. resetEdges();
  944. }
  945. /**
  946. * Get all Subnets.
  947. *
  948. * @return all Subnets
  949. */
  950. public ArrayList<SubNet> getSubNets() {
  951. return subNets;
  952. }
  953. /**
  954. * Get broken Edges
  955. */
  956. // public ArrayList<CpsEdge> getBrokenEdges() {
  957. // return brokenEdges;
  958. // }
  959. /**
  960. * checks whether a given object is connected to an object inside the
  961. * upperNode. if yes, the state for the edge is changed in "connected" or
  962. * "not connected"
  963. */
  964. private void checkForConnectedStates(AbstractCpsObject cps,
  965. CpsUpperNode cUNode, CpsEdge theEdge) {
  966. AbstractCpsObject tmp;
  967. for (CpsEdge edge : cps.getConnections()) {
  968. if (edge.getA().getId() == cps.getId()) {
  969. tmp = edge.getB();
  970. } else {
  971. tmp = edge.getA();
  972. }
  973. if (cUNode.getNodes().contains(tmp)) {
  974. if (tmp instanceof CpsUpperNode) {
  975. checkForConnectedStates(cps, (CpsUpperNode) tmp, theEdge);
  976. } else {
  977. theEdge.setConnected(CpsEdge.CON_UPPER_NODE_AND_INSIDE);
  978. break;
  979. }
  980. }
  981. }
  982. }
  983. public FlexiblePane getFlexiblePane() {
  984. return flexPane;
  985. }
  986. void setFlexiblePane(FlexiblePane fp) {
  987. flexPane = fp;
  988. }
  989. public DecoratedState getActualDecorStateWithOffSet(int offSet) {
  990. return getDecorState(timeStep + offSet);
  991. }
  992. public DecoratedState getActualDecorState() {
  993. return getDecorState(timeStep);
  994. }
  995. public DecoratedState getDecorState(int timestep) {
  996. return saves.getOrDefault(timestep, null);
  997. }
  998. }