package holeg.algorithm.objective_function; import java.util.Locale; import java.util.logging.Logger; import holeg.model.Holon; import holeg.model.HolonObject; import holeg.model.Model; import holeg.utility.math.decimal.Sampler; public class TopologieObjectiveFunction { private static final Logger log = Logger.getLogger(TopologieObjectiveFunction.class.getName()); //Parameters //weight for f_g(H) static double w_eb = 0.2, w_max = 0.5, w_holon= 0.1, w_selection = .1, w_grid = 0.1; //--> f_eb parameter /** * Maximum Energie Difference(kappa) */ static double k_eb = 5000.f; /** * Maximum when all on Energie Difference(kappa) */ static double k_max = 10.f; static double lambda_max = 10.; //--> f_holon parameter /** * maximum penalty from holon element distribution */ static double k_holon= 4000; //--> f_selection paramaeter; /** * average Maximum Cost for selction(kappa) of switch and elements. */ static double k_selection = 200000; static double cost_switch = 3000; private static double cost_of_cable_per_meter = 6; //--> f_grid parameter /** * The avergae shortest path maximum length -> kappa for the squash function */ static double k_avg_shortest_path = 1600; //Disjpijoint path cant have zero as output it starts with the value 1 static double centerValue_disjoint_path = 1.0; static double k_disjoint_path = 2.4; static double lambda_avg_shortest_path = 10; static double lambda_disjoint_path = 10; static double k_grid = lambda_avg_shortest_path;// + lambda_disjoint_path; //pre-calculated parameters for partial function terms: /** * Pre calculated for the squash function *
* {@link TopologieObjectiveFunction#squash} */ static double squash_subtract = 1.0f / (1.f + (float) Math.exp(5.0)); static double range_for_k_avg_shortest_path = range(k_avg_shortest_path); static double range_for_k_disjoint_path = range(k_disjoint_path - centerValue_disjoint_path); public static Sampler averageLog = new Sampler(); static boolean useLog = false; static { //init checkParameter(); } /** * Check parameter Setting and print error when wrong values are put in. * Here should all invariants be placed to be checked on initialization. */ private static void checkParameter() { if(!(Math.abs(w_eb + w_holon + w_selection + w_grid + w_max - 1) < 0.001)) { System.err.println("ParameterError in ObjectiveFunction: Sum of all weights should be 1"); } } /** * ObjectifeFunction by Carlos. * Function computes f_g: * f_g = w1 * squash(f_eb, k1) + w2 * squash(f_state, k2) + w3 * squash(f_pro, k3) + w4 * squash(f_perf, k4) + w5 * squash(f_holon, k5) * * * squash is the squashing function {@link TopologieObjectiveFunction#squash} * * * @param moreInformation if more prints should be made * @return f_g value between 0 and 100 */ static public float getFitnessValueForState(Model model, int amountOfAddedSwitch, double addedCableMeters, boolean moreInformation) { int holonCount = model.holons.size(); //Calculate f_eb the penalty for unbalenced energy in the network double f_eb = 0; for(Holon holon : model.holons) { //abs f_eb += Math.abs(holon.getTotalConsumption() - holon.getTotalProduction()); } //Average f_eb /= holonCount; double f_maximum = 0; for(Holon net : model.holons) { double prod = net.getTotalProduction(); double con = net.getTotalConsumption(); if(prod == 0 || con == 0) { f_maximum += lambda_max; }else { f_maximum += lambda_max * (Math.abs(prod - con)/Math.max(prod, con)); } } //Average? f_maximum /= holonCount; //calculate f_holon double f_holon = 0; for(Holon net : model.holons) { double f_elements_deviation_production = net.getDeviationInProductionInNetworkForHolonObjects(); double f_elements_deviation_consumption = net.getDeviationInConsumptionInNetworkForHolonObjects(); double f_element = f_elements_deviation_production+f_elements_deviation_consumption; f_holon += f_element; } f_holon /= holonCount; //calculating f_selection double f_selection = calculateTopologieCost(model, amountOfAddedSwitch, addedCableMeters); //if(moreInformation)LOGGER.info("CostForWildcards:" + cost + ", CostSwitches(#" + amountOfAddedSwitch +"):" + cost_switch * amountOfAddedSwitch + ", CostCables(" +addedCableMeters+ "m):" + cost_of_cable_per_meter * addedCableMeters); //calculating f_grid double f_grid = 0; //each network is a holon for(Holon net : model.holons) { GraphMetrics.Graph G = GraphMetrics.convertDecoratedNetworkToGraph(model, net); //We have to penalize single Networks; if(G.V.length <= 1 || G.S.length <= 1) { f_grid += lambda_avg_shortest_path;// + lambda_disjoint_path; continue; } double avgShortestPath = GraphMetrics.averageShortestDistance(G); //double disjpointPaths = GraphMetrics.averageEdgeDisjointPathProblem(G); if(useLog) { averageLog.addSample("avgShortestPath", (float)avgShortestPath); } f_grid += avgShortestPathPenalty(avgShortestPath);// + disjoinPathPenalty(disjpointPaths); } //take average to encourage splitting f_grid /= holonCount; if(moreInformation) { printWeightedValues(f_eb, f_maximum, f_holon, f_selection, f_grid); if(useLog) { log.info(averageLog.toString()); } } //printUnsquashedValues(f_eb, f_maximum, f_holon, f_selection, f_grid); if(useLog) { averageLog.addSample("Unsquashed f_eb", (float)f_eb); averageLog.addSample("Unsquashed f_maximum", (float)f_maximum); averageLog.addSample("Unsquashed f_holon", (float)f_holon); averageLog.addSample("Unsquashed f_selection", (float)f_selection); averageLog.addSample("Unsquashed f_grid", (float)f_grid); } return (float) (w_eb * squash(f_eb, k_eb) + w_max * squash(f_maximum, k_max) + w_holon * squash(f_holon, k_holon) + w_selection * squash(f_selection, k_selection) + w_grid * squash(f_grid, k_grid)); } public static double calculateTopologieCost(Model model, int amountOfAddedSwitch, double addedCableMeters) { double cost = calculateWildcardCost(model); cost += calculateAddedSwitchCost(amountOfAddedSwitch); cost += calculateAddedCableCost(addedCableMeters); return cost; } public static double calculateAddedCableCost(double addedCableMeters) { return cost_of_cable_per_meter * addedCableMeters; } public static double calculateAddedSwitchCost(int amountOfAddedSwitch) { return cost_switch * amountOfAddedSwitch; } public static double calculateWildcardCost(Model model) { double cost = 0; for(Holon net : model.holons) { for(HolonObject hO : net.holonObjects) { if(hO.getName().contains("Wildcard")){ if(hO.getName().length() > 9) { String costString = hO.getName().substring(9); cost += Double.parseDouble(costString); } } } } return cost; } private static String doubleToString(double value) { return String.format (Locale.US, "%.2f", value); } @SuppressWarnings("unused") private static double disjoinPathPenalty(double value) { return -(2.0 * lambda_disjoint_path) / (1 + Math.exp(- (value - centerValue_disjoint_path)/ range_for_k_disjoint_path)) + (2.0 * lambda_disjoint_path); } private static double avgShortestPathPenalty(double value) { return (2.0 * lambda_avg_shortest_path) / (1 + Math.exp(- value/ range_for_k_avg_shortest_path)) - lambda_avg_shortest_path; } /** * Attention Math.log calcultae ln not log * @param kappa * @return */ private static double range(double kappa) { return - kappa / Math.log(Math.pow(2.0, 0.05) - 1.0 ); } /** * The squashing function in paper * @param x the input * @param kappa the corresponding kappa * @return */ static public double squash(double x, double kappa) { return 100.f/(1.0f + Math.exp(-(10.f * (x - kappa/2.f))/ kappa)) - squash_subtract; } /** * f_sup in paper * @param supply from 0 to 1 * @return */ static public double supplyPenalty(double supply) { double supplyPercentage = 100 * supply; return (supplyPercentage < 100) ? -0.5 * supplyPercentage + 50: supplyPercentage - 100; } static void printWeightedValues(double f_eb, double f_maximum, double f_holon, double f_selection, double f_grid){ log.info("==================================================================="); log.info(" f_eb: " + f_eb + ", k_eb: " + k_eb + ", w_eb: " + w_eb); log.info(" squash(f_eb, k_eb): " + doubleToString(squash(f_eb, k_eb))); log.info(" w_eb * squash(f_eb, k_eb): " + doubleToString(w_eb * squash(f_eb, k_eb))); log.info("==================================================================="); log.info(" f_maximum: " + f_maximum + ", k_max: " + k_max + ", w_max: " + w_max); log.info(" squash(f_maximum, k_max): " + doubleToString(squash(f_maximum, k_max))); log.info(" w_max * squash(f_maximum, k_max): " + doubleToString(w_max * squash(f_maximum, k_max))); log.info("==================================================================="); log.info(" f_selection: " + f_selection + ", k_selection: " + k_selection + ", w_selection: " + w_selection); log.info(" squash(f_selection, k_selection): " + doubleToString(squash(f_selection, k_selection))); log.info(" w_selection * squash(f_selection, k_selection): " + doubleToString(w_selection * squash(f_selection, k_selection))); log.info("==================================================================="); log.info(" f_holon: " + f_holon + ", k_holon: " + k_holon + ", w_holon: " + w_holon); log.info(" squash(f_holon, k_holon): " + doubleToString(squash(f_holon, k_holon))); log.info(" w_holon * squash(f_holon, k_holon): " + doubleToString(w_holon * squash(f_holon, k_holon))); log.info("==================================================================="); log.info(" f_grid: " + f_grid + ", k_grid: " + k_grid + ", w_grid: " + w_grid); log.info(" squash(f_grid, k_grid): " + doubleToString(squash(f_grid, k_grid))); log.info(" w_grid * squash(f_grid, k_grid): " + doubleToString(w_grid * squash(f_grid, k_grid))); log.info("==================================================================="); } static void printUnsquashedValues(double f_eb, double f_maximum, double f_holon, double f_selection, double f_grid){ System.out.print(" f_eb(" + f_eb + ") "); System.out.print(" f_maximum(" + f_maximum + ") "); System.out.print(" f_holon(" + f_holon + ") "); System.out.print(" f_selection(" + f_selection + ") "); log.info(" f_grid(" + f_grid + ") "); } }