All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.powertac.householdcustomer.customers.Village Maven / Gradle / Ivy

/*
 * Copyright 2009-2011 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an
 * "AS IS" BASIS,  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package org.powertac.householdcustomer.customers;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Properties;
import java.util.Random;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.joda.time.Instant;
import org.powertac.common.AbstractCustomer;
import org.powertac.common.CustomerInfo;
import org.powertac.common.Tariff;
import org.powertac.common.TariffSubscription;
import org.powertac.common.TimeService;
import org.powertac.common.Timeslot;
import org.powertac.common.configurations.HouseholdConstants;
import org.powertac.common.enumerations.PowerType;
import org.powertac.common.repo.TimeslotRepo;
import org.powertac.common.spring.SpringApplicationContext;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * The village domain class in this first version is a set of households that comprise a small
 * village that consumes agreggated energy by the appliances installed in each household.Later on
 * other types of building will be added.
 * @author Antonios Chrysopoulos
 * @version 1, 13/02/2011
 */
public class Village extends AbstractCustomer
{

  /**
   * logger for trace logging -- use log.info(), log.warn(), and log.error() appropriately. Use
   * log.debug() for output you want to see in testing or debugging.
   */
  static protected Logger log = Logger.getLogger(Village.class.getName());

  @Autowired
  TimeService timeService;

  @Autowired
  TimeslotRepo timeslotRepo;

  /**
   * These are the vectors containing aggregated each day's base load from the appliances installed
   * inside the households of each type.
   **/
  Vector> aggDailyBaseLoadNS = new Vector>();
  Vector> aggDailyBaseLoadRaS = new Vector>();
  Vector> aggDailyBaseLoadReS = new Vector>();
  Vector> aggDailyBaseLoadSS = new Vector>();

  /**
   * These are the vectors containing aggregated each day's controllable load from the appliances
   * installed inside the households.
   **/
  Vector> aggDailyControllableLoadNS = new Vector>();
  Vector> aggDailyControllableLoadRaS = new Vector>();
  Vector> aggDailyControllableLoadReS = new Vector>();
  Vector> aggDailyControllableLoadSS = new Vector>();

  /**
   * These are the agreggated vectors containing each day's base load of all the households in
   * hours.
   **/
  Vector> aggDailyBaseLoadInHoursNS = new Vector>();
  Vector> aggDailyBaseLoadInHoursRaS = new Vector>();
  Vector> aggDailyBaseLoadInHoursReS = new Vector>();
  Vector> aggDailyBaseLoadInHoursSS = new Vector>();

  /**
   * These are the agreggated vectors containing each day's controllable load of all the households
   * in hours.
   **/
  Vector> aggDailyControllableLoadInHoursNS = new Vector>();
  Vector> aggDailyControllableLoadInHoursRaS = new Vector>();
  Vector> aggDailyControllableLoadInHoursReS = new Vector>();
  Vector> aggDailyControllableLoadInHoursSS = new Vector>();

  /**
   * This is an vector containing the days of the competition that the household model will use in
   * order to check which of the tariffs that are available at any given moment are the optimal for
   * their consumption or production.
   **/
  Vector daysList = new Vector();

  /**
   * This variable is utilized for the creation of the random numbers and is taken from the service.
   */
  Random gen;

  /** This is the constructor function of the Village customer */
  public Village (CustomerInfo customerInfo)
  {
    super(customerInfo);

    timeslotRepo = (TimeslotRepo) SpringApplicationContext.getBean("timeslotRepo");
    timeService = (TimeService) SpringApplicationContext.getBean("timeService");
  }

  /**
   * These vectors contain the houses of type in the village. There are 4 types available: 1) Not
   * Shifting Houses: They do not change the tariff subscriptions during the game. 2) Randomly
   * Shifting Houses: They change their tariff subscriptions in a random way. 3) Regularly Shifting
   * Houses: They change their tariff subscriptions during the game in regular time periods. 4)
   * Smart Shifting Houses: They change their tariff subscriptions in a smart way in order to
   * minimize their costs.
   */
  Vector notShiftingHouses = new Vector();
  Vector randomlyShiftingHouses = new Vector();
  Vector regularlyShiftingHouses = new Vector();
  Vector smartShiftingHouses = new Vector();

