All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgap.impl.SwappingMutationOperator Maven / Gradle / Ivy

/*
 * This file is part of JGAP.
 *
 * JGAP offers a dual license model containing the LGPL as well as the MPL.
 *
 * For licensing information please see the file license.txt included with JGAP
 * or have a look at the top of class org.jgap.Chromosome which representatively
 * includes the JGAP license policy applicable for any file delivered with JGAP.
 */
package org.jgap.impl;

import java.util.*;
import org.jgap.*;

/**
 * Swaps the genes instead of mutating them. This kind of operator is
 * required by Traveling Salesman Problem.
 *
 * See J. Grefenstette, R. Gopal, R. Rosmaita, and D. Gucht.
 *  Genetic algorithms for the traveling salesman problem.
 * In Proceedings of the Second International Conference on Genetic Algorithms.
 *  Lawrence Eribaum Associates, Mahwah, NJ, 1985.
 * and also 
 * Sushil J. Louis & Gong Li  }
 *
 * @author Audrius Meskauskas
 * @author Neil Rotstan
 * @author Klaus Meffert
 * @since 2.0
 */
public class SwappingMutationOperator
    extends MutationOperator {
  /** String containing the CVS revision. Read out via reflection!*/
  private final static String CVS_REVISION = "$Revision: 1.21 $";

  private int m_startOffset = 1;

  /**
   * Constructs a new instance of this operator.

* Attention: The configuration used is the one set with the static method * Genotype.setConfiguration. * * @throws InvalidConfigurationException * * @author Klaus Meffert */ public SwappingMutationOperator() throws InvalidConfigurationException { super(); } /** * @param a_config the configuration to use * @throws InvalidConfigurationException * * @author Klaus Meffert * @since 3.0 */ public SwappingMutationOperator(final Configuration a_config) throws InvalidConfigurationException { super(a_config); } /** * Constructs a new instance of this operator with a specified * mutation rate calculator, which results in dynamic mutation being turned * on. * * @param a_config the configuration to use * @param a_mutationRateCalculator calculator for dynamic mutation rate * computation * @throws InvalidConfigurationException * * @author Klaus Meffert * @since 3.0 (previously: without a_config) */ public SwappingMutationOperator(final Configuration a_config, final IUniversalRateCalculator a_mutationRateCalculator) throws InvalidConfigurationException { super(a_config, a_mutationRateCalculator); } /** * Constructs a new instance of this MutationOperator with the given * mutation rate. * * @param a_config the configuration to use * @param a_desiredMutationRate desired rate of mutation, expressed as * the denominator of the 1 / X fraction. For example, 1000 would result * in 1/1000 genes being mutated on average. A mutation rate of zero disables * mutation entirely * @throws InvalidConfigurationException * * @author Klaus Meffert * @since 3.0 (previously: without a_config) */ public SwappingMutationOperator(final Configuration a_config, final int a_desiredMutationRate) throws InvalidConfigurationException { super(a_config, a_desiredMutationRate); } /** * @param a_population the population of chromosomes from the current * evolution prior to exposure to any genetic operators. Chromosomes in this * array should not be modified. Please, notice, that the call in * Genotype.evolve() to the implementations of GeneticOperator overgoes this * due to performance issues * @param a_candidateChromosomes the pool of chromosomes that have been * selected for the next evolved population * * @author Audrius Meskauskas * @author Klaus Meffert * @since 2.0 */ public void operate(final Population a_population, List a_candidateChromosomes) { // this was a private variable, now it is local reference. final IUniversalRateCalculator m_mutationRateCalc = getMutationRateCalc(); // If the mutation rate is set to zero and dynamic mutation rate is // disabled, then we don't perform any mutation. // ---------------------------------------------------------------- if (getMutationRate() == 0 && m_mutationRateCalc == null) { return; } // Determine the mutation rate. If dynamic rate is enabled, then // calculate it based upon the number of genes in the chromosome. // Otherwise, go with the mutation rate set upon construction. // -------------------------------------------------------------- int currentRate; if (m_mutationRateCalc != null) { currentRate = m_mutationRateCalc.calculateCurrentRate(); } else { currentRate = getMutationRate(); } RandomGenerator generator = getConfiguration().getRandomGenerator(); // It would be inefficient to create copies of each Chromosome just // to decide whether to mutate them. Instead, we only make a copy // once we've positively decided to perform a mutation. // ---------------------------------------------------------------- int size = a_population.size(); for (int i = 0; i < size; i++) { IChromosome x = a_population.getChromosome(i); // This returns null if not mutated: IChromosome xm = operate(x, currentRate, generator); if (xm != null) { a_candidateChromosomes.add(xm); } } } /** * Operate on the given chromosome with the given mutation rate. * * @param a_chrom chromosome to operate * @param a_rate mutation rate * @param a_generator random generator to use (must not be null) * @return mutated chromosome of null if no mutation has occured. * * @author Audrius Meskauskas * @since 2.0 */ protected IChromosome operate(final IChromosome a_chrom, final int a_rate, final RandomGenerator a_generator) { IChromosome chromosome = null; // ---------------------------------------- for (int j = m_startOffset; j < a_chrom.size(); j++) { // Ensure probability of 1/currentRate for applying mutation. // ---------------------------------------------------------- if (a_generator.nextInt(a_rate) == 0) { if (chromosome == null) { chromosome = (IChromosome) a_chrom.clone(); // In case monitoring is active, support it. // ----------------------------------------- if (m_monitorActive) { chromosome.setUniqueIDTemplate(a_chrom.getUniqueID(), 1); } } Gene[] genes = chromosome.getGenes(); Gene[] mutated = operate(a_generator, j, genes); // setGenes is not required for this operator, but it may // be needed for the derived operators. // ------------------------------------------------------ try { chromosome.setGenes(mutated); } catch (InvalidConfigurationException cex) { throw new Error("Gene type not allowed by constraint checker", cex); } } } return chromosome; } /** * Operate on the given array of genes. This method is only called * when it is already clear that the mutation must occur under the given * mutation rate. * * @param a_generator a random number generator that may be needed to * perform a mutation * @param a_target_gene an index of gene in the chromosome that will mutate * @param a_genes the array of all genes in the chromosome * @return the mutated gene array * * @author Audrius Meskauskas * @since 2.0 */ protected Gene[] operate(final RandomGenerator a_generator, final int a_target_gene, final Gene[] a_genes) { // swap this gene with the other one now: // mutateGene(genes[j], generator); // ------------------------------------- int other = m_startOffset + a_generator.nextInt(a_genes.length - m_startOffset); Gene t = a_genes[a_target_gene]; a_genes[a_target_gene] = a_genes[other]; a_genes[other] = t; if (m_monitorActive) { a_genes[a_target_gene].setUniqueIDTemplate(a_genes[other].getUniqueID(), 1); a_genes[other].setUniqueIDTemplate(a_genes[a_target_gene].getUniqueID(), 1); } return a_genes; } /** * Sets a number of genes at the start of chromosome, that are * excluded from the swapping. In the Salesman task, the first city * in the list should (where the salesman leaves from) probably should * not change as it is part of the list. The default value is 1. * * @param a_offset the offset to set * * @author Audrius Meskauskas * @since 2.0 */ public void setStartOffset(final int a_offset) { m_startOffset = a_offset; } /** * Gets a number of genes at the start of chromosome, that are * excluded from the swapping. In the Salesman task, the first city * in the list should (where the salesman leaves from) probably should * not change as it is part of the list. The default value is 1. * * @return the start offset * * @author Audrius Meskauskas * @since 2.0 */ public int getStartOffset() { return m_startOffset; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy