Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TournamentSelection AllowWinnerCompeteNextTournament=false not working #127

Open
leshacsharp opened this issue Oct 11, 2024 · 1 comment

Comments

@leshacsharp
Copy link

Describe the bug
If the AllowWinnerCompeteNextTournament is set up to false, the TournamentSelector always throw

System.ArgumentOutOfRangeException: The length is 2, but the possible unique values between 0 (inclusive) and 1 (exclusive) are 1. (Parameter 'length')
at GeneticSharp.RandomizationBase.GetUniqueInts(Int32 length, Int32 min, Int32 max)
at GeneticSharp.TournamentSelection.PerformSelectChromosomes(Int32 number, Generation generation)
at GeneticSharp.SelectionBase.SelectChromosomes(Int32 number, Generation generation)
at GeneticSharp.GeneticAlgorithm.SelectParents()
at GeneticSharp.GeneticAlgorithm.EvolveOneGeneration()
at GeneticSharp.GeneticAlgorithm.Resume()
at GeneticSharp.GeneticAlgorithm.Start()

For example,
Population minSize = 10, maxSize=20
TournametSelection size=2, allowWinnerCompeteNextTournament=false

The selector tries to select two chromosomes for comparison, then adds the winner to the result until the population is fully initialized (MinSize). After that, the winner is no longer allowed to participate in further tournaments. The issue arises when the selector attempts to add the 10th chromosome, but it fails because only one individual is available, while two are required for comparison.

var candidates = generation.Chromosomes.ToList();
var selected = new List<IChromosome>();
while (selected.Count < number)
{
var randomIndexes = RandomizationProvider.Current.GetUniqueInts(Size, 0, candidates.Count);
var tournamentWinner = candidates.Where((c, i) => randomIndexes.Contains(i)).OrderByDescending(c => c.Fitness).First();
selected.Add(tournamentWinner.Clone());
if (!AllowWinnerCompeteNextTournament)
{
candidates.Remove(tournamentWinner);
}
}
return selected;

To Reproduce
The exception is thrown on the second generation. The first (initial) proceed without the selection.

Expected behavior
Consider removing the AllowWinnerCompeteNextTournament=false as it useless option. If the selector prevents winning chromosomes from participating the next tournaments, the result population will be without any filtration and will remain the same as before.

Sample code

     `  private const int PopulationMinSize = 10;
        private const int PopulationMaxSize = 20;
        private const int MaxGenerationNumber = 10;
        private const int TournamentSize = 2;
        private const bool AllowWinnerCompeteNextTournament = false;

        var chromosome = new TestChromosome();
        var population = new Population(PopulationMinSize, PopulationMaxSize, chromosome);
        var fitness = new TestFitness();
        var selection = new TournamentSelection(TournamentSize, AllowWinnerCompeteNextTournament);
        var crossover = new UniformCrossover();
        var mutation = new UniformMutation();
        var termination = new GenerationNumberTermination(MaxGenerationNumber);

        var ga = new GeneticAlgorithm(population,
                                      fitness,
                                      selection,
                                      crossover,
                                      mutation); 
                                      
        ga.Termination = termination; 
        ga.Start(); `

Version:
3.1.4

@leshacsharp
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant