SimulationManager.java 34 KB

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