@Override public org.powertac.common.CapacityProfile getCapacityProfile(Tariff tariff) { double usageSign = bundle.getPowerType().isConsumption() ? +1 : -1; // New code: shifted prediction - correct for tariff-eval purposes // =============================================================== double[] newForecast; // new code HashMap<CapacityOriginator, double[]> originator2usage = new HashMap<>(); for (CapacityOriginator capacityOriginator : bundle.getCapacityOriginators()) { double[] usageForecast = new double[CapacityProfile.NUM_TIMESLOTS]; // BUG FIX: this function is called from forecastCost() and used // by TariffEvaluationHelper, which assumes the forcast starts // at the next timeslot CapacityProfile forecast = capacityOriginator.getForecastForNextTimeslot(); for (int i = 0; i < CapacityProfile.NUM_TIMESLOTS; ++i) { double hourlyUsage = usageSign * forecast.getCapacity(i); usageForecast[i] = hourlyUsage; // don't divide yet / bundle.getPopulation(); } originator2usage.put(capacityOriginator, usageForecast); } // Refactored the following code for LearningUtilityOptimizer - shift profile // // create dummy subscription for the above usage vector: // 1 population member under 'tariff', (consuming the sum // of the originators' usage) TariffSubscription dummySubscription = new DummyTariffSubscription(getCustomerInfo(), tariff); newForecast = adjustForecastPerTariff(originator2usage, dummySubscription, bundle); double[] result = newForecast; Instant start = service.getTimeService().getCurrentTime().plus(TimeService.HOUR); return new org.powertac.common.CapacityProfile(result, start); }
DefaultUtilityOptimizer(CustomerStructure customerStructure, List<CapacityBundle> bundles) { this.customerStructure = customerStructure; this.capacityBundles = bundles; this.evaluatorMap = new HashMap<>(); // create evaluation wrappers and tariff evaluators for each bundle for (CapacityBundle bundle : bundles) { TariffSubscriberStructure subStructure = bundle.getSubscriberStructure(); TariffEvaluator evaluator = new TariffEvaluator(new TariffEvaluationWrapper(bundle)) .withChunkSize(Math.max(1, bundle.getPopulation() / 1000)) .withTariffSwitchFactor(subStructure.getTariffSwitchFactor()) .withPreferredContractDuration(subStructure.getExpectedDuration()) .withInconvenienceWeight(subStructure.getInconvenienceWeight()) .withRationality(subStructure.getLogitChoiceRationality()) .withEvaluateAllTariffs(true); evaluator.initializeCostFactors( subStructure.getExpMeanPriceWeight(), subStructure.getMaxValuePriceWeight(), subStructure.getRealizedPriceWeight(), subStructure.getTariffVolumeThreshold()); evaluator.initializeInconvenienceFactors( subStructure.getTouFactor(), subStructure.getTieredRateFactor(), subStructure.getVariablePricingFactor(), subStructure.getInterruptibilityFactor()); evaluatorMap.put(bundle, evaluator); } }
// @StateChange private void subscribe(Tariff tariff, CapacityBundle bundle, int customerCount, boolean verbose) { getTariffMarket().subscribeToTariff(tariff, bundle.getCustomerInfo(), customerCount); if (verbose) { log.info( bundle.getName() + ": Subscribed " + customerCount + " customers to tariff " + tariff.getId() + " successfully"); } }
// Tariff Evaluation -------------------------------- @Override public void evaluateTariffs() { for (CapacityBundle bundle : capacityBundles) { TariffEvaluator evaluator = evaluatorMap.get(bundle); if (bundle.getSubscriberStructure().getInertiaDistribution() != null) { evaluator.withInertia( bundle.getSubscriberStructure().getInertiaDistribution().drawSample()); } else { log.warn("no inertia distro, using default value 0.7"); evaluator.withInertia(0.7); } evaluator.evaluateTariffs(); } }
@Override public void initialize(CustomerStructure structure) { log.info("Initializing customer " + customerStructure.name); NodeList capacityBundleNodes = customerStructure.getConfigXml().getElementsByTagName("capacityBundle"); for (int i = 0; i < capacityBundleNodes.getLength(); ++i) { Element capacityBundleElement = (Element) capacityBundleNodes.item(i); CapacityBundle capacityBundle = createCapacityBundle(structure, capacityBundleElement); capacityBundle.initialize(structure, capacityBundleElement); capacityBundles.add(capacityBundle); customerRepo.add(capacityBundle.getCustomerInfo()); } utilityOptimizer = createUtilityOptimizer(structure, capacityBundles); utilityOptimizer.initialize(); log.info("Successfully initialized customer " + customerStructure.name); }
private double useCapacity(TariffSubscription subscription, CapacityBundle bundle) { double capacity = 0; for (CapacityOriginator capacityOriginator : bundle.getCapacityOriginators()) { capacity += capacityOriginator.useCapacity(subscription); } return capacity; }
/** * Is it correct to sum inconveniences over originators? currently every shifting customer has 1 * originator so this doesn't matter, but it might change in the future. */ @Override public double getShiftingInconvenienceFactor(Tariff tariff) { double inconv = 0; for (CapacityOriginator capacityOriginator : bundle.getCapacityOriginators()) { inconv += capacityOriginator.getShiftingInconvenienceFactor(tariff); } return inconv; }
/** @Override hook */ protected void subscribeDefault() { for (CapacityBundle bundle : capacityBundles) { PowerType powerType = bundle.getPowerType(); if (getTariffMarket().getDefaultTariff(powerType) != null) { log.info( bundle.getName() + ": Subscribing " + bundle.getPopulation() + " customers to default " + powerType + " tariff"); subscribe( getTariffMarket().getDefaultTariff(powerType), bundle, bundle.getPopulation(), false); } else { log.info( bundle.getName() + ": No default tariff for power type " + powerType + "; trying generic type"); PowerType genericType = powerType.getGenericType(); if (getTariffMarket().getDefaultTariff(genericType) == null) { log.error( bundle.getName() + ": No default tariff for generic power type " + genericType + " either!"); } else { log.info( bundle.getName() + ": Subscribing " + bundle.getPopulation() + " customers to default " + genericType + " tariff"); subscribe( getTariffMarket().getDefaultTariff(genericType), bundle, bundle.getPopulation(), false); } } } }
/** * HACK, accessed from inner class, overriden from derived class * * <p>sum all originators' usage arrays * * @param originator2usage * @param dummySubscription * @param bundle * @return */ public double[] adjustForecastPerTariff( HashMap<CapacityOriginator, double[]> originator2usage, TariffSubscription dummySubscription, CapacityBundle bundle) { // sum all originators' usage arrays double[] result = new double[originator2usage.values().iterator().next().length]; for (double[] usage : originator2usage.values()) { for (int i = 0; i < result.length; ++i) { result[i] += usage[i] / bundle.getPopulation(); } } return result; }
private void usePower(Timeslot timeslot) { for (CapacityBundle bundle : capacityBundles) { List<TariffSubscription> subscriptions = getTariffSubscriptionRepo().findActiveSubscriptionsForCustomer(bundle.getCustomerInfo()); double totalCapacity = 0.0; double totalUsageCharge = 0.0; for (TariffSubscription subscription : subscriptions) { double usageSign = bundle.getPowerType().isConsumption() ? +1 : -1; double currCapacity = usageSign * useCapacity(subscription, bundle); if (Config.getInstance().isUsageChargesLogging()) { double charge = subscription .getTariff() .getUsageCharge(currCapacity, subscription.getTotalUsage(), false); totalUsageCharge += charge; } subscription.usePower(currCapacity); totalCapacity += currCapacity; } log.info( bundle.getName() + ": Total " + bundle.getPowerType() + " capacity for timeslot " + timeslot.getSerialNumber() + " = " + totalCapacity); logUsageCharges( bundle.getName() + ": Total " + bundle.getPowerType() + " usage charge for timeslot " + timeslot.getSerialNumber() + " = " + totalUsageCharge); } }
@Override public CustomerInfo getCustomerInfo() { return bundle.getCustomerInfo(); }
TariffEvaluationWrapper(CapacityBundle bundle) { this.bundle = bundle; subStructure = bundle.getSubscriberStructure(); }