
org.powertac.factoredcustomer.TimeseriesGenerator Maven / Gradle / Ivy
/*
* Copyright 2011-2013 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.factoredcustomer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.joda.time.DateTime;
import org.powertac.common.config.ConfigurableValue;
import org.powertac.common.repo.TimeslotRepo;
import org.powertac.factoredcustomer.interfaces.StructureInstance;
import org.powertac.factoredcustomer.utils.SeedIdGenerator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
/**
* Utility class that generates various time series patterns that can be
* used as base capacity series by implementations of @code{CapacityOriginator}.
*
* @author Prashant Reddy, Govert Buijs
*/
public final class TimeseriesGenerator implements StructureInstance
{
private static Logger log = LogManager.getLogger(TimeseriesGenerator.class);
private TimeslotRepo timeslotRepo;
private final int FORECAST_HORIZON = 2 * 24; // two days
private String name;
// These will come from the properties file
@ConfigurableValue(valueType = "Double")
private double y0;
@ConfigurableValue(valueType = "List")
private List yh;
@ConfigurableValue(valueType = "List")
private List yd;
@ConfigurableValue(valueType = "Double")
private double phi1;
@ConfigurableValue(valueType = "Double")
private double Phi1;
@ConfigurableValue(valueType = "Double")
private double theta1;
@ConfigurableValue(valueType = "Double")
private double Theta1;
@ConfigurableValue(valueType = "Double")
private double sigma;
@ConfigurableValue(valueType = "Double")
private double lambda;
@ConfigurableValue(valueType = "Double")
private double gamma;
@ConfigurableValue(valueType = "List")
private List refSeries;
private final Map genSeries = new HashMap<>();
private Random arimaNoise;
public TimeseriesGenerator (String name)
{
this.name = name;
}
public void initialize (FactoredCustomerService service)
{
timeslotRepo = service.getTimeslotRepo();
arimaNoise = new Random(service.getRandomSeedRepo()
.getRandomSeed("factoredcustomer.TimeseriesGenerator",
SeedIdGenerator.getId(), "ArimaNoise").getValue());
}
@Override
public String getName ()
{
return name;
}
public double generateNext (int timeslot)
{
if (genSeries.isEmpty()) {
initArima101x101GenSeries(timeslot);
}
Double next = genSeries.get(timeslot);
if (next == null) {
next = generateNextArima101x101(timeslot);
genSeries.put(timeslot, next);
}
return next;
}
private void initArima101x101GenSeries (int timeslot)
{
for (int i = 0; i < refSeries.size(); ++i) {
genSeries.put(timeslot + i, Double.parseDouble(refSeries.get(i)));
}
}
private double generateNextArima101x101 (int timeslot)
{
/** R code
boostTimeSeries = function(Xt, lambda, t, N, Xht, Xdt, gamma) {
return (Xt + (lambda * ((log(t-26))^2/(log(N-26))^2) * ((1 - gamma) * Xht + gamma * Xdt)))
}
for (t in compRange) {
Zf[t] = Y0 + Yd[D[t]] + Yh[H[t]] + phi1 * Zf[t-1] + Phi1 * Zf[t-24] #+ rnorm(1, 0, sigma^2) +
theta1 * (Zf[t-1] - Zf[t-2]) + Theta1 * (Zf[t-24] - Zf[t-25]) +
theta1 * Theta1 * (Zf[t-25] - Zf[t-26])
Zbf[t] = boostTimeSeries(Zf[t], lambda, t, N, Yh[H[t]], Yd[D[t]], gamma) #+ rnorm(1, 0, sigma^2)
}
**/
DateTime now = timeslotRepo.getDateTimeForIndex(timeslot);
int day = now.getDayOfWeek(); // 1=Monday, 7=Sunday
int hour = now.getHourOfDay(); // 0-23
double yh_hour = Double.parseDouble(yh.get(hour));
double yd_day = Double.parseDouble(yd.get(day - 1));
double logNext = y0 + yd_day + yh_hour
+ phi1 * getLog(timeslot - 1) + Phi1 * getLog(timeslot - 24)
+ theta1 * (getLog(timeslot - 1) - getLog(timeslot - 2))
+ Theta1 * (getLog(timeslot - 24) - getLog(timeslot - 25))
+ theta1 * Theta1 * (getLog(timeslot - 25) - getLog(timeslot - 26));
double nom = Math.pow(Math.log(timeslot - 26), 2);
double denom = Math.pow(Math.log(FORECAST_HORIZON - 26), 2);
double fact = ((1 - gamma) * yh_hour + gamma * yd_day);
logNext += lambda * (nom / denom) * fact;
logNext += Math.pow(sigma, 2) * arimaNoise.nextGaussian();
double next = Math.exp(logNext);
if (Double.isNaN(next)) {
throw new Error("Generated NaN as next time series element!");
}
return next;
}
private double getLog (int timeslot)
{
Double val = genSeries.get(timeslot);
if (null == val) {
log.error("Null value in genSeries for ts " + timeslot);
return 1.0;
}
return Math.log(val);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy