/*
 * Copyright (C) 2006 
 * Thomas van Dijk
 * Jan-Pieter van den Heuvel
 * Wouter Slob
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

package nl.uu.cs.treewidth.testing;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;

import nl.uu.cs.treewidth.algorithm.AllStartMaximumCardinalitySearch;
import nl.uu.cs.treewidth.algorithm.AllStartMaximumMinimumDegree;
import nl.uu.cs.treewidth.algorithm.AllStartMaximumMinimumDegreePlusLeastC;
import nl.uu.cs.treewidth.algorithm.AllStartMinorMinWidth;
import nl.uu.cs.treewidth.algorithm.LowerBound;
import nl.uu.cs.treewidth.algorithm.MaximumCardinalitySearch;
import nl.uu.cs.treewidth.algorithm.MaximumMinimumDegree;
import nl.uu.cs.treewidth.algorithm.MaximumMinimumDegreePlusLeastC;
import nl.uu.cs.treewidth.algorithm.MaximumMinimumDegreePlusMaxD;
import nl.uu.cs.treewidth.algorithm.MaximumMinimumDegreePlusMinD;
import nl.uu.cs.treewidth.algorithm.MinDegree;
import nl.uu.cs.treewidth.algorithm.MinorMinWidth;
import nl.uu.cs.treewidth.algorithm.Ramachandramurthi;
import nl.uu.cs.treewidth.input.DgfReader;
import nl.uu.cs.treewidth.input.GraphInput;
import nl.uu.cs.treewidth.input.InputException;
import nl.uu.cs.treewidth.input.GraphInput.InputData;
import nl.uu.cs.treewidth.ngraph.NGraph;

public class BigTest {
	
	/**
	 * @param args
	 */
	public static void main( String[] args ) {
		
		System.out.println( "libtw for the win." );
		
		String outputFile = "results.csv";
		PrintStream out = null;
		try {
			out = new PrintStream( new File(outputFile) );	
		} catch (FileNotFoundException e) {
			System.out.println( "Couldn't open results.csv for writing." );
			return;
		}
		
		ArrayList<String> graphFiles = graphFiles();
		
		out.println( "BigTest" );
		
		out.println();
		
		String here = "-";
		try {
			here = InetAddress.getLocalHost().toString();
		} catch (UnknownHostException e) {}
		out.println( "Generated by:," + here );
		out.println( "Generated at:," + new Date() );
		out.println();
		
		// graph headers
		printGraphHeaders(out, graphFiles);
		
		// lowerbounds
		LowerBound.Creator[] lbs = lowerbounds();
		for( LowerBound.Creator lbc : lbs ) {
			String algoName = lbc.create().getName();
			out.print( algoName );
			for( String filename : graphFiles ) {
				System.out.println( "Running " + algoName + " on " + filename );
				out.print( "," );
				LowerBound<InputData> lb = lbc.create();
				GraphInput input = new DgfReader(filename);
				NGraph<InputData> g = null;
				try {
					g = input.get();
				} catch (InputException e) {
					out.print( "InputException" );
					continue;
				}
				lb.setInput( g );
				lb.run();
				out.print( lb.getLowerBound() );
				
			}
			out.println();
		}
		out.println();
		
		System.out.println( "Done." );
		
	}

	private static void printGraphHeaders(PrintStream out, ArrayList<String> graphFiles) {
		out.print( "Graph:" );
		for( String file : graphFiles ) {
			out.print( ","+file );
		}
		out.println();
		
		out.print( "num vertices");
		for( String filename : graphFiles ) {
			GraphInput input = new DgfReader(filename);
			NGraph<InputData> g = null;
			try {
				g = input.get();
			} catch (InputException e) {
				out.print( ",InputException" );
				continue;
			}
			out.print(","+g.getNumberOfVertices());
		}
		out.println();
		
		out.print( "num edges");
		for( String filename : graphFiles ) {
			GraphInput input = new DgfReader(filename);
			NGraph<InputData> g = null;
			try {
				g = input.get();
			} catch (InputException e) {
				out.print( ",InputException" );
				continue;
			}
			out.print(","+g.getNumberOfEdges());
		}
		out.println();
		
	}

	private static ArrayList<String> graphFiles() {
		// perhaps list all files in the graphs directory here?
		ArrayList<String> graphFiles = new ArrayList<String>();
		File dir = new File("/private/probabilistic_networks");
		if( !dir.isDirectory() ) {
			System.err.println( "directory bork");
		}
		File[] fs = dir.listFiles();
		for( File f : fs ) {
			try {
				graphFiles.add( f.getCanonicalPath() );
			} catch (IOException e) {}
		}
		/*String[] graphFiles = {
			"graphs/alarm.dgf",
			"graphs/anna.dgf",
			"graphs/anna-pp.dgf",
			"graphs/barley.dgf",
			"graphs/barley-pp.dgf",
			"graphs/celar02.dgf",
			"graphs/celar07.dgf",
			"graphs/celar09pp.dgf",
			"graphs/david.dgf",
			"graphs/david-pp.dgf",
			"graphs/DSJC125.9.dgf",
			"graphs/DSJR500.1c.dgf",
			"graphs/eil51.tsp.dgf",
			"graphs/fpsol2.i.dgf",
			"graphs/munin2-wpp.dgf",
			"graphs/LabeledTest.dgf",
			"graphs/MCSTestGraph.dgf",
			"graphs/MCSTestGraph2.dgf"
		};*/
		return graphFiles;
	}
	
	
	private static LowerBound.Creator[] lowerbounds() {
		// perhaps list all files in the graphs directory here?
		LowerBound.Creator[] lowerbounds = {
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new AllStartMaximumCardinalitySearch<InputData>(); } },
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new AllStartMaximumMinimumDegree<InputData>(); } },
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new AllStartMaximumMinimumDegreePlusLeastC<InputData>(); } },
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new AllStartMinorMinWidth<InputData>(); } },
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new MaximumCardinalitySearch<InputData>(); } },
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new MaximumMinimumDegree<InputData>(); } },
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new MaximumMinimumDegreePlusLeastC<InputData>(); } },
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new MaximumMinimumDegreePlusMaxD<InputData>(); } },
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new MaximumMinimumDegreePlusMinD<InputData>(); } },
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new MinDegree<InputData>(); } },
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new MinorMinWidth<InputData>(); } },
			new LowerBound.Creator() { public LowerBound<InputData> create() { return new Ramachandramurthi<InputData>(); } },
		};
		return lowerbounds;
	}

}
