TargetStateAssembler.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. package classes.holonControlUnit;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import com.google.gson.Gson;
  6. import classes.holonControlUnit.OptimizationManager.OptimizationScheme;
  7. import classes.holonControlUnit.messages.MergeMsg;
  8. import classes.holonControlUnit.messages.Message;
  9. import classes.holonControlUnit.messages.OrderMsg;
  10. import classes.holonControlUnit.messages.StateMsg;
  11. public class TargetStateAssembler {
  12. private HolonControlUnit hcu;
  13. private float desiredPowerUsage = 100f;
  14. private OrderMsg order;
  15. // private HashMap<String, OrderMsg> ordersForSubholon;
  16. public TargetStateAssembler(HolonControlUnit hcu) {
  17. this.order = null;
  18. this.hcu = hcu;
  19. // this.ordersForSubholon = new HashMap<String, OrderMsg>();
  20. }
  21. public void assembleTargetState(int timeStep) {
  22. if(timeStep <= 1) {
  23. //for init
  24. this.desiredPowerUsage = this.hcu.getStateEstimator().getPredictedPowerUsage().get(0);
  25. } else if(this.order == null || this.order.getTimeStep() < timeStep-1) {
  26. this.desiredPowerUsage = 0f;
  27. } else {
  28. this.desiredPowerUsage = this.order.getDesiredPowerUsage();
  29. }
  30. // this.ordersForSubholon.clear();
  31. // System.out.println(this.hcu.getHolon().name+" opt scheme: "+this.hcu.getOptimizer().getOptimizationScheme());
  32. // System.out.println(this.hcu.getHolon().getUniqueID()+" power: "+this.hcu.getStateEstimator().getPowerUsage()+" des: "+this.desiredPowerUsage);
  33. //balance the sub holons
  34. OptimizationScheme optScheme = this.hcu.getOptimizer().getOptimizationScheme();
  35. switch(optScheme) {
  36. case COMFORT:
  37. assembleTargetStateComfort(timeStep);
  38. break;
  39. case MIN_COST:
  40. break;
  41. case ENERGY_CONSUMPTION:
  42. break;
  43. case STABILITY:
  44. assembleTargetStateStability(timeStep);
  45. break;
  46. case RECOVERY:
  47. assembleTargetStateRecovery(timeStep);
  48. break;
  49. default:
  50. System.err.println("Unknown optimization scheme in "+this.hcu.getHolon().getUniqueID());
  51. }
  52. this.hcu.getHierarchyController().propagateMergeReqToParent(timeStep-1);
  53. }
  54. private void assembleTargetStateComfort(int timeStep) {
  55. //overall power usage inside this holarchy
  56. float powerUsage = this.hcu.getStateEstimator().getPowerUsage();
  57. ArrayList<Float> predictedPowerUsage = this.hcu.getStateEstimator().getPredictedPowerUsage();
  58. if(predictedPowerUsage.size() < 1) {
  59. //no more iterations inside simulator
  60. return;
  61. }
  62. //check if this holon can run independent from parent without risking stability
  63. if(this.hcu.matchPowerRange(powerUsage, 0f, predictedPowerUsage, this.hcu.getOptimizer().getCurrentPowerThreshold())
  64. && this.hcu.getHolon().getParent().canRunIndependent(this.hcu.getHolon()) && this.hcu.getHolon().getLayer() > 1) {
  65. // System.out.println(this.hcu.getHolon().getUniqueID()+" can run independent");
  66. this.hcu.getHierarchyController().splitSuperHolon(timeStep);
  67. this.desiredPowerUsage = 0f;
  68. orderSubholonsPredictedPower(timeStep);
  69. return;
  70. }
  71. //powerUsage already matches desired value, everything as before
  72. if(this.hcu.matchPowerRange(powerUsage, this.desiredPowerUsage, this.hcu.getOptimizer().getCurrentPowerThreshold())) {
  73. // System.out.println(this.hcu.getHolon().getUniqueID()+" power usage as desired "+powerUsage);
  74. orderSubholonsPredictedPower(timeStep);
  75. return;
  76. }
  77. // System.out.println(this.hcu.getHolon().getUniqueID()+" power usage "+powerUsage+" not as desired "+this.desiredPowerUsage);
  78. float requiredPower = this.desiredPowerUsage - powerUsage;
  79. //find flexibility which matches required power
  80. float savedWithFlexibilities = this.hcu.getFlexMan().applyFlexibilities(powerUsage, requiredPower, predictedPowerUsage, timeStep);
  81. if(savedWithFlexibilities == requiredPower) {
  82. orderSubholonsPredictedPower(timeStep);
  83. return;
  84. }
  85. requiredPower -= savedWithFlexibilities;
  86. //go through merge requests from last iteration
  87. float savedByMerging = gothroughMergeReq(timeStep, powerUsage, requiredPower, predictedPowerUsage, OptimizationScheme.COMFORT);
  88. if(savedByMerging == requiredPower) {
  89. orderSubholonsPredictedPower(timeStep);
  90. return;
  91. }
  92. requiredPower -= savedByMerging;
  93. //look out for another superholon
  94. findNewSuperHolon(timeStep, powerUsage, predictedPowerUsage);
  95. //tell all holons to use a little more/less energy
  96. orderSubholonsRequiredPower(timeStep, powerUsage, requiredPower);
  97. }
  98. private void assembleTargetStateStability(int timeStep) {
  99. //overall power usage inside this holarchy
  100. float powerUsage = this.hcu.getStateEstimator().getPowerUsage();
  101. ArrayList<Float> predictedPowerUsage = this.hcu.getStateEstimator().getPredictedPowerUsage();
  102. if(predictedPowerUsage.size() < 1) {
  103. //no more iterations inside simulator
  104. return;
  105. }
  106. //powerUsage already matches desired value, everything as before
  107. if(this.hcu.matchPowerRange(powerUsage, this.desiredPowerUsage, this.hcu.getOptimizer().getCurrentPowerThreshold())) {
  108. // System.out.println(this.hcu.getHolon().getUniqueID()+" power usage as desired "+powerUsage);
  109. orderSubholonsPredictedPower(timeStep);
  110. return;
  111. }
  112. // System.out.println(this.hcu.getHolon().getUniqueID()+" power usage "+powerUsage+" not as desired "+this.desiredPowerUsage);
  113. float requiredPower = this.desiredPowerUsage - powerUsage;
  114. //find flexibility which matches required power
  115. float savedWithFlexibilities = this.hcu.getFlexMan().applyFlexibilities(powerUsage, requiredPower, predictedPowerUsage, timeStep);
  116. if(savedWithFlexibilities == requiredPower) {
  117. orderSubholonsPredictedPower(timeStep);
  118. return;
  119. }
  120. requiredPower -= savedWithFlexibilities;
  121. //go through merge requests from last iteration
  122. float savedByMerging = gothroughMergeReq(timeStep, powerUsage, requiredPower, predictedPowerUsage, OptimizationScheme.STABILITY);
  123. if(savedByMerging == requiredPower) {
  124. orderSubholonsPredictedPower(timeStep);
  125. return;
  126. }
  127. requiredPower -= savedByMerging;
  128. //look out for another superholon
  129. findNewSuperHolon(timeStep, powerUsage, predictedPowerUsage);
  130. //tell all holons to use a little more/less energy
  131. orderSubholonsRequiredPower(timeStep, powerUsage, requiredPower);
  132. }
  133. private void assembleTargetStateRecovery(int timeStep) {
  134. //overall power usage inside this holarchy
  135. float powerUsage = this.hcu.getStateEstimator().getPowerUsage();
  136. ArrayList<Float> predictedPowerUsage = this.hcu.getStateEstimator().getPredictedPowerUsage();
  137. if(predictedPowerUsage.size() < 1) {
  138. //no more iterations inside simulator
  139. return;
  140. }
  141. //powerUsage already matches desired value, everything as before
  142. if(this.hcu.matchPowerRange(powerUsage, this.desiredPowerUsage, this.hcu.getOptimizer().getCurrentPowerThreshold())) {
  143. // System.out.println(this.hcu.getHolon().getUniqueID()+" power usage as desired "+powerUsage);
  144. orderSubholonsPredictedPower(timeStep);
  145. return;
  146. }
  147. // System.out.println(this.hcu.getHolon().getUniqueID()+" power usage "+powerUsage+" not as desired "+this.desiredPowerUsage);
  148. float requiredPower = this.desiredPowerUsage - powerUsage;
  149. //find flexibility which matches required power
  150. float savedWithFlexibilities = this.hcu.getFlexMan().applyFlexibilities(powerUsage, requiredPower, predictedPowerUsage, timeStep);
  151. if(savedWithFlexibilities == requiredPower) {
  152. orderSubholonsPredictedPower(timeStep);
  153. return;
  154. }
  155. requiredPower -= savedWithFlexibilities;
  156. //go through merge requests from last iteration
  157. float savedByMerging = gothroughMergeReq(timeStep, powerUsage, requiredPower, predictedPowerUsage, OptimizationScheme.RECOVERY);
  158. if(savedByMerging == requiredPower) {
  159. orderSubholonsPredictedPower(timeStep);
  160. return;
  161. }
  162. requiredPower -= savedByMerging;
  163. // float p = this.hcu.getHolon().isPhysical ? this.hcu.getHolon().getHolonObject().getEnergyAtTimeStepFlex(timeStep) : 0f;
  164. // requiredPower = this.desiredPowerUsage - p;
  165. //split dysfunctional parts
  166. HashMap<String, StateMsg> childStates = this.hcu.getStateEstimator().getChildStates();
  167. List<List<String>> childPerm = getAllPermutations(List.copyOf(childStates.keySet()));
  168. HashMap<Float, List<String>> potChild = new HashMap<Float, List<String>>();
  169. for(List<String> l : childPerm) {
  170. //check how much power this subset of child would consume
  171. Float[] savings = new Float[predictedPowerUsage.size()+1];
  172. for(int i=0; i<savings.length; i++)
  173. savings[i] = 0f;
  174. for(String s : l) {
  175. StateMsg state = childStates.get(s);
  176. // if(!this.hcu.decreasesPowerUsage(List.of(savings), powerUsage, predictedPowerUsage, this.desiredPowerUsage))
  177. // break;
  178. savings[0] = savings[0] + state.getPowerUsage();
  179. for(int i=1; i<savings.length; i++) {
  180. savings[i] += state.getPredictedPowerUsage().get(i-1);
  181. }
  182. }
  183. if(this.hcu.decreasesPowerUsage(List.of(savings), powerUsage, predictedPowerUsage, this.desiredPowerUsage)) {
  184. float pu = 0f;
  185. for(int i=0; i<savings.length; i++)
  186. pu += savings[i];
  187. pu = pu/savings.length;
  188. if(potChild.containsKey(pu) && potChild.get(pu).size() >= l.size())
  189. continue;
  190. potChild.put(pu, l);
  191. }
  192. }
  193. //find subset of children with most fitting powerUsage
  194. float min = Float.MAX_VALUE;
  195. //the required power usage without any child holons
  196. float r = this.desiredPowerUsage - this.hcu.getHolon().getHolonObject().getEnergyAtTimeStepFlex(timeStep);
  197. for(float f : potChild.keySet()) {
  198. if(Math.abs(f+r) < Math.abs(min+r)) {
  199. min = f;
  200. }
  201. }
  202. //split all other subholons
  203. List<String> list = new ArrayList<String>();
  204. if(potChild.containsKey(min)) {
  205. list = potChild.get(min);
  206. }
  207. List<String> subs = List.copyOf(this.hcu.getHierarchyController().getSubHolons());
  208. for(String s : subs) {
  209. if(!list.contains(s)) {
  210. this.hcu.getHierarchyController().splitSubHolon(s, timeStep);
  211. // requiredPower -= childStates.getOrDefault(s, new StateMsg(0f, 0f, null, null)).getPowerUsage();
  212. }
  213. }
  214. requiredPower = r + min;
  215. if(requiredPower == 0) {
  216. //by removing child holons we have regained stability
  217. orderSubholonsPredictedPower(timeStep);
  218. return;
  219. }
  220. //Split from superholon?
  221. if(Math.abs(requiredPower) > Math.abs(powerUsage) && this.hcu.getHolon().getLayer() > 1) {
  222. // System.out.println("----"+requiredPower+" "+powerUsage);
  223. this.hcu.getHierarchyController().splitSuperHolon(timeStep);
  224. orderSubholonsRequiredPower(timeStep, powerUsage, 0f-powerUsage);
  225. return;
  226. }
  227. //look out for another superholon
  228. findNewSuperHolon(timeStep, powerUsage, predictedPowerUsage);
  229. //tell all holons to use a little more/less energy
  230. orderSubholonsRequiredPower(timeStep, powerUsage, requiredPower);
  231. }
  232. /**
  233. * go through all previously received merge requests from other holons
  234. * if there is a fitting one merge
  235. * @param timeStep
  236. * @param requiredPower
  237. * @return saved power
  238. */
  239. private float gothroughMergeReq(int timeStep, float currentPower, float requiredPower, ArrayList<Float> predictedPower,
  240. OptimizationScheme optScheme) {
  241. List<MergeMsg> requests = this.hcu.getHierarchyController().getMergeRequestsForTimeStep(timeStep-1);
  242. if(requests == null)
  243. return 0f;
  244. //store holon which would help decrease |requiredPower|
  245. ArrayList<MergeMsg> poten = new ArrayList<MergeMsg>();
  246. //find a perfect match or holon which would help decrease |requiredPower|
  247. for(MergeMsg req : requests) {
  248. float r = req.getPredictedPowerUsage().get(0); //since merge req is from timeStep-1
  249. String requester = req.getRequester();
  250. float newThroughput = req.getNetThroughput() + this.hcu.getStateEstimator().getNetThroughput();
  251. if(!this.hcu.getHierarchyController().canMerge(requester, newThroughput)) {
  252. //cannot merge with the requester
  253. continue;
  254. }
  255. // System.out.println(this.hcu.getHolon().getUniqueID()+" merge req "+req.getPower()+" "
  256. // +this.hcu.matchPowerRange(r, requiredPower, predictedPower, this.hcu.getOptimizer().getCurrentPowerThreshold()));
  257. if(this.hcu.matchPowerRange(r, requiredPower, predictedPower, this.hcu.getOptimizer().getCurrentPowerThreshold())) {
  258. //perfect match
  259. this.hcu.getHierarchyController().sendMergeAck(timeStep, req, true);
  260. // OrderMsg o = new OrderMsg(r, optScheme, timeStep);
  261. // this.ordersForSubholon.put(requester, o);
  262. requests.remove(req);
  263. return r;
  264. }
  265. // } else if( ((r < 0 && requiredPower < 0) || (r > 0 && requiredPower > 0))
  266. // && this.hcu.decreasesPowerUsage(req.getPredictedPowerUsage(), currentPower, predictedPower, requiredPower)) {
  267. //accepting this request would help this holon
  268. poten.add(req);
  269. // }
  270. }
  271. //go through all poten candidates and find most suiting subset
  272. //all candidates have either power < 0 or > 0
  273. if(poten.size() < 1)
  274. return 0f;
  275. List<List<MergeMsg>> potPermut = getAllPermutations(poten);
  276. HashMap<Float, List<MergeMsg>> potSavings = new HashMap<Float, List<MergeMsg>>();
  277. for(List<MergeMsg> l : potPermut) {
  278. //check how much power this subset of merges would save
  279. Float[] savings = new Float[predictedPower.size()];
  280. for(int i=0; i<savings.length; i++)
  281. savings[i] = 0f;
  282. for(MergeMsg m : l) {
  283. // if(!this.hcu.decreasesPowerUsage(List.of(savings), currentPower, predictedPower, requiredPower))
  284. // break;
  285. for(int i=0; i<savings.length; i++) {
  286. savings[i] = savings[i] + m.getPredictedPowerUsage().get(i);
  287. }
  288. }
  289. // System.out.println("l "+l+"\nsaving: "+savings[0]);
  290. if(this.hcu.decreasesPowerUsage(List.of(savings), currentPower, predictedPower, requiredPower)) {
  291. float s = 0f;
  292. for(int i=0; i<savings.length; i++)
  293. s += savings[i];
  294. s = s/savings.length; //average saving over the next time periods
  295. if(potSavings.containsKey(s) && potSavings.get(s).size() >= l.size())
  296. continue;
  297. potSavings.put(s, l);
  298. }
  299. }
  300. if(potSavings.size() < 1) {
  301. return 0f;
  302. }
  303. float min = Float.MAX_VALUE;
  304. for(float f : potSavings.keySet()) {
  305. // System.out.println(requiredPower+" "+currentPower+" "+min+" "+f+" "+Math.abs(requiredPower-f)+" < "+Math.abs(requiredPower-min));
  306. if(Math.abs(requiredPower-f) < Math.abs(requiredPower-min)) {
  307. min = f;
  308. }
  309. }
  310. // System.out.println("min "+min);
  311. // System.out.println(potSavings.keySet());
  312. //merge with all holons that are part of the subset with the max saving
  313. if(potSavings.containsKey(min)) {
  314. for(MergeMsg req : potSavings.get(min)) {
  315. // System.out.println("I wanna merge");
  316. // float r = req.getPower();
  317. // String requester = req.getRequester();
  318. this.hcu.getHierarchyController().sendMergeAck(timeStep, req, min == requiredPower);
  319. // OrderMsg o = new OrderMsg(r, optScheme, timeStep);
  320. // this.ordersForSubholon.put(requester, o);
  321. }
  322. //remove merge requests so they don't get propagated to super holon
  323. requests.removeAll(potSavings.get(min));
  324. return min;
  325. }
  326. return 0f;
  327. }
  328. private void findNewSuperHolon(int timeStep, float powerUsage, ArrayList<Float> predictedPowerUsage) {
  329. for(String physicalNeighbor : this.hcu.getHierarchyController().getPhysicalNeighborsFromOtherHolarchy()) {
  330. this.hcu.getHierarchyController().sendMergeReq(powerUsage, predictedPowerUsage, timeStep, physicalNeighbor);
  331. }
  332. }
  333. private void orderSubholonsPredictedPower(int timeStep) {
  334. HashMap<String, StateMsg> childStates = this.hcu.getStateEstimator().getChildStates();
  335. Gson gson = this.hcu.getCommunicator().getGson();
  336. for(String s : childStates.keySet()) {
  337. OrderMsg o = new OrderMsg(childStates.get(s).getPredictedPowerUsage().get(0), timeStep);
  338. // this.ordersForSubholon.put(s, o);
  339. this.hcu.getCommunicator().sendMsg(s, Message.Type.ORDER, gson.toJson(o));
  340. }
  341. }
  342. /**
  343. * compute a new target value for all subholons
  344. * "fairness": all subholons get same target value
  345. * @param timeStep
  346. * @param powerUsage
  347. * @param requiredPower
  348. * @param optScheme
  349. */
  350. private void orderSubholonsRequiredPower(int timeStep, float powerUsage, float requiredPower) {
  351. // float p = this.hcu.getHolon().isPhysical ? this.hcu.getHolon().getHolonObject().getEnergyAtTimeStep(timeStep) : 0f;
  352. // requiredPower = this.desiredPowerUsage - p;
  353. // HashMap<String, StateMsg> childStates = this.hcu.getStateEstimator().getChildStates();
  354. Gson gson = this.hcu.getCommunicator().getGson();
  355. float opt = - requiredPower/this.hcu.getHierarchyController().getSubHolons().size(); //(childStates.size() - this.ordersForSubholon.size() != 0 ? childStates.size() - this.ordersForSubholon.size() : 1);
  356. for(String s : this.hcu.getHierarchyController().getSubHolons()) {
  357. //order for subholon
  358. // if(this.ordersForSubholon.containsKey(s))
  359. // continue;
  360. OrderMsg o = new OrderMsg(opt, timeStep);
  361. // this.ordersForSubholon.put(s, o);
  362. //send order to subholon
  363. this.hcu.getCommunicator().sendMsg(s, Message.Type.ORDER, gson.toJson(o));
  364. }
  365. //send order to subholons
  366. // for(String s : this.ordersForSubholon.keySet()) {
  367. // if(this.hcu.getHierarchyController().getSubHolons().contains(s))
  368. // this.hcu.getCommunicator().sendMsg(s, Message.Type.ORDER, gson.toJson(this.ordersForSubholon.get(s)));
  369. // }
  370. }
  371. private <T> List<List<T>> getAllPermutations(List<T> set){
  372. List<List<T>> out = new ArrayList<List<T>>();
  373. for(int i=0; i<set.size(); i++) {
  374. for(int j=i; j<set.size(); j++) {
  375. List<T> l = new ArrayList<T>();
  376. l.addAll(set.subList(i, j+1));
  377. out.add(l);
  378. }
  379. }
  380. return out;
  381. }
  382. public float getDesiredPowerUsage() {
  383. return this.desiredPowerUsage;
  384. }
  385. public void setOrder(OrderMsg order, String sender) {
  386. // System.out.println(this.hcu.getHolon().getUniqueID()+" received order "+order);
  387. if(sender.equals(this.hcu.getHierarchyController().getSuperHolon())) {
  388. this.order = order;
  389. }
  390. }
  391. }