001/*
002 * Java Genetic Algorithm Library (jenetics-7.2.0).
003 * Copyright (c) 2007-2023 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.Chromosome;
025import io.jenetics.Mutator;
026import io.jenetics.MutatorResult;
027import io.jenetics.internal.math.Probabilities;
028
029import io.jenetics.ext.util.FlatTreeNode;
030import io.jenetics.ext.util.TreeNode;
031
032/**
033 * Abstract class for mutating tree chromosomes.
034 *
035 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
036 * @version 4.1
037 * @since 4.1
038 */
039public abstract class TreeMutator<
040        A,
041        G extends TreeGene<A, G>,
042        C extends Comparable<? super C>
043>
044        extends Mutator<G, C>
045{
046
047        public TreeMutator() {
048                this(DEFAULT_ALTER_PROBABILITY);
049        }
050
051        public TreeMutator(final double probability) {
052                super(probability);
053        }
054
055
056        /**
057         * Mutates the given chromosome.
058         *
059         * @param chromosome the chromosome to mutate
060         * @param p the mutation probability for the underlying genetic objects
061         * @param random the random engine used for the genotype mutation
062         * @return the mutation result
063         */
064        @Override
065        protected MutatorResult<Chromosome<G>> mutate(
066                final Chromosome<G> chromosome,
067                final double p,
068                final RandomGenerator random
069        ) {
070                final int P = Probabilities.toInt(p);
071                return random.nextInt() < P
072                        ? mutate(chromosome)
073                        : new MutatorResult<>(chromosome, 0);
074        }
075
076        private MutatorResult<Chromosome<G>> mutate(final Chromosome<G> chromosome) {
077                final TreeNode<A> tree = TreeNode.ofTree(chromosome.gene());
078                mutate(tree);
079
080                final var flat = FlatTreeNode.ofTree(tree);
081                final var genes = flat.map(t -> chromosome.gene().newInstance(t));
082                return new MutatorResult<>(chromosome.newInstance(genes), 1);
083        }
084
085        /**
086         * This method does the actual mutating, in place.
087         *
088         * @param tree the mutable tree to mutate
089         */
090        protected abstract void mutate(final TreeNode<A> tree);
091
092}