View Javadoc
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 }