SimulationManager.java 35 KB

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