content: package aima.gui.fx.applications.search.local;
  
  import java.text.DecimalFormat;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.Comparator;
  import java.util.List;
  import java.util.function.Function;
  
  import aima.core.search.local.FitnessFunction;
  import aima.core.search.local.GeneticAlgorithm.ProgressTracker;
  import aima.core.search.local.GeneticAlgorithmForNumbers;
  import aima.core.search.local.Individual;
  
  /**
   * Command line demo which demonstrates how the generic algorithm for numbers
   * can be used to find maximums in a mathematical function.
   * 
   * @author Ruediger Lunde
   */
  public class GeneticMaximumFinderDemo {
  
  	private Function<Double, Double> func = Functions.f1;
  	private double mutProb = 0.2;
  
  	private int populationSize = 20;
  	private int maxIterations = 100;
  
  	private FitnessFunction<Double> fitnessFn;
  
  	public static void main(String[] args) {
  		System.out.println("Genetic Maximum Finder Experiment (f1, mutProb=0.2) -->");
  		GeneticMaximumFinderDemo demo = new GeneticMaximumFinderDemo();
  		demo.startExperiment(demo::printGeneration);
  		System.out.println("Experiment finished.");
  	}
  	
  	public void setFunction(Function<Double, Double> func) {
  		this.func = func;
  	}
  
  	public void setMutationProb(double mutProb) {
  		this.mutProb = mutProb;
  	}
  
  	public void setPopulationSize(int populationSize) {
  		this.populationSize = populationSize;
  	}
  
  	public void setMaxIterations(int maxIterations) {
  		this.maxIterations = maxIterations;
  	}
  
  	public void startExperiment(ProgressTracker<Double> pTracer) {
  		GeneticAlgorithmForNumbers genAlgo = new GeneticAlgorithmForNumbers(1, Functions.minX, Functions.maxX, mutProb);
  		genAlgo.addProgressTracer(pTracer);
  		fitnessFn = ind -> func.apply(ind.getRepresentation().get(0));
  		List<Individual<Double>> population = new ArrayList<Individual<Double>>();
  		for (int i = 0; i < populationSize; i++)
  			population.add(genAlgo.createRandomIndividual());
  		@SuppressWarnings("unused")
  		Individual<Double> best = genAlgo.geneticAlgorithm(population, fitnessFn, maxIterations);
  	}
  
  	private void printGeneration(int itCount, Collection<Individual<Double>> gen) {
  		System.out.println("\n" + getIterationInfo(itCount, gen));
  		List<Individual<Double>> generation = new ArrayList<>();
  		generation.addAll(gen);
  		Collections.sort(generation, Comparator.comparingDouble(fitnessFn::apply));
  		for (Individual<Double> ind : generation)
  			System.out.println(ind + " -> " + fitnessFn.apply(ind));
  	}
  
  	public String getIterationInfo(int itCount, Collection<Individual<Double>> gen) {
  		double avg = 0.0;
  		double max = Double.NEGATIVE_INFINITY;
  		DecimalFormat f = new DecimalFormat("#0.00");
  		for (Individual<Double> ind : gen) {
  			double fval = fitnessFn.apply(ind);
  			avg += fval;
  			max = Math.max(max, fval);
  		}
  		avg /= gen.size();
  		return "Generation: " + itCount + " Avg: " + f.format(avg) + " Max: " + f.format(max);
  	}
  }
  