  /**
   * This is the initialization function. It uses the variable values for the configuration file to
   * create the village with its households and then fill them with persons and appliances.
   * @param conf
   * @param gen
   */
  public void initialize (Properties conf, Random generator)
  {
    // Initializing variables

    int nshouses = Integer.parseInt(conf.getProperty("NotShiftingCustomers"));
    int rashouses = Integer.parseInt(conf.getProperty("RegularlyShiftingCustomers"));
    int reshouses = Integer.parseInt(conf.getProperty("RandomlyShiftingCustomers"));
    int sshouses = Integer.parseInt(conf.getProperty("SmartShiftingCustomers"));
    int days = Integer.parseInt(conf.getProperty("PublicVacationDuration"));

    gen = generator;

    createCostEstimationDaysList(HouseholdConstants.RANDOM_DAYS_NUMBER);

    Vector publicVacationVector = createPublicVacationVector(days);

    for (int i = 0; i < nshouses; i++) {
      log.info("Initializing " + customerInfo.toString() + " NSHouse " + i);
      Household hh = new Household();
      hh.initialize(customerInfo.toString() + " NSHouse" + i, conf, publicVacationVector, gen);
      notShiftingHouses.add(hh);
      hh.householdOf = this;
    }

    for (int i = 0; i < rashouses; i++) {
      log.info("Initializing " + customerInfo.toString() + " RaSHouse " + i);
      Household hh = new Household();
      hh.initialize(customerInfo.toString() + " RaSHouse" + i, conf, publicVacationVector, gen);
      randomlyShiftingHouses.add(hh);
      hh.householdOf = this;
    }

    for (int i = 0; i < reshouses; i++) {
      log.info("Initializing " + customerInfo.toString() + " ReSHouse " + i);
      Household hh = new Household();
      hh.initialize(customerInfo.toString() + " ReSHouse" + i, conf, publicVacationVector, gen);
      regularlyShiftingHouses.add(hh);
      hh.householdOf = this;
    }

    for (int i = 0; i < sshouses; i++) {
      log.info("Initializing " + customerInfo.toString() + " SSHouse " + i);
      Household hh = new Household();
      hh.initialize(customerInfo.toString() + " SSHouse" + i, conf, publicVacationVector, gen);
      smartShiftingHouses.add(hh);
      hh.householdOf = this;
    }

    fillAggWeeklyLoad("NotShifting");
    fillAggWeeklyLoad("RandomlyShifting");
    fillAggWeeklyLoad("RegularlyShifting");
    fillAggWeeklyLoad("SmartShifting");
    /*
        showAggLoad("NotShifting");
        showAggLoad("RandomlyShifting");
        showAggLoad("RegularlyShifting");
        showAggLoad("SmartShifting");
    */
  }

  /**
   * This function is used in order to fill each week day of the aggregated daily Load of the
   * village households for each quarter of the hour.
   * @param portion
   * @return
   */
  void fillAggWeeklyLoad (String portion)
  {

    if (portion.equals("NotShifting")) {
      for (int i = 0; i < HouseholdConstants.DAYS_OF_WEEK * (HouseholdConstants.WEEKS_OF_COMPETITION + HouseholdConstants.WEEKS_OF_BOOTSTRAP); i++) {
        aggDailyBaseLoadNS.add(fillAggDailyBaseLoad(i, portion));
        aggDailyControllableLoadNS.add(fillAggDailyControllableLoad(i, portion));
        aggDailyBaseLoadInHoursNS.add(fillAggDailyBaseLoadInHours(i, portion));
        aggDailyControllableLoadInHoursNS.add(fillAggDailyControllableLoadInHours(i, portion));
      }
    } else if (portion.equals("RandomlyShifting")) {
      for (int i = 0; i < HouseholdConstants.DAYS_OF_WEEK * (HouseholdConstants.WEEKS_OF_COMPETITION + HouseholdConstants.WEEKS_OF_BOOTSTRAP); i++) {
        aggDailyBaseLoadRaS.add(fillAggDailyBaseLoad(i, portion));
        aggDailyControllableLoadRaS.add(fillAggDailyControllableLoad(i, portion));
        aggDailyBaseLoadInHoursRaS.add(fillAggDailyBaseLoadInHours(i, portion));
        aggDailyControllableLoadInHoursRaS.add(fillAggDailyControllableLoadInHours(i, portion));
      }
    } else if (portion.equals("RegularlyShifting")) {
      for (int i = 0; i < HouseholdConstants.DAYS_OF_WEEK * (HouseholdConstants.WEEKS_OF_COMPETITION + HouseholdConstants.WEEKS_OF_BOOTSTRAP); i++) {
        aggDailyBaseLoadReS.add(fillAggDailyBaseLoad(i, portion));
        aggDailyControllableLoadReS.add(fillAggDailyControllableLoad(i, portion));
        aggDailyBaseLoadInHoursReS.add(fillAggDailyBaseLoadInHours(i, portion));
        aggDailyControllableLoadInHoursReS.add(fillAggDailyControllableLoadInHours(i, portion));
      }
    } else {
      for (int i = 0; i < HouseholdConstants.DAYS_OF_WEEK * (HouseholdConstants.WEEKS_OF_COMPETITION + HouseholdConstants.WEEKS_OF_BOOTSTRAP); i++) {
        aggDailyBaseLoadSS.add(fillAggDailyBaseLoad(i, portion));
        aggDailyControllableLoadSS.add(fillAggDailyControllableLoad(i, portion));
        aggDailyBaseLoadInHoursSS.add(fillAggDailyBaseLoadInHours(i, portion));
        aggDailyControllableLoadInHoursSS.add(fillAggDailyControllableLoadInHours(i, portion));
      }
    }
  }

