/*
 * ATSP.java
 *
 * Created on 27 de diciembre de 2003, 0:35
 */

package ATSP;
import java.util.Properties;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
/**
 *
 * @author  gabriel
 */
public class ATSP {
     
    private GA ga;
    private int numGeneracionsDesastre = 20;
    private int maxGeneracions = 100;
    private double minFitness = -1;
    
    /** Creates a new instance of ATSP */
    public ATSP( String file ) throws java.io.FileNotFoundException, java.io.IOException {
        this.ga = new GA();
        
        java.util.Properties props = new java.util.Properties();
        BufferedInputStream inStream = new BufferedInputStream( new FileInputStream(file) );
        props.load(inStream);
        this.numGeneracionsDesastre = Integer.parseInt(props.getProperty("numGeneracionsDesastre", "-1"));
        this.maxGeneracions = Integer.parseInt(props.getProperty("parada.maxGeneracions", "100"));
        this.minFitness = Double.parseDouble(props.getProperty("parada.minFitness", "-1"));
        if (this.numGeneracionsDesastre < 0)
            this.numGeneracionsDesastre = this.maxGeneracions + 1;
        String [] poblacions = props.getProperty("nomsPoblacions").split(",");
        for(int i=0; i<poblacions.length; i++)
        {
            int numIndividus = Integer.parseInt(props.getProperty(poblacions[i] + ".numIndividus", "100"));
            Poblacio p = new Poblacio(numIndividus,50,poblacions[i]);
            
            String tipusSel = props.getProperty(poblacions[i] + ".tipusSeleccio", "elitism").toLowerCase();
            if ( tipusSel.equals("elitism") )
                p.setTipusSeleccio(Poblacio.SELECCIO_ELITISM);
            else
                throw new java.lang.IllegalArgumentException("Algorisme de selecció no implementat");
            double probCreuament = Double.parseDouble(props.getProperty(poblacions[i] + ".probCreuament", "0.9"));
            p.setProbCreuament(probCreuament);
            double probMutacio = Double.parseDouble(props.getProperty(poblacions[i] + ".probMutacio", "0.1"));
            p.setProbMutacio(probMutacio);
            double probEmigracio = Double.parseDouble(props.getProperty(poblacions[i] + ".probEmigracio", "0.1"));
            p.setProbEmigracio(probEmigracio);
            double probInmigracio = Double.parseDouble(props.getProperty(poblacions[i] + ".probInmigracio", "0.1"));
            p.setProbInmigracio(probInmigracio);
            boolean hibrid = Boolean.valueOf((props.getProperty(poblacions[i] + ".hibrid", "false"))).booleanValue();
            p.setHibrid(hibrid);
            String tipusCre = props.getProperty(poblacions[i] + ".tipusCreuament", "pmx").toLowerCase();
            if( tipusCre.equals("pmx") )
                p.setTipusCreuament(Individu.CREUAMENT_PMX);
            else if( tipusCre.equals("erx") )
                p.setTipusCreuament(Individu.CREUAMENT_ERX);
            else if( tipusCre.equals("erx_heur") )
                p.setTipusCreuament(Individu.CREUAMENT_ERX_HEUR);
            else if( tipusCre.equals("dpx") )
                p.setTipusCreuament(Individu.CREUAMENT_DPX);
            else if( tipusCre.equals("sax") )
                p.setTipusCreuament(Individu.CREUAMENT_SAX);
            else 
                throw new java.lang.IllegalArgumentException("Tipus de creuament no implementat: " + tipusCre);
            String tipusMut = props.getProperty(poblacions[i] + ".tipusMutacio", "canvi2").toLowerCase();
            if( tipusMut.equals("canvi2") )
                p.setTipusMutacio(Individu.MUTACIO_CANVI2);
            else if( tipusMut.equals("nr3opt") )
                p.setTipusMutacio(Individu.MUTACIO_NR3OPT);
            else if( tipusMut.equals("2opt") )
                p.setTipusMutacio(Individu.MUTACIO_2OPT);
            else if( tipusMut.equals("best_nr3opt") )
                p.setTipusMutacio(Individu.MUTACIO_BEST_NR3OPT);
            else 
                throw new java.lang.IllegalArgumentException("Tipus de mutacio no implementat: " + tipusMut);
            this.ga.addPoblacio(p);            
        }
    }
    
    public void run()
    {
        Individu ind = null, indMillor = null;
        int iGenMillor = -1;
        double anticFitness = Double.MAX_VALUE;
        int iVoltesIgual = 0;
        int iNumDesastres = 0;
        for(int i=1; i<=this.maxGeneracions && (indMillor==null || indMillor.getFitness()> this.minFitness); i++)
        {
            ind = this.ga.novaGeneracio();
            if (i%(this.maxGeneracions/5)==0 || i==1)
            {
	            System.out.print("Generació: ");
	            System.out.print(i);
	            System.out.print(", fitness: ");
	            System.out.print(ind.getFitness());
	            System.out.print(", edat: ");
	            System.out.println(ind.getEdat());
	    }
            if( anticFitness == ind.getFitness() )
                iVoltesIgual++;
            else
                iVoltesIgual=0;
            if (iVoltesIgual>=numGeneracionsDesastre)
            {
                //System.out.println("desastre");
                iNumDesastres++;
                this.ga.desastre();
                iVoltesIgual=0;
            }
            if ( indMillor==null || indMillor.getFitness()> ind.getFitness() )
            {
                indMillor=(Individu)ind.clone();
                iGenMillor = i;
                //System.out.println(indMillor);
            }
            anticFitness = ind.getFitness();
        }
        System.out.println("Generació millor: " + String.valueOf(iGenMillor) );
        System.out.println("Desastres: " + String.valueOf(iNumDesastres) );
        System.out.println(indMillor);
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        String file = "p.properties";
        if ( args.length > 0 )
            file = args[0];
        try
        {
            java.io.File f = new java.io.File(file);
            file = f.getCanonicalPath();
            ATSP atsp = new ATSP( file );
            atsp.run();
        }
        catch( java.io.FileNotFoundException e )
        {
            System.err.println("El fitxer " + file + " no existeix.");
        }
        catch( java.io.IOException e )
        {
            System.err.println("Problemes llegint el fitxer " + file);
        }
        catch( java.lang.IllegalArgumentException e )
        {
            System.err.println("El format del fitxer " + file + " es incorrecte: \n" + e.getMessage());
        }
    }
    
}

