crossoverParents method

List<List<G>> crossoverParents(
  1. P a,
  2. P b, {
  3. int crossoverPointsCount = 2,
})

Returns a List of length 2 (2 children), each having a List of genes created by crossing over parents' genes.

By default, the "chromosomes" are cut and crossed over at 2 random points, like in human DNA. You can tweak this by specifying a different crossoverPointsCount.

The crossover only happens with crossoverProbability. Otherwise, exact copies of parents are returned.

Implementation

List<List<G>> crossoverParents(P a, P b, {int crossoverPointsCount = 2}) {
  var random = math.Random();

  if (random.nextDouble() < (1 - crossoverProbability)) {
    // No crossover. Return genes as they are.
    return [
      List.from(a.genes, growable: false),
      List.from(b.genes, growable: false)
    ];
  }

  assert(crossoverPointsCount < a.genes.length - 1);
  var length = a.genes.length;
  assert(length == b.genes.length);
  var crossoverPoints = <int>{};

  // Genes:   0 1 2 3 4 5 6
  // Xpoints:  0 1 2 3 4 5
  while (crossoverPoints.length < crossoverPointsCount) {
    crossoverPoints.add(random.nextInt(length - 1));
  }
  var child1genes = List<G?>.filled(length, null);
  var child2genes = List<G?>.filled(length, null);
  var crossover = false;
  for (var i = 0; i < length; i++) {
    if (!crossover) {
      child1genes[i] = a.genes[i];
      child2genes[i] = b.genes[i];
    } else {
      child1genes[i] = b.genes[i];
      child2genes[i] = a.genes[i];
    }
    if (crossoverPoints.contains(i)) {
      crossover = !crossover;
    }
  }
  return [
    List<G>.from(child1genes, growable: false),
    List<G>.from(child2genes, growable: false)
  ];
}