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.ext; 021 022import java.util.random.RandomGenerator; 023 024import io.jenetics.AbstractAlterer; 025import io.jenetics.Chromosome; 026import io.jenetics.Gene; 027import io.jenetics.Mutator; 028import io.jenetics.MutatorResult; 029import io.jenetics.internal.math.Probabilities; 030import io.jenetics.internal.math.Subsets; 031import io.jenetics.util.MSeq; 032 033/** 034 * The Hybridizing PSM and RSM Operator (HPRM) constructs an offspring from a 035 * pair of parents by hybridizing two mutation operators, PSM and RSM. 036 * <p> 037 * This mutator is described in <a href="https://arxiv.org/abs/1203.5028">A New 038 * Mutation Operator for Solving an NP-Complete Problem: Travelling Salesman 039 * Problem</a>, by <em>Otman Abdoun, Chakir Tajani</em> and 040 * <em>Jaafar Abouchabka</em>. 041 * 042 * @see RSMutator 043 * @see io.jenetics.SwapMutator 044 * 045 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 046 * @version 5.0 047 * @since 5.0 048 */ 049public class HPRMutator< 050 G extends Gene<?, G>, 051 C extends Comparable<? super C> 052> 053 extends Mutator<G, C> 054{ 055 056 /** 057 * Constructs an alterer with a given recombination probability. 058 * 059 * @param probability the crossover probability. 060 * @throws IllegalArgumentException if the {@code probability} is not in the 061 * valid range of {@code [0, 1]}. 062 */ 063 public HPRMutator(final double probability) { 064 super(probability); 065 } 066 067 /** 068 * Default constructor, with default mutation probability 069 * ({@link AbstractAlterer#DEFAULT_ALTER_PROBABILITY}). 070 */ 071 public HPRMutator() { 072 this(DEFAULT_ALTER_PROBABILITY); 073 } 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 int P = Probabilities.toInt(p); 084 final int[] points = Subsets.next(random, chromosome.length(), 2); 085 final MSeq<G> genes = MSeq.of(chromosome); 086 087 int mutations = (points[1] - points[0] + 1)/2; 088 for (int i = points[0], j = points[1]; i < j; ++i, --j) { 089 genes.swap(i, j); 090 if (random.nextInt() < P) { 091 genes.swap(i, random.nextInt(chromosome.length())); 092 ++mutations; 093 } 094 } 095 096 result = new MutatorResult<>( 097 chromosome.newInstance(genes.toISeq()), 098 mutations 099 ); 100 } else { 101 result = new MutatorResult<>(chromosome, 0); 102 } 103 104 return result; 105 } 106 107}