/*
* This file is part of n-genes2.
*
* n-genes2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* n-genes2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with n-genes2. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2010, Paradigmatic <paradigmatic@streum.org>
*
*/
package ngenes2.examples;
import java.util.List;
import java.util.Random;
import ngenes2.builder.BasicDIBuilder;
import ngenes2.breeder.Breeder;
import ngenes2.breeder.ClassicalBreeder;
import ngenes2.builder.Builder;
import ngenes2.evolver.ClassicEvolver;
import ngenes2.evolver.Evolver;
import ngenes2.evolver.monitor.GenerationMonitor;
import ngenes2.evolver.stop.FitnessTarget;
import ngenes2.evolver.stop.MaxGeneration;
import ngenes2.evolver.stop.StopCondition;
import ngenes2.individual.LinearIndividual;
import ngenes2.individual.generator.Generator;
import ngenes2.individual.generator.bool.RandomBooleanGenerator;
import ngenes2.ops.crossover.Crossover;
import ngenes2.ops.crossover.MidBreakCrossover;
import ngenes2.ops.mutator.Mutator;
import ngenes2.ops.mutator.PointMutation;
import ngenes2.ops.mutator.genes.bool.BooleanFlipper;
import ngenes2.ops.selector.KTournament;
import ngenes2.ops.selector.Selector;
import ngenes2.population.BasicPopulation;
import ngenes2.population.Population;
import ngenes2.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* MaxOnes is a classical GA toy problem, considered as a good introductory
* problem. The goal is to "optimized" random boolean individuals until
* all genes have a true value.
*/
public class MaxOnes {
private final static Logger logger = LoggerFactory.getLogger(MaxOnes.class);
/**
* MaxOnes Fitness. Simply count the number of False genes and divide the
* count by the chromosome size.
*/
public static class Fitness implements ngenes2.fitness.Fitness<Boolean> {
public double compute(List<Boolean> chromosome) {
double sum = 0.0;
for( Boolean b: chromosome ) {
if( ! b ) {
sum += 1.0;
}
}
return sum / chromosome.size();
}
}
/**
* This monitor logs the best individual of each generation.
*/
public final static GenerationMonitor<Boolean,LinearIndividual<Boolean>> monitor
= new GenerationMonitor<Boolean, LinearIndividual<Boolean>>() {
public void newGeneration(int generationNumber, Population<Boolean, LinearIndividual<Boolean>> pop) {
LinearIndividual<Boolean> best = pop.stats().best();
logger.info("Generation {}: best individual fitness = {}", generationNumber, best.fitness());
}
};
/**
* Example of maxones setting with handmade wiring of components.
*/
private static void exampleByHand() {
Random rng = new Random();
final int indSize = 20;
final int popSize = 100;
final int genNum = 50;
Properties props = new Properties()
.put("tournament_size",3)
.put("population_size",20)
.put("chromosome_size", indSize)
.put("fitness_target", 10e-9)
.put("max_generation", genNum);
Generator<Boolean,LinearIndividual<Boolean>> gen =
new Generator<Boolean, LinearIndividual<Boolean>>(
new LinearIndividual.Factory<Boolean>(),
new Fitness(),
new RandomBooleanGenerator(rng, props)
);
Population<Boolean,LinearIndividual<Boolean>> pop =
new BasicPopulation<Boolean, LinearIndividual<Boolean>>(
gen.generate(props.getInt("population_size"))
);
Selector<LinearIndividual<Boolean>> sel =
new KTournament<LinearIndividual<Boolean>>(rng,props);
Crossover<Boolean,LinearIndividual<Boolean>> co =
new Crossover<Boolean, LinearIndividual<Boolean>>( new MidBreakCrossover<Boolean>() );
Mutator<Boolean,LinearIndividual<Boolean>> mut = new Mutator<Boolean, LinearIndividual<Boolean>>(
new PointMutation<Boolean>( rng, new BooleanFlipper() )
);
StopCondition<Boolean,LinearIndividual<Boolean>> stop =
new FitnessTarget<Boolean,LinearIndividual<Boolean>>(props)
.or( new MaxGeneration<Boolean,LinearIndividual<Boolean>>(props) );
Breeder<Boolean,LinearIndividual<Boolean>> breeder =
new ClassicalBreeder<Boolean,LinearIndividual<Boolean>>(co, mut);
Evolver<Boolean,LinearIndividual<Boolean>> evolver =
new ClassicEvolver<Boolean, LinearIndividual<Boolean>>(sel, breeder, monitor,stop);
evolver.evolve(pop);
}
/**
* Example of maxones setting using automatic wiring.
*/
@SuppressWarnings("unchecked")
private static void exampleWithDIBuilder() {
Properties prop = new Properties()
.put("tournament_size",3)
.put("chromosome_size", 200)
.put("population_size", 100)
.put("fitness_target", 10e-9)
.put("max_generation", 500);
Builder builder = new BasicDIBuilder()
.with(prop)
.with(LinearIndividual.Factory.class)
.with(new Fitness())
.with(RandomBooleanGenerator.class)
.with(KTournament.class)
.with(BooleanFlipper.class)
.with(PointMutation.class)
.with(MidBreakCrossover.class)
.with(monitor)
.with( new FitnessTarget(prop).or( new MaxGeneration(prop) ) );
Evolver evolver = builder.evolver();
Population pop = builder.population();
evolver.evolve(pop);
System.out.println( pop.stats().best() );
}
public static void main(String[] args) {
//exampleByHand();
exampleWithDIBuilder();
}
}