/*
 * Main.java
 *
 * Created on June 5, 2004, 12:38 PM
 */

package spamfilter;

import java.text.NumberFormat;

import spamfilter.decisiontree.*;
import spamfilter.email.*;
import spamfilter.genetic.*;


/**
 *
 * @author  aaronstj
 */
public class Main {
    
    public static final int verbosityLevel = 0;
    
    public static final int SIZE_OF_POPULATION = 50;
    public static final int NUM_GENERATIONS = 100;
    public static final int NEW_SOLUTION_PER_GENERATION = 15;
    public static final double MUTATION_CHANCE = .75;    
    
    /** Creates a new instance of Main */
    public Main() {
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {        
        
        System.out.println("Creating non-spam corpus");
        Corpus nonSpam = new Corpus("spamfilter/lingspam_public/medium/nonspam",false);
        
        System.out.println("Creating spam corpus");
        Corpus spam = new Corpus("spamfilter/lingspam_public/medium/spam",true);
        
        System.out.println("finished creating corpuses");        
        
        doIt(spam, nonSpam);                    
                
    }
    
    private static void doIt(Corpus spam, Corpus nonSpam) {               
            
        System.out.println("Starting program");        
        
        NumberFormat nf = NumberFormat.getInstance();
        nf.setMaximumFractionDigits(3);
        
        int generation = 0;
        
        //create a new population, and seed it randomly
        verboseln(1,"Creating initial population");
        Population pop = new Population(spam, nonSpam, SIZE_OF_POPULATION);           
                
        verboseln(2,"Starting population:");
        verboseln(2,pop);                
        
        while(generation < NUM_GENERATIONS && 
                !(pop.getBestSolutionSoFar().getExactFalseNegativeRatio() == 0 &&
                  pop.getBestSolutionSoFar().getExactFalsePositiveRatio() == 0)) { 
            
            //select a new breeding population
            verboseln(1,"Selecting a breeding population");
            pop.selectNewBreedingPopulation(SIZE_OF_POPULATION - NEW_SOLUTION_PER_GENERATION);
            
            //add new random solutions
            verboseln(1,"Adding new random solutions");
            pop.addNewRandomSolutions(NEW_SOLUTION_PER_GENERATION);
            
            verboseln(2,"Selected breeding population:");
            verboseln(2,pop);
            
            //repopulate the population by breeding random members of the breeding population.            
            verboseln(1,"Breeding new population");
            pop.breedToCreateWorkingSolution(SIZE_OF_POPULATION - 1);
            
            //mutate the population
            verboseln(1,"Mutating population");
            pop.mutate(MUTATION_CHANCE);
            
            verboseln(1,"Adding best solution so far back to working population");
            pop.add(pop.getBestSolutionSoFar());
            pop.getBestSolutionSoFar().refreshStats();
            
            generation++;
            
            verbose(2,"\n");
            verboseln(0,"New working population (generation " + generation + ")");
            verboseln(0,"Best solution so far: " + pop.getBestSolutionSoFar() +
                " (fitness " + nf.format(pop.getBestSolutionSoFar().getFitness()) + ")");
            verboseln(2,pop);       
            
            //pause();
        } 
        
        System.out.println("Best solution is: " + pop.getBestSolutionSoFar());
        System.out.println("fitness: " + pop.getBestSolutionSoFar().getFitness());
        
        NumberFormat pf = NumberFormat.getPercentInstance();
        pf.setMinimumFractionDigits(4);
        System.out.println("Exact false positive rate%: " + pf.format(pop.getBestSolutionSoFar().getExactFalsePositiveRatio()));
        System.out.println("Exact false negative rate%: " + pf.format(pop.getBestSolutionSoFar().getExactFalseNegativeRatio()));
        
        System.out.println(pop.getBestSolutionSoFar().getTree());
        
    }    
    
    public static void verbose(int level, Object o)
    {
        if(level <= verbosityLevel)
            System.out.print(o.toString());
    }
    
    public static void verboseln(int level, Object o)
    {
        if(level <= verbosityLevel)
            System.out.println(o.toString());
    }
    
}
