-
-
Notifications
You must be signed in to change notification settings - Fork 334
/
TwoPointCrossover.cs
103 lines (93 loc) · 4.11 KB
/
TwoPointCrossover.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;
namespace GeneticSharp
{
/// <summary>
/// Two-Point Crossover (C2)
/// <remarks>
/// Two-point crossover calls for two points to be selected on the parents.
/// Everything between the two points is swapped between the parents, rendering two children.
/// <see href="http://en.wikipedia.org/wiki/Crossover_(genetic_algorithm)#Two-point_crossover">Wikipedia</see>
/// </remarks>
/// </summary>
[DisplayName("Two-Point")]
public class TwoPointCrossover : OnePointCrossover
{
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="GeneticSharp.TwoPointCrossover"/> class.
/// </summary>
/// <param name="swapPointOneGeneIndex">Swap point one gene index.</param>
/// <param name="swapPointTwoGeneIndex">Swap point two gene index.</param>
public TwoPointCrossover(int swapPointOneGeneIndex, int swapPointTwoGeneIndex)
{
if (swapPointOneGeneIndex >= swapPointTwoGeneIndex)
{
throw new ArgumentOutOfRangeException(nameof(swapPointTwoGeneIndex), "The swap point two gene index should be greater than swap point one index.");
}
SwapPointOneGeneIndex = swapPointOneGeneIndex;
SwapPointTwoGeneIndex = swapPointTwoGeneIndex;
MinChromosomeLength = 3;
}
/// <summary>
/// Initializes a new instance of the <see cref="GeneticSharp.TwoPointCrossover"/> class.
/// </summary>
public TwoPointCrossover() : this(0, 1)
{
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the index of the swap point one gene.
/// </summary>
/// <value>The index of the swap point one gene.</value>
public int SwapPointOneGeneIndex { get; set; }
/// <summary>
/// Gets or sets the index of the swap point two gene.
/// </summary>
/// <value>The index of the swap point two gene.</value>
public int SwapPointTwoGeneIndex { get; set; }
#endregion
#region Methods
/// <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 secondParent = parents[1];
var parentLength = firstParent.Length;
var swapPointsLength = parentLength - 1;
if (SwapPointTwoGeneIndex >= swapPointsLength)
{
throw new ArgumentOutOfRangeException(
nameof(parents),
"The swap point two index is {0}, but there is only {1} genes. The swap should result at least one gene to each sides.".With(SwapPointTwoGeneIndex, parentLength));
}
return CreateChildren(firstParent, secondParent);
}
/// <summary>
/// Creates the child.
/// </summary>
/// <returns>The child.</returns>
/// <param name="leftParent">Left parent.</param>
/// <param name="rightParent">Right parent.</param>
protected override IChromosome CreateChild(IChromosome leftParent, IChromosome rightParent)
{
var firstCutGenesCount = SwapPointOneGeneIndex + 1;
var secondCutGenesCount = SwapPointTwoGeneIndex + 1;
var child = leftParent.CreateNew();
child.ReplaceGenes(0, leftParent.GetGenes().Take(firstCutGenesCount).ToArray());
child.ReplaceGenes(firstCutGenesCount, rightParent.GetGenes().Skip(firstCutGenesCount).Take(secondCutGenesCount - firstCutGenesCount).ToArray());
child.ReplaceGenes(secondCutGenesCount, leftParent.GetGenes().Skip(secondCutGenesCount).ToArray());
return child;
}
#endregion
}
}