package gdsc.smlm.ga; import java.util.Arrays; import java.util.List; import org.apache.commons.math3.random.RandomDataGenerator; import gdsc.core.logging.TrackProgress; /*----------------------------------------------------------------------------- * GDSC SMLM Software * * Copyright (C) 2015 Alex Herbert * Genome Damage and Stability Centre * University of Sussex, UK * * This program 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. *---------------------------------------------------------------------------*/ /** * Selects the top individuals */ public class SimpleSelectionStrategy<T extends Comparable<T>> extends Randomiser implements SelectionStrategy<T> { final double fraction; final int max; private List<? extends Chromosome<T>> individuals = null; TrackProgress tracker = null; /** * Instantiates a new simple selection strategy. * * @param random * the random * @param fraction * The fraction of the individuals to select (set between 0 and 1) * @param max * The maximum number of individuals to select */ public SimpleSelectionStrategy(RandomDataGenerator random, double fraction, int max) { super(random); if (fraction > 1) fraction = 1; this.fraction = fraction; this.max = max; } /** * Select the top individuals using the configured fraction. The resulting subset will be at least size 2 (unless * the input is smaller or there are not enough valid individuals (fitness not null)). * * @param individuals * @return the subset * @see gdsc.smlm.ga.SelectionStrategy#select(java.util.List) */ public List<? extends Chromosome<T>> select(List<? extends Chromosome<T>> individuals) { if (individuals == null || individuals.size() < 2) return individuals; @SuppressWarnings("unchecked") Chromosome<T>[] subset = new Chromosome[individuals.size()]; int size = 0; // Add only those with a fitness score for (Chromosome<T> c : individuals) if (c.getFitness() != null) { subset[size++] = c; } if (size < 3) return Arrays.asList(Arrays.copyOf(subset, size)); if (tracker != null) tracker.progress(0.5); ChromosomeComparator.sort(subset, 0, size); // Get the fraction relative to the input list size //size = getSize(size); size = Math.min(size, getSize(individuals.size())); if (tracker != null) tracker.progress(1); return Arrays.asList(Arrays.copyOf(subset, size)); } /** * Calculate the new size of the population after selection * * @param size * The current size of the population before selection * @return The new size of the population */ protected int getSize(int size) { // Get the size using the fraction size = (int) Math.round(size * fraction); // Check against the max number to select if (max > 2 && size > max) size = max; // Check the size is at least 2 if (size < 2) size = 2; return size; } /* * (non-Javadoc) * * @see gdsc.smlm.ga.SelectionStrategy#initialiseBreeding(java.util.List) */ public void initialiseBreeding(List<? extends Chromosome<T>> individuals) { if (individuals != null && individuals.size() < 2) individuals = null; this.individuals = individuals; } /** * Select pairs randomly from the population * * @see gdsc.smlm.ga.SelectionStrategy#next() */ public ChromosomePair<T> next() { if (individuals == null) return null; int first, second; if (individuals.size() == 2) { first = 0; second = 1; } else { // Bounds are inclusive so subtract 1 final int upper = individuals.size() - 1; first = random.nextInt(0, upper); second = random.nextInt(0, upper); // Avoid crossover with the same parent while (second == first) second = random.nextInt(0, upper); } return new ChromosomePair<T>(individuals.get(first), individuals.get(second)); } /* * (non-Javadoc) * * @see gdsc.smlm.ga.SelectionStrategy#finishBreeding() */ public void finishBreeding() { // Free memory individuals = null; } /* * (non-Javadoc) * * @see gdsc.smlm.ga.SelectionStrategy#setTracker(gdsc.core.logging.TrackProgress) */ public void setTracker(TrackProgress tracker) { this.tracker = tracker; } }