001/* 002 * Java Genetic Algorithm Library (jenetics-8.1.0). 003 * Copyright (c) 2007-2024 Franz Wilhelmstötter 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 * Author: 018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com) 019 */ 020package io.jenetics; 021 022import static io.jenetics.internal.math.Randoms.indexes; 023 024import java.util.random.RandomGenerator; 025 026import io.jenetics.util.MSeq; 027 028/** 029 * The {@code SwapMutation} changes the order of genes in a chromosome, with the 030 * hope of bringing related genes closer together, thereby facilitating the 031 * production of building blocks. This mutation operator can also be used for 032 * combinatorial problems, where no duplicated genes within a chromosome are 033 * allowed, e.g., for the TSP. 034 * <p> 035 * This mutator is also known as <em>Partial Shuffle Mutator</em> (PSM). 036 * 037 * @see <a href="https://arxiv.org/ftp/arxiv/papers/1203/1203.3099.pdf"> 038 * Analyzing the Performance of Mutation Operators to Solve the Travelling 039 * Salesman Problem</a> 040 * 041 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 042 * @since 1.0 043 * @version 5.0 044 */ 045public class SwapMutator< 046 G extends Gene<?, G>, 047 C extends Comparable<? super C> 048> 049 extends Mutator<G, C> 050{ 051 052 /** 053 * Constructs an alterer with a given recombination probability. 054 * 055 * @param probability the crossover probability. 056 * @throws IllegalArgumentException if the {@code probability} is not in the 057 * valid range of {@code [0, 1]}. 058 */ 059 public SwapMutator(final double probability) { 060 super(probability); 061 } 062 063 /** 064 * Default constructor, with default mutation probability 065 * ({@link AbstractAlterer#DEFAULT_ALTER_PROBABILITY}). 066 */ 067 public SwapMutator() { 068 this(DEFAULT_ALTER_PROBABILITY); 069 } 070 071 /** 072 * Swaps the genes in the given array, with the mutation probability of this 073 * mutation. 074 */ 075 @Override 076 protected MutatorResult<Chromosome<G>> mutate( 077 final Chromosome<G> chromosome, 078 final double p, 079 final RandomGenerator random 080 ) { 081 final MutatorResult<Chromosome<G>> result; 082 if (chromosome.length() > 1) { 083 final MSeq<G> genes = MSeq.of(chromosome); 084 final int mutations = (int)indexes(random, genes.length(), p) 085 .peek(i -> genes.swap(i, random.nextInt(genes.length()))) 086 .count(); 087 088 result = new MutatorResult<>( 089 chromosome.newInstance(genes.toISeq()), 090 mutations 091 ); 092 } else { 093 result = new MutatorResult<>(chromosome, 0); 094 } 095 096 return result; 097 } 098 099}