SimulationManager.java 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  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 neededEnergy = -hO.getCurrentEnergyAtTimeStep(x);
  263. if(neededEnergy < 0)continue; //Producer
  264. if(neededEnergy <= currentProduction)
  265. {
  266. hO.setCurrentSupply(neededEnergy+hO.getCurrentSupply());
  267. currentProduction -= neededEnergy;
  268. }else
  269. {
  270. hO.setCurrentSupply(currentProduction+hO.getCurrentSupply());
  271. currentProduction = 0;
  272. break;
  273. }
  274. }
  275. }
  276. }
  277. }
  278. //Visualize the Color
  279. for(HolonObject hO : singleSubNet.getObjects())
  280. {
  281. float neededEnergy = -hO.getCurrentEnergyAtTimeStep(x); // convert negative energy in positive for calculations
  282. if(neededEnergy < 0)
  283. {
  284. hO.setState(HolonObject.PRODUCER);
  285. }
  286. else if(neededEnergy > 0)
  287. {
  288. float currentSupply = hO.getCurrentSupply() ;
  289. if(currentSupply > neededEnergy)
  290. {
  291. hO.setState(HolonObject.OVER_SUPPLIED);
  292. }else if (currentSupply == neededEnergy)
  293. {
  294. hO.setState(HolonObject.SUPPLIED);
  295. }else if (currentSupply < neededEnergy)
  296. {
  297. float minEnergy = -hO.getMinEnergy(x);
  298. if(currentSupply >= minEnergy || hO.getSelfMadeEnergy(x) >= minEnergy )
  299. {
  300. hO.setState(HolonObject.PARTIALLY_SUPPLIED);
  301. }else
  302. {
  303. hO.setState(HolonObject.NOT_SUPPLIED);
  304. }
  305. }
  306. }
  307. else if(neededEnergy == 0)
  308. {
  309. hO.setState(HolonObject.NO_ENERGY);
  310. }
  311. }
  312. }
  313. canvas.repaint();
  314. flexPane.recalculate();
  315. }
  316. private void calculation(int x, SubNet singleSubNet, float production, float consumption, float energySurplus,
  317. float currentProduction, ArrayList<HolonObject> partiallySuppliedList,
  318. ArrayList<HolonObject> notSuppliedList, float energyPerHolonObject) {
  319. long numberOfConsumers;
  320. if (model.getFairnessModel() == fairnessMininumDemandFirst) {
  321. /**
  322. * supply Buildings with minimal Energy first, if conflicts
  323. * happen
  324. */
  325. singleSubNet.getObjects().sort(new MinEnergyComparator(x));
  326. } else if (model.getFairnessModel() == fairnessAllEqual) {
  327. /*
  328. * give every building (just consumer) the same energy
  329. */
  330. numberOfConsumers = singleSubNet
  331. .getObjects()
  332. .stream()
  333. .filter(hl -> (hl.getState() != HolonObject.NO_ENERGY
  334. && hl.getState() != HolonObject.PRODUCER && hl
  335. .getConnectedTo().stream()
  336. .filter(e -> (e.getFlow() > 0)).count() > 0))
  337. .count();
  338. if (numberOfConsumers != 0)
  339. energyPerHolonObject = currentProduction / numberOfConsumers;
  340. }
  341. for (HolonObject hl : singleSubNet.getObjects()) {
  342. hl.setCurrentSupply(0);
  343. if (hl.getState() != HolonObject.NO_ENERGY
  344. && hl.getState() != HolonObject.PRODUCER) {
  345. for (int i = 0; i < hl.getConnections().size(); i++) {
  346. CpsEdge edge = hl.getConnectedTo().get(i);
  347. if (edge.isWorking()
  348. && edge.getFlow() > 0
  349. || edge.getCapacity() == CpsEdge.CAPACITY_INFINITE) {
  350. if (model.getFairnessModel() == fairnessAllEqual) {
  351. /* fairness: everyone receives the Same Energy */
  352. float neededEnergy = hl
  353. .getCurrentEnergyAtTimeStep(x);
  354. if (neededEnergy > 0) {
  355. hl.setState(HolonObject.PRODUCER);
  356. } else if (energyPerHolonObject > -neededEnergy) {
  357. hl.setState(HolonObject.OVER_SUPPLIED);
  358. } else if (energyPerHolonObject == -neededEnergy) {
  359. hl.setState(HolonObject.SUPPLIED);
  360. } else if (energyPerHolonObject >= -hl
  361. .getMinEnergy(x)) {
  362. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  363. } else {
  364. hl.setState(HolonObject.NOT_SUPPLIED);
  365. }
  366. hl.setCurrentSupply(energyPerHolonObject);
  367. } else if (model.getFairnessModel() == fairnessMininumDemandFirst) {
  368. /* fairness: minimum demand gets Energy first */
  369. if ((production + consumption) >= 0) {
  370. if (energySurplus > 0) {
  371. hl.setState(HolonObject.OVER_SUPPLIED);
  372. hl.setCurrentSupply((-energySurplus
  373. / consumption + 1)
  374. * hl.getCurrentEnergyAtTimeStep(x));
  375. } else {
  376. hl.setState(HolonObject.SUPPLIED);
  377. hl.setCurrentSupply(-hl
  378. .getCurrentEnergyAtTimeStep(x));
  379. }
  380. } else {
  381. float minEnergy = hl.getMinEnergy(x);
  382. if (hl.checkIfPartiallySupplied(timeStep)) {
  383. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  384. currentProduction += minEnergy;
  385. hl.setCurrentSupply(-minEnergy);
  386. partiallySuppliedList.add(hl);
  387. } else {
  388. /**
  389. * Case that only some HolonObjects can
  390. * be supplied
  391. */
  392. if (-hl.getCurrentEnergyAtTimeStep(x) <= currentProduction) {
  393. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  394. currentProduction += minEnergy;
  395. hl.setCurrentSupply(-minEnergy);
  396. partiallySuppliedList.add(hl);
  397. } else if (-hl.getMinEnergy(x) <= currentProduction) {
  398. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  399. currentProduction += minEnergy;
  400. hl.setCurrentSupply(-minEnergy);
  401. partiallySuppliedList.add(hl);
  402. } else {
  403. hl.setState(HolonObject.NOT_SUPPLIED);
  404. hl.setCurrentSupply(0.0f);
  405. notSuppliedList.add(hl);
  406. // currentProduction +=
  407. // hl.getCurrentEnergyAtTimeStep(x);
  408. }
  409. }
  410. }
  411. }
  412. hl.getCurrentEnergyAtTimeStep(x);
  413. break;
  414. }
  415. }
  416. /**
  417. * check if some object cn self supply itself
  418. */
  419. if (hl.checkIfPartiallySupplied(timeStep)
  420. && hl.getState() != HolonObject.SUPPLIED
  421. && hl.getState() != HolonObject.OVER_SUPPLIED) {
  422. hl.setState(HolonObject.PARTIALLY_SUPPLIED);
  423. }
  424. }
  425. }
  426. if (model.getFairnessModel() == fairnessMininumDemandFirst) {
  427. /**
  428. * check if some partially supplied building might be fully
  429. * supplied.
  430. */
  431. partiallySuppliedList.sort(new EnergyMinToMaxComparator(x));
  432. for (HolonObject hl : partiallySuppliedList) {
  433. float minEnergy = hl.getMinEnergy(x);
  434. currentProduction -= minEnergy;
  435. /*
  436. * if possible, supply fully
  437. */
  438. float currentEnergyAtTimeStep = hl
  439. .getCurrentEnergyAtTimeStep(x);
  440. if (-currentEnergyAtTimeStep <= currentProduction) {
  441. hl.setState(HolonObject.SUPPLIED);
  442. currentProduction += currentEnergyAtTimeStep;
  443. hl.setCurrentSupply(-currentEnergyAtTimeStep);
  444. hl.getCurrentEnergyAtTimeStep(x);
  445. } else {
  446. currentProduction += minEnergy;
  447. notSuppliedList.add(hl);
  448. }
  449. }
  450. if (!notSuppliedList.isEmpty() && currentProduction > 0) {
  451. float energyPerHolon = currentProduction
  452. / notSuppliedList.size();
  453. for (HolonObject hl : notSuppliedList) {
  454. hl.setCurrentSupply(hl.getCurrentSupply()
  455. + energyPerHolon);
  456. hl.getCurrentEnergyAtTimeStep(x);
  457. }
  458. }
  459. }
  460. }
  461. /**
  462. * add all battries.getOut() from a list of battries and return them
  463. * @param aL a List of HolonBattries likely from subnet.getBatteries()
  464. * @param x TimeStep
  465. * @return
  466. *
  467. */
  468. private float GetOutAllBatteries(ArrayList<HolonBattery> aL, int x)
  469. {
  470. float OutEnergy = 0;
  471. for(HolonBattery hB : aL)
  472. {
  473. //System.out.println("Iteration: "+ x +"OutBattery: "+ hB.getOutAtTimeStep(x-1));
  474. OutEnergy += hB.getOutAtTimeStep(x-1);
  475. }
  476. //System.out.println("Iteration: "+ x +"GetOutAllBatteries: "+ OutEnergy);
  477. return OutEnergy;
  478. }
  479. /**
  480. * search for all flexible devices in the network and turn them on, until
  481. * energy surplus = 0 or all devices have been examined.
  482. *
  483. * This code could be compressed (cases inside over- and underproduction are
  484. * the same), but we decided that it is better readable this way
  485. *
  486. * @param subNet
  487. * the subnet
  488. * @param energySurplus
  489. * the current surplus of energy
  490. */
  491. private void turnOnFlexibleDevices(SubNet subNet, float energySurplus,
  492. int timestep) {
  493. for (HolonObject holonOb : subNet.getObjects()) {
  494. for (HolonElement holonEl : holonOb.getElements()) {
  495. // if this element is flexible and active (can be considered for
  496. // calculations)
  497. if (holonEl.isFlexible() && holonEl.isActive()) {
  498. float energyAvailableSingle = holonEl
  499. .getAvailableEnergyAt(timestep);
  500. float energyAvailableMultiple = energyAvailableSingle
  501. * holonEl.getAmount();
  502. // ------------- flexible consumer / OVERPRODUCTION
  503. // -------------
  504. if (energyAvailableMultiple < 0 && energySurplus > 0) {
  505. // if there is more wasted energy than energy that this
  506. // device can give, give all energy available
  507. if (Math.abs(energyAvailableMultiple) <= Math
  508. .abs(energySurplus)) {
  509. energySurplus += energyAvailableMultiple;
  510. // set the new energy consumption to the maximum
  511. holonEl.setEnergyPerElement(energyAvailableSingle);
  512. flexDevicesTurnedOnThisTurn.put(holonEl,
  513. energyAvailableMultiple);
  514. }
  515. // else: we just need to turn on part of the flexible
  516. // energy available
  517. else {
  518. float energyNeeded = -energySurplus;
  519. energySurplus += energyNeeded; // should give 0, but
  520. // was kept this was
  521. // for consistency
  522. // the energy needed divided through the amount of
  523. // elements
  524. holonEl.setEnergyPerElement(energyNeeded
  525. / holonEl.getAmount());
  526. flexDevicesTurnedOnThisTurn.put(holonEl,
  527. energyNeeded);
  528. }
  529. }
  530. // ------------- flexible producer / UNDERPRODUCTION
  531. // -------------
  532. else if (energyAvailableMultiple > 0 && energySurplus < 0) {
  533. // if there is more energy needed than this device can
  534. // give, give all the energy available
  535. if (Math.abs(energyAvailableMultiple) <= Math
  536. .abs(energySurplus)) {
  537. energySurplus += energyAvailableMultiple;
  538. // set the new energy consumption to the maximum
  539. holonEl.setEnergyPerElement(energyAvailableSingle);
  540. flexDevicesTurnedOnThisTurn.put(holonEl,
  541. energyAvailableMultiple);
  542. }
  543. // else: we just need to turn on part of the flexible
  544. // energy available
  545. else {
  546. float energyNeeded = -energySurplus;
  547. int i = 0;
  548. energySurplus += energyNeeded; // should give 0, but
  549. // was kept this was
  550. // for consistency
  551. // the energy needed divided through the amount of
  552. // elements
  553. holonEl.setEnergyPerElement(energyNeeded
  554. / holonEl.getAmount());
  555. flexDevicesTurnedOnThisTurn.put(holonEl,
  556. energyNeeded);
  557. }
  558. }
  559. }
  560. if (energySurplus == 0) {
  561. break;
  562. }
  563. }
  564. if (energySurplus == 0) {
  565. break;
  566. }
  567. }
  568. }
  569. /**
  570. * Set Flow Simulation.
  571. *
  572. * @param sN
  573. * Subnet
  574. */
  575. private void setFlowSimulation(SubNet sN) {
  576. ArrayList<AbstractCpsObject> producers = new ArrayList<>();
  577. AbstractCpsObject tmp = null;
  578. tagTable = new HashMap<>();
  579. // traverse all objects in this subnet
  580. for (HolonObject hl : sN.getObjects()) {
  581. float energy = hl.getCurrentEnergyAtTimeStep(timeStep);
  582. // if their production is higher than their consumption
  583. if (energy > 0) {
  584. tagTable.put(hl.getId(), energy);
  585. hl.addTag(hl.getId());
  586. for (CpsEdge edge : hl.getConnections()) {
  587. if (edge.isWorking()) {
  588. // set other end of edge as tmp-object
  589. // and add this end to the other end's tag-list
  590. AbstractCpsObject a = edge.getA();
  591. AbstractCpsObject b = edge.getB();
  592. if (a.getId() == hl.getId()) {
  593. b.addTag(hl.getId());
  594. tmp = b;
  595. }
  596. if (b.getId() == hl.getId()) {
  597. a.addTag(hl.getId());
  598. tmp = a;
  599. }
  600. edge.setFlow(edge.getFlow() + energy);
  601. edge.calculateState();
  602. edge.addTag(hl.getId());
  603. if (edge.isWorking() && !producers.contains(tmp)) {
  604. if (tmp instanceof HolonSwitch) {
  605. if (((HolonSwitch) tmp).getState(timeStep)) {
  606. producers.add(tmp);
  607. }
  608. } else if (!(tmp instanceof CpsUpperNode)) {
  609. producers.add(tmp);
  610. }
  611. }
  612. }
  613. }
  614. }
  615. }
  616. setFlowSimRec(producers, 0);
  617. }
  618. /**
  619. * Set Flow Simulation Rec.
  620. *
  621. * @param nodes
  622. * the nodes
  623. * @param iter
  624. * the Iteration
  625. */
  626. private void setFlowSimRec(ArrayList<AbstractCpsObject> nodes, int iter) {
  627. ArrayList<AbstractCpsObject> newNodes = new ArrayList<>();
  628. ArrayList<CpsEdge> changedEdges = new ArrayList<>();
  629. AbstractCpsObject tmp;
  630. if (nodes.size() != 0) {
  631. for (AbstractCpsObject cps : nodes) {
  632. // check whether the cps is in a legit state if it is a switch
  633. if (legitState(cps)) {
  634. for (CpsEdge edge : cps.getConnections()) {
  635. // is edge working
  636. // and does the edge's tag-list not (yet) contain all
  637. // tags of the cps
  638. if (edge.isWorking()
  639. && (!(edge.containsTags(edge.getTags(),
  640. cps.getTag())))) {
  641. if (edge.getA().getId() == cps.getId()) {
  642. tmp = edge.getB();
  643. } else {
  644. tmp = edge.getA();
  645. }
  646. for (Integer tag : cps.getTag()) {
  647. if (!(edge.getTags().contains(tag))
  648. && !(edge.getPseudoTags().contains(tag))) {
  649. edge.setFlow(edge.getFlow()
  650. + tagTable.get(tag));
  651. edge.addTag(tag);
  652. }
  653. }
  654. // uppernodes do not spread energy
  655. if (!(tmp instanceof CpsUpperNode)) {
  656. for (Integer tag : tmp.getTag()) {
  657. if (!(edge.getTags().contains(tag))
  658. && tagTable.get(tag) != null
  659. && !(edge.getPseudoTags()
  660. .contains(tag))) {
  661. edge.setFlow(edge.getFlow()
  662. + tagTable.get(tag));
  663. edge.addPseudoTag(tag);
  664. changedEdges.add(edge);
  665. }
  666. }
  667. }
  668. edge.calculateState();
  669. if (edge.isWorking()
  670. && !(tmp instanceof CpsUpperNode)) {
  671. tmp.addAllPseudoTags(cps.getTag());
  672. if (!newNodes.contains(tmp)) {
  673. newNodes.add(tmp);
  674. }
  675. }
  676. }
  677. }
  678. }
  679. }
  680. setPseudoTags(newNodes, changedEdges);
  681. setFlowSimRec(newNodes, iter + 1);
  682. }
  683. }
  684. /**
  685. * Set the Pseudo Tags.
  686. *
  687. * @param nodes
  688. * Array of AbstractCpsObjects
  689. */
  690. private void setPseudoTags(ArrayList<AbstractCpsObject> nodes,
  691. ArrayList<CpsEdge> edges) {
  692. for (AbstractCpsObject node : nodes) {
  693. node.recalculateTags();
  694. node.setPseudoTags(new ArrayList<>());
  695. }
  696. for (CpsEdge edge : edges) {
  697. edge.recalculateTags();
  698. edge.setPseudoTag(new ArrayList<>());
  699. }
  700. }
  701. /**
  702. * Reset the Connection.
  703. *
  704. * @param cps
  705. * CpsObject
  706. * @param visitedObj
  707. * the visited Objects
  708. * @param visitedEdges
  709. * the visited Edges
  710. */
  711. private void resetConnections(AbstractCpsObject cps,
  712. ArrayList<Integer> visitedObj, ArrayList<CpsEdge> visitedEdges) {
  713. visitedObj.add(cps.getId());
  714. cps.resetTags();
  715. for (CpsEdge e : cps.getConnections()) {
  716. if (!(visitedEdges.contains(e))) {
  717. e.setFlow(0);
  718. e.calculateState();
  719. e.setTags(new ArrayList<>());
  720. visitedEdges.add(e);
  721. if (!(visitedObj.contains(e.getA().getId()))) {
  722. resetConnections(e.getA(), visitedObj, visitedEdges);
  723. e.getA().resetTags();
  724. }
  725. if (!(visitedObj.contains(e.getB().getId()))) {
  726. resetConnections(e.getB(), visitedObj, visitedEdges);
  727. e.getB().resetTags();
  728. }
  729. }
  730. }
  731. }
  732. /**
  733. * calculates the energy of either all producers or consumers. Flexible
  734. * devices are filtered out
  735. *
  736. * @param type
  737. * Type
  738. * @param sN
  739. * Subnet
  740. * @param x
  741. * Integer
  742. * @return The Energy
  743. */
  744. private float calculateEnergyWithoutFlexDevices(String type, SubNet sN,
  745. int x) {
  746. float energy = 0;
  747. for (HolonObject hl : sN.getObjects()) {
  748. float currentEnergyWithoutFlexibles = hl
  749. .getCurrentEnergyAtTimeStepWithoutFlexiblesAndResetFlexibles(x);
  750. if (type.equals("prod")) {
  751. if (currentEnergyWithoutFlexibles > 0) {
  752. energy += currentEnergyWithoutFlexibles;
  753. hl.setState(HolonObject.PRODUCER);
  754. }
  755. }
  756. if (type.equals("cons")) {
  757. if (currentEnergyWithoutFlexibles < 0) {
  758. energy += currentEnergyWithoutFlexibles;
  759. hl.setState(HolonObject.NOT_SUPPLIED);
  760. }
  761. }
  762. if (currentEnergyWithoutFlexibles == 0) {
  763. hl.setState(HolonObject.NO_ENERGY);
  764. }
  765. }
  766. return energy;
  767. }
  768. /**
  769. * calculates the energy of either all producers or consumers. Flexible
  770. * devices are filtered out
  771. *
  772. * @param type
  773. * Type
  774. * @param sN
  775. * Subnet
  776. * @param x
  777. * Integer
  778. * @return The Energy
  779. */
  780. private float calculateEnergyWithFlexDevices(String type, SubNet sN, int x) {
  781. float energy = 0;
  782. for (HolonObject hl : sN.getObjects()) {
  783. float currentEnergy = hl.getCurrentEnergyAtTimeStep(x);
  784. if (type.equals("prod")) {
  785. if (currentEnergy > 0) {
  786. energy += currentEnergy;
  787. hl.setState(HolonObject.PRODUCER);
  788. }
  789. }
  790. if (type.equals("cons")) {
  791. if (currentEnergy < 0) {
  792. energy = energy + currentEnergy;
  793. hl.setState(HolonObject.NOT_SUPPLIED);
  794. }
  795. }
  796. if (currentEnergy == 0) {
  797. hl.setState(HolonObject.NO_ENERGY);
  798. }
  799. }
  800. return energy;
  801. }
  802. /**
  803. * Calculate the Minimum Energy of a Subnet.
  804. *
  805. * @param sN
  806. * Subnet
  807. * @param x
  808. * Integer
  809. * @return the Calculated minimum Energy of a Subnet
  810. */
  811. private float calculateMinimumEnergy(SubNet sN, int x) {
  812. float minimummConsumptionSubnet = 0;
  813. for (HolonObject hl : sN.getObjects()) {
  814. float minElement = 0;
  815. // Search for a activ element
  816. for (HolonElement he : hl.getElements()) {
  817. if (he.isActive()) {
  818. float overallEnergy = he.getOverallEnergyAtTimeStep(x);
  819. if (overallEnergy < 0) {
  820. // Is a consumer
  821. minElement = overallEnergy;
  822. }
  823. }
  824. }
  825. for (HolonElement he : hl.getElements()) {
  826. if (he.isActive()) {
  827. float overallEnergy = he.getOverallEnergyAtTimeStep(x);
  828. if (minElement < overallEnergy && overallEnergy < 0) {
  829. // is a smaller consumer
  830. minElement = overallEnergy;
  831. }
  832. }
  833. }
  834. minimummConsumptionSubnet += minElement;
  835. }
  836. System.out.println("MinimumEnergy = "+ minimummConsumptionSubnet);
  837. return minimummConsumptionSubnet;
  838. }
  839. /**
  840. * generates all subNets from all objectsToHandle.
  841. */
  842. private void searchForSubNets() {
  843. subNets = new ArrayList<>();
  844. brokenEdges.clear();
  845. boolean end = false;
  846. int i = 0;
  847. AbstractCpsObject cps;
  848. if (objectsToHandle.size() > 0) {
  849. while (!end) {
  850. cps = objectsToHandle.get(i);
  851. SubNet singleSubNet = new SubNet(new ArrayList<>(),
  852. new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
  853. singleSubNet = buildSubNet(cps, new ArrayList<>(), singleSubNet);
  854. if (singleSubNet.getObjects().size() + singleSubNet.getBatteries().size() != 0 ) {
  855. subNets.add(singleSubNet);
  856. }
  857. if (0 == objectsToHandle.size()) {
  858. end = true;
  859. }
  860. }
  861. }
  862. }
  863. /**
  864. * recursivly generates a subnet of all objects, that one specific object is
  865. * connected to.
  866. *
  867. * @param cps
  868. * AbstractCpsObject
  869. * @param visited
  870. * visited Array of Integer
  871. * @param sN
  872. * Subnets
  873. * @return Subnet
  874. */
  875. private SubNet buildSubNet(AbstractCpsObject cps,
  876. ArrayList<Integer> visited, SubNet sN) {
  877. visited.add(cps.getId());
  878. if (cps instanceof HolonObject) {
  879. sN.getObjects().add((HolonObject) cps);
  880. }
  881. if (cps instanceof HolonSwitch) {
  882. sN.getSwitches().add((HolonSwitch) cps);
  883. }
  884. if (cps instanceof HolonBattery) {
  885. sN.getBatteries().add((HolonBattery) cps);
  886. }
  887. removeFromToHandle(cps.getId());
  888. AbstractCpsObject a;
  889. AbstractCpsObject b;
  890. for (CpsEdge edge : cps.getConnections()) {
  891. if (edge.isWorking()) {
  892. a = edge.getA();
  893. b = edge.getB();
  894. if (!(cps instanceof HolonSwitch)) {
  895. if (!(sN.getEdges().contains(edge))) {
  896. sN.getEdges().add(edge);
  897. }
  898. }
  899. if (cps instanceof HolonSwitch
  900. && ((HolonSwitch) cps).getState(timeStep)) {
  901. if (!(sN.getEdges().contains(edge))) {
  902. sN.getEdges().add(edge);
  903. }
  904. }
  905. if (!visited.contains(a.getId()) && legitState(cps)
  906. && !(a instanceof CpsUpperNode)) {
  907. sN = buildSubNet(a, visited, sN);
  908. }
  909. if (!visited.contains(b.getId()) && legitState(cps)
  910. && !(b instanceof CpsUpperNode)) {
  911. sN = buildSubNet(b, visited, sN);
  912. }
  913. if (a instanceof CpsUpperNode && a.getId() != cps.getId()) {
  914. edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
  915. checkForConnectedStates(b, (CpsUpperNode) a, edge);
  916. }
  917. if (b instanceof CpsUpperNode && b.getId() != cps.getId()) {
  918. edge.setConnected(CpsEdge.CON_UPPER_NODE_NOT_INSIDE);
  919. checkForConnectedStates(a, (CpsUpperNode) b, edge);
  920. }
  921. } else {
  922. brokenEdges.add(edge);
  923. }
  924. }
  925. return sN;
  926. }
  927. /**
  928. * is the Switch in a legitimate State.
  929. *
  930. * @param current
  931. * AbstractCpsObject
  932. * @return boolean
  933. */
  934. private boolean legitState(AbstractCpsObject current) {
  935. return !(current instanceof HolonSwitch)
  936. || ((HolonSwitch) current).getState(timeStep);
  937. }
  938. // /**
  939. // * ensures that objectsToHandle only contains HolonObjects.
  940. // */
  941. // public void cleanObjectsToHandle() {
  942. // for (int i = 0; i < objectsToHandle.size(); i++) {
  943. // if (!(objectsToHandle.get(i) instanceof HolonObject)) {
  944. // objectsToHandle.remove(i);
  945. // }
  946. // }
  947. // }
  948. /**
  949. * removes an Object that already has been handled.
  950. *
  951. * @param id
  952. * the Object ID
  953. */
  954. private void removeFromToHandle(int id) {
  955. for (int i = 0; i < objectsToHandle.size(); i++) {
  956. if (objectsToHandle.get(i).getId() == id) {
  957. objectsToHandle.remove(i);
  958. }
  959. }
  960. }
  961. /**
  962. * copies the data of an array of Objects.
  963. *
  964. * @param toCopy
  965. * the ArrayList of CpsObjects co Copy
  966. */
  967. private void copyObjects(ArrayList<AbstractCpsObject> toCopy) {
  968. for (AbstractCpsObject cps : toCopy) {
  969. if (cps instanceof CpsUpperNode) {
  970. copyObjects(((CpsUpperNode) cps).getNodes());
  971. } else {
  972. objectsToHandle.add(cps);
  973. }
  974. }
  975. }
  976. /**
  977. * Prints the Components auf all subnets.
  978. */
  979. private void printNetsToConsole() {
  980. for (int i = 0; i < subNets.size(); i++) {
  981. SubNet subNet = subNets.get(i);
  982. System.out.println("SUBNET NR:" + i);
  983. subNet.toString(timeStep);
  984. }
  985. }
  986. /**
  987. * Set the Canvas.
  988. *
  989. * @param can
  990. * the Canvas
  991. */
  992. public void setCanvas(MyCanvas can) {
  993. canvas = can;
  994. }
  995. /**
  996. * Reset all Data to the current state of the Model.
  997. */
  998. public void reset() {
  999. objectsToHandle = new ArrayList<>();
  1000. copyObjects(model.getObjectsOnCanvas());
  1001. flexDevicesTurnedOnThisTurn = new HashMap<>();
  1002. }
  1003. /**
  1004. * Resets the State of all Edges
  1005. */
  1006. private void resetEdges() {
  1007. for (CpsEdge e : brokenEdges) {
  1008. e.setWorkingState(true);
  1009. }
  1010. }
  1011. /**
  1012. * Resets the State for the whole Simulation Model
  1013. */
  1014. void resetSimulation() {
  1015. reset();
  1016. resetEdges();
  1017. }
  1018. /**
  1019. * Get all Subnets.
  1020. *
  1021. * @return all Subnets
  1022. */
  1023. public ArrayList<SubNet> getSubNets() {
  1024. return subNets;
  1025. }
  1026. /**
  1027. * Get broken Edges
  1028. */
  1029. // public ArrayList<CpsEdge> getBrokenEdges() {
  1030. // return brokenEdges;
  1031. // }
  1032. /**
  1033. * checks whether a given object is connected to an object inside the
  1034. * upperNode. if yes, the state for the edge is changed in "connected" or
  1035. * "not connected"
  1036. */
  1037. private void checkForConnectedStates(AbstractCpsObject cps,
  1038. CpsUpperNode cUNode, CpsEdge theEdge) {
  1039. AbstractCpsObject tmp;
  1040. for (CpsEdge edge : cps.getConnections()) {
  1041. if (edge.getA().getId() == cps.getId()) {
  1042. tmp = edge.getB();
  1043. } else {
  1044. tmp = edge.getA();
  1045. }
  1046. if (cUNode.getNodes().contains(tmp)) {
  1047. if (tmp instanceof CpsUpperNode) {
  1048. checkForConnectedStates(cps, (CpsUpperNode) tmp, theEdge);
  1049. } else {
  1050. theEdge.setConnected(CpsEdge.CON_UPPER_NODE_AND_INSIDE);
  1051. break;
  1052. }
  1053. }
  1054. }
  1055. }
  1056. public FlexiblePane getFlexiblePane() {
  1057. return flexPane;
  1058. }
  1059. void setFlexiblePane(FlexiblePane fp) {
  1060. flexPane = fp;
  1061. }
  1062. }