/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package lt.ktu.mockus.srgm;

import lp.constant;
import lp.lprec;
import lp.solve;

public class MyLp implements constant {
    public static int result;

    public MyLp() {

    }

    public double[] predict ( double[] data, int p ) {
        double A = -0.01;
        int data_count = data.length;
        double[] new_data = new double[data_count+1];
        new_data[0] = 0;
        
        System.arraycopy(data, 0, new_data, 1, data_count);

        solve lpSolve = new solve();
        lprec lpIn = new lprec(0,(data_count+p*2));

        double minf[] = new double[data_count+p*2+1];
        double rib1[] = new double[data_count+p*2+1];
        double rib2[] = new double[data_count+p*2+1];

        for ( int i=1; i<=data_count; i++ ) {
            minf[i] = 1;
            lpSolve.set_lowbo(lpIn, i, A);
        }

        for ( int i=data_count+1; i<=data_count+p*2; i++ ) {
            minf[i] = 0;
            lpSolve.set_lowbo(lpIn, i, A);
        }

        lpSolve.set_obj_fn(lpIn, minf);
        lpSolve.set_minim(lpIn);

        for ( int i=1; i<=data_count; i++ ) {
            for ( int j=1; j<=data_count; j++ ) {
                if ( i == j ) {
                    rib1[j] = 1;
                    rib2[j] = -1;
                }
                else {
                    rib1[j] = 0;
                    rib2[j] = 0;
                }
            }
            for ( int j=1; j<=p; j++ ) {
                if ( i-j > 0 ) {
                    rib1[data_count+j] = new_data[i-j];
                    rib1[data_count+p+j] = -1*new_data[i-j];
                    rib2[data_count+j] = new_data[i-j];
                    rib2[data_count+p+j] = -1*new_data[i-j];
                }
            }
            lpSolve.add_constraint(lpIn, rib1, GE, new_data[i]);
            lpSolve.add_constraint(lpIn, rib2, LE, new_data[i]);
        }

        try {
            result = lpSolve.solve(lpIn);
        }
        catch ( ArrayIndexOutOfBoundsException ex ) {
            System.out.println("Error2:" + ex);
            result = 1000000;
        }

        if ( result == constant.OPTIMAL ) {
            int rows = lpIn.getRows();

            for ( int i=1; i<=data_count+p*2; i++ ) {
                minf[i] = lpIn.getBestSolution(rows+i);
            }
            
            double[] coef = new double[p];
            for ( int i=0; i<p; i++ ) {
                coef[i] = minf[data_count+i+1] - minf[data_count+p+i+1];
            }
            return coef;
        }
        else {
            //double[] coef = new double[0];
            //igor
            if ( p > 1 ) {
                System.out.println("No optimal solution with p = " + p );
                double[] coef = this.predict( data, p-1 );
                return coef;// = new double[p];
            }
            else {
                double[] coef = new double[p];
                for ( int i = 0; i < p; i++ ) {
                    coef[i] = 1 / p;
                }
                return coef;
            }
            //double
            //return coef;
        }
    }
}