/**
 * This is the main class for the backward sampling algorithm.
 * 
 * Ref.: Lozano, L. and Smith, J. C. (2014). 
 * A Backward Sampling Framework for Interdiction Problems with Fortification
 * 
 * @author L. Lozano & J. C. Smith
 * @affiliation Clemson University
 * @url www.leo-loza.com
 * 
 */
package backwardAlgorithm;

import gurobi.GRBException;

import java.io.IOException;

public class CLSPMain {

	public static void main(String[] args) throws IOException, GRBException, InterruptedException {

		// Create an output file
		java.io.PrintStream ps = new java.io.PrintStream( new java.io.FileOutputStream("Results.txt"));
		//Define Q
		int[] dBudgets={3,5,3,5,3,5};
		//Define B
		int[] aBudgets={2,2,3,3,4,4};
		// Set the time limit
		int timeLimit=3600*4;
	//Iterate over (Q,B) pairs
	for (int k = 0; k <dBudgets.length; k++) {
			ps.println("********************************************* "+dBudgets[k]+" "+aBudgets[k]+" **************************************************************");
	//Iterate over instance sizes
	for (int t = 0; t <= 3; t++) {			
	//Iterate over the random instances	
	for (int i = 0; i <=9; i++) {
		
		// Create the instance data and store it on a DataHandler		
		DataHandler data = new DataHandler(10+10*t);
		data.createRandomInstance(i);
	
		//Set budgets
		data.dBudget = dBudgets[k];
		data.aBudget = aBudgets[k];
				
		// Begin the time count						
		double Atime = System.nanoTime();
			
		// Create an AlgorithmHandler
		AlgorithmHandler alg = new AlgorithmHandler(data);
		// Initialize the iteration counter
		int iter=0;
		// First sample
		alg.sample(data);
		// Set the stopping conditions
while(alg.globalStop == false && (System.nanoTime()-Atime)/1000000000<timeLimit){		
	while (alg.masterFeasible==true && (System.nanoTime()-Atime)/1000000000<timeLimit) {	
		// Select a feasible defense plan
		alg.solveDefenderProblem(data);
		// Solve the corresponding restricted interdiction problem 
		alg.solveMaxMin(data, Atime);
	}
	// If the set of tentative constraints is empty, then terminate
	if(alg.guessCutPool.size()==0 && (System.nanoTime()-Atime)/1000000000<timeLimit){
		alg.globalStop = true;
	}
	// Else, evaluate the guess pool
	else{
		alg.evaluateGuessPool(data, Atime);
	}

}		
//Print the results
	System.out.println("Instance "+i+" T: "+data.T+" EXECUTION TIME: "+(System.nanoTime()-Atime)/1000000000+" OBJ: "+alg.zbar+" Zstar: "+alg.zstar);
	//If the final zbar does not match the final objective value incumbent... cry! 
	if(alg.zbar-alg.zstar>0.01 || alg.zbar-alg.zstar<-0.01 ){
		System.out.println("OH NOOOOOOOOOOOOOOOOOOOOOOOOO NOOOOOOOOOO NOOOOOOOOOOOOOOOOOO");
	}

/*	System.out.println("HAT TIME: "+alg.hatTime/1000.0);
	System.out.println("W-HAT EVALS: "+alg.wHatEval);
	System.out.println("W-HAT PAUSED: "+alg.aborted);
	System.out.println("# MAXMIN: "+alg.maxMinIter);
	System.out.println("MAXMIN TIME: "+alg.maxMinTime/1000.0);
*/	
	
	ps.print((System.nanoTime()-Atime)/1000000000+" "+alg.zbar+" ");
	
	//System.out.print((System.nanoTime()-Atime)/1000000000+" "+alg.zbar);
	
	alg = null;
	data = null;
	System.gc();
				}
		ps.println();
		System.out.println();
			}
		}	
	}
}
