Coverage Report - org.dishevelled.evolve.impl.EvolutionaryAlgorithmImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
EvolutionaryAlgorithmImpl
99%
100/101
78%
47/60
3.846
 
 1  
 /*
 2  
 
 3  
     dsh-evolve  Framework for evolutionary algorithms.
 4  
     Copyright (c) 2005-2013 held jointly by the individual authors.
 5  
 
 6  
     This library is free software; you can redistribute it and/or modify it
 7  
     under the terms of the GNU Lesser General Public License as published
 8  
     by the Free Software Foundation; either version 3 of the License, or (at
 9  
     your option) any later version.
 10  
 
 11  
     This library is distributed in the hope that it will be useful, but WITHOUT
 12  
     ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
 13  
     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 14  
     License for more details.
 15  
 
 16  
     You should have received a copy of the GNU Lesser General Public License
 17  
     along with this library;  if not, write to the Free Software Foundation,
 18  
     Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
 19  
 
 20  
     > http://www.fsf.org/licensing/licenses/lgpl.html
 21  
     > http://www.opensource.org/licenses/lgpl-license.php
 22  
 
 23  
 */
 24  
 package org.dishevelled.evolve.impl;
 25  
 
 26  
 import java.util.ArrayList;
 27  
 import java.util.Collection;
 28  
 import java.util.Iterator;
 29  
 
 30  
 import javax.swing.event.EventListenerList;
 31  
 
 32  
 import org.dishevelled.evolve.EvolutionaryAlgorithm;
 33  
 import org.dishevelled.evolve.EvolutionaryAlgorithmEvent;
 34  
 import org.dishevelled.evolve.EvolutionaryAlgorithmListener;
 35  
 import org.dishevelled.evolve.ExitStrategy;
 36  
 import org.dishevelled.evolve.Fitness;
 37  
 import org.dishevelled.evolve.Mutation;
 38  
 import org.dishevelled.evolve.Recombination;
 39  
 import org.dishevelled.evolve.Selection;
 40  
 
 41  
 import org.dishevelled.weighted.WeightedMap;
 42  
 import org.dishevelled.weighted.HashWeightedMap;
 43  
 
 44  
 /**
 45  
  * Implementation of an evolutionary algorithm function.
 46  
  *
 47  
  * @param <I> individual type
 48  
  * @author  Michael Heuer
 49  
  * @version $Revision: 320 $ $Date: 2007-10-23 14:06:38 -0500 (Tue, 23 Oct 2007) $
 50  
  */
 51  
 public final class EvolutionaryAlgorithmImpl<I>
 52  
     implements EvolutionaryAlgorithm<I>
 53  
 {
 54  
     /** Default hash map load factor. */
 55  
     private static final float DEFAULT_LOAD_FACTOR = 0.75f;
 56  
 
 57  
     /** Listener list. */
 58  6
     private EventListenerList listenerList = new EventListenerList();
 59  
 
 60  
 
 61  
     /**
 62  
      * Create a new evolutionary algorithm function implementation.
 63  
      */
 64  
     public EvolutionaryAlgorithmImpl()
 65  6
     {
 66  
         // empty
 67  6
     }
 68  
 
 69  
 
 70  
     /** {@inheritDoc} */
 71  
     public Collection<I> evolve(final Collection<I> individuals,
 72  
                                 final ExitStrategy<I> exitStrategy,
 73  
                                 final Recombination<I> recombination,
 74  
                                 final Mutation<I> mutation,
 75  
                                 final Fitness<I> fitness,
 76  
                                 final Selection<I> selection)
 77  
     {
 78  8
         checkParameters(individuals, exitStrategy, recombination, mutation, fitness, selection);
 79  
 
 80  
         // initialize population with individuals
 81  1
         Collection<I> population = new ArrayList<I>(individuals);
 82  
         // initialize fitness scores to 0.0d
 83  1
         WeightedMap<I> scores = new HashWeightedMap<I>(population.size(), DEFAULT_LOAD_FACTOR);
 84  1
         for (I i : individuals)
 85  
         {
 86  1
             scores.put(i, Double.valueOf(0.0d));
 87  1
         }
 88  
 
 89  1
         int time = 0;
 90  2
         while (!exitStrategy.evaluate(population, scores, time))
 91  
         {
 92  1
             fireExitFailed(population, scores, time);
 93  
 
 94  
             // recombine population
 95  1
             Collection<I> recombined = recombination.recombine(population);
 96  1
             fireRecombined(population, recombined);
 97  
 
 98  
             // mutate amongst themselves
 99  1
             Collection<I> mutated = mutation.mutate(recombined);
 100  1
             fireMutated(recombined, mutated);
 101  
 
 102  
             // evalute fitness
 103  1
             for (I i : mutated)
 104  
             {
 105  1
                 Double score = fitness.score(i);
 106  1
                 scores.put(i, score);
 107  1
                 fireFitnessCalculated(i, score);
 108  1
             }
 109  
 
 110  
             // select individuals for next generation
 111  1
             population = selection.select(mutated, scores);
 112  1
             fireSelected(mutated, population, scores);
 113  
 
 114  
             // remove last generation from scores
 115  1
             for (Iterator<I> keys = scores.keySet().iterator(); keys.hasNext(); )
 116  
             {
 117  1
                 I i = keys.next();
 118  1
                 if (!population.contains(i))
 119  
                 {
 120  0
                     keys.remove();
 121  
                 }
 122  1
             }
 123  
 
 124  1
             time++;
 125  1
         }
 126  
 
 127  
         // exit strategy condition(s) met, return successful population
 128  1
         fireExitSucceeded(population, scores, time);
 129  1
         return population;
 130  
     }
 131  
 
 132  
 
 133  
     /**
 134  
      * Check that the specified parameters are valid.
 135  
      *
 136  
      * @param individuals collection of individuals, must not be null and must contain
 137  
      *    at least one individual
 138  
      * @param exitStrategy exit strategy function, must not be null
 139  
      * @param recombination recombination function, must not be null
 140  
      * @param mutation mutation function, must not be null
 141  
      * @param fitness fitness function, must not be null
 142  
      * @param selection selection function, must not be null
 143  
      */
 144  
     private void checkParameters(final Collection<I> individuals,
 145  
                                  final ExitStrategy<I> exitStrategy,
 146  
                                  final Recombination<I> recombination,
 147  
                                  final Mutation<I> mutation,
 148  
                                  final Fitness<I> fitness,
 149  
                                  final Selection<I> selection)
 150  
     {
 151  
         // check for null or otherwise illegal parameters
 152  8
         if (individuals == null)
 153  
         {
 154  1
             throw new IllegalArgumentException("individuals must not be null");
 155  
         }
 156  7
         if (individuals.size() == 0)
 157  
         {
 158  1
             throw new IllegalArgumentException("individuals must not be empty");
 159  
         }
 160  6
         if (exitStrategy == null)
 161  
         {
 162  1
             throw new IllegalArgumentException("exitStrategy must not be null");
 163  
         }
 164  5
         if (recombination == null)
 165  
         {
 166  1
             throw new IllegalArgumentException("recombination must not be null");
 167  
         }
 168  4
         if (mutation == null)
 169  
         {
 170  1
             throw new IllegalArgumentException("mutation must not be null");
 171  
         }
 172  3
         if (fitness == null)
 173  
         {
 174  1
             throw new IllegalArgumentException("fitness must not be null");
 175  
         }
 176  2
         if (selection == null)
 177  
         {
 178  1
             throw new IllegalArgumentException("selection must not be null");
 179  
         }
 180  1
     }
 181  
 
 182  
    /**
 183  
      * Add the specified evolutionary algorithm listener.
 184  
      *
 185  
      * @param l evolutionary algorithm listener to add
 186  
      */
 187  
     /** {@inheritDoc} */
 188  
     public void addEvolutionaryAlgorithmListener(final EvolutionaryAlgorithmListener<I> l)
 189  
     {
 190  3
         listenerList.add(EvolutionaryAlgorithmListener.class, l);
 191  3
     }
 192  
 
 193  
     /** {@inheritDoc} */
 194  
     public void removeEvolutionaryAlgorithmListener(final EvolutionaryAlgorithmListener<I> l)
 195  
     {
 196  4
         listenerList.remove(EvolutionaryAlgorithmListener.class, l);
 197  4
     }
 198  
 
 199  
     /** {@inheritDoc} */
 200  
     public int getEvolutionaryAlgorithmListenerCount()
 201  
     {
 202  5
         return listenerList.getListenerCount(EvolutionaryAlgorithmListener.class);
 203  
     }
 204  
 
 205  
     /** {@inheritDoc} */
 206  
     public EvolutionaryAlgorithmListener<I>[] getEvolutionaryAlgorithmListeners()
 207  
     {
 208  13
         return (EvolutionaryAlgorithmListener<I>[]) listenerList.getListeners(EvolutionaryAlgorithmListener.class);
 209  
     }
 210  
 
 211  
     /**
 212  
      * Fire an exit failed event to all registered listeners.
 213  
      *
 214  
      * @param population population
 215  
      * @param scores fitness scores
 216  
      * @param time time
 217  
      */
 218  
     private void fireExitFailed(final Collection<I> population, final WeightedMap<I> scores, final int time)
 219  
     {
 220  1
         Object[] listeners = listenerList.getListenerList();
 221  1
         EvolutionaryAlgorithmEvent<I> e = null;
 222  
 
 223  2
         for (int i = listeners.length - 2; i >= 0; i -= 2)
 224  
         {
 225  1
             if (listeners[i] == EvolutionaryAlgorithmListener.class)
 226  
             {
 227  1
                 if (e == null)
 228  
                 {
 229  1
                     e = new EvolutionaryAlgorithmEvent<I>(this, population, scores, time);
 230  
                 }
 231  
 
 232  1
                 ((EvolutionaryAlgorithmListener<I>) listeners[i + 1]).exitFailed(e);
 233  
             }
 234  
         }
 235  1
     }
 236  
 
 237  
     /**
 238  
      * Fire an exit succeeded event to all registered listeners.
 239  
      *
 240  
      * @param population population
 241  
      * @param scores fitness scores
 242  
      * @param time time
 243  
      */
 244  
     private void fireExitSucceeded(final Collection<I> population, final WeightedMap<I> scores, final int time)
 245  
     {
 246  1
         Object[] listeners = listenerList.getListenerList();
 247  1
         EvolutionaryAlgorithmEvent<I> e = null;
 248  
 
 249  2
         for (int i = listeners.length - 2; i >= 0; i -= 2)
 250  
         {
 251  1
             if (listeners[i] == EvolutionaryAlgorithmListener.class)
 252  
             {
 253  1
                 if (e == null)
 254  
                 {
 255  1
                     e = new EvolutionaryAlgorithmEvent<I>(this, population, scores, time);
 256  
                 }
 257  
 
 258  1
                 ((EvolutionaryAlgorithmListener<I>) listeners[i + 1]).exitSucceeded(e);
 259  
             }
 260  
         }
 261  1
     }
 262  
 
 263  
     /**
 264  
      * Fire a recombined event to all registered listeners.
 265  
      *
 266  
      * @param population population
 267  
      * @param recombined recombined
 268  
      */
 269  
     private void fireRecombined(final Collection<I> population, final Collection<I> recombined)
 270  
     {
 271  1
         Object[] listeners = listenerList.getListenerList();
 272  1
         EvolutionaryAlgorithmEvent<I> e = null;
 273  
 
 274  2
         for (int i = listeners.length - 2; i >= 0; i -= 2)
 275  
         {
 276  1
             if (listeners[i] == EvolutionaryAlgorithmListener.class)
 277  
             {
 278  1
                 if (e == null)
 279  
                 {
 280  1
                     e = new EvolutionaryAlgorithmEvent<I>(this, population, recombined, (Collection<I>) null);
 281  
                 }
 282  
 
 283  1
                 ((EvolutionaryAlgorithmListener<I>) listeners[i + 1]).recombined(e);
 284  
             }
 285  
         }
 286  1
     }
 287  
 
 288  
     /**
 289  
      * Fire a mutated event to all registered listeners.
 290  
      *
 291  
      * @param recombined recombined
 292  
      * @param mutated mutated
 293  
      */
 294  
     private void fireMutated(final Collection<I> recombined, final Collection<I> mutated)
 295  
     {
 296  1
         Object[] listeners = listenerList.getListenerList();
 297  1
         EvolutionaryAlgorithmEvent<I> e = null;
 298  
 
 299  2
         for (int i = listeners.length - 2; i >= 0; i -= 2)
 300  
         {
 301  1
             if (listeners[i] == EvolutionaryAlgorithmListener.class)
 302  
             {
 303  1
                 if (e == null)
 304  
                 {
 305  1
                     e = new EvolutionaryAlgorithmEvent<I>(this, null, recombined, mutated);
 306  
                 }
 307  
 
 308  1
                 ((EvolutionaryAlgorithmListener<I>) listeners[i + 1]).mutated(e);
 309  
             }
 310  
         }
 311  1
     }
 312  
 
 313  
     /**
 314  
      * Fire a fitness calculated event to all registered listeners.
 315  
      *
 316  
      * @param individual individual
 317  
      * @param score score
 318  
      */
 319  
     private void fireFitnessCalculated(final I individual, final Double score)
 320  
     {
 321  1
         Object[] listeners = listenerList.getListenerList();
 322  1
         EvolutionaryAlgorithmEvent<I> e = null;
 323  
 
 324  2
         for (int i = listeners.length - 2; i >= 0; i -= 2)
 325  
         {
 326  1
             if (listeners[i] == EvolutionaryAlgorithmListener.class)
 327  
             {
 328  1
                 if (e == null)
 329  
                 {
 330  1
                     e = new EvolutionaryAlgorithmEvent<I>(this, individual, score);
 331  
                 }
 332  
 
 333  1
                 ((EvolutionaryAlgorithmListener<I>) listeners[i + 1]).fitnessCalculated(e);
 334  
             }
 335  
         }
 336  1
     }
 337  
 
 338  
     /**
 339  
      * Fire a selected event to all registered listeners.
 340  
      *
 341  
      * @param population population
 342  
      * @param selected selected
 343  
      * @param scores fitness scores
 344  
      */
 345  
     private void fireSelected(final Collection<I> population,
 346  
                               final Collection<I> selected,
 347  
                               final WeightedMap<I> scores)
 348  
     {
 349  1
         Object[] listeners = listenerList.getListenerList();
 350  1
         EvolutionaryAlgorithmEvent<I> e = null;
 351  
 
 352  2
         for (int i = listeners.length - 2; i >= 0; i -= 2)
 353  
         {
 354  1
             if (listeners[i] == EvolutionaryAlgorithmListener.class)
 355  
             {
 356  1
                 if (e == null)
 357  
                 {
 358  1
                     e = new EvolutionaryAlgorithmEvent<I>(this, population, selected, scores);
 359  
                 }
 360  
 
 361  1
                 ((EvolutionaryAlgorithmListener<I>) listeners[i + 1]).selected(e);
 362  
             }
 363  
         }
 364  1
     }
 365  
 }