  /**
   * This function is used in order to print the aggregated load of the village households.
   * @param portion
   * @return
   */
  void showAggLoad (String portion)
  {

    log.info("Portion " + portion + " Weekly Aggregated Load");

    if (portion.equals("NotShifting")) {
      for (int i = 0; i < HouseholdConstants.DAYS_OF_COMPETITION + HouseholdConstants.DAYS_OF_BOOTSTRAP; i++) {
        log.info("Day " + i);
        for (int j = 0; j < HouseholdConstants.HOURS_OF_DAY; j++) {
          log.info("Hour : " + j + " Base Load : " + aggDailyBaseLoadInHoursNS.get(i).get(j) + " Controllable Load: " + aggDailyControllableLoadInHoursNS.get(i).get(j));
        }
      }
    } else if (portion.equals("RandomlyShifting")) {
      for (int i = 0; i < HouseholdConstants.DAYS_OF_COMPETITION + HouseholdConstants.DAYS_OF_BOOTSTRAP; i++) {
        log.info("Day " + i);
        for (int j = 0; j < HouseholdConstants.HOURS_OF_DAY; j++) {
          log.info("Hour : " + j + " Base Load : " + aggDailyBaseLoadInHoursRaS.get(i).get(j) + " Controllable Load: " + aggDailyControllableLoadInHoursRaS.get(i).get(j));
        }
      }
    } else if (portion.equals("RegularlyShifting")) {
      for (int i = 0; i < HouseholdConstants.DAYS_OF_COMPETITION + HouseholdConstants.DAYS_OF_BOOTSTRAP; i++) {
        log.info("Day " + i);
        for (int j = 0; j < HouseholdConstants.HOURS_OF_DAY; j++) {
          log.info("Hour : " + j + " Base Load : " + aggDailyBaseLoadInHoursReS.get(i).get(j) + " Controllable Load: " + aggDailyControllableLoadInHoursReS.get(i).get(j));
        }
      }
    } else {
      for (int i = 0; i < HouseholdConstants.DAYS_OF_COMPETITION + HouseholdConstants.DAYS_OF_BOOTSTRAP; i++) {
        log.info("Day " + i);
        for (int j = 0; j < HouseholdConstants.HOURS_OF_DAY; j++) {
          log.info("Hour : " + j + " Base Load : " + aggDailyBaseLoadInHoursSS.get(i).get(j) + " Controllable Load: " + aggDailyControllableLoadInHoursSS.get(i).get(j));
        }
      }
    }
  }

  @Override
  public void consumePower ()
  {
    Timeslot ts = timeslotRepo.currentTimeslot();
    double summary = 0;
    List subscriptions = tariffSubscriptionRepo.findActiveSubscriptionsForCustomer(this.getCustomerInfo());

    for (TariffSubscription sub : subscriptions) {
      if (ts == null) {
        log.error("Current timeslot is null");
        int serial = (int) ((timeService.getCurrentTime().getMillis() - timeService.getBase()) / TimeService.HOUR);
        summary = getConsumptionByTimeslot(serial);
      } else {
        summary = getConsumptionByTimeslot(ts.getSerialNumber());
      }
      log.info("Consumption Load: " + summary + "/" + subscriptions.size());
      sub.usePower(summary / subscriptions.size());
    }
  }

  /**
   * This method takes as an input the timeslot serial number (in order to know in the current time)
   * and estimates the consumption for this timeslot over the population under the Generic Consumer.
   */
  double getConsumptionByTimeslot (int serial)
  {

    int day = (int) (serial / HouseholdConstants.HOURS_OF_DAY);
    int hour = (int) (serial % HouseholdConstants.HOURS_OF_DAY);
    long summary = 0;

    log.info("Serial : " + serial + " Day: " + day + " Hour: " + hour);

    summary = (getBaseConsumptions(day, hour) + getControllableConsumptions(day, hour));

    return (double) summary / HouseholdConstants.THOUSAND;
  }

  /** This function returns the quantity of base load for a specific day and hour of that day */
  long getBaseConsumptions (int day, int hour)
  {

    long summaryBase = aggDailyBaseLoadInHoursNS.get(day).get(hour) + aggDailyBaseLoadInHoursRaS.get(day).get(hour) + aggDailyBaseLoadInHoursReS.get(day).get(hour)
        + aggDailyBaseLoadInHoursSS.get(day).get(hour);

    log.info("Base Load " + summaryBase);
    return summaryBase;
  }

  /**
   * This function returns the quantity of controllable load for a specific day in form of a vector
   */
  Vector getControllableConsumptions (int day)
  {
    Vector houses = getHouses();
    Vector controllableVector = new Vector();

    for (int j = 0; j < HouseholdConstants.HOURS_OF_DAY; j++) {
      long summaryControllable = 0;
      for (Household house : houses) {
        summaryControllable += house.weeklyControllableLoadInHours.get(day).get(j);
      }
      controllableVector.add(summaryControllable);
    }

    return controllableVector;
  }

  /**
   * This function returns the quantity of controllable load for a specific day and hour of that day
   */
  long getControllableConsumptions (int day, int hour)
  {
    long summaryControllable = aggDailyControllableLoadInHoursNS.get(day).get(hour) + aggDailyControllableLoadInHoursRaS.get(day).get(hour) + aggDailyControllableLoadInHoursReS.get(day).get(hour)
        + aggDailyControllableLoadInHoursSS.get(day).get(hour);
    log.info("Controllable Load " + summaryControllable);
    return summaryControllable;
  }

  /**
   * This function returns a vector with all the houses of a certain type that are present in this
   * village
   */
  Vector getHouses (String portion)
  {

    Vector houses = new Vector();

    if (portion.equals("NotShifting")) {
      for (Household house : notShiftingHouses) {
        houses.add(house);
      }
    } else if (portion.equals("RandomlyShifting")) {
      for (Household house : regularlyShiftingHouses) {
        houses.add(house);
      }
    } else if (portion.equals("RegularlyShifting")) {
      for (Household house : randomlyShiftingHouses) {
        houses.add(house);
      }
    } else {
      for (Household house : smartShiftingHouses) {
        houses.add(house);
      }
    }

    return houses;

  }

  /** This function returns a vector with all the houses that are present in this village */
  Vector getHouses ()
  {

    Vector houses = new Vector();

    for (Household house : notShiftingHouses) {
      houses.add(house);
    }

    for (Household house : randomlyShiftingHouses) {
      houses.add(house);
    }

    for (Household house : regularlyShiftingHouses) {
      houses.add(house);
    }

    for (Household house : smartShiftingHouses) {
      houses.add(house);
    }

    return houses;

  }

  /**
   * This function is used in order to fill the aggregated daily Base Load of the village households
   * for each quarter of the hour.
   * @param day
   * @param portion
   * @return
   */
  Vector fillAggDailyBaseLoad (int day, String portion)
  {

    Vector houses = new Vector();

    if (portion.equals("NotShifting")) {
      houses = notShiftingHouses;
    } else if (portion.equals("RandomlyShifting")) {
      houses = randomlyShiftingHouses;
    } else if (portion.equals("RegularlyShifting")) {
      houses = regularlyShiftingHouses;
    } else {
      houses = smartShiftingHouses;
    }

    Vector v = new Vector(HouseholdConstants.QUARTERS_OF_DAY);
    long sum = 0;
    for (int i = 0; i < HouseholdConstants.QUARTERS_OF_DAY; i++) {
      sum = 0;
      for (Household house : houses) {
        sum = sum + house.weeklyBaseLoad.get(day).get(i);
      }
      v.add(sum);
    }
    return v;
  }

  /**
   * This function is used in order to fill the aggregated daily Controllable Load of the village
   * households for each quarter of the hour.
   * @param day
   * @param portion
   * @return
   */
  Vector fillAggDailyControllableLoad (int day, String portion)
  {

    Vector houses = new Vector();

    if (portion.equals("NotShifting")) {
      houses = notShiftingHouses;
    } else if (portion.equals("RandomlyShifting")) {
      houses = randomlyShiftingHouses;
    } else if (portion.equals("RegularlyShifting")) {
      houses = regularlyShiftingHouses;
    } else {
      houses = smartShiftingHouses;
    }

    Vector v = new Vector(HouseholdConstants.QUARTERS_OF_DAY);
    long sum = 0;
    for (int i = 0; i < HouseholdConstants.QUARTERS_OF_DAY; i++) {
      sum = 0;
      for (Household house : houses) {
        sum = sum + house.weeklyControllableLoad.get(day).get(i);
      }
      v.add(sum);
    }
    return v;
  }

  /**
   * This function is used in order to fill the daily Base Load of the household for each hour.
   * @param day
   * @param portion
   * @return
   */
  Vector fillAggDailyBaseLoadInHours (int day, String portion)
  {

    Vector daily = new Vector();
    long sum = 0;

    if (portion.equals("NotShifting")) {
      for (int i = 0; i < HouseholdConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum = aggDailyBaseLoadNS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR) + aggDailyBaseLoadNS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 1)
            + aggDailyBaseLoadNS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 2) + aggDailyBaseLoadNS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    } else if (portion.equals("RandomlyShifting")) {
      for (int i = 0; i < HouseholdConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum = aggDailyBaseLoadRaS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR) + aggDailyBaseLoadRaS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 1)
            + aggDailyBaseLoadRaS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 2) + aggDailyBaseLoadRaS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    } else if (portion.equals("RegularlyShifting")) {
      for (int i = 0; i < HouseholdConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum = aggDailyBaseLoadReS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR) + aggDailyBaseLoadReS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 1)
            + aggDailyBaseLoadReS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 2) + aggDailyBaseLoadReS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    } else {
      for (int i = 0; i < HouseholdConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum = aggDailyBaseLoadSS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR) + aggDailyBaseLoadSS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 1)
            + aggDailyBaseLoadSS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 2) + aggDailyBaseLoadSS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }

    return daily;
  }

  /**
   * This function is used in order to fill the daily Base Load of the household for each hour.
   * @param day
   * @param portion
   * @return
   */
  Vector fillAggDailyControllableLoadInHours (int day, String portion)
  {

    Vector daily = new Vector();
    long sum = 0;

    if (portion.equals("NotShifting")) {
      for (int i = 0; i < HouseholdConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum = aggDailyControllableLoadNS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR) + aggDailyControllableLoadNS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 1)
            + aggDailyControllableLoadNS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 2) + aggDailyControllableLoadNS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    } else if (portion.equals("RandomlyShifting")) {
      for (int i = 0; i < HouseholdConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum = aggDailyControllableLoadRaS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR) + aggDailyControllableLoadRaS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 1)
            + aggDailyControllableLoadRaS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 2) + aggDailyControllableLoadRaS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    } else if (portion.equals("RegularlyShifting")) {
      for (int i = 0; i < HouseholdConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum = aggDailyControllableLoadReS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR) + aggDailyControllableLoadReS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 1)
            + aggDailyControllableLoadReS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 2) + aggDailyControllableLoadReS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    } else {
      for (int i = 0; i < HouseholdConstants.HOURS_OF_DAY; i++) {
        sum = 0;
        sum = aggDailyControllableLoadSS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR) + aggDailyControllableLoadSS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 1)
            + aggDailyControllableLoadSS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 2) + aggDailyControllableLoadSS.get(day).get(i * HouseholdConstants.QUARTERS_OF_HOUR + 3);
        daily.add(sum);
      }
    }

    return daily;
  }

  /**
   * This is the basic evaluation function, taking into consideration the minimum cost without
   * shifting the appliances' load but the tariff chosen is picked up randomly by using a
   * possibility pattern. The better tariffs have more chances to be chosen.
   */
  public void possibilityEvaluationNewTariffs (List newTariffs)
  {

    List subscriptions = tariffSubscriptionRepo.findActiveSubscriptionsForCustomer(this.getCustomerInfo());

    if (subscriptions == null || subscriptions.size() == 0) {
      subscribeDefault();
      return;
    }

    Vector estimation = new Vector();

    // adds current subscribed tariffs for reevaluation
    ArrayList evaluationTariffs = new ArrayList(newTariffs);
    //Collections.copy(evaluationTariffs, newTariffs);

    log.debug("Estimation size for " + this.toString() + " = " + evaluationTariffs.size());

    if (evaluationTariffs.size() > 1) {
      for (Tariff tariff : evaluationTariffs) {
        log.info("Tariff : " + tariff.toString() + " Tariff Type : " + tariff.getTariffSpecification().getPowerType());
        if (tariff.isExpired() == false && tariff.getTariffSpecification().getPowerType() == PowerType.CONSUMPTION) {
          estimation.add(-(costEstimation(tariff)));
        } else
          estimation.add(Double.NEGATIVE_INFINITY);
      }

      int minIndex = logitPossibilityEstimation(estimation);

      for (TariffSubscription sub : subscriptions) {
        log.info("Equality: " + sub.getTariff().getTariffSpec().toString() + " = " + evaluationTariffs.get(minIndex).getTariffSpec().toString());
        if (!(sub.getTariff().getTariffSpec() == evaluationTariffs.get(minIndex).getTariffSpec())) {
          log.info("Existing subscription " + sub.toString());
          int populationCount = sub.getCustomersCommitted();
          subscribe(evaluationTariffs.get(minIndex), populationCount);
          unsubscribe(sub, populationCount);
        }
      }
    }
  }

  /**
   * This function estimates the overall cost, taking into consideration the fixed payments as well
   * as the variable that are depending on the tariff rates
   */
  double costEstimation (Tariff tariff)
  {
    double costVariable = estimateShiftingVariableTariffPayment(tariff);
    double costFixed = estimateFixedTariffPayments(tariff);
    return (costVariable + costFixed) / HouseholdConstants.MILLION;
  }

  /**
   * This function estimates the fixed cost, comprised by fees, bonuses and penalties that are the
   * same no matter how much you consume
   */
  double estimateFixedTariffPayments (Tariff tariff)
  {
    double lifecyclePayment = -tariff.getEarlyWithdrawPayment() - tariff.getSignupPayment();
    double minDuration;

    // When there is not a Minimum Duration of the contract, you cannot divide with the duration
    // because you don't know it.
    if (tariff.getMinDuration() == 0)
      minDuration = HouseholdConstants.MEAN_TARIFF_DURATION * TimeService.DAY;
    else
      minDuration = tariff.getMinDuration();

    log.info("Minimum Duration: " + minDuration);
    return (-tariff.getPeriodicPayment() + (lifecyclePayment / minDuration));
  }

  /**
   * This function estimates the variable cost, depending only to the load quantity you consume
   */
  double estimateVariableTariffPayment (Tariff tariff)
  {

    double finalCostSummary = 0;

    int serial = (int) ((timeService.getCurrentTime().getMillis() - timeService.getBase()) / TimeService.HOUR);
    Instant base = new Instant(timeService.getCurrentTime().getMillis() - serial * TimeService.HOUR);
    int daylimit = (int) (serial / HouseholdConstants.HOURS_OF_DAY) + 1; // this will be changed to
                                                                         // one

    for (int day : daysList) {
      if (day < daylimit)
        day = (int) (day + (daylimit / HouseholdConstants.RANDOM_DAYS_NUMBER));
      Instant now = base.plus(day * TimeService.DAY);
      double costSummary = 0;
      double summary = 0, cumulativeSummary = 0;

      for (int hour = 0; hour < HouseholdConstants.HOURS_OF_DAY; hour++) {

        summary = getBaseConsumptions(day, hour) + getControllableConsumptions(day, hour);

        log.debug("Cost for hour " + hour + ":" + tariff.getUsageCharge(now, 1, 0));
        cumulativeSummary += summary;
        costSummary -= tariff.getUsageCharge(now, summary, cumulativeSummary);
        now = now.plus(TimeService.HOUR);
      }
      log.debug("Variable Cost Summary: " + finalCostSummary);
      finalCostSummary += costSummary;
    }
    return finalCostSummary / HouseholdConstants.RANDOM_DAYS_NUMBER;
  }

  /**
   * This is the new function, used in order to find the most cost efficient tariff over the
   * available ones. It is using Daily shifting in order to put the appliances operation in most
   * suitable hours of the day.
   * @param tariff
   * @return
   */
  double estimateShiftingVariableTariffPayment (Tariff tariff)
  {

    double finalCostSummary = 0;

    int serial = (int) ((timeService.getCurrentTime().getMillis() - timeService.getBase()) / TimeService.HOUR);
    Instant base = timeService.getCurrentTime().minus(serial * TimeService.HOUR);
    int daylimit = (int) (serial / HouseholdConstants.HOURS_OF_DAY) + 1; // this will be changed to

    for (int day : daysList) {
      if (day < daylimit)
        day = (int) (day + (daylimit / HouseholdConstants.RANDOM_DAYS_NUMBER));
      Instant now = base.plus(day * TimeService.DAY);
      double costSummary = 0;
      double summary = 0, cumulativeSummary = 0;

      long[] newControllableLoad = dailyShifting(tariff, now, day);

      for (int hour = 0; hour < HouseholdConstants.HOURS_OF_DAY; hour++) {
        summary = getBaseConsumptions(day, hour) + newControllableLoad[hour];
        cumulativeSummary += summary;
        costSummary -= tariff.getUsageCharge(now, summary, cumulativeSummary);
        now = now.plus(TimeService.HOUR);
      }
      log.debug("Variable Cost Summary: " + finalCostSummary);
      finalCostSummary += costSummary;
    }
    return finalCostSummary / HouseholdConstants.RANDOM_DAYS_NUMBER;
  }

  /**
   * This is the function that realizes the mathematical possibility formula for the choice of
   * tariff.
   */
  int logitPossibilityEstimation (Vector estimation)
  {

    double lamda = 10; // 0 the random - 10 the logic
    double summedEstimations = 0;
    Vector randomizer = new Vector();
    Vector possibilities = new Vector();

    for (int i = 0; i < estimation.size(); i++) {
      summedEstimations += Math.pow(HouseholdConstants.EPSILON, lamda * estimation.get(i));
      log.info("Cost variable: " + estimation.get(i));
      log.info("Summary of Estimation: " + summedEstimations);
    }

    for (int i = 0; i < estimation.size(); i++) {
      possibilities.add((int) (HouseholdConstants.PERCENTAGE * (Math.pow(HouseholdConstants.EPSILON, lamda * estimation.get(i)) / summedEstimations)));
      for (int j = 0; j < possibilities.get(i); j++) {
        randomizer.add(i);
      }
    }

    log.info("Randomizer Vector: " + randomizer);
    log.info("Possibility Vector: " + possibilities.toString());
    int index = randomizer.get((int) (randomizer.size() * rs1.nextDouble()));
    log.info("Resulting Index = " + index);
    return index;
  }

  /**
   * This is the function that takes every household in the village and readies the shifted
   * Controllable Consumption for the needs of the tariff evaluation.
   * @param tariff
   * @param now
   * @param day
   * @return
   */
  long[] dailyShifting (Tariff tariff, Instant now, int day)
  {

    long[] newControllableLoad = new long[HouseholdConstants.HOURS_OF_DAY];

    Vector houses = getHouses();

    for (Household house : houses) {
      long[] temp = house.dailyShifting(tariff, now, day, gen);
      for (int j = 0; j < HouseholdConstants.HOURS_OF_DAY; j++)
        newControllableLoad[j] += temp[j];
    }

    log.debug("New Controllable Load of Village " + toString() + " for Tariff " + tariff.toString());

    for (int i = 0; i < HouseholdConstants.HOURS_OF_DAY; i++) {
      log.debug("Hour: " + i + " Cost: " + tariff.getUsageCharge(now, 1, 0) + " Load: " + newControllableLoad[i]);
      now = new Instant(now.getMillis() + TimeService.HOUR);
    }

    return newControllableLoad;

  }

  /**
   * This is the function that takes every household in the village and readies the shifted
   * Controllable Consumption for the needs of the tariff evaluation.
   * @param tariff
   * @param now
   * @param day
   * @param portion
   * @return
   */
  long[] dailyShifting (Tariff tariff, Instant now, int day, String portion)
  {

    long[] newControllableLoad = new long[HouseholdConstants.HOURS_OF_DAY];

    Vector houses = new Vector();

    if (portion.equals("NotShifting")) {
      houses = notShiftingHouses;
    } else if (portion.equals("RandomlyShifting")) {
      houses = randomlyShiftingHouses;
    } else if (portion.equals("RegularlyShifting")) {
      houses = regularlyShiftingHouses;
    } else {
      houses = smartShiftingHouses;
    }

    for (Household house : houses) {
      long[] temp = house.dailyShifting(tariff, now, day, gen);
      for (int j = 0; j < HouseholdConstants.HOURS_OF_DAY; j++)
        newControllableLoad[j] += temp[j];
    }

    log.debug("New Controllable Load of Village " + toString() + " for Tariff " + tariff.toString());

    for (int i = 0; i < HouseholdConstants.HOURS_OF_DAY; i++) {
      log.debug("Hour: " + i + " Cost: " + tariff.getUsageCharge(now, 1, 0) + " Load: " + newControllableLoad[i]);
      now = new Instant(now.getMillis() + TimeService.HOUR);
    }
    return newControllableLoad;
  }

  /**
   * This function prints to the screen the daily load of the village's households for the weekday
   * at hand.
   * @param day
   * @param portion
   * @return
   */
  void printDailyLoad (int day, String portion)
  {

    Vector houses = new Vector();

    if (portion.equals("NotShifting")) {
      houses = notShiftingHouses;
    } else if (portion.equals("RandomlyShifting")) {
      houses = randomlyShiftingHouses;
    } else if (portion.equals("RegularlyShifting")) {
      houses = regularlyShiftingHouses;
    } else {
      houses = smartShiftingHouses;
    }

    log.info("Day " + day);

    for (Household house : houses) {
      house.printDailyLoad(day);
    }

  }

  /**
   * This function represents the function that shows the status of all the households in the
   * village each moment in time.
   * @param day
   * @param quarter
   * @return
   */
  void stepStatus (int day, int quarter)
  {
    Vector houses = getHouses();

    for (Household house : houses) {
      house.stepStatus(day, quarter);
    }
  }

  /**
   * This function is creating a certain number of random days that will be public vacation for the
   * people living in the environment.
   * @param days
   * @param gen
   * @return
   */
  Vector createPublicVacationVector (int days)
  {
    // Creating auxiliary variables
    Vector v = new Vector(days);

    for (int i = 0; i < days; i++) {
      int x = gen.nextInt(HouseholdConstants.DAYS_OF_COMPETITION + HouseholdConstants.DAYS_OF_BOOTSTRAP);
      ListIterator iter = v.listIterator();
      while (iter.hasNext()) {
        int temp = (int) iter.next();
        if (x == temp) {
          x = x + 1;
          iter = v.listIterator();
        }
      }
      v.add(x);
    }
    java.util.Collections.sort(v);
    return v;
  }

  /**
   * This function is creating the list of days for each village that will be utilized for the
   * tariff evaluation.
   * @param days
   * @param gen
   * @return
   */
  void createCostEstimationDaysList (int days)
  {

    for (int i = 0; i < days; i++) {
      int x = gen.nextInt(HouseholdConstants.DAYS_OF_COMPETITION + HouseholdConstants.DAYS_OF_BOOTSTRAP);
      ListIterator iter = daysList.listIterator();
      while (iter.hasNext()) {
        int temp = (int) iter.next();
        if (x == temp) {
          x = x + 1;
          iter = daysList.listIterator();
        }
      }
      daysList.add(x);
    }
    java.util.Collections.sort(daysList);

  }

  @Override
  public void step ()
  {
    checkRevokedSubscriptions();
    consumePower();
    if (timeService.getHourOfDay() == 23) {
      rescheduleNextDay("RandomlyShifting");
      rescheduleNextDay("RegularlyShifting");
      rescheduleNextDay("SmartShifting");
    }

  }

  /**
   * This function is utilized in order to reschedule the consumption load for the next day of the
   * competition according to the tariff rates of the subscriptions under contract.
   */
  void rescheduleNextDay (String portion)
  {
    int serial = (int) ((timeService.getCurrentTime().getMillis() - timeService.getBase()) / TimeService.HOUR);
    int day = (int) (serial / HouseholdConstants.HOURS_OF_DAY) + 1; // this will be changed to one
    Instant now = new Instant(timeService.getCurrentTime().getMillis() + TimeService.HOUR);
    Vector controllableVector = new Vector();

    List subscriptions = tariffSubscriptionRepo.findSubscriptionsForCustomer(this.getCustomerInfo());
    for (TariffSubscription sub : subscriptions) {
      log.info("Old Consumption for day " + day + ": " + getControllableConsumptions(day).toString());
      long[] newControllableLoad = dailyShifting(sub.getTariff(), now, day, portion);
      for (int i = 0; i < HouseholdConstants.HOURS_OF_DAY; i++)
        controllableVector.add(newControllableLoad[i]);
      log.info("New Consumption for day " + day + ": " + controllableVector.toString());

      if (portion.equals("RandomlyShifting")) {
        aggDailyBaseLoadInHoursRaS.set(day, controllableVector);
      } else if (portion.equals("RegularlyShifting")) {
        aggDailyBaseLoadInHoursReS.set(day, controllableVector);
      } else if (portion.equals("SmartShifting")) {
        aggDailyBaseLoadInHoursSS.set(day, controllableVector);
      } else {

      }

    }
  }

  public String toString ()
  {
    return customerInfo.toString();
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy