1 package net.bmahe.genetics4j.gp.mutation; 2 3 import java.util.List; 4 import java.util.Objects; 5 import java.util.random.RandomGenerator; 6 7 import org.apache.commons.lang3.Validate; 8 import org.apache.logging.log4j.LogManager; 9 import org.apache.logging.log4j.Logger; 10 11 import net.bmahe.genetics4j.core.Genotype; 12 import net.bmahe.genetics4j.core.chromosomes.Chromosome; 13 import net.bmahe.genetics4j.core.chromosomes.TreeChromosome; 14 import net.bmahe.genetics4j.core.chromosomes.TreeNode; 15 import net.bmahe.genetics4j.core.mutation.Mutator; 16 import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration; 17 import net.bmahe.genetics4j.core.spec.chromosome.ChromosomeSpec; 18 import net.bmahe.genetics4j.gp.Operation; 19 import net.bmahe.genetics4j.gp.program.Program; 20 import net.bmahe.genetics4j.gp.program.ProgramGenerator; 21 import net.bmahe.genetics4j.gp.spec.chromosome.ProgramTreeChromosomeSpec; 22 import net.bmahe.genetics4j.gp.spec.mutation.TrimTree; 23 24 public class TrimTreeMutator implements Mutator { 25 final static public Logger logger = LogManager.getLogger(TrimTreeMutator.class); 26 27 private final ProgramGenerator programGenerator; 28 private final RandomGenerator randomGenerator; 29 private final AbstractEAConfiguration eaConfiguration; 30 private final TrimTree trimTree; 31 32 public TrimTreeMutator(final ProgramGenerator _programGenerator, final RandomGenerator _randomGenerator, 33 final AbstractEAConfiguration _eaConfiguration, final TrimTree _trimTree) { 34 Objects.requireNonNull(_programGenerator); 35 Objects.requireNonNull(_randomGenerator); 36 Objects.requireNonNull(_eaConfiguration); 37 Objects.requireNonNull(_trimTree); 38 39 this.programGenerator = _programGenerator; 40 this.randomGenerator = _randomGenerator; 41 this.eaConfiguration = _eaConfiguration; 42 this.trimTree = _trimTree; 43 } 44 45 protected TreeNode<Operation<?>> duplicateAndMutate(final Program program, final TreeNode<Operation<?>> root, 46 final int maxDepth, final int currentDepth) { 47 Objects.requireNonNull(program); 48 Objects.requireNonNull(root); 49 50 final Operation<?> rootData = root.getData(); 51 52 if (currentDepth == maxDepth && root.getSize() > 1) { 53 return programGenerator.generate(program, 1, rootData.returnedType()); 54 } 55 56 final List<TreeNode<Operation<?>>> children = root.getChildren(); 57 58 final TreeNode<Operation<?>> duplicateRoot = new TreeNode<Operation<?>>(rootData); 59 60 for (int i = 0; i < children.size(); i++) { 61 final TreeNode<Operation<?>> treeNode = children.get(i); 62 final int childSize = treeNode.getSize(); 63 64 final TreeNode<Operation<?>> childCopy = duplicateAndMutate(program, treeNode, maxDepth, currentDepth + 1); 65 duplicateRoot.addChild(childCopy); 66 } 67 68 return duplicateRoot; 69 } 70 71 private int maxDepthValue(final Program program, final TrimTree trimTree) { 72 Objects.requireNonNull(program); 73 Objects.requireNonNull(trimTree); 74 75 return trimTree.maxDepth() 76 .orElseGet(() -> program.maxDepth()); 77 } 78 79 @Override 80 public Genotype mutate(final long generation, final Genotype originalGenotype) { 81 Validate.isTrue(generation >= 0); 82 Objects.requireNonNull(originalGenotype); 83 84 logger.trace("Mutating genotype {}", originalGenotype); 85 86 final Chromosome[] newChromosomes = new Chromosome[originalGenotype.getSize()]; 87 final Chromosome[] chromosomes = originalGenotype.getChromosomes(); 88 for (int chromosomeIndex = 0; chromosomeIndex < chromosomes.length; chromosomeIndex++) { 89 final ChromosomeSpec chromosomeSpec = eaConfiguration.getChromosomeSpec(chromosomeIndex); 90 final Chromosome chromosome = chromosomes[chromosomeIndex]; 91 92 if (chromosomeSpec instanceof ProgramTreeChromosomeSpec == false) { 93 throw new IllegalArgumentException("This mutator does not support chromosome specs " + chromosomeSpec); 94 } 95 96 if (chromosome instanceof TreeChromosome<?> == false) { 97 throw new IllegalArgumentException( 98 "This mutator does not support chromosome of type " + chromosome.getClass() 99 .getSimpleName()); 100 } 101 102 final ProgramTreeChromosomeSpec programTreeChromosomeSpec = (ProgramTreeChromosomeSpec) chromosomeSpec; 103 final Program program = programTreeChromosomeSpec.program(); 104 105 final TreeChromosome<Operation<?>> treeChromosome = (TreeChromosome<Operation<?>>) chromosome; 106 107 final int maxDepthValue = maxDepthValue(program, trimTree); 108 109 if (treeChromosome.getRoot() 110 .getDepth() > maxDepthValue) { 111 final TreeNode<Operation<?>> root = treeChromosome.getRoot(); 112 final TreeNode<Operation<?>> newRoot = duplicateAndMutate(program, root, maxDepthValue, 0); 113 final TreeChromosome<Operation<?>> newTreeChromosome = new TreeChromosome<>(newRoot); 114 newChromosomes[chromosomeIndex] = newTreeChromosome; 115 } else { 116 newChromosomes[chromosomeIndex] = chromosome; 117 } 118 119 logger.trace("\tChromosome {} - {}", chromosomeIndex, newChromosomes[chromosomeIndex]); 120 } 121 122 return new Genotype(newChromosomes); 123 } 124 }