GeneticAlgorithm.java
0001 /*
0002  * Java Genetic Algorithm Library (jenetics-1.5.0).
0003  * Copyright (c) 2007-2013 Franz Wilhelmstötter
0004  *
0005  * Licensed under the Apache License, Version 2.0 (the "License");
0006  * you may not use this file except in compliance with the License.
0007  * You may obtain a copy of the License at
0008  *
0009  *      http://www.apache.org/licenses/LICENSE-2.0
0010  *
0011  * Unless required by applicable law or agreed to in writing, software
0012  * distributed under the License is distributed on an "AS IS" BASIS,
0013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014  * See the License for the specific language governing permissions and
0015  * limitations under the License.
0016  *
0017  * Author:
0018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
0019  */
0020 package org.jenetics;
0021 
0022 import static java.lang.Math.round;
0023 import static java.lang.String.format;
0024 import static java.util.Objects.requireNonNull;
0025 import static org.jenetics.util.arrays.forEach;
0026 import static org.jenetics.util.object.NonNull;
0027 import static org.jenetics.util.object.checkProbability;
0028 
0029 import java.util.Collection;
0030 import java.util.concurrent.atomic.AtomicInteger;
0031 import java.util.concurrent.locks.Lock;
0032 import java.util.concurrent.locks.ReentrantLock;
0033 
0034 import org.jscience.mathematics.number.Float64;
0035 
0036 import org.jenetics.util.Array;
0037 import org.jenetics.util.Concurrency;
0038 import org.jenetics.util.Factory;
0039 import org.jenetics.util.Function;
0040 import org.jenetics.util.Timer;
0041 import org.jenetics.util.functions;
0042 
0043 /**
0044  <h3>Getting started</h3>
0045  *
0046  * The minimum GA setup needs a genotype factory, {@code Factory<Genotype<?>>},
0047  * and a fitness {@link Function}. The {@link Genotype} implements the
0048  {@link Factory} interface and can therefore be used as prototype for creating
0049  * the initial Population and for creating new random Genotypes.
0050  *
0051  * [code]
0052  * public static void main(final String[] args) {
0053  *     final Factory〈Genotype〈BitGene〉〉 gtf = Genotype.valueOf(
0054  *         BitChromosome.valueOf(10, 0.5)
0055  *     );
0056  *     final Function〈Genotype〈BitGene〉 Float64〉 ff = ...
0057  *     final GeneticAlgorithm〈BitGene, Float64〉
0058  *     ga = new GeneticAlgorithm〈〉(gtf, ff, Optimize.MAXIMUM);
0059  *
0060  *     ga.setup();
0061  *     ga.evolve(100);
0062  *     System.out.println(ga.getBestPhenotype());
0063  * }
0064  * [/code]
0065  *
0066  <p>
0067  * The genotype factory, {@code gtf}, in the example above will create genotypes
0068  * which consists of one {@link BitChromosome} with length 10. The one to zero
0069  * probability of the newly created genotypes is set to 0.5. The fitness function
0070  * is parametrized with a {@link BitGene} and a {@link Float64}. That means
0071  * that the fitness function is calculating the fitness value as {@link Float64}.
0072  * The return type of the fitness function must be at least a {@link Comparable}.
0073  * The {@code GeneticAlgorithm} object is then created with the genotype factory
0074  * and the fitness function. In this example the GA tries to maximize the fitness
0075  * function. If you want to find the minimal value you have to change the optimize
0076  * parameter from {@code Optimize.MAXIMUM} to {@code Optimize.MINIMUM}. The
0077  * {@code ga.setup()} call creates the initial population and calculates its
0078  * fitness value. Then the GA evolves 100 generations ({@code ga.evolve(100)})
0079  * an prints the best phenotype found so far onto the console.
0080  </p>
0081  * In a more advanced setup you may want to change the default mutation and/or
0082  * selection strategies.
0083  *
0084  * [code]
0085  * public static void main(final String[] args) {
0086  *     ...
0087  *     ga.setSelectors(new RouletteWheelSelector〈BitGene〉());
0088  *     ga.setAlterers(
0089  *         new SinglePointCrossover〈BitGene〉(0.1),
0090  *         new Mutator〈BitGene〉(0.01)
0091  *     );
0092  *
0093  *     ga.setup();
0094  *     ga.evolve(100);
0095  *     System.out.println(ga.getBestPhenotype());
0096  * }
0097  * [/code]
0098  *
0099  * The selection strategy for offspring and survivors are set to the
0100  * roulette-wheel selector. It is also possible to set the selector for
0101  * offspring and survivors independently with the {@code setOffspringSelector}
0102  * and {@code setSurvivorSelector} methods. The alterers are concatenated, at
0103  * first the crossover (with probability 0.1) is performed and then the
0104  * chromosomes are mutated (with probability 0.01).
0105  <p/>
0106  *
0107  <h3>Serialization</h3>
0108  *
0109  * With the serialization mechanism you can write a population to disk and load
0110  * it into an GA at a later time. It can also be used to transfer populations to
0111  * GAs, running on different hosts, over a network link. The IO class, located
0112  * in the {@code org.jenetics.util} package, supports native Java serialization
0113  * and XML serialization. For XML marshaling <em>Jenetics</em> internally uses
0114  * the XML support from the Javolution project.
0115  *
0116  * [code]
0117  * // Writing the population to disk.
0118  * final File file = new File("population.xml");
0119  * IO.xml.write(ga.getPopulation(), file);
0120  *
0121  * // Reading the population from disk.
0122  * Population〈Float64Gene,Float64〉 population =
0123  *     (Population〈Float64Gene, Float64〉)IO.xml.read(file);
0124  * ga.setPopulation(population);
0125  * [/code]
0126  *
0127  @see <a href="http://en.wikipedia.org/wiki/Genetic_algorithm">
0128  *          Wikipedia: Genetic algorithm
0129  *      </a>
0130  @see Alterer
0131  @see Selector
0132  *
0133  @param <G> The gene type this GA evaluates,
0134  @param <C> The result type (of the fitness function).
0135  *
0136  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
0137  @since 1.0
0138  @version 1.0 &mdash; <em>$Date: 2013-12-05 $</em>
0139  */
0140 public class GeneticAlgorithm<
0141     extends Gene<?, G>,
0142     extends Comparable<? super C>
0143 >
0144 {
0145 
0146     /**
0147      * The default population size used by this GA.
0148      */
0149     public static final int DEFAULT_POPULATION_SIZE = 50;
0150 
0151     /**
0152      * The default maximal phenotype age of this GA:
0153      */
0154     public static final int DEFAULT_MAXIMAL_PHENOTYPE_AGE = 70;
0155 
0156     /**
0157      * The default offspring fraction used by this GA.
0158      */
0159     public static final double DEFAULT_OFFSPRING_FRACTION = 0.6;
0160 
0161 
0162     private final Lock _lock = new ReentrantLock(true);
0163 
0164     private final Optimize _optimization;
0165 
0166     private final Factory<Genotype<G>> _genotypeFactory;
0167     private final Factory<Phenotype<G, C>> _phenotypeFactory;
0168     private final Function<Genotype<G>, C> _fitnessFunction;
0169     private Function<C, C> _fitnessScaler;
0170 
0171     private double _offspringFraction = DEFAULT_OFFSPRING_FRACTION;
0172 
0173     // Alterers
0174     private Alterer<G> _alterer = CompositeAlterer.valueOf(
0175         new SinglePointCrossover<G>(0.1),
0176         new Mutator<G>(0.05)
0177     );
0178 
0179     // Selectors
0180     private Selector<G, C> _survivorSelector = new TournamentSelector<>(3);
0181     private Selector<G, C> _offspringSelector = new TournamentSelector<>(3);
0182 
0183     // Population
0184     private int _populationSize = DEFAULT_POPULATION_SIZE;
0185     private Population<G, C> _population = new Population<>(_populationSize);
0186     private int _maximalPhenotypeAge = DEFAULT_MAXIMAL_PHENOTYPE_AGE;
0187     private volatile int _generation = 0;
0188 
0189     // Statistics
0190     private Statistics.Calculator<G, C> _calculator = new Statistics.Calculator<>();
0191     private Statistics<G, C> _bestStatistics = null;
0192     private Statistics<G, C> _statistics = null;
0193     private final AtomicInteger _killed = new AtomicInteger(0);
0194     private final AtomicInteger _invalid = new AtomicInteger(0);
0195 
0196     //Some performance measure.
0197     private final Timer _executionTimer = new Timer("Execution time");
0198     private final Timer _selectTimer = new Timer("Select time");
0199     private final Timer _alterTimer = new Timer("Alter time");
0200     private final Timer _combineTimer = new Timer("Combine survivors and offspring time");
0201     private final Timer _statisticTimer = new Timer("Statistic time");
0202     private final Timer _evaluateTimer = new Timer("Evaluate time");
0203 
0204 
0205     /**
0206      * Create a new genetic algorithm.
0207      *
0208      @param genotypeFactory the genotype factory this GA is working with.
0209      @param fitnessFunction the fitness function this GA is using.
0210      @param fitnessScaler the fitness scaler this GA is using.
0211      @param optimization Determine whether this GA maximize or minimize the
0212      *        fitness function.
0213      @throws NullPointerException if one of the arguments is {@code null}.
0214      */
0215     public GeneticAlgorithm(
0216         final Factory<Genotype<G>> genotypeFactory,
0217         final Function<Genotype<G>, C> fitnessFunction,
0218         final Function<C, C> fitnessScaler,
0219         final Optimize optimization
0220     ) {
0221         _genotypeFactory = requireNonNull(genotypeFactory, "GenotypeFactory");
0222         _fitnessFunction = requireNonNull(fitnessFunction, "FitnessFunction");
0223         _fitnessScaler = requireNonNull(fitnessScaler, "FitnessScaler");
0224         _optimization = requireNonNull(optimization, "Optimization");
0225 
0226         _phenotypeFactory = new Factory<Phenotype<G, C>>() {
0227             @Override public Phenotype<G, C> newInstance() {
0228                 return Phenotype.valueOf(
0229                     _genotypeFactory.newInstance(),
0230                     _fitnessFunction,
0231                     _fitnessScaler,
0232                     _generation
0233                 );
0234             }
0235         };
0236     }
0237 
0238     /**
0239      * Create a new genetic algorithm. By default the GA tries to maximize the
0240      * fitness function.
0241      *
0242      @param genotypeFactory the genotype factory this GA is working with.
0243      @param fitnessFunction the fitness function this GA is using.
0244      @throws NullPointerException if one of the arguments is {@code null}.
0245      */
0246     public GeneticAlgorithm(
0247         final Factory<Genotype<G>> genotypeFactory,
0248         final Function<Genotype<G>, C> fitnessFunction
0249     ) {
0250         this(
0251             genotypeFactory,
0252             fitnessFunction,
0253             functions.<C>Identity(),
0254             Optimize.MAXIMUM
0255         );
0256     }
0257 
0258     /**
0259      * Create a new genetic algorithm.
0260      *
0261      @param genotypeFactory the genotype factory this GA is working with.
0262      @param fitnessFunction the fitness function this GA is using.
0263      @param optimization Determine whether this GA maximize or minimize the
0264      *        fitness function.
0265      @throws NullPointerException if one of the arguments is {@code null}.
0266      */
0267     public GeneticAlgorithm(
0268         final Factory<Genotype<G>> genotypeFactory,
0269         final Function<Genotype<G>, C> fitnessFunction,
0270         final Optimize optimization
0271     ) {
0272         this(
0273             genotypeFactory,
0274             fitnessFunction,
0275             functions.<C>Identity(),
0276             optimization
0277         );
0278     }
0279 
0280     /**
0281      * Create a new genetic algorithm. By default the GA tries to maximize the
0282      * fitness function.
0283      *
0284      @param genotypeFactory the genotype factory this GA is working with.
0285      @param fitnessFunction the fitness function this GA is using.
0286      @param fitnessScaler the fitness scaler this GA is using.
0287      @throws NullPointerException if one of the arguments is {@code null}.
0288      */
0289     public GeneticAlgorithm(
0290         final Factory<Genotype<G>> genotypeFactory,
0291         final Function<Genotype<G>, C> fitnessFunction,
0292         final Function<C, C> fitnessScaler
0293     ) {
0294         this(
0295             genotypeFactory,
0296             fitnessFunction,
0297             fitnessScaler,
0298             Optimize.MAXIMUM
0299         );
0300     }
0301 
0302     /**
0303      * Create the initial population of the GA. Subsequent calls to this
0304      * method throw IllegalStateException. If no initial population has been
0305      * set (with {@link #setPopulation(Collection)} or
0306      {@link #setGenotypes(Collection)}) a random population is generated.
0307      *
0308      @throws IllegalStateException if called more than once.
0309      */
0310     public void setup() {
0311         _lock.lock();
0312         try {
0313             prepareSetup();
0314             _population.fill(
0315                 _phenotypeFactory,
0316                 _populationSize - _population.size()
0317             );
0318             finishSetup();
0319         finally {
0320             _lock.unlock();
0321         }
0322     }
0323 
0324     /**
0325      * Setting up the {@code GeneticAlgorithm} with the given initial
0326      * population. Subsequent calls to this method throw an IllegalStateException.
0327      * This method is similar to the {@link #setGenotypes(Collection)} and
0328      {@link #setPopulation(Collection)} methods, but this method is required
0329      * to be called only once and before starting evaluation. It also calculates
0330      * the timing statistics when (calculating the fitness values for the given
0331      * genotypes.
0332      *
0333      @see #setGenotypes(Collection)
0334      @see #setPopulation(Collection)
0335      @param genotypes the initial population.
0336      @throws IllegalStateException if called more than once.
0337      */
0338     public void setup(final Collection<Genotype<G>> genotypes) {
0339         _lock.lock();
0340         try {
0341             prepareSetup();
0342             setGenotypes(genotypes);
0343             finishSetup();
0344         finally {
0345             _lock.unlock();
0346         }
0347     }
0348 
0349     private void prepareSetup() {
0350         if (_generation > 0) {
0351             throw new IllegalStateException(
0352                 "The method GeneticAlgorithm.setup() must be called only once."
0353             );
0354         }
0355 
0356         ++_generation;
0357         _executionTimer.start();
0358     }
0359 
0360     private void finishSetup() {
0361         //Evaluate the fitness.
0362         evaluate();
0363 
0364         //First valuation of the initial population.
0365         _statisticTimer.start();
0366         _statistics = _calculator.evaluate(
0367             _population, _generation, _optimization
0368         ).build();
0369 
0370         _bestStatistics = _statistics;
0371         _statisticTimer.stop();
0372 
0373         _executionTimer.stop();
0374 
0375         setTimes(_statistics);
0376     }
0377 
0378     /**
0379      * Evolve one generation.
0380      *
0381      @throws IllegalStateException if the {@link GeneticAlgorithm#setup()}
0382      *         method was not called first.
0383      */
0384     public void evolve() {
0385         _lock.lock();
0386         try {
0387             // Check the setup state.
0388             if (_generation == 0) {
0389                 throw new IllegalStateException(
0390                     "Call the GeneticAlgorithm.setup() method before " +
0391                     "calling GeneticAlgorithm.evolve()."
0392                 );
0393             }
0394 
0395             //Start the overall execution timer.s
0396             _executionTimer.start();
0397 
0398             //Increment the generation and the generation.
0399             ++_generation;
0400 
0401             //Select the survivors and the offsprings.
0402             _selectTimer.start();
0403             final Array<Population<G, C>> selection = select();
0404             final Population<G, C> survivors = selection.get(0);
0405             final Population<G, C> offsprings = selection.get(1);
0406             _selectTimer.stop();
0407 
0408             //Alter the offsprings (Recombination, Mutation ...).
0409             _alterTimer.start();
0410             _alterer.alter(offsprings, _generation);
0411             _alterTimer.stop();
0412 
0413             // Combining the new population (containing the survivors and the
0414             // altered offsprings).
0415             _combineTimer.start();
0416             final int killed = _killed.get();
0417             final int invalid = _invalid.get();
0418             _population = combine(survivors, offsprings);
0419             _combineTimer.stop();
0420 
0421             //Evaluate the fitness
0422             evaluate();
0423 
0424             //Evaluate the statistic
0425             _statisticTimer.start();
0426             final Statistics.Builder<G, C> builder = _calculator.evaluate(
0427                     _population, _generation, _optimization
0428                 );
0429             builder.killed(_killed.get() - killed);
0430             builder.invalid(_invalid.get() - invalid);
0431             _statistics = builder.build();
0432 
0433             final int comp = _optimization.compare(
0434                 _statistics.getBestPhenotype(),
0435                 _bestStatistics.getBestPhenotype()
0436             );
0437 
0438             if (comp > 0) {
0439                 _bestStatistics = _statistics;
0440             }
0441 
0442             _statisticTimer.stop();
0443 
0444             _executionTimer.stop();
0445 
0446             setTimes(_statistics);
0447         finally {
0448             _lock.unlock();
0449         }
0450     }
0451 
0452     private void setTimes(final Statistics<?, ?> statistic) {
0453         statistic.getTime().execution.set(_executionTimer.getInterimTime());
0454         statistic.getTime().selection.set(_selectTimer.getInterimTime());
0455         statistic.getTime().alter.set(_alterTimer.getInterimTime());
0456         statistic.getTime().combine.set(_combineTimer.getInterimTime());
0457         statistic.getTime().evaluation.set(_evaluateTimer.getInterimTime());
0458         statistic.getTime().statistics.set(_statisticTimer.getInterimTime());
0459     }
0460 
0461     private void evaluate() {
0462         _evaluateTimer.start();
0463         try (Concurrency c = Concurrency.start()) {
0464             for (int i =  _population.size(); --i >= 0;) {
0465                 c.execute(_population.get(i));
0466             }
0467         }
0468         _evaluateTimer.stop();
0469     }
0470 
0471     /**
0472      * Evolve the given number of {@code generations}
0473      *
0474      @param generations the number of {@code generations} to evolve.
0475      */
0476     public void evolve(final int generations) {
0477         for (int i = 0; i < generations; ++i) {
0478             evolve();
0479         }
0480     }
0481 
0482     /**
0483      * Evolve the GA as long the given {@link Function} returns {@code true}.
0484      *
0485      @see termination
0486      *
0487      @param until the predicate which defines the termination condition.
0488      @throws NullPointerException if the given predicate is {@code null}.
0489      */
0490     public void evolve(final Function<? super Statistics<G, C>, Boolean> until) {
0491         requireNonNull(until, "Termination condition");
0492         while (until.apply(getStatistics())) {
0493             evolve();
0494         }
0495     }
0496 
0497     private Array<Population<G, C>> select() {
0498         final Array<Population<G, C>> selection = new Array<>(2);
0499         final int numberOfSurvivors = getNumberOfSurvivors();
0500         final int numberOfOffspring = getNumberOfOffsprings();
0501         assert (numberOfSurvivors + numberOfOffspring == _populationSize);
0502 
0503         try (Concurrency c = Concurrency.start()) {
0504             c.execute(new Runnable() { @Override public void run() {
0505                 final Population<G, C> survivors = _survivorSelector.select(
0506                     _population, numberOfSurvivors, _optimization
0507                 );
0508 
0509                 assert (survivors.size() == numberOfSurvivors);
0510                 selection.set(0, survivors);
0511             }});
0512 
0513             final Population<G, C> offsprings = _offspringSelector.select(
0514                 _population, numberOfOffspring, _optimization
0515             );
0516 
0517             assert (offsprings.size() == numberOfOffspring);
0518             selection.set(1, offsprings);
0519         }
0520 
0521         return selection;
0522     }
0523 
0524     private Population<G, C> combine(
0525         final Population<G, C> survivors,
0526         final Population<G, C> offsprings
0527     ) {
0528         assert (survivors.size() + offsprings.size() == _populationSize);
0529         final Population<G, C> population = new Population<>(_populationSize);
0530 
0531         try (Concurrency c = Concurrency.start()) {
0532             // Kill survivors which are to old and replace it with new one.
0533             c.execute(new Runnable() { @Override public void run() {
0534                 for (int i = 0, n = survivors.size(); i < n; ++i) {
0535                     final Phenotype<G, C> survivor = survivors.get(i);
0536 
0537                     final boolean isTooOld =
0538                         survivor.getAge(_generation> _maximalPhenotypeAge;
0539 
0540                     final boolean isInvalid = isTooOld || !survivor.isValid();
0541 
0542                     // Sorry, too old or not valid.
0543                     if (isInvalid) {
0544                         survivors.set(i, _phenotypeFactory.newInstance());
0545                     }
0546 
0547                     if (isTooOld) {
0548                         _killed.incrementAndGet();
0549                     else if (isInvalid) {
0550                         _invalid.incrementAndGet();
0551                     }
0552                 }
0553             }});
0554 
0555             // In the mean time we can add the offsprings.
0556             population.addAll(offsprings);
0557         }
0558 
0559         population.addAll(survivors);
0560 
0561         return population;
0562     }
0563 
0564     private int getNumberOfSurvivors() {
0565         return _populationSize - getNumberOfOffsprings();
0566     }
0567 
0568     private int getNumberOfOffsprings() {
0569         return (int)round(
0570             _offspringFraction*_populationSize
0571         );
0572     }
0573 
0574     /**
0575      * Return {@code true} if the {@link #setup()} method has already been called,
0576      * {@code false} otherwise.
0577      *
0578      @return {@code true} if the {@link #setup()} method has already been called,
0579      *         {@code false} otherwise.
0580      */
0581     public boolean isInitialized() {
0582         _lock.lock();
0583         try {
0584             return _generation > 0;
0585         finally {
0586             _lock.unlock();
0587         }
0588     }
0589 
0590     /**
0591      <p>
0592      * If you are using the {@code GeneticAlgorithm} in an threaded environment
0593      * and you want to change some of the GAs parameters you can use the returned
0594      {@link Lock} to synchronize your parameter changes. The GA acquires the
0595      * lock at the begin of the {@link #setup()} and the {@link #evolve()}
0596      * methods and releases it at the end of these methods.
0597      </p>
0598      * To set one ore more GA parameter you will write code like this:
0599      * [code]
0600      * final GeneticAlgorithm〈Float64Gene, Float64〉 ga = ...
0601      * final Function〈GeneticAlgorithm〈?, ?〉, Boolean〉 until = ...
0602      *
0603      * //Starting the GA in separate thread.
0604      * final Thread thread = new Thread(new Runnable() {
0605      *     public void run() {
0606      *         while (!Thread.currentThread().isInterrupted() &&
0607      *                !until.apply(ga))
0608      *         {
0609      *             if (ga.getGeneration() == 0) {
0610      *                 ga.setup();
0611      *             } else {
0612      *                 ga.evolve();
0613      *             }
0614      *         }
0615      *     }
0616      * });
0617      * thread.start();
0618      *
0619      *  //Changing the GA parameters outside the evolving thread. All parameters
0620      *  //are changed before the next evolve step.
0621      * ga.getLock().lock();
0622      * try {
0623      *     ga.setAlterer(new Mutation(0.02);
0624      *     ga.setPopulationSize(55);
0625      *     ga.setMaximalPhenotypeAge(30);
0626      * } finally {
0627      *     ga.getLock().unlock();
0628      * }
0629      * [/code]
0630      *
0631      * You can use the same lock if you want get a consistent state of the used
0632      * parameters, if they where changed within an other thread.
0633      *
0634      * [code]
0635      * ga.getLock().lock();
0636      * try {
0637      *     final Statistics〈?, ?〉 statistics = ga.getStatistic();
0638      *     final Function〈?, ?〉 scaler = ga.getFitnessScaler();
0639      * } finally {
0640      *     ga.getLock().unlock();
0641      * }
0642      * [/code]
0643      *
0644      * The code above ensures that the returned {@code statistics} and
0645      * {@code scaler} where used together within the same {@link #evolve()} step.
0646      *
0647      @return the lock acquired in the {@link #setup()} and the {@link #evolve()}
0648      *         method.
0649      */
0650     public Lock getLock() {
0651         return _lock;
0652     }
0653 
0654     /**
0655      * Return the used genotype {@link Factory} of the GA. The genotype factory
0656      * is used for creating the initial population and new, random individuals
0657      * when needed (as replacement for invalid and/or died genotypes).
0658      *
0659      @return the used genotype {@link Factory} of the GA.
0660      */
0661     public Factory<Genotype<G>> getGenotypeFactory() {
0662         return _genotypeFactory;
0663     }
0664 
0665     /**
0666      <p>
0667      * Return the used fitness {@link Function} of the GA. The fitness function
0668      * is also an important part when modeling the GA. It takes a genotype as
0669      * argument and returns, at least, a Comparable object as result---the
0670      * fitness value. This allows the GA, respectively the selection operators,
0671      * to select the offspring- and survivor population. Some selectors have
0672      * stronger requirements to the fitness value than a Comparable, but this
0673      * constraints is checked by the Java type system at compile time.
0674      </p>
0675      * The following example shows the simplest possible fitness function. It's
0676      * the identity function and returns the allele of an 1x1  float genotype.
0677      * [code]
0678      * class Id implements Function〈Genotype〈Float64Gene〉, Float64〉 {
0679      *     public Float64 apply(final Genotype〈Float64Gene〉 genotype) {
0680      *         return genotype.getGene().getAllele();
0681      *     }
0682      * }
0683      * [/code]
0684      * The first type parameter of the {@link Function} defines the kind of
0685      * genotype from which the fitness value is calculated and the second type
0686      * parameter determines the return type. As already mentioned, the return
0687      * type must implement the {@link Comparable} interface.
0688      *
0689      @return the used fitness {@link Function} of the GA.
0690      */
0691     public Function<Genotype<G>, C> getFitnessFunction() {
0692         return _fitnessFunction;
0693     }
0694 
0695     /**
0696      * Set the currently used fitness scaler. The fitness value, calculated by
0697      * the fitness function, is the raw-fitness of an individual. The
0698      <em>Jenetics</em> library allows you to apply an additional scaling
0699      * function on the raw-fitness to form the fitness value which is used by
0700      * the selectors. This can be useful when using probability selectors, where
0701      * the actual amount of the fitness value influences the selection
0702      * probability. In such cases, the fitness scaler gives you additional
0703      * flexibility when selecting offspring and survivors. In the default
0704      * configuration the raw-fitness is equal to the actual fitness value, that
0705      * means, the used fitness scaler is the identity function.
0706      * [code]
0707      * class Sqrt extends Function〈Float64, Float64〉 {
0708      *     public Float64 apply(final Float64 value) {
0709      *         return Float64.valueOf(sqrt(value.doubleValue()));
0710      *     }
0711      * }
0712      * [/code]
0713      *
0714      <p>
0715      * The listing above shows a fitness scaler which reduces the the raw-fitness
0716      * to its square root. This gives weaker individuals a greater changes being
0717      * selected and weakens the influence of super-individuals.
0718      </p>
0719      * When using a fitness scaler you have to take care, that your scaler
0720      * doesn't destroy your fitness value. This can be the case when your
0721      * fitness value is negative and your fitness scaler squares the value.
0722      * Trying to find the minimum will not work in this configuration.</b>
0723      *
0724      @param scaler The fitness scaler.
0725      @throws NullPointerException if the scaler is {@code null}.
0726      */
0727     public void setFitnessScaler(final Function<C, C> scaler) {
0728         _fitnessScaler = requireNonNull(scaler, "FitnessScaler");
0729     }
0730 
0731     /**
0732      * Return the currently used fitness scaler {@link Function} of the GA.
0733      *
0734      @return the currently used fitness scaler {@link Function} of the GA.
0735      */
0736     public Function<C, C> getFitnessScaler() {
0737         return _fitnessScaler;
0738     }
0739 
0740     /**
0741      * Return the currently used offspring fraction of the GA.
0742      *
0743      @return the currently used offspring fraction of the GA.
0744      */
0745     public double getOffspringFraction() {
0746         return _offspringFraction;
0747     }
0748 
0749     /**
0750      * Return the currently used offspring {@link Selector} of the GA.
0751      *
0752      @return the currently used offspring {@link Selector} of the GA.
0753      */
0754     public Selector<G, C> getOffspringSelector() {
0755         return _offspringSelector;
0756     }
0757 
0758     /**
0759      * Return the currently used survivor {@link Selector} of the GA.
0760      *
0761      @return the currently used survivor {@link Selector} of the GA.
0762      */
0763     public Selector<G, C> getSurvivorSelector() {
0764         return _survivorSelector;
0765     }
0766 
0767     /**
0768      * Return the currently used {@link Alterer} of the GA.
0769      *
0770      @return the currently used {@link Alterer} of the GA.
0771      */
0772     public Alterer<G> getAlterer() {
0773         return _alterer;
0774     }
0775 
0776     /**
0777      * Return the current overall generation.
0778      *
0779      @return the current overall generation.
0780      */
0781     public int getGeneration() {
0782         return _generation;
0783     }
0784 
0785     /**
0786      * Return the maximal age of the {@link Phenotype}s.
0787      *
0788      @return the maximal age of the {@link Phenotype}s.
0789      */
0790     public int getMaximalPhenotypeAge() {
0791         return _maximalPhenotypeAge;
0792     }
0793 
0794     /**
0795      * Return the best {@link Phenotype} so far or {@code null} if the GA hasn't
0796      * been initialized yet.
0797      *
0798      @return the best {@link Phenotype} so far or {@code null} if the GA hasn't
0799      *         been initialized yet.
0800      */
0801     public Phenotype<G, C> getBestPhenotype() {
0802         return _bestStatistics != null ? _bestStatistics.getBestPhenotype() null;
0803     }
0804 
0805     /**
0806      * Return the current {@link Population} {@link Statistics} or {@code null}
0807      * if the GA hasn't been initialized yet.
0808      *
0809      @return the current {@link Population} {@link Statistics} or {@code null}
0810      *         if the GA hasn't been initialized yet.
0811      */
0812     public Statistics<G, C> getStatistics() {
0813         return _statistics;
0814     }
0815 
0816     /**
0817      * Set the offspring selector.
0818      *
0819      @param selector The offspring selector.
0820      @throws NullPointerException, if the given selector is null.
0821      */
0822     public void setOffspringSelector(final Selector<G, C> selector) {
0823         _offspringSelector = requireNonNull(selector, "Offspring selector");
0824     }
0825 
0826     /**
0827      * Set the survivor selector.
0828      *
0829      @param selector The survivor selector.
0830      @throws NullPointerException, if the given selector is null.
0831      */
0832     public void setSurvivorSelector(final Selector<G, C> selector) {
0833         _survivorSelector = requireNonNull(selector, "Survivor selector");
0834     }
0835 
0836     /**
0837      * Set both, the offspring selector and the survivor selector.
0838      *
0839      @param selector The selector for the offspring and the survivors.
0840      @throws NullPointerException if the {@code selector} is {@code null}
0841      */
0842     public void setSelectors(final Selector<G, C> selector) {
0843         setOffspringSelector(selector);
0844         setSurvivorSelector(selector);
0845     }
0846 
0847     /**
0848      * Set the offspring fraction.
0849      *
0850      @param offspringFraction The offspring fraction.
0851      @throws IllegalArgumentException if the offspring fraction is out of
0852      *         range.
0853      */
0854     public void setOffspringFraction(final double offspringFraction) {
0855         _offspringFraction = checkProbability(offspringFraction);
0856     }
0857 
0858     /**
0859      * Set the alterer.
0860      *
0861      @param alterer The alterer.
0862      @throws NullPointerException if the alterer is null.
0863      */
0864     public void setAlterer(final Alterer<G> alterer) {
0865         _alterer = requireNonNull(alterer, "Alterer");
0866     }
0867 
0868     /**
0869      * Set the given alterers.
0870      *
0871      @param alterers the alterers to set.
0872      @throws NullPointerException if the alterers are null.
0873      */
0874     @SafeVarargs
0875     public final void setAlterers(final Alterer<G>... alterers) {
0876         setAlterer(CompositeAlterer.valueOf(alterers));
0877     }
0878 
0879     /**
0880      * Set the maximum age of the phenotypes in the population.
0881      *
0882      @param age Maximal phenotype age.
0883      @throws IllegalArgumentException if the age is smaller then one.
0884      */
0885     public void setMaximalPhenotypeAge(final int age) {
0886         if (age < 1) {
0887             throw new IllegalArgumentException(format(
0888                 "Phenotype age must be greater than one, but was %s.", age
0889             ));
0890         }
0891         _maximalPhenotypeAge = age;
0892     }
0893 
0894     /**
0895      * Set the desired population size.
0896      *
0897      @param size The population size.
0898      @throws IllegalArgumentException if the population size is smaller than
0899      *         one.
0900      */
0901     public void setPopulationSize(final int size) {
0902         if (size < 1) {
0903             throw new IllegalArgumentException(format(
0904                 "Population size must be greater than zero, but was %s.", size
0905             ));
0906         }
0907         _populationSize = size;
0908     }
0909 
0910     /**
0911      * Set the (initial) population in form of a list of phenotypes. The fitness
0912      * function and fitness scaler of the phenotypes will be changed with the
0913      * current one of this GA. The fitness values are calculated as needed by
0914      * the next <i>evolve</i> step. <em>This method doesn't acquire the GA lock.
0915      * When used from another thread, the lock must be acquired from outside.</em>
0916      *
0917      @see #setGenotypes(Collection)
0918      @see #setup(Collection)
0919      @param population The list of phenotypes to set. The population size is
0920      *        set to {@code phenotype.size()}.
0921      @throws NullPointerException if the population, or one of its element, is
0922      *         {@code null}.
0923      @throws IllegalArgumentException it the population size is smaller than
0924      *         one.
0925      */
0926     public void setPopulation(final Collection<Phenotype<G, C>> population) {
0927         forEach(population, NonNull);
0928         if (population.size() 1) {
0929             throw new IllegalArgumentException(format(
0930                 "Population size must be greater than zero, but was %s.",
0931                 population.size()
0932             ));
0933         }
0934 
0935         final Population<G, C> pop = new Population<>(population.size());
0936         for (Phenotype<G, C> phenotype : population) {
0937             pop.add(phenotype.newInstance(
0938                 _fitnessFunction, _fitnessScaler, _generation
0939             ));
0940         }
0941 
0942         _population = pop;
0943         _populationSize = population.size();
0944     }
0945 
0946     /**
0947      * Set/change the population in form of a list of genotypes. The fitness
0948      * function and fitness scaler will not be changed. The fitness values are
0949      * calculated as needed by the next <i>evolve</i> step. <em>This method
0950      * doesn't acquire the GA lock. When used from another thread, the lock must
0951      * be acquired from outside.</em>
0952      *
0953      @see #setPopulation(Collection)
0954      @see #setup(Collection)
0955      @param genotypes The list of genotypes to set. The population size is set
0956      *        to {@code genotypes.size()}.
0957      @throws NullPointerException if the population, or one of its elements,
0958      *         is {@code null}s.
0959      @throws IllegalArgumentException it the population size is smaller than
0960      *         one.
0961      */
0962     public void setGenotypes(final Collection<Genotype<G>> genotypes) {
0963         forEach(genotypes, NonNull);
0964         if (genotypes.size() 1) {
0965             throw new IllegalArgumentException(
0966                 "Genotype size must be greater than zero, but was " +
0967                 genotypes.size() ". "
0968             );
0969         }
0970 
0971         final Population<G, C> population = new Population<>(genotypes.size());
0972         for (Genotype<G> genotype : genotypes) {
0973             population.add(Phenotype.valueOf(
0974                 genotype,
0975                 _fitnessFunction,
0976                 _fitnessScaler,
0977                 _generation
0978             ));
0979         }
0980 
0981         _population = population;
0982         _populationSize = genotypes.size();
0983     }
0984 
0985     /**
0986      * Return a copy of the current population.
0987      *
0988      @return The copy of the current population.
0989      */
0990     public Population<G, C> getPopulation() {
0991         return new Population<>(_population);
0992     }
0993 
0994     /**
0995      * Return the desired population size of the GA.
0996      *
0997      @return the desired population size of the GA.
0998      */
0999     public int getPopulationSize() {
1000         return _populationSize;
1001     }
1002 
1003     /**
1004      * Return the statistics of the best phenotype. The returned statistics is
1005      * {@code null} if the algorithms hasn't been initialized.
1006      *
1007      @return the statistics of the best phenotype, or {@code null} if the GA
1008      *         hasn't been initialized yet.
1009      */
1010     public Statistics<G, C> getBestStatistics() {
1011         return _bestStatistics;
1012     }
1013 
1014     /**
1015      * Return the number of killed phenotypes, so far.
1016      *
1017      @return the number of killed phenotypes
1018      */
1019     public int getNumberOfKilledPhenotypes() {
1020         return _killed.get();
1021     }
1022 
1023     /**
1024      * Return the number of invalid phenotypes, so far.
1025      *
1026      @return the number of invalid phenotypes
1027      */
1028     public int getNumberOfInvalidPhenotypes() {
1029         return _invalid.get();
1030     }
1031 
1032     /**
1033      * Set the statistic calculator for this genetic algorithm instance.
1034      *
1035      @param calculator the new statistic calculator.
1036      @throws NullPointerException if the given {@code calculator} is
1037      *         {@code null}.
1038      */
1039     public void setStatisticsCalculator(
1040         final Statistics.Calculator<G, C> calculator
1041     ) {
1042         _calculator = requireNonNull(calculator, "Statistic calculator");
1043     }
1044 
1045     /**
1046      * Return the current statistics calculator.
1047      *
1048      @return the current statistics calculator.
1049      */
1050     public Statistics.Calculator<G, C> getStatisticsCalculator() {
1051         return _calculator;
1052     }
1053 
1054     /**
1055      * Return the current time statistics of the GA. This method acquires the
1056      * lock to ensure that the returned values are consistent.
1057      *
1058      @return the current time statistics.
1059      */
1060     public Statistics.Time getTimeStatistics() {
1061         _lock.lock();
1062         try {
1063             final Statistics.Time time = new Statistics.Time();
1064             time.alter.set(_alterTimer.getTime());
1065             time.combine.set(_combineTimer.getTime());
1066             time.evaluation.set(_evaluateTimer.getTime());
1067             time.execution.set(_executionTimer.getTime());
1068             time.selection.set(_selectTimer.getTime());
1069             time.statistics.set(_statisticTimer.getTime());
1070             return time;
1071         finally {
1072             _lock.unlock();
1073         }
1074     }
1075 
1076     /**
1077      * This method acquires the lock to ensure that the returned value is
1078      * consistent.
1079      */
1080     @Override
1081     public String toString() {
1082         Phenotype<G, C> phenotype = null;
1083         int generation = 0;
1084 
1085         _lock.lock();
1086         try {
1087             generation = _generation;
1088             phenotype = getStatistics().getBestPhenotype();
1089         finally {
1090             _lock.unlock();
1091         }
1092 
1093         return format("%4d: (best) %s", generation, phenotype);
1094     }
1095 
1096 }
1097 
1098 
1099 
1100 
1101 
1102