/* * 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.ops.selector; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Random; import ngenes2.individual.Individual; import ngenes2.population.Population; import ngenes2.util.Properties; /** * Select individuals from a population using a <i>K</i>-tournament operation. Each time * an individual must be selected, <i>K</i> individuals are drawn at random from the population * (equal probability) and the individual with the best fitness is returned. The tournament * size must be specified using the integer property <b>tournament_size</b>. * @param <I> Individual type */ public class KTournament<I extends Individual<?,I>> implements Selector<I> { private final int K; private final Random rng; /** * Sole constructor. * @param rng A random number generator. * @param props A property instance holding the integer property <b>tournament_size</b> */ public KTournament(Random rng, Properties props) { this.K = props.getInt("tournament_size"); this.rng = rng; } private I getRandom( Population<?,I> pop ) { return pop.get( rng.nextInt( pop.size() ) ); } public I select(Population<?,I> pop) { I winner = getRandom(pop); double bestFitness = winner.fitness(); for( int i=1; i<K; i++ ) { I challenger = getRandom(pop); double fit = challenger.fitness(); if( fit < bestFitness ) { winner = challenger; bestFitness = fit; } } return winner; } public Iterator<I> select(int number, Population<?, I> pop) { return new KTIterator<I>(pop,this,number); } private static class KTIterator<I extends Individual<?,I>> implements Iterator<I> { private final Population<?,I> pop; private final KTournament<I> KTournament; private final int size; private int count = 0; private KTIterator(Population<?, I> pop, KTournament<I> KTournament, int size) { this.pop = pop; this.KTournament = KTournament; this.size = size; } public boolean hasNext() { return count < size; } public I next() { if( ! hasNext() ) { throw new NoSuchElementException(); } count++; return KTournament.select(pop); } public void remove() { throw new UnsupportedOperationException("Not supported yet."); } } }