Initial project commit
This commit is contained in:
159
lib/nightscout/com/eveningoutpost/dexdrip/Models/Forecast.java
Normal file
159
lib/nightscout/com/eveningoutpost/dexdrip/Models/Forecast.java
Normal file
@@ -0,0 +1,159 @@
|
||||
package com.eveningoutpost.dexdrip.Models;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.commons.math3.linear.MatrixUtils;
|
||||
import org.apache.commons.math3.linear.RealMatrix;
|
||||
import org.apache.commons.math3.stat.regression.OLSMultipleLinearRegression;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Created by jamorham on 08/02/2016.
|
||||
*/
|
||||
public class Forecast {
|
||||
|
||||
private static final String TAG = "jamorham forecast";
|
||||
// from stackoverflow.com/questions/17592139/trend-lines-regression-curve-fitting-java-library
|
||||
|
||||
public interface TrendLine {
|
||||
void setValues(double[] y, double[] x); // y ~ f(x)
|
||||
|
||||
double predict(double x); // get a predicted y for a given x
|
||||
|
||||
double errorVarience();
|
||||
}
|
||||
|
||||
public abstract static class OLSTrendLine implements TrendLine {
|
||||
|
||||
RealMatrix coef = null; // will hold prediction coefs once we get values
|
||||
Double last_error_rate = null;
|
||||
|
||||
protected abstract double[] xVector(double x); // create vector of values from x
|
||||
|
||||
protected abstract boolean logY(); // set true to predict log of y (note: y must be positive)
|
||||
|
||||
|
||||
@Override
|
||||
public void setValues(double[] y, double[] x) {
|
||||
if (x.length != y.length) {
|
||||
throw new IllegalArgumentException(String.format("The numbers of y and x values must be equal (%d != %d)", y.length, x.length));
|
||||
}
|
||||
double[][] xData = new double[x.length][];
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
// the implementation determines how to produce a vector of predictors from a single x
|
||||
xData[i] = xVector(x[i]);
|
||||
}
|
||||
if (logY()) { // in some models we are predicting ln y, so we replace each y with ln y
|
||||
y = Arrays.copyOf(y, y.length); // user might not be finished with the array we were given
|
||||
for (int i = 0; i < x.length; i++) {
|
||||
y[i] = Math.log(y[i]);
|
||||
}
|
||||
}
|
||||
final OLSMultipleLinearRegression ols = new OLSMultipleLinearRegression();
|
||||
ols.setNoIntercept(true); // let the implementation include a constant in xVector if desired
|
||||
ols.newSampleData(y, xData); // provide the data to the model
|
||||
coef = MatrixUtils.createColumnRealMatrix(ols.estimateRegressionParameters()); // get our coefs
|
||||
last_error_rate = ols.estimateErrorVariance();
|
||||
Log.d(TAG, getClass().getSimpleName() + " Forecast Error rate: errorvar:"
|
||||
+ JoH.qs(last_error_rate, 4)
|
||||
+ " regssionvar:" + JoH.qs(ols.estimateRegressandVariance(), 4)
|
||||
+ " stderror:" + JoH.qs(ols.estimateRegressionStandardError(), 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double predict(double x) {
|
||||
double yhat = coef.preMultiply(xVector(x))[0]; // apply coefs to xVector
|
||||
if (logY()) yhat = (Math.exp(yhat)); // if we predicted ln y, we still need to get y
|
||||
return yhat;
|
||||
}
|
||||
|
||||
public static double[] toPrimitive(Double[] array) {
|
||||
if (array == null) {
|
||||
return null;
|
||||
} else if (array.length == 0) {
|
||||
return new double[0];
|
||||
}
|
||||
final double[] result = new double[array.length];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
result[i] = array[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double[] toPrimitiveFromList(Collection<Double> array) {
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return toPrimitive(array.toArray(new Double[array.size()]));
|
||||
}
|
||||
|
||||
public double errorVarience() {
|
||||
return last_error_rate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class PolyTrendLine extends OLSTrendLine {
|
||||
final int degree;
|
||||
|
||||
public PolyTrendLine(int degree) {
|
||||
if (degree < 0)
|
||||
throw new IllegalArgumentException("The degree of the polynomial must not be negative");
|
||||
this.degree = degree;
|
||||
}
|
||||
|
||||
protected double[] xVector(double x) { // {1, x, x*x, x*x*x, ...}
|
||||
double[] poly = new double[degree + 1];
|
||||
double xi = 1;
|
||||
for (int i = 0; i <= degree; i++) {
|
||||
poly[i] = xi;
|
||||
xi *= x;
|
||||
}
|
||||
return poly;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean logY() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExpTrendLine extends OLSTrendLine {
|
||||
@Override
|
||||
protected double[] xVector(double x) {
|
||||
return new double[]{1, x};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean logY() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class PowerTrendLine extends OLSTrendLine {
|
||||
@Override
|
||||
protected double[] xVector(double x) {
|
||||
return new double[]{1, Math.log(x)};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean logY() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LogTrendLine extends OLSTrendLine {
|
||||
@Override
|
||||
protected double[] xVector(double x) {
|
||||
return new double[]{1, Math.log(x)};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean logY() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user