/// <summary> /// Destructively crosses over the individual with another in some default manner. In most /// implementations provided in ECJ, one-, two-, and any-point crossover is done with a /// for loop, rather than a possibly more efficient approach like arrayCopy(). The disadvantage /// is that Array.Copy(...) takes advantage of a CPU's bulk copying. The advantage is that Array.Copy(...) /// would require a scratch array, so you'd be allocing and GCing an array for every crossover. /// Dunno which is more efficient. /// </summary> public virtual void DefaultCrossover(IEvolutionState state, int thread, VectorIndividual ind) { }
public override void DefaultCrossover(IEvolutionState state, int thread, VectorIndividual ind) { var s = (IntegerVectorSpecies)Species; var i = (ShortVectorIndividual)ind; short tmp; int point; if (genome.Length != i.genome.Length) { state.Output.Fatal("Genome lengths are not the same for fixed-length vector crossover"); } switch (s.CrossoverType) { case VectorSpecies.C_ONE_POINT: point = state.Random[thread].NextInt((genome.Length / s.ChunkSize) + 1); for (var x = 0; x < point * s.ChunkSize; x++) { tmp = i.genome[x]; i.genome[x] = genome[x]; genome[x] = tmp; } break; case VectorSpecies.C_TWO_POINT: var point0 = state.Random[thread].NextInt((genome.Length / s.ChunkSize) + 1); point = state.Random[thread].NextInt((genome.Length / s.ChunkSize) + 1); if (point0 > point) { var p = point0; point0 = point; point = p; } for (var x = point0 * s.ChunkSize; x < point * s.ChunkSize; x++) { tmp = i.genome[x]; i.genome[x] = genome[x]; genome[x] = tmp; } break; case VectorSpecies.C_ANY_POINT: for (var x = 0; x < genome.Length / s.ChunkSize; x++) { if (state.Random[thread].NextBoolean(s.CrossoverProbability)) { for (var y = x * s.ChunkSize; y < (x + 1) * s.ChunkSize; y++) { tmp = i.genome[y]; i.genome[y] = genome[y]; genome[y] = tmp; } } } break; case VectorSpecies.C_LINE_RECOMB: { var alpha = state.Random[thread].NextDouble() * (1 + 2 * s.LineDistance) - s.LineDistance; var beta = state.Random[thread].NextDouble() * (1 + 2 * s.LineDistance) - s.LineDistance; for (var x = 0; x < genome.Length; x++) { var min = s.GetMinGene(x); var max = s.GetMaxGene(x); var t = (long)Math.Floor(alpha * genome[x] + (1 - alpha) * i.genome[x] + 0.5); var u = (long)Math.Floor(beta * i.genome[x] + (1 - beta) * genome[x] + 0.5); if ((t < min || t > max || u < min || u > max)) { continue; } genome[x] = (short)t; i.genome[x] = (short)u; } } break; case VectorSpecies.C_INTERMED_RECOMB: { for (var x = 0; x < genome.Length; x++) { long t; long u; long min; long max; do { var alpha = state.Random[thread].NextDouble() * (1 + 2 * s.LineDistance) - s.LineDistance; var beta = state.Random[thread].NextDouble() * (1 + 2 * s.LineDistance) - s.LineDistance; min = s.GetMinGene(x); max = s.GetMaxGene(x); t = (long)Math.Floor(alpha * genome[x] + (1 - alpha) * i.genome[x] + 0.5); u = (long)Math.Floor(beta * i.genome[x] + (1 - beta) * genome[x] + 0.5); } while (t < min || t > max || u < min || u > max); genome[x] = (short)t; i.genome[x] = (short)u; } } break; } }
public override void DefaultCrossover(IEvolutionState state, int thread, VectorIndividual ind) { var s = (FloatVectorSpecies)Species; var i = (DoubleVectorIndividual)ind; double tmp; int point; if (genome.Length != i.genome.Length) { state.Output.Fatal("Genome lengths are not the same for fixed-length vector crossover"); } switch (s.CrossoverType) { case VectorSpecies.C_ONE_POINT: point = state.Random[thread].NextInt((genome.Length / s.ChunkSize) + 1); for (var x = 0; x < point * s.ChunkSize; x++) { tmp = i.genome[x]; i.genome[x] = genome[x]; genome[x] = tmp; } break; case VectorSpecies.C_TWO_POINT: var point0 = state.Random[thread].NextInt((genome.Length / s.ChunkSize) + 1); point = state.Random[thread].NextInt((genome.Length / s.ChunkSize) + 1); if (point0 > point) { var p = point0; point0 = point; point = p; } for (var x = point0 * s.ChunkSize; x < point * s.ChunkSize; x++) { tmp = i.genome[x]; i.genome[x] = genome[x]; genome[x] = tmp; } break; case VectorSpecies.C_ANY_POINT: for (var x = 0; x < genome.Length / s.ChunkSize; x++) { if (state.Random[thread].NextBoolean(s.CrossoverProbability)) { for (var y = x * s.ChunkSize; y < (x + 1) * s.ChunkSize; y++) { tmp = i.genome[y]; i.genome[y] = genome[y]; genome[y] = tmp; } } } break; case VectorSpecies.C_LINE_RECOMB: { var alpha = state.Random[thread].NextDouble(includeZero: true, includeOne: true) * (1 + 2 * s.LineDistance) - s.LineDistance; var beta = state.Random[thread].NextDouble(includeZero: true, includeOne: true) * (1 + 2 * s.LineDistance) - s.LineDistance; for (var x = 0; x < genome.Length; x++) { var min = s.GetMinGene(x); var max = s.GetMaxGene(x); var t = alpha * genome[x] + (1 - alpha) * i.genome[x]; var u = beta * i.genome[x] + (1 - beta) * genome[x]; if ((t < min || t > max || u < min || u > max)) { continue; } genome[x] = t; i.genome[x] = u; } } break; case VectorSpecies.C_INTERMED_RECOMB: { for (var x = 0; x < genome.Length; x++) { double t; double u; double min; double max; do { var alpha = state.Random[thread].NextDouble(includeZero: true, includeOne: true) * (1 + 2 * s.LineDistance) - s.LineDistance; var beta = state.Random[thread].NextDouble(includeZero: true, includeOne: true) * (1 + 2 * s.LineDistance) - s.LineDistance; min = s.GetMinGene(x); max = s.GetMaxGene(x); t = alpha * genome[x] + (1 - alpha) * i.genome[x]; u = beta * i.genome[x] + (1 - beta) * genome[x]; } while (t < min || t > max || u < min || u > max); genome[x] = t; i.genome[x] = u; } } break; case VectorSpecies.C_SIMULATED_BINARY: { SimulatedBinaryCrossover(state.Random[thread], i, s.CrossoverDistributionIndex); } break; } }