public Evolve (String [] params) {
        loadDefaults();
	loadFile(getS("param.file"));
        loadArguments(params);
        initalize();
	System.err.println(Parameter.dumpStats());
        
        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            Logger.getLogger(Evolve.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        
        generations = new ArrayList<Tree>();
        best = new Tree(null);
        best.score = Float.POSITIVE_INFINITY;
        breeder = new Breeder();
        
        int popsize = getI("population");
        int gensize = getI("generations");
        int threads = getI("threads");
        long current;
	GPproblem problem = null;
        ThreadManager manager;
        
	try {
            problem = (GPproblem) ((Class) get("problem.class")).newInstance();
            problem.setInfo(0);
	} catch (Exception ex) {
	    System.exit(2);
	}
        problem.setup();
	
        // Create initial generation
        for (int i = 0; i < popsize; i++) {
            generations.add(breeder.createTree());
        }
        
        //spit(generations);
                
        // Begin training.
        System.err.println("Begin");
        for (int i = 0; i < gensize; i++) {
            set("generation", i);
            System.err.println("Generation: " + i );
            
            current = System.currentTimeMillis();
            manager = new ThreadManager(threads, problem.getClass());
            manager.execute(generations.toArray(new Tree[0]));
            try {
                manager.executor.shutdown();
                manager.executor.allowCoreThreadTimeOut(true);
                manager.executor.setKeepAliveTime(5, TimeUnit.SECONDS);
                manager.executor.awaitTermination(5, TimeUnit.HOURS);
            } catch (InterruptedException ex) {
                Logger.getLogger(Evolve.class.getName()).log(Level.SEVERE, null, ex);
            }
            
            // Sort. 0 is best. eg) 0, 1, -2, 3, 3...
	    Collections.sort(generations);
            if (best.score > generations.get(0).score)
                best = (Tree) generations.get(0).clone();
                       
            if ( getI("elitism") == 1 )
                generations.add(best);
            problem.stats(i, generations.toArray(new Tree[0]));
            problem.cleanUpMemory();
            
            if (generations.get(0).score == 0) {
                System.err.println("Optimal found");
                break;
            }

            if (i != gensize-1) // Don't breed on last run.
                // Will look to 'selector.tourney' to decide who to breed.
                breeder.breeeed(generations);
            //System.gc();
        }
        System.err.println("Finished");	
        problem.best(best);
        System.exit(0);
    }