All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.vergne.optimization.population.impl.CompetitionManager Maven / Gradle / Ivy

The newest version!
package fr.vergne.optimization.population.impl;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

import fr.vergne.optimization.generator.Mutator;
import fr.vergne.optimization.population.PopulationManager;

/**
 * This {@link CompetitionManager} aims at keeping only the best candidates, by
 * removing all the losers of a {@link Competition}. Each time a new
 * {@link Individual} is provided by {@link #push(Object)}, a competition
 * occurs. If the new {@link Individual} does not perform better, it is removed,
 * otherwise it is kept with potential other winners. The method
 * {@link #getScore(Object)} allows to know how many competitions each
 * {@link Individual} has won.
*
* The method {@link #setCompetitors(Collection)} can be used to consider * specific {@link Individual}s during the competition. For instance, if the new * {@link Individual} has been generated by a {@link Mutator}, one can want to * make compete the original {@link Individual} with its mutant. As long as this * method is not re-used, the competitors are the previous winners (i.e. all the * current population by default). * * @author Matthieu Vergne * * @param * @param */ public class CompetitionManager implements PopulationManager { private final Collection competitors = new HashSet(); private final Map> scores = new HashMap>(); private final Competition competition; private Tournament currentTournament = null; private Map maxScoreGlobal = new HashMap(); public CompetitionManager(Competition competition) { this.competition = competition; } /** * * @param competitors * the {@link Individual}s to consider in the next competition */ public void setCompetitors(Collection candidates) { competitors.clear(); for (Individual candidate : candidates) { if (getPopulation().contains(candidate)) { competitors.add(candidate); } else { throw new IllegalArgumentException( "Candidate not in the current population: " + candidate); } } } /** * * @param tournament * the current {@link Tournament} */ public void setCurrentTournament(Tournament tournament) { this.currentTournament = tournament; } /** * * @return the current {@link Tournament} */ public Tournament getCurrentTournament() { return currentTournament; } @Override public void push(Individual individual) { competitors.add(individual); Collection winners = new HashSet( competition.compete(competitors)); Collection losers = new HashSet(competitors); losers.removeAll(winners); for (Individual winner : winners) { Integer score = getScore(currentTournament, winner); setScore(currentTournament, winner, score + 1); } for (Individual loser : losers) { competitors.remove(loser); scores.remove(loser); } } @Override public Collection getPopulation() { return scores.keySet(); } /** * This method is a shortcut to getPopulation().size(). * * @return the size of the current population */ public int size() { return getPopulation().size(); } @Override public Iterator getBest() { return new Iterator() { LinkedList winners = new LinkedList(); Set remaining = new HashSet(getPopulation()); @Override public boolean hasNext() { return !remaining.isEmpty() || !winners.isEmpty(); } @Override public Individual next() { if (hasNext()) { if (winners.isEmpty()) { winners.addAll(competition.compete(remaining)); remaining.removeAll(winners); } else { // consider the remaining winners } return winners.removeFirst(); } else { throw new NoSuchElementException(); } } @Override public void remove() { throw new UnsupportedOperationException(); } }; } /** * * @param tournament * the {@link Tournament} to consider * @param individual * an {@link Individual} * @return the number of competitions won by this {@link Individual} for * this specific {@link Tournament}, 0 by default */ public Integer getScore(Tournament tournament, Individual individual) { Map individualScores = retrieveIndividualScores(individual); return individualScores.containsKey(tournament) ? individualScores .get(tournament) : 0; } /** * * @param tournament * the {@link Tournament} to consider * @param individual * an {@link Individual} * @param score * the score of this {@link Individual} for this specific * {@link Tournament} */ public void setScore(Tournament tournament, Individual individual, int score) { retrieveIndividualScores(individual).put(tournament, score); int currentMax = maxScoreGlobal.containsKey(tournament) ? maxScoreGlobal .get(tournament) : 0; maxScoreGlobal.put(tournament, Math.max(score, currentMax)); } private Map retrieveIndividualScores( Individual individual) { Map individualScores = scores.get(individual); if (individualScores == null) { individualScores = new HashMap(); scores.put(individual, individualScores); } else { // use the one retrieved } return individualScores; } /** * * @param tournament * the {@link Tournament} to consider * @return the smallest score for the given {@link Tournament} in the * current population, null if the population is empty */ public Integer getMinScore(Tournament tournament) { Integer minScore = Integer.MAX_VALUE; for (Map individualScores : scores.values()) { if (individualScores.containsKey(tournament)) { minScore = Math.min(minScore, individualScores.get(tournament)); } else { continue; } } return minScore == Integer.MAX_VALUE ? null : minScore; } /** * * @param tournament * the {@link Tournament} to consider * @return the highest score for the given {@link Tournament} in the current * population, null if the population is empty */ public Integer getMaxScore(Tournament tournament) { Integer maxScore = -1; for (Map individualScores : scores.values()) { if (individualScores.containsKey(tournament)) { maxScore = Math.max(maxScore, individualScores.get(tournament)); } else { continue; } } return maxScore == -1 ? null : maxScore; } /** * * @param tournament * the {@link Tournament} to consider * @return the highest score reached since the beginning for this * {@link Tournament} */ public int getMaxScoreGlobal(Tournament tournament) { return maxScoreGlobal.containsKey(tournament) ? maxScoreGlobal .get(tournament) : 0; } public Iterator> getScoreDescriptors() { return new Iterator>() { private final Iterator tournaments = maxScoreGlobal .keySet().iterator(); private ScoreDescriptor next = null; @Override public boolean hasNext() { findNextIfNecessary(); return next != null; } @Override public ScoreDescriptor next() { findNextIfNecessary(); ScoreDescriptor descriptor = next; next = null; return descriptor; } private void findNextIfNecessary() { while (tournaments.hasNext() && next == null) { Tournament tournament = tournaments.next(); try { int min = getMinScore(tournament); int max = getMaxScore(tournament); next = new ScoreDescriptor(tournament, min, max); } catch (NullPointerException e) { continue; } } } @Override public void remove() { throw new UnsupportedOperationException(); } }; } /** * A {@link ScoreDescriptor} provide detailed information about scores as * returned by {@link CompetitionManager#getScore(Object, Object)} and * related methods. * * @author Matthieu Vergne * */ public static class ScoreDescriptor { private final int min; private final int max; private final Tournament tournament; public ScoreDescriptor(Tournament tournament, int min, int max) { this.tournament = tournament; this.min = min; this.max = max; } public Tournament getTournament() { return tournament; } public int getMin() { return min; } public int getMax() { return max; } public double getRatio() { return min == 0 ? 0 : (double) min / max; } } /** * A {@link Competition} aims at making competing {@link Individual}s in * order to differentiate winners/losers. * * @author Matthieu Vergne * * @param */ public static interface Competition { /** * This method should return all the winners among the competitors. It * can contain all the competitors, but not be empty. If no winner/loser * can be identified, all the competitors should be returned. If several * winners are returned, it means that none of them perform better than * the other winners. * * @param competitors * the {@link Individual}s to make compete * @return the winning {@link Individual}s */ public Collection compete(Collection competitors); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy