package holeg.algorithm.objective_function; import holeg.model.Flexibility; import holeg.model.Holon; import holeg.model.HolonElement.Priority; import holeg.model.HolonObject; import holeg.model.Model; import java.util.logging.Logger; public class ObjectiveFunctionByCarlos { // Parameters private static final Logger log = Logger.getLogger(ObjectiveFunctionByCarlos.class.getName()); static double w_eb = .3, w_state = .3, w_pro = .2, w_perf = .1, w_holon = .1; static double k_eb = 750000.f, k_state = 20000, k_pro = 3000, k_perf = 15000, k_holon = 200000; // theta for f_pro static double theta = 3; // kappas for f_perf: static double kappa_f_unre = 120; static double kappa_f_cool = 60 * 60 * 24; static double kappa_f_dur = 60 * 60; // lambdas for f_perf: static double lambda_f_unre = 10; static double lambda_f_cool = 10; static double lambda_f_dur = 10; static double lambda_f_change = 1000; // pre-calculated parameters for partial function terms: /** * Pre calculated for the squash function
{@link ObjectiveFunctionByCarlos#squash} */ static double squash_subtract = 100.f / (1.f + (float) Math.exp(5.0)); static double range_for_kappa_f_unre = range(kappa_f_unre); static double range_for_kappa_f_cool = range(kappa_f_cool); static double range_for_kappa_f_dur = range(kappa_f_dur); 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() { boolean parameterSumOne = Math.abs(w_eb + w_state + w_pro + w_perf + w_holon - 1) < 0.001; if (!parameterSumOne) { log.warning("ParameterError in ObjectiveFunction: w1 + w2 + w3 + w4 + w5 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 ObjectiveFunctionByCarlos#squash} * * @return f_g value between 0 and 100 */ static public double getFitnessValueForState(Model model) { // Calculate f_eb the penalty for unbalenced energy in the network double f_eb = 0; // sum over all objects for (Holon holon : model.holons) { double netEnergyDifference = holon.holonObjects.stream() .map(hO -> Math.abs(hO.getActualEnergy())).reduce(0.0f, Float::sum); f_eb += netEnergyDifference; } // Calculate f_state the penalty function for the supply state double f_state = 0; for (Holon holon : model.holons) { f_state += holon.holonObjects.stream() .filter(hO -> hO.getState() != HolonObject.HolonObjectState.PRODUCER) .map(HolonObject::getSupplyBarPercentage).reduce(0.f, Float::sum); } // calculate f_pro the penalty function for priority usage // for each active flexibility punish double f_pro = model.getAllFlexibilities().stream() .filter(flex -> flex.getState().equals(Flexibility.FlexState.IN_USE)) .map(flex -> Math.pow(theta, priorityToDouble(flex.getElement().getPriority())) - 1.0) .reduce(0.0, Double::sum); // calculate f_perf the penalty function for the quality of a flexibility used // and the subfuction f_unre, f_cool, f_dur double f_perf = 0; for (Flexibility flex : model.getAllFlexibilities().stream() .filter(flex -> flex.getState().equals(Flexibility.FlexState.IN_USE)).toList()) { double f_unre = unresponsivnessPenalty(flex.getSpeed()); double f_cool = cooldownPenalty(flex.getCooldown()); double f_dur = durationPenalty(flex.getDuration()); f_perf += f_unre + f_cool + f_dur; } // 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.getDeviationInProductionInNetworkForHolonObjects(); double f_flexibility_deviation_consumption = net.getDeviationInFlexibilityConsumption(); double f_flexibility_deviation_production = net.getDeviationInFlexibilityProduction(); double con = net.getTotalConsumption(); double prod = net.getTotalProduction(); double flexcapProd = net.getFlexibilityProductionCapacity(); double flexcapCon = net.getFlexibilityConsumptionCapacity(); double f_change_positive = lambda_f_change - lambda_f_change * Math.min(1, (con > 0.0) ? flexcapProd / con : 1.0); double f_change_negativ = lambda_f_change - lambda_f_change * Math.min(1, (prod > 0.0) ? flexcapCon / prod : 1.0); double f_element = f_elements_deviation_production + f_elements_deviation_consumption; double f_flexibility = f_flexibility_deviation_consumption + f_flexibility_deviation_production; double f_change = f_change_positive + f_change_negativ; f_holon += f_element + f_flexibility + f_change; } double q1 = squash(f_eb, k_eb); double q2 = squash(f_state, k_state); double q3 = squash(f_pro, k_pro); double q4 = squash(f_perf, k_perf); double q5 = squash(f_holon, k_holon); log.finer("f_eb= " + f_eb + " f_state= " + f_state + " f_pro= " + f_pro + " f_perf= " + f_perf + " f_holon= " + f_holon + " q1= " + q1 + " q2= " + q2 + " q3= " + q3 + " q4= " + q4 + " q5= " + q5); return w_eb * q1 + w_state * q2 + w_pro * q3 + w_perf * q4 + w_holon * q5; } /** * The squashing function in paper * * @param x the input * @param kappa the corresponding kappa */ 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 */ static public double supplyPenalty(double supply) { double supplyPercentage = 100 * supply; // double test = (supplyPercentage < 100) ? -0.5 * supplyPercentage + 50: // supplyPercentage - 100; return (supplyPercentage < 100) ? -0.5 * supplyPercentage + 50 : supplyPercentage - 100; } private static double priorityToDouble(Priority priority) { return switch (priority) { case Essential -> 3.; case High -> 2.; case Medium -> 1.; default -> 0.; }; } /** * Attention Math.log calcultae ln not log */ private static double range(double kappa) { return -kappa / Math.log(Math.pow(2.0, 0.05) - 1.0); } /** * f_unre */ private static double unresponsivnessPenalty(double unresponsiv) { return (2.0 * lambda_f_unre) / (1 + Math.exp(-unresponsiv / range_for_kappa_f_unre)) - lambda_f_unre; } /** * f_cool */ private static double cooldownPenalty(double cooldown) { return (2.0 * lambda_f_cool) / (1 + Math.exp(-cooldown / range_for_kappa_f_cool)) - lambda_f_cool; } private static double durationPenalty(double duration) { double lambda_dur_times2 = 2.0 * lambda_f_dur; return -lambda_dur_times2 / (1 + Math.exp(-duration / range_for_kappa_f_dur)) + lambda_dur_times2; } }