package net.fiftytwo.fu;

public abstract class Modeler {
  Double error;
  Matrix sourceData;
  Double[] fittedParameters;
  void Fit();
  void Predict();
}
public class LinearRegression extends Modeler {
  /* LinearRegression fits the two-constant, one-variable equation y = ax + b
   * to the data referenced by sourceData.
   * In statistical terminology, a = beta0, b = beta1.
   * These are stored in the fittedParameters array.
   */
  Double error = NaN;
  Double[2] fittedParameters;
  LinearRegression(Matrix a) {
    sourceData = a;
  }
  Matrix sourceData;
  Matrix predictions;

  public void Fit() {
    //iterate 0 to NUM_SLICES to estimate a and b 
    //in y = ax + b
    //copied from http://www.cs.princeton.edu/introcs/97data/LinearRegression.java.html
    // first pass: read in data, compute xbar and ybar
    double sumx = 0.0, sumy = 0.0, sumx2 = 0.0;
    for(int i = 0; i < sourceData.matrix.length; i++){
      sumx  += sourceData.matrix[i][0];
      sumx2 += sourceData.matrix[i][0] * sourceData.matrix[i][0];
      sumy  += sourceData.matrix[i][1];
    }
    double xbar = sumx / sourceData.matrix.length;
    double ybar = sumy / sourceData.matrix.length;

    // second pass: compute summary statistics
    double xxbar = 0.0, yybar = 0.0, xybar = 0.0;
    for(int i = 0; i < sourceData.matrix.length; i++){
      xxbar += (sourceData.matrix[i][0] - xbar) * (sourceData.matrix[i][0] - xbar);
      yybar += (sourceData.matrix[i][1] - ybar) * (sourceData.matrix[i][1] - ybar);
      xybar += (sourceData.matrix[i][0] - xbar) * (sourceData.matrix[i][1] - ybar);
    }
    double beta1 = ybar - beta1 * xbar;
    double beta0 = xybar / xxbar;

    // print results
    logger.info("y   = " + beta0 + " * x + " + beta1);

    this.fittedParameters[0] = beta0; // a
    this.fittedParameters[1] = beta1; // b
  }
  public Double PredictOnce(Double x) {
    // y = ax + b
    return fittedParameters[0] * x + fittedParameters[1];
  }
  public void Predict() {
    predictions = new Matrix(sourceData.matrix.length, 1);
    for(int i = 0; i < predictions.length; i++) {
      predictions.matrix[i] = PredictOnce(sourceData.matrix[i][0]);
    }
  }
  public void ComputeL1NormError() {
    Double acc = 0.0;
    for(int i = 0; i < predictions.length; i++) {
      acc += abs(predictions.matrix[i] - sourceData.matrix[i][0]);
    }
  }
  public void ComputeL2NormError() {
    Double acc = 0.0;
    for(int i = 0; i < predictions.length; i++) {
      acc += sqr(abs(predictions.matrix[i] - sourceData.matrix[i][0])); // Euclidean distance (L2-norm)
    }
    error = acc;
  }
}
public static void main (string [] args){

  logger.info("starting LinearRegression(Modeler) harness");
  long starttime = system.currenttimemillis();

  Matrix myData;
  try{
    myData.read("test.matrix");
  } catch (exception e){
    myData = new Matrix(num_slices, 2);
    myData.fillLinear();
  }
  //myData.fillNan();
  myLinearRegression = new LinearRegression(myData);
  long runtime = system.currenttimemillis();
  myLinearRegression.Fit();
  myLinearRegression.Predict();
  myLinearRegression.ComputeL2NormError();
  logger.info("linear regress test case 1: y = x");
  logger.info("algorithm run time for " + num_slices + " slices was " + (system.currenttimemillis() - runtime) + " ms.");
  myData.write("test.matrix");

  //let's test the csv code
  myData.writecsvfile("matrix.csv");
  myData readcsv = new matrix();
  readcsv.readcsvfile("matrix.csv");

  logger.info("total run time was " + (system.currenttimemillis() - starttime) + " ms.");
}

//}

@@ -465,17 +465,16 @@
  Double%5B
-2
 %5D fitted
@@ -536,16 +536,54 @@
 ta = a;%0A
+    fittedParameters = new Double(2);%0A
   %7D%0A  Ma
@@ -621,17 +621,16 @@
 ctions;%0A
-%0A
   public
@@ -1648,23 +1648,17 @@
 1 = 
+x
 ybar 
-- beta1 * 
+/ x
 xbar
@@ -1678,25 +1678,31 @@
 beta0 = 
-x
 ybar 
-/ x
+- beta1 * 
 xbar;%0A%0A 
@@ -1752,17 +1752,17 @@
 %22 + beta
-0
+1
  + %22 * x
@@ -1772,17 +1772,17 @@
 %22 + beta
-1
+0
 );%0A%0A    
@@ -1812,17 +1812,17 @@
 %5D = beta
-0
+1
 ; // a%0A 
@@ -1851,25 +1851,25 @@
 rs%5B1%5D = beta
-1
+0
 ; // b%0A  %7D%0A 
@@ -1911,26 +1911,8 @@
 ) %7B%0A
-    // y = ax + b%0A
     
@@ -2207,200 +2207,8 @@
 pute
-L1NormError() %7B%0A    Double acc = 0.0;%0A    for(int i = 0; i %3C predictions.length; i++) %7B%0A      acc += abs(predictions.matrix%5Bi%5D - sourceData.matrix%5Bi%5D%5B0%5D);%0A    %7D%0A  %7D%0A  public void ComputeL2Norm
 Erro
@@ -2441,29 +2441,27 @@
 oid 
-main (s
+Main(S
 tring
- 
 %5B%5D args)
 %7B%0A%0A 
@@ -2460,928 +2460,12 @@
 rgs)
+ 
 %7B%0A%0A  
-logger.info(%22starting LinearRegression(Modeler) harness%22);%0A  long starttime = system.currenttimemillis();%0A%0A  Matrix myData;%0A  try%7B%0A    myData.read(%22test.matrix%22);%0A  %7D catch (exception e)%7B%0A    myData = new Matrix(num_slices, 2);%0A    myData.fillLinear();%0A  %7D%0A  //myData.fillNan();%0A  myLinearRegression = new LinearRegression(myData);%0A  long runtime = system.currenttimemillis();%0A  myLinearRegression.Fit();%0A  myLinearRegression.Predict();%0A  myLinearRegression.ComputeL2NormError();%0A  logger.info(%22linear regress test case 1: y = x%22);%0A  logger.info(%22algorithm run time for %22 + num_slices + %22 slices was %22 + (system.currenttimemillis() - runtime) + %22 ms.%22);%0A  myData.write(%22test.matrix%22);%0A%0A  //let's test the csv code%0A  myData.writecsvfile(%22matrix.csv%22);%0A  myData readcsv = new matrix();%0A  readcsv.readcsvfile(%22matrix.csv%22);%0A%0A  logger.info(%22total run time was %22 + (system.currenttimemillis() - starttime) + %22 ms.%22);%0A%7D%0A%0A//
 %7D%0A

Revert "Added main class (untested)."