1

This question builds on another one.

How could we efficiently implement a crossover operation on chromosomes formed by ordered collections of unique elements?

Two such parent chromosomes would be {'a','b','c','d'} and {'e','f','a','b'}; and two possible child chromosomes for those parents would be {'e','f','c','d'} and {'a','f','c','b'}.

Community
  • 1
  • 1
srctaha
  • 1,394
  • 1
  • 14
  • 16
  • What does 'ordered' mean? the first, {'a','b','c','d'}, seems to be ordered by ascending value but what is the ordering that gives {'e','f','a','b'}? – DAV May 02 '16 at 22:36
  • An ordered collection means a collection of items for which order matters -- for example {'a', 'b', 'c', 'd'} is different than {'d', 'c', 'b', 'a'}. Think of it as Python dictionaries where order is the gene number, such as `{'gene#1':'a', 'gene#2':'b', 'gene#3':'c', 'gene#4':'d'}` – srctaha May 06 '16 at 03:54

3 Answers3

2

You could try a sort of uniform crossover.

In general Uniform Crossover uses a fixed mixing ratio between two parents and the operator evaluates each gene in the parent chromosomes for exchange with a probability of 0.5.

Using Python syntax:

import random

p = [['a','b','c','d'], ['e','f','a','b']]    # parents

for i in range(len(p[0])):
   offspring.append(p[random.randint(0, 1)][i])

Uniform Crossover

Given the uniqueness constraint, the basic scheme has to be modified:

import random

p = [['a','b','c','d'], ['e','f','a','b']]    # parents

for i in range(len(p[0])):
    if p[1][i] in p[0]:    # cannot risk crossover, keep basic gene
        offspring.append(p[0][i])
    else:                  # standard uniform crossover
        offspring.append(p[random.randint(0, 1)][i])

The constraint is "automatically" satisfied and you have a smaller search space.

Note that the crossover is somewhat bound to the first parent (p[0]) and we get a limited number of variations:

CHROMOSOME FREQUENCY
abcd       *************************
efcd       ************************
ebcd       ************************
afcd       ************************

In this regards a small improvement is:

if p[1][i] in offspring or p[1][i] in p[0][i:]:
    offspring.append(p[0][i])
else:
    offspring.append(p[random.randint(0, 1)][i])

and

CHROMOSOME FREQUENCY
efcd       ******
afcd       ************
efad       ******
ebcd       ************
efcb       ******
efab       ******
ebad       ************
abcd       *************************
afcb       ************

But the "trick" works only for some parents. E.g. switching the parents:

p = [['e','f','a','b'], ['a','b','c','d']]

you have again:

CHROMOSOME FREQUENCY
efcd       *************************
efcb       ************************
efad       *************************
efab       ************************

The edge recombination operator is another possibility:

ERO creates a path that is similar to a set of existing paths (parents) by looking at the edges rather than the vertices. The main application of this is for crossover in genetic algorithms when a genotype with non-repeating gene sequences is needed such as for the travelling salesman problem.

(not sure it's your case)

manlio
  • 18,345
  • 14
  • 76
  • 126
1

Yes. That's a cross over. Do that. Assuming the elements are in the same place so long as you do a crossover by picking a point and then swapping the arrays beyond that point, you're not going to duplicate elements.

But, then it's a genetic algorithm, it doesn't matter if you make something faulty it should die out anyway, so you don't have to worry about maintaining some kind of forced purity. It'll just solve for improvements in the fitness function anyhow.

Tatarize
  • 10,238
  • 4
  • 58
  • 64
0

The simplest solution is to select a random index between 0 and parents' length. Let's name that index n.

Then just put the first n elements of the first parent in the child, followed by the rest length-n elements from the second parent.

See how I implemented the crossover method here:

https://github.com/amihaiemil/eva/blob/master/src/main/java/com/amihaiemil/eva/util/BinaryArraySolution.java

There's also a "crossover probability" involved which is basically a random between 0 and 1 which dictates it the parents have a child or not. If they cannot have a child, then the best of the 2 is returned.

amihaiemil
  • 623
  • 8
  • 19