forked from giacomelli/GeneticSharp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
VotingRecombinationCrossover.cs
103 lines (94 loc) · 4.44 KB
/
VotingRecombinationCrossover.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using GeneticSharp.Domain.Chromosomes;
using GeneticSharp.Domain.Mutations;
namespace GeneticSharp.Domain.Crossovers
{
/// <summary>
/// Voting Recombination Crossover (VR).
/// <remarks>
/// <para>
/// It can be seen as a P-sexual crossover operator, where p (parents number) is a natural number greater than, or equal to, 2.
/// </para>
/// <para>
/// It starts by defining a threshold, which is a natural number smaller than, or equal to p.
/// </para>
/// <para>
/// Next, for every; i E {l, 2, . . .N} the set of ith elements of all the parents is considered.
/// If in this set an element occurs at least the threshold number of times, it is copied into the offspring.
/// </para>
/// <para>
/// For example, if we consider the parents(p = 4) (1 4 3 5 2 6), (1 2 4 3 5 6), (3 2 1 5 4 6), (1 2 3 4 5 6) and we define the threshold to be equal to 3 we find(1 2 x x x 6).
/// The remaining positions of the offspring are filled with mutations.
/// <see href="http://ictactjournals.in/paper/IJSC_V6_I1_paper_4_pp_1083_1092.pdf">Crossover operators in genetic algorithms: A review</see>
/// </para>
/// <para>
/// The voting recombination produce one child of parents number (p) based on a threshold.
/// <see href="https://www.cs.vu.nl/~gusz/papers/Handbook-Multiparent-Eiben.pdf">Multiparent Recombination</see>
/// </para>
/// </remarks>
/// </summary>
[DisplayName("Voting Recombination (VR)")]
public sealed class VotingRecombinationCrossover : CrossoverBase
{
private readonly int _threshold;
/// <summary>
/// Initializes a new instance of the <see cref="GeneticSharp.Domain.Crossovers.VotingRecombinationCrossover"/> class.
/// </summary>
/// <param name="parentsNumber">The number of parents need for cross.</param>
/// <param name="threshold">An element occurs at least the threshold number of times, it is copied into the offspring</param>
public VotingRecombinationCrossover(int parentsNumber, int threshold)
: base(parentsNumber, 1)
{
if (threshold > parentsNumber)
{
throw new ArgumentOutOfRangeException(nameof(threshold), "The threshold should be smaller or equal to the parents number.");
}
IsOrdered = false;
_threshold = threshold;
}
// <summary>
/// Initializes a new instance of the <see cref="GeneticSharp.Domain.Crossovers.VotingRecombinationCrossover"/> class.
/// </summary>
public VotingRecombinationCrossover() : this(3, 2)
{
}
/// <summary>
/// Performs the cross with specified parents generating the children.
/// </summary>
/// <param name="parents">The parents chromosomes.</param>
/// <returns>The offspring (children) of the parents.</returns>
protected override IList<IChromosome> PerformCross(IList<IChromosome> parents)
{
var firstParent = parents[0];
var child = firstParent.CreateNew();
var mutableGenesIndexes = new List<int>();
for (int i = 0; i < child.Length; i++)
{
// If in this set an element occurs at least the threshold number of times, it is copied into the offspring.
var moreOcurrencesGeneValue = parents
.GroupBy(p => p.GetGene(i).Value)
.Where(p => p.Count() >= _threshold)
.OrderByDescending(g => g.Count())
.FirstOrDefault();
if (moreOcurrencesGeneValue != null)
{
child.ReplaceGene(i, new Gene(moreOcurrencesGeneValue.Key));
}
else
{
mutableGenesIndexes.Add(i);
}
}
// The remaining positions of the offspring are filled with mutations.
if (mutableGenesIndexes.Count > 0)
{
new UniformMutation(mutableGenesIndexes.ToArray())
.Mutate(child, 1);
}
return new List<IChromosome> { child };
}
}
}