Commit 3371f582 authored by Sören Henning's avatar Sören Henning

added ForecasterConfigurations

parent a414943e
package teead.forecast;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.REngineException;
import teead.timeseries.EquidistantTimeSeries;
public class ARIMAForecaster extends AbstractRForecaster {
public ARIMAForecaster(final String host, final int port) {
super(host, port);
}
@Override
protected double performRForecast(final EquidistantTimeSeries timeSeries) throws REXPMismatchException, REngineException {
if (timeSeries.isEmpty()) {
return 0; // TODO
}
// Transfer time series to R
super.rConnection.assign("timeSeries", timeSeries.toValuesArray());
// Do ARIMA forecast on time Series
super.rConnection.eval("forecast <- forecast(auto.arima(ts(timeSeries)), h=1)");
// Retrieve result
double result = super.rConnection.eval("as.numeric(forecast$mean)").asDouble();
return result;
}
}
package teead.forecast;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.REngineException;
import teead.timeseries.EquidistantTimeSeries;
public class ARIMAForecaster extends AbstractRForecaster {
public ARIMAForecaster(final String host, final int port) {
super(host, port);
}
public ARIMAForecaster(final ForecasterConfiguration configuration) {
super(configuration);
}
@Override
protected double performRForecast(final EquidistantTimeSeries timeSeries) throws REXPMismatchException, REngineException {
if (timeSeries.isEmpty()) {
return 0; // TODO
}
// Transfer time series to R
super.rConnection.assign("timeSeries", timeSeries.toValuesArray());
// Do ARIMA forecast on time Series
super.rConnection.eval("forecast <- forecast(auto.arima(ts(timeSeries)), h=1)");
// Retrieve result
double result = super.rConnection.eval("as.numeric(forecast$mean)").asDouble();
return result;
}
}
package teead.forecast;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.REngineException;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;
import teead.timeseries.EquidistantTimeSeries;
public abstract class AbstractRForecaster implements Forecaster {
final RConnection rConnection;
public AbstractRForecaster(final String host, final int port) {
try {
this.rConnection = new RConnection(host, port);
this.rConnection.eval("library(forecast)");
} catch (RserveException e) {
// TODO Exception Handling
e.printStackTrace();
throw new IllegalStateException(e); // TODO
}
}
@Override
public final double forecast(final EquidistantTimeSeries timeSeries) {
// TODO Exception Handling
try {
return performRForecast(timeSeries);
} catch (REXPMismatchException | REngineException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Double.NaN; // TODO
}
protected abstract double performRForecast(final EquidistantTimeSeries timeSeries) throws REXPMismatchException, REngineException;
}
package teead.forecast;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.REngineException;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;
import teead.timeseries.EquidistantTimeSeries;
public abstract class AbstractRForecaster implements Forecaster {
protected final RConnection rConnection;
public final static String HOST_CONFIGURATION_KEY = "rserve.host";
public final static String PORT_CONFIGURATION_KEY = "rserve.port";
public AbstractRForecaster(final String host, final int port) {
try {
this.rConnection = new RConnection(host, port);
this.rConnection.eval("library(forecast)");
} catch (RserveException e) {
// TODO Exception Handling
e.printStackTrace();
throw new IllegalStateException(e); // TODO
}
}
public AbstractRForecaster(final ForecasterConfiguration configuration) {
this(configuration.get(HOST_CONFIGURATION_KEY), Integer.parseInt(configuration.get(PORT_CONFIGURATION_KEY)));
}
@Override
public final double forecast(final EquidistantTimeSeries timeSeries) {
// TODO Exception Handling
try {
return performRForecast(timeSeries);
} catch (REXPMismatchException | REngineException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Double.NaN; // TODO
}
protected abstract double performRForecast(final EquidistantTimeSeries timeSeries) throws REXPMismatchException, REngineException;
}
package teead.forecast;
public class ForecasterConfiguration {
import java.util.HashMap;
public ForecasterConfiguration() {
// TODO Auto-generated constructor stub
}
public class ForecasterConfiguration extends HashMap<String, String> {
private static final long serialVersionUID = 1L;
}
......@@ -11,6 +11,12 @@ import teead.timeseries.EquidistantTimeSeries;
*/
public class MeanForecaster implements Forecaster {
public MeanForecaster() {}
public MeanForecaster(final ForecasterConfiguration configuration) {
this();
}
@Override
public double forecast(final EquidistantTimeSeries timeSeries) {
......
package teead.forecast;
import org.apache.commons.math3.stat.regression.SimpleRegression;
import teead.timeseries.EquidistantTimeSeries;
import teead.timeseries.TimeSeriesPoint;
public class RegressionForecaster implements Forecaster {
@Override
public double forecast(final EquidistantTimeSeries timeSeries) {
if (timeSeries.isEmpty()) {
return 0; // TODO Double.NaN
}
final SimpleRegression regression = new SimpleRegression();
for (TimeSeriesPoint point : timeSeries) {
regression.addData(point.getTime().toEpochMilli(), point.getValue());
}
double prediction = regression.predict(timeSeries.getNextEndTime().toEpochMilli());
// TODO Temp
if (Double.isNaN(prediction)
|| prediction < 0
|| Double.isInfinite(prediction)) {
prediction = 0;
}
return prediction;
}
}
package teead.forecast;
import org.apache.commons.math3.stat.regression.SimpleRegression;
import teead.timeseries.EquidistantTimeSeries;
import teead.timeseries.TimeSeriesPoint;
public class RegressionForecaster implements Forecaster {
public RegressionForecaster() {}
public RegressionForecaster(final ForecasterConfiguration configuration) {
this();
}
@Override
public double forecast(final EquidistantTimeSeries timeSeries) {
if (timeSeries.isEmpty()) {
return 0; // TODO Double.NaN
}
final SimpleRegression regression = new SimpleRegression();
for (TimeSeriesPoint point : timeSeries) {
regression.addData(point.getTime().toEpochMilli(), point.getValue());
}
double prediction = regression.predict(timeSeries.getNextEndTime().toEpochMilli());
// TODO Temp
if (Double.isNaN(prediction)
|| prediction < 0
|| Double.isInfinite(prediction)) {
prediction = 0;
}
return prediction;
}
}
package teead.forecast;
import teead.timeseries.EquidistantTimeSeries;
import teead.timeseries.TimeSeriesPoint;
/**
* @author Christian Claus Wiechmann, Sören Henning
*
*/
public class WeightedForecaster implements Forecaster {
public enum WeightMethod {
LOGARITHMIC, LINEAR, EXPONENTIAL
}
private final WeightMethod weightMethod;
public WeightedForecaster(final WeightMethod weightMethod) {
this.weightMethod = weightMethod;
}
@Override
public double forecast(final EquidistantTimeSeries timeSeries) {
double weightedSum = 0;
double totalWeights = 0;
// more recent entry means more weight
int position = 1; // Position > 0, because logarithmic forecast method
for (TimeSeriesPoint point : timeSeries) {
final double weight = getWeight(position);
totalWeights += weight;
weightedSum += point.getValue() * weight;
position++;
}
return weightedSum / totalWeights;
}
private double getWeight(final int position) {
switch (this.weightMethod) {
case LOGARITHMIC:
return Math.log(position);
case LINEAR:
return position;
case EXPONENTIAL:
return Math.exp(position);
default:
return position;
}
}
}
package teead.forecast;
import teead.timeseries.EquidistantTimeSeries;
import teead.timeseries.TimeSeriesPoint;
/**
* @author Christian Claus Wiechmann, Sören Henning
*
*/
public class WeightedForecaster implements Forecaster {
public final static String WEIGHT_METHOD_CONFIGURATION_KEY = "weightMethod";
public enum WeightMethod {
LOGARITHMIC, LINEAR, EXPONENTIAL
}
private final WeightMethod weightMethod;
public WeightedForecaster(final WeightMethod weightMethod) {
this.weightMethod = weightMethod;
}
public WeightedForecaster(final ForecasterConfiguration configuration) {
this(WeightMethod.valueOf(configuration.get(WEIGHT_METHOD_CONFIGURATION_KEY)));
}
@Override
public double forecast(final EquidistantTimeSeries timeSeries) {
double weightedSum = 0;
double totalWeights = 0;
// more recent entry means more weight
int position = 1; // Position > 0, because logarithmic forecast method
for (TimeSeriesPoint point : timeSeries) {
final double weight = getWeight(position);
totalWeights += weight;
weightedSum += point.getValue() * weight;
position++;
}
return weightedSum / totalWeights;
}
private double getWeight(final int position) {
switch (this.weightMethod) {
case LOGARITHMIC:
return Math.log(position);
case LINEAR:
return position;
case EXPONENTIAL:
return Math.exp(position);
default:
return position;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment