| 
001 /*002  * Java Genetic Algorithm Library (jenetics-6.3.0).
 003  * Copyright (c) 2007-2021 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  */
 020 package io.jenetics.ext;
 021
 022 import java.util.Random;
 023
 024 import io.jenetics.AbstractAlterer;
 025 import io.jenetics.Chromosome;
 026 import io.jenetics.Gene;
 027 import io.jenetics.Mutator;
 028 import io.jenetics.MutatorResult;
 029 import io.jenetics.internal.math.Combinatorics;
 030 import io.jenetics.internal.math.Probabilities;
 031 import 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  */
 049 public 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 Random random
 080     ) {
 081         final MutatorResult<Chromosome<G>> result;
 082         if (chromosome.length() > 1) {
 083             final int P = Probabilities.toInt(p);
 084             final int[] points = Combinatorics.subset(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 = MutatorResult.of(
 097                 chromosome.newInstance(genes.toISeq()),
 098                 mutations
 099             );
 100         } else {
 101             result = MutatorResult.of(chromosome);
 102         }
 103
 104         return result;
 105     }
 106
 107 }
 |