SimulationManager.java 33 KB

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