Class PositionBasedCrossover

All Implemented Interfaces:
PermutationFullBinaryOperator, Splittable<CrossoverOperator<Permutation>>, CrossoverOperator<Permutation>

public final class PositionBasedCrossover extends Object implements CrossoverOperator<Permutation>, PermutationFullBinaryOperator
Implementation of position based crossover (PBX). The PBX operator attempts to cause children to inherit most element positions from the parents, and in particular such that each child gets the positions of equal number of elements (on average) from each of its parents.

To illustrate its behavior, consider the following example. Let parent p1 = [2, 5, 1, 4, 3, 0] and parent p2 = [5, 4, 3, 2, 1, 0]. Step 1 generates a list that maps each element to its indexes in the parents. From the above, we'd have the element to index mapping: [ 0 : {5, 5}, 1 : {2, 4}, 2 : {0, 3}, 3 : {4, 2}, 4 : {3, 1}, 5 : {1, 0}]. Randomize the ordering of this list of element to index mappings: [3 : {4, 2}, 5 : {1, 0}, 0 : {5, 5}, 2 : {0, 3}, 1 : {2, 4}, 4 : {3, 1}]. Pick a random subset of elements, with each element equally likely chosen (on average n/2 elements will be chosen). For this example, imagine that elements 5 and 1 were chosen. For each of these, in the element to index mappings list, swap the two indexes. For example, element 5 currently has the mapping: 5 : {1, 0}. Swap the indexes to instead get: 5 : {0, 1}. Doing this for both elements 5 and 1 leads to: [3 : {4, 2}, 5 : {0, 1}, 0 : {5, 5}, 2 : {0, 3}, 1 : {4, 2}, 4 : {3, 1}]. In this list of element to index mappings, the first index for each element is where we will attempt to put that element in child c1, and the second is where we will attempt to put it in c2. Proceed as follows. Initialize empty children c1 = [x, x, x, x, x, x] and c2 = [x, x, x, x, x, x]. Iterate over the mappings and if the corresponding index in a child is empty, place the element there. Otherwise skip that element in that child for now. In this case, we'll get: c1 = [5, x, x, 4, 3, 0] and c2 = [x, 5, 3, 2, x, 0]. Next, using the same ordering, attempt to put the missing elements in the opposite index. For example, c1 is missing element 2. Its mapping is {0, 3}. We failed to put it at index 0 because the 5 was already there in c1. So we would attempt to put it at index 3. However, c1 already has 4 there, so we will again skip element 2 for now. Element 1 is mapped to the indexes {4, 2}. We couldn't put it at index 4 in c1 because the 3 is there, and we couldn't put it at index 2 in c2 because the 3 is there. So try the opposite indexes. Both of which work, so we now have: c1 = [5, x, 1, 4, 3, 0] and c2 = [x, 5, 3, 2, 1, 0]. The next element in the ordered mapping list is 4, which we failed to put in c2 at index 3 because the 2 is there, so we would instead try to put it at the other index 1, but that index is also taken. The last stage fills in any missing elements. It again uses the ordered list, and it fills them into any empty indexes left to right. In this case, there is only one missing element in each, so those elements go in the only remaining spots: c1 = [5, 2, 1, 4, 3, 0] and c2 = [4, 5, 3, 2, 1, 0].

The worst case runtime of a call to cross is O(n), where n is the length of the permutations.

The PBX operator was introduced in the following paper:

T. Barecke and M. Detyniecki, Memetic algorithms for inexact graph matching. 2007 IEEE Congress on Evolutionary Computation, Singapore, 2007, pp. 4238-4245, doi: 10.1109/CEC.2007.4425024.

  • Constructor Details

    • PositionBasedCrossover

      public PositionBasedCrossover()
      Constructs a position based crossover (PBX) operator.
  • Method Details

    • cross

      public void cross(Permutation c1, Permutation c2)
      Description copied from interface: CrossoverOperator
      Performs a crossover for an evolutionary algorithm, such that crossover forms two children from two parents. Implementations of this method modify the parameters, transforming the parents into the children.
      Specified by:
      cross in interface CrossoverOperator<Permutation>
      c1 - A candidate solution subject to the crossover. This method changes the state of c1.
      c2 - A candidate solution subject to the crossover. This method changes the state of c2.
    • split

      public PositionBasedCrossover split()
      Description copied from interface: Splittable
      Generates a functionally identical copy of this object, for use in multithreaded implementations of search algorithms. The state of the object that is returned may or may not be identical to that of the original. Thus, this is a distinct concept from the functionality of the Copyable interface. Classes that implement this interface must ensure that the object returned performs the same functionality, and that it does not share any state data that would be either unsafe or inefficient for concurrent access by multiple threads. The split method is allowed to simply return the this reference, provided that it is both safe and efficient for multiple threads to share a single copy of the Splittable object. The intention is to provide a multithreaded search with the capability to provide spawned threads with their own distinct search operators. Such multithreaded algorithms can call the split method for each thread it spawns to generate a functionally identical copy of the operator, but with independent state.
      Specified by:
      split in interface Splittable<CrossoverOperator<Permutation>>
      A functionally identical copy of the object, or a reference to this if it is both safe and efficient for multiple threads to share a single instance of this Splittable object.
    • apply

      public void apply(int[] raw1, int[] raw2, Permutation p1, Permutation p2)
      See PermutationFullBinaryOperator for details of this method. This method is not intended for direct usage. Use the cross(org.cicirello.permutations.Permutation, org.cicirello.permutations.Permutation) method instead.
      Specified by:
      apply in interface PermutationFullBinaryOperator
      raw1 - The raw representation of the first permutation.
      raw2 - The raw representation of the second permutation.
      p1 - The first permutation.
      p2 - The second permutation.