HPRMutator.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-5.1.0).
003  * Copyright (c) 2007-2019 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.comb;
030 import io.jenetics.internal.math.probability;
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     extends Gene<?, G>,
051     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 = probability.toInt(p);
084             final int[] points = comb.subset(chromosome.length()2);
085             final MSeq<G> genes = chromosome.toSeq().copy();
086 
087             int mutations = (points[1- points[01)/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 }