/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jenetics.example.image; import static java.lang.String.format; import java.util.Random; import org.jenetics.Crossover; import org.jenetics.Gene; import org.jenetics.util.MSeq; import org.jenetics.util.RandomRegistry; /** * Perform Uniform Crossover [UX] on the specified genes. A fixed mixing ratio * is used to combine genes from the first and second parents, e.g. using a * ratio of 0.5 would result in approximately 50% of genes coming from each * parent. This is typically a poor method of crossover, but empirical evidence * suggests that it is more exploratory and results in a larger part of the * problem space being searched. * <p> * This crossover policy evaluates each gene of the parent genes by choosing a * uniform random number {@code p} in the range [0, 1]. If {@code p} < * {@code ratio}, the parent genes are swapped. This means with a ratio of 0.7, * 30% of the genes from the first parent and 70% from the second parent will * be selected for the first offspring (and vice versa for the second offspring). * <p> * The genes must have same lengths. * * @see <a href="http://en.wikipedia.org/wiki/Crossover_%28genetic_algorithm%29"> * Crossover techniques (Wikipedia)</a> * @see <a href="http://www.obitko.com/tutorials/genetic-algorithms/crossover-mutation.php"> * Crossover (Obitko.com)</a> * @see <a href="http://www.tomaszgwiazda.com/uniformX.htm">Uniform crossover</a> */ final class UniformCrossover< G extends Gene<?, G>, C extends Comparable<? super C> > extends Crossover<G, C> { /** * Constructs an alterer with a given recombination probability. * * @param probability the crossover probability. * @throws IllegalArgumentException if the {@code probability} is not in the * valid range of {@code [0, 1]}. */ public UniformCrossover(final double probability) { super(probability); } @Override protected int crossover(final MSeq<G> that, final MSeq<G> other) { assert that.length() == other.length(); int alteredGenes = 0; final Random random = RandomRegistry.getRandom(); for (int i = 0; i < that.length(); ++i) { if (random.nextFloat() < getProbability()) { crossover(that, other, i); ++alteredGenes; } } return alteredGenes; } // Package private for testing purpose. static <T> void crossover( final MSeq<T> that, final MSeq<T> other, final int index ) { assert index >= 0 : format( "Crossover index must be within [0, %d) but was %d", that.length(), index ); that.swap(index, index + 1, other, index); } }