ca.uwaterloo.iss4e.algorithm.PARX.java Source code

Java tutorial

Introduction

Here is the source code for ca.uwaterloo.iss4e.algorithm.PARX.java

Source

package ca.uwaterloo.iss4e.algorithm;

import ca.uwaterloo.iss4e.common.SMASException;
import org.apache.commons.math.stat.regression.OLSMultipleLinearRegression;

import java.math.BigDecimal;
import java.sql.*;
import java.util.List;
import java.util.Properties;

/**
 * Copyright (c) 2014 Xiufeng Liu ( xiufeng.liu@uwaterloo.ca )
 * <p/>
 * This file is free software: you may copy, redistribute and/or modify it
 * under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 * <p/>
 * This file is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * <p/>
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 */
public class PARX {

    public static Pair prepareVariable(final BigDecimal[] observations, int currentIndex, int trainingSize,
            int order, int seasons) throws SMASException {
        int numberOfElem = Math.min(trainingSize, currentIndex + 1);
        int size = numberOfElem / seasons;
        if (size < order + 1) {
            throw new SMASException("The number of backward elements should be at least " + (order + 1) * seasons);
        }
        double[] Y = new double[size];
        double[][] X = new double[size][order];
        for (int i = 0; i < size; ++i) {
            int idx = currentIndex - i * seasons;
            Y[i] = observations[idx].doubleValue();
            for (int j = 0; j < order; ++j) {
                X[i][order - 1 - j] = observations[idx - 1 - j].doubleValue();
            }
        }
        return new Pair(Y, X);
    }

    public static Pair prepareVariable(final double[] observations, int currentIndex, int trainingSize, int order,
            int seasons) throws SMASException {
        int numberOfElem = Math.min(trainingSize, currentIndex + 1);
        int size = numberOfElem / seasons;
        if (size < order + 1) {
            throw new SMASException("The number of backward elements should be at least " + (order + 1) * seasons);
        }
        double[] Y = new double[size];
        double[][] X = new double[size][order];
        for (int i = 0; i < size; ++i) {
            int idx = currentIndex - i * seasons;
            Y[i] = observations[idx];
            for (int j = 0; j < order; ++j) {
                X[i][order - 1 - j] = observations[idx - 1 - j];
            }
        }
        return new Pair(Y, X);
    }

    /*
    * Prepare exogenous variable, temperature, XT1, XT2, XT3
    * */
    public static double[][] prepareTemperatureExoVariable(final double[] temperatures, int currentIndex,
            int trainingSize, int seasons, int size) {
        double[][] XT = new double[size][3];
        for (int i = 0; i < size; ++i) {
            double t = temperatures[currentIndex - i * seasons];
            XT[i][0] = t > 20 ? (t - 20) : 0;
            XT[i][1] = (5 <= t && t < 16) ? (16 - t) : 0;
            XT[i][2] = t < 5 ? (5 - t) : 0;
        }
        return XT;
    }

    /*
    * Auto-regression variables, and the exogenous variable, temperature.
    * */
    public static Pair prepareAllVariables(final List<Double> readings, final List<Double> temperatures,
            int currentIndex, int trainingSize, int order, int seasons) throws SMASException {
        int numberOfElem = Math.min(trainingSize, currentIndex + 1);
        int size = numberOfElem / seasons;
        if (size < order + 1) {
            throw new SMASException("The number of backward elements should be at least " + (order + 1) * seasons);
        }

        double[] Y = new double[size];
        double[][] X = new double[size][order + 3];
        for (int i = 0; i < size; ++i) {
            int idx = currentIndex - i * seasons;
            Y[i] = readings.get(idx);
            for (int j = 0; j < order; ++j) {
                X[i][order - 1 - j] = readings.get(idx - 1 - j);
            }
            double t = temperatures.get(idx);
            X[i][order + 0] = t > 20 ? (t - 20) : 0;
            X[i][order + 1] = (5 <= t && t < 16) ? (16 - t) : 0;
            X[i][order + 2] = t < 5 ? (5 - t) : 0;
        }
        return new Pair(Y, X);
    }

