/*
 * MaxMinAlgorithm.java
 *
 * Created on Ketvirtadienis, 2007, Sausio 25, 17.08
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package Main.algorithms;

import java.util.Arrays;

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

/**
 * @author Arturas Gusevas & Remigijus Paulavicius & Vytautas Putna 
 * 
 */
public class MaxMinAlgorithm extends AbstractAlgorithm {

	public void solve() {
		solve(true);
	}

	public void solve(boolean calculteUV) {
		solve(true, false);
	}

	public void solve(boolean calculteUV, boolean switchXY) {
	//	mLog.logn("----------------------------------");
            indeksas = 10;
            if (indeksas2 == 0 ){
                mLog.logn("----------------------------------");
                mLog.logn("ALTRUISTIC ALGORITHM BEGINS");
		if(calculteUV)
		{
			mLog.logn("-- MATRIX U");
			calculateMatrixU();
			outputMatrix(getMatrixU());
			mLog.logn("-- MATRIX V");
			calculateMatrixV();
			outputMatrix(getMatrixV());
		}
            } else
            {
               if(calculteUV)
		{
		//	mLog.logn("-- MATRIX U");
			calculateMatrixU();
		//	outputMatrix(getMatrixU());
		//	mLog.logn("-- MATRIX V");
			calculateMatrixV();
		//	outputMatrix(getMatrixV());
		} 
            }
		
            
		
		/**
		*  building matrix of Y
		*/
		
	//	mLog.logn("-- SOLVING Y");
		int rows= matrixU.length+2;
	    int cols= matrixU.length*2+3;
		double[][] matrixSolve= new double[rows][cols];
		
		int k;
		for(int i= 1; i<rows-1;i++)
		{
			k= 1;
			for(int j= 1; j< cols-2;j+=2, k++)
			{
				matrixSolve[i][j]= matrixU[k - 1][i - 1];
				matrixSolve[i][j+1]= -matrixU[k - 1][i - 1];
			}
			matrixSolve[i][cols-1]= -1;
			matrixSolve[i][cols-2]= 1;
		}
		
		for(int j= 1; j< cols-2;j+=2 )
		{
			matrixSolve[rows-1][j]= 1;
			matrixSolve[rows-1][j+1]= -1;
		}
		matrixSolve[rows-1][cols-1]= 0;
		matrixSolve[rows-1][cols-2]= 0;
                
                
		double x_constraint [][] = new double[rows-1][cols]; 
		for (int i = 0; i < rows-1; i++) {
			Arrays.fill(x_constraint[i], -0);		
		}
		
		for (int i = 0; i < rows-1; i++) {
			x_constraint[i][i*2+1] = 1;
			x_constraint[i][i*2+2] = -1;
		}
                
                 
		
		
		
		//create
        solve lpSolve = new solve();
        lprec lpIn = new lprec(0,cols-1);

		double[] bvalue= new double[cols];
		Arrays.fill(bvalue, 0);
		
		/*int val= -1;
		for(int i= 0; i<bvalue.length;i++)
		{
			bvalue[i]= -1*val;
		}*/
		
		
		bvalue[cols-1]= 1;
		bvalue[cols-2]= -1;
		//bvalue[1]= 1;

		//max
        lpSolve.set_obj_fn(lpIn,bvalue);
        lpSolve.set_maxim(lpIn);

		//x-y
		for(int i = 1; i < rows-1; i++)
			lpSolve.add_constraint(lpIn,matrixSolve[i],constant.GE,0);
		for(int i = 0; i < rows-2; i++)
			lpSolve.add_constraint(lpIn,x_constraint[i],constant.GE,0);

		lpSolve.add_constraint(lpIn,matrixSolve[matrixSolve.length-1],constant.EQ,1);
		
		//x1,y1
		
		int resultInt = lpSolve.solve(lpIn);
		if(resultInt != constant.OPTIMAL)
        {
    		mLog.logn("-- ALTRUISTIC ALGORITHM FAILED");
			setSolved(false);
    		//return res;
    	}
		else
		{
			setSolved(true);
		}
		
		
		result= new double[matrixU.length][2];
		
		k= 1;
		for(int i = 0; i < result.length; i++, k+=2)
        {
			double v1= lpIn.getBestSolution(lpIn.getRows()+k);
		    double v2= lpIn.getBestSolution(lpIn.getRows()+k+1);
			v1= v1 - v2;
			result[i][1]= v1;   
		}

		k=1;
		for(int i = 0; i < result.length; i++, k+=1)
        {
			double v1= lpIn.getBestSolution(lpIn.getRows()+k);
			System.out.println("BEST SOLUTION" + i + " :  " + v1);
		}
                
	//	U= lpIn.getBestSolution(lpIn.getRows()+k+1)- lpIn.getBestSolution(lpIn.getRows()+k); 
                
        /*        U = 0;
                for (int i=0;i < result.length; i++){
                  for (int j=0; j < result.length; j++){
                    U = U + result[i][0] * getMatrixU()[i][j] * result[j][1]; // x[i]*u[i][j]*y[j]
                   //U = 0.4 + matrixU[i][j]*result[i][1]*result[j][0];
                  }
                }*/
		
		lpSolve.print_lp(lpIn);
		lpSolve.print_duals(lpIn);
		lpSolve.print_solution(lpIn);
		lpSolve.print_scales(lpIn); 
		
		//lpSolve.print_solution(lpIn);
		
        //double[][] rezultsY= lpSolve.getMatrix();
		
		/**
		*  building matrix of X
		*/
	//	mLog.logn("-- SOLVING X");
		matrixSolve= new double[rows][cols];
		for(int i= 1; i<rows-1;i++)
		{
			k= 1;
			for(int j= 1; j< cols-2;j+=2, k++)
			{
				matrixSolve[i][j]= matrixV[k - 1][i - 1];
				matrixSolve[i][j+1]= -matrixV[k - 1][i - 1];
			}
			matrixSolve[i][cols-1]= -1;
			matrixSolve[i][cols-2]= 1;
		}
		
		for(int j= 1; j<= cols-2;j+=2)
		{
			matrixSolve[rows-1][j]= 1;
			matrixSolve[rows-1][j+1]= -1;
		}
		matrixSolve[rows-1][cols-1]= 0;
		matrixSolve[rows-1][cols-2]= 0;
		
		lpSolve = new solve();
        lpIn = new lprec(0,cols-1);
		
		/*bvalue= new double[cols];
		Arrays.fill(bvalue, 0);*/
		
		//max
        lpSolve.set_obj_fn(lpIn,bvalue);
        lpSolve.set_maxim(lpIn);

		//x-y
		for(int i = 0; i < rows-1; i++)
			lpSolve.add_constraint(lpIn,matrixSolve[i],constant.GE,0);
		for(int i = 0; i < rows-2; i++)
			lpSolve.add_constraint(lpIn,x_constraint[i],constant.GE,0);

		lpSolve.add_constraint(lpIn,matrixSolve[matrixSolve.length-1],constant.EQ,1);

		//x1,y1
		
		resultInt = lpSolve.solve(lpIn);
		if(resultInt != constant.OPTIMAL)
        {
    			    mLog.logn("-- ALTRUISTIC ALGORITHM FAILED");
					setSolved(false);
    	}
		else
		{
			setSolved(true&&isSolved());
		}
		
		k= 1;
		for(int i = 0; i < result.length; i++, k+=2)
        {
			double v1= lpIn.getBestSolution(lpIn.getRows()+k);
		    double v2= lpIn.getBestSolution(lpIn.getRows()+k+1);
		    
			v1-=v2;
			result[i][0]= v1;
		}
		
//		k=1;
//		for(int i = 0; i < lpIn.getRows()+result.length; i++, k+=1)
//        {
//			double v1= lpIn.getBestSolution(i);
//			System.out.println("BEST SOLUTION" + i + " :  " + v1);
//		}
		
		V= lpIn.getBestSolution(lpIn.getRows()+k+1)- lpIn.getBestSolution(lpIn.getRows()+k);
		
		/*    U = 0;
                    V = 0;
                    for (int i=0;i < result.length; i++){
                      for (int j=0; j < result.length; j++){
                        U = U + result[i][1] * getMatrixU()[i][j] * result[j][0]; // x[i]*u[i][j]*y[j]
                        V = V + result[i][1] * getMatrixV()[i][j] * result[j][0]; // x[i]*v[i][j]*y[j]
                      }
                    }    */          
                
		lpSolve.print_lp(lpIn);
		lpSolve.print_duals(lpIn);
		lpSolve.print_solution(lpIn);
		lpSolve.print_scales(lpIn);   
		
		//lpSolve.print_solution(lpIn);

        //double[][] rezultsX= temp.getMatrix();
		
		//result= new double[matrixU.length][2];
		if (indeksas2 == 0)
                    mLog.logn("-- GENERATING OUTPUT:");
		for(int i= 0;i<result.length;i++)
		{
			if(result[i][0] <0 || result[i][1] <0)
			{
				mLog.logn("-- ALTRUISTIC ALGORITHM FAILED");
				setSolved(false);
				break;
			}
		}
		
		//mLog.logn("ALTRUISTIC U = " + Utility.Round(U));
	//	mLog.logn("ALTRUISTIC V = " + Utility.Round(V));

	//	mLog.logn("ALTRUISTIC ENDS");
	//	mLog.logn("----------------------------------");*/
		//solveTMP(true);

		u= calculateU();
		v= calculateV();
                
               // U = u;
               // V = v;
                   	
  /*              mLog.logn("MMUmax = " + Utility.Round(U));
		mLog.logn("MMVmax = " + Utility.Round(V));
		
		mLog.logn("MMU* = " + Utility.Round(u));
        	mLog.logn("MMV* = " + Utility.Round(v));*/
		indeksas3 = 5; 
              //  if (indeksas2 != 0)
              //  {
                    if ((u >= U) && (v >= V)) {
    //			mLog.logn("TESTING CONDITIONS ARE TRUE");
    //			mLog.logn("Umax <= U* AND Vmax <= V*");
                        //    indeksas = 10;        // Tegul nesprendzia DSA
                                 // TEgul sprendzia fine problema
                    } else {
                        //mLog.logn("MaxMinindeksas = 0");
                     //   indeksas = 0;        // Tegul sprendzia DSA
    //			mLog.logn("TESTING CONDITIONS ARE FALSE: ");
    //			mLog.logn("Umax > U* OR Vmax > V*");
                            //indeksas = 10;
                            //indeksas3 = 0;
                            //indeksas = 0;        // Tegul nesprendzia DSA
                            //indeksas = 0;

                    }
       //         }
                indeksas2 +=1; 
                
		
		//mLog.logn("----------------------------------");
	}

}

