/**
 * 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 backwardSampling;

import gurobi.GRBException;

import java.io.IOException;

import sampling.PulseGraph;

public class SPIFMain {

	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 the (c,d) configurations
		String[] costConfigurations ={"10-5","10-10","10-20","100-50","100-100","100-200"};
		//Define Q
		int[] dBudgets={3,4,3,5,4,7};
		//Define B
		int[] aBudgets={3,3,4,4,5,5};
		// 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 the network sizes
		for (int i = 1; i <=6 ; i++) {
		//Iterate over the random instances	
		for	(int s = 0; s <=9 ; s++) {
		//Iterate over the cost configurations
		for (int costCon=0; costCon<costConfigurations.length; costCon++){
				
		// Read a config file with the instance information
		String ini = "ini/"+i+"0x"+i+"0_"+costConfigurations[costCon]+"_"+s+".txt";
		Settings Instance;
		Instance= new Settings(ini);
		// Read the data file and store the data on a DataHandler		
		DataHandler data = new DataHandler(Instance);
		data.ReadDimacs();
		
		//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 if ((System.nanoTime()-Atime)/1000000000<timeLimit){
		alg.evaluateGuessPool(data , Atime);
	}

}		

// Print the results
	System.out.println(ini+" EXECUTION TIME: "+(System.nanoTime()-Atime)/1000000000+" OBJ: "+alg.zbar+" Zstar: "+alg.zstar+" e: "+alg.epsilon);
	//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");
	}
		
	/*
	ps.println(alg.hatTime/1000.0);
	ps.println(alg.wHatEval);
	ps.println(alg.aborted);
	ps.println(alg.maxMinIter);
	ps.println(alg.maxMinTime/1000.0);
	ps.println((System.nanoTime()-Atime)/1000000000);
*/	
	ps.print((System.nanoTime()-Atime)/1000000000+" "+alg.zbar+" ");
	
	alg = null;
	data = null;
	System.gc();
	}	
	ps.println();
		}
		ps.println();
		System.out.println();
		}
	
	}
		
		
		
		
		
	}	

}