    public static double[] computePARModel(final List<Double> readings, final List<Double> temperatures,
            int currentIndex, int trainingSize, int order, int seasons) throws SMASException {
        Pair pair = PARX.prepareAllVariables(readings, temperatures, currentIndex, trainingSize, order, seasons);
        double[] Y = (double[]) pair.getKey();
        double[][] X = (double[][]) pair.getValue();

        OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
        regression.setNoIntercept(true);
        regression.newSampleData(Y, X);

        double[] beta = regression.estimateRegressionParameters();
        return beta;
    }

    public static double[] getLoadByTemperature(final List<Double> readings, final List<Double> temperatures,
            int order) throws SMASException {
        int seasons = 24;
        Pair pair = PARX.prepareAllVariables(readings, temperatures, readings.size() - 1, readings.size(), order,
                seasons);
        double[] Y = (double[]) pair.getKey();
        double[][] X = (double[][]) pair.getValue();

        OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
        regression.setNoIntercept(true);
        regression.newSampleData(Y, X);

        double[] beta = regression.estimateRegressionParameters();
        double[] loadByTemp = new double[Y.length * seasons];
        int startIndex = readings.size() - Y.length * seasons;
        for (int i = 0; i < loadByTemp.length; ++i) {
            double t = temperatures.get(i + startIndex);
            loadByTemp[i] = beta[order + 0] * (t > 20 ? (t - 20) : 0)
                    + beta[order + 1] * ((5 <= t && t < 16) ? (16 - t) : 0)
                    + beta[order + 2] * (t < 5 ? (5 - t) : 0);
        }
        return loadByTemp;
    }

    public static void main(String[] args) {

        String url = "jdbc:postgresql://localhost/essex";
        Properties props = new Properties();
        props.setProperty("user", "xiliu");
        props.setProperty("password", "Abcd1234");

        try {
            /* Random generator = new Random();
             BigDecimal[] d = new BigDecimal[40];
             for (int i=0; i<40; ++i){
            d[i] = new BigDecimal(generator.nextInt(10));
            System.out.print(d[i].doubleValue()+"("+i+") |");
             }
             System.out.println("\n ---------------");
             Pair<double[], double[][]> values = PARX.prepareVariable(d, 11, 12, 2, 4);
             double[] Y = values.getKey();
             double X[][] = values.getValue();
             for (int i=0; i<Y.length; ++i){
                
            for (int j=0; j<X[i].length; ++j) {
                System.out.print(X[i][j] + " |");
            }
            System.out.print("|" +Y[i]);
            System.out.println();
             }
            */

            Class.forName("org.postgresql.Driver");
            Connection conn = DriverManager.getConnection(url, props);
            PreparedStatement pstmt = conn.prepareStatement(
                    "select array_agg(A.reading) from (select reading from meterreading where homeid=? and readdate between ? and ? order by readdate desc, readtime desc) A ");
            pstmt.setInt(1, 19419);
            pstmt.setDate(2, java.sql.Date.valueOf("2011-04-03"));
            pstmt.setDate(3, java.sql.Date.valueOf("2011-09-07"));

            ResultSet rs = pstmt.executeQuery();

            int order = 3;

            int numOfSeasons = 24;
            int intervalOfUpdateModel = 4; //Every four hours
            int startPredict = 6 * 24;
            int numOfPointsForTraining = 24 * 5;
            double[] pointsForPredict = new double[order];

            if (rs.next()) {
                BigDecimal[] readings = (BigDecimal[]) (rs.getArray(1).getArray());
                double[][] data = new double[2][readings.length + 1];
                int i = 0;
                for (; i < startPredict; ++i) {
                    data[0][i] = readings[i].doubleValue();
                    data[1][i] = 0.0;
                }

                double[] beta = null;
                int updateModelCount = 0;
                for (; i < readings.length; ++i) {
                    // if (updateModelCount%intervalOfUpdateModel==0) {
                    // beta = PARX.computePARModel(readings, i, i+1, order, numOfSeasons);
                    ++updateModelCount;
                    //}
                    for (int p = 0; p < order; ++p) {
                        pointsForPredict[order - 1 - p] = readings[i - p].doubleValue();
                    }
                    data[0][i] = readings[i].doubleValue();
                    //   data[1][i+1] = PARX.predict(pointsForPredict, order, beta);
                }

                for (int j = 0; j < readings.length + 1; ++j) {
                    System.out.println(data[0][j] + ", " + data[1][j]);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}