/*
 * LocalOpt.class
 * Part of package project
 *
 * Author: Philip Bradley
 *
 */

package project;

import java.util.Random;


public class LocalOpt {
	
	Random numberGen;

	public LocalOpt(GeometricGraph g, int partitionSize, double iWeight) {
		System.out.print("# Creating solution...");
		Solution s = new Solution(g,partitionSize);
		System.out.println("done!");

		localOpt(g, partitionSize, iWeight, s);
	}


        public LocalOpt(GeometricGraph g, int partitionSize, double iWeight, String solnFile) {
	  System.out.print("# Reading solution from file.....");
	  Solution s = Solution.readFromFile(solnFile);
	  System.out.println("..done");
	  s.setGraph(g);
	  localOpt(g, partitionSize, iWeight, s);
	}

	private void localOpt(GeometricGraph g, int k, double iWeight, Solution initSolution) {

                double delta = 0;
		double newCost = 0;
		long startTime = System.currentTimeMillis();
		long finishTime;	
		Solution currentSolution = initSolution;
                Solution newSolution;
		currentSolution.setImbalanceWeight(iWeight);
                double currentCost = currentSolution.getCost();
		int graphOrder = g.getOrder();	
		int partitionCount = 0;
		int vertexCount = 0;
		int activeVertex = 0;
		int iterationCount=0;

		System.out.println("# Starting Local Optimisation!");
		while (vertexCount < graphOrder) {
			while (partitionCount < k) {
                        	newSolution = currentSolution.legalMigration(activeVertex, partitionCount);
				currentCost = currentSolution.getCost();
				newCost = newSolution.getCost();
                        	delta = (newSolution.getCost() - currentSolution.getCost());
 
                        	if (delta < 0) {
                                	currentSolution = (Solution)newSolution.clone();
					System.out.println(iterationCount + " " + currentSolution.getCost() + " " + currentSolution.getCutEdges());
					partitionCount = 0;
					vertexCount = 0;
                        	} else {
					partitionCount++;
				}
				iterationCount++;
			}
			partitionCount = 0;
			vertexCount++;

			activeVertex++;
			activeVertex %= graphOrder;
               	}          

		finishTime = System.currentTimeMillis();
		System.out.println("# Total running time in milliseconds: " + (finishTime - startTime));
		System.out.println("# Solution: " + currentSolution.getCost() + " " + currentSolution.getCutEdges());
        }

	public static void main(String[] args) {

		int numberOfArgs = args.length;
		int i = 0;	
		String tmpString = new String();

		GeometricGraph g = (GeometricGraph)null;
                int partition = 0;
		double initProb = 0;
                double rate = 0;
                int runLength = 0;
                double minRatio = 0;
		double imbalanceScaling = 1;
		String filename = "";


		if ((numberOfArgs != 6) && (numberOfArgs != 8)) {
			System.out.print("Error:");
			System.out.println("LocalOpt -g GraphFile -k Partition Size -s Imbalance Scaling [-sol Initial Solution]");
		} else {
			while (i < numberOfArgs) {
			
				tmpString = args[i];
				if (tmpString.equals("-g")) {
					System.out.print("# Reading graph from file...");
					g = GeometricGraph.readFromFile(args[++i]);	
					System.out.println("done!");
				} else if (tmpString.equals("-k")) {
				        partition = new Integer(args[++i]).intValue();       	
				} else if (tmpString.equals("-s")) {
					imbalanceScaling = new Double(args[++i]).doubleValue();
				} else if (tmpString.equals("-sol")) {
					filename = args[++i];
				} else {
					System.out.println("Error: arg: " + args[i]);
				}
				i++;
			}

			System.out.println("# Running LocalOpt on graph of order " + g.getOrder() + " and size " + g.getSize());

			if (filename.equals("")) {
				LocalOpt s = new LocalOpt(g, partition, imbalanceScaling);
			} else {
				LocalOpt s = new LocalOpt(g, partition, imbalanceScaling, filename);
			}
		}
	}

}


