View Javadoc
1   package net.bmahe.genetics4j.gp.mutation;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   import java.util.Optional;
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.spec.chromosome.ProgramTreeChromosomeSpec;
21  import net.bmahe.genetics4j.gp.spec.mutation.Rule;
22  import net.bmahe.genetics4j.gp.utils.TreeNodeUtils;
23  
24  public class ProgramRulesApplicatorMutator implements Mutator {
25  	final static public Logger logger = LogManager.getLogger(ProgramRulesApplicatorMutator.class);
26  
27  	private final List<Rule> rules;
28  	private final AbstractEAConfiguration eaConfiguration;
29  
30  	public ProgramRulesApplicatorMutator(final List<Rule> _rules, final AbstractEAConfiguration _eaConfiguration) {
31  		Validate.notNull(_rules);
32  		Validate.isTrue(_rules.isEmpty() == false);
33  		Validate.notNull(_eaConfiguration);
34  
35  		this.rules = _rules;
36  		this.eaConfiguration = _eaConfiguration;
37  	}
38  
39  	protected TreeNode<Operation<?>> duplicateAndApplyRule(final Program program, final TreeNode<Operation<?>> root) {
40  		Validate.notNull(root);
41  
42  		logger.trace("A - {}", TreeNodeUtils.toStringTreeNode(root));
43  
44  		final Operation<?> rootOperation = root.getData();
45  		final List<TreeNode<Operation<?>>> children = root.getChildren();
46  
47  		TreeNode<Operation<?>> currentRoot = new TreeNode<Operation<?>>(rootOperation);
48  
49  		if (children.size() > 0) {
50  			final List<TreeNode<Operation<?>>> newChildren = new ArrayList<>();
51  			for (int i = 0; i < children.size(); i++) {
52  				final TreeNode<Operation<?>> childNode = children.get(i);
53  
54  				final TreeNode<Operation<?>> childCopy = duplicateAndApplyRule(program, childNode);
55  				newChildren.add(childCopy);
56  
57  			}
58  			currentRoot.addChildren(newChildren);
59  		}
60  
61  		boolean done = false;
62  		while (done == false) {
63  			final TreeNode<Operation<?>> localRoot = currentRoot;
64  
65  			logger.trace("B - {}", TreeNodeUtils.toStringTreeNode(localRoot));
66  
67  			final Optional<Rule> applicableRule = rules.stream().filter((rule) -> rule.test(localRoot)).findFirst();
68  			final Optional<TreeNode<Operation<?>>> newRootOpt = applicableRule.map(x -> x.apply(program, localRoot));
69  
70  			done = newRootOpt.map(newRoot -> TreeNodeUtils.areSame(newRoot, localRoot)).orElse(true);
71  
72  			if (newRootOpt.isPresent()) {
73  				currentRoot = newRootOpt.get();
74  			}
75  		}
76  
77  		return currentRoot;
78  	}
79  
80  	@Override
81  	public Genotype mutate(final Genotype original) {
82  		Validate.notNull(original);
83  
84  		logger.trace("Mutating genotype: {}", original);
85  
86  		final Chromosome[] newChromosomes = new Chromosome[original.getSize()];
87  		final Chromosome[] chromosomes = original.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().getSimpleName());
99  			}
100 
101 			final ProgramTreeChromosomeSpec programTreeChromosomeSpec = (ProgramTreeChromosomeSpec) chromosomeSpec;
102 
103 			final TreeChromosome<Operation<?>> treeChromosome = (TreeChromosome<Operation<?>>) chromosome;
104 			final TreeNode<Operation<?>> root = treeChromosome.getRoot();
105 
106 			if (logger.isTraceEnabled()) {
107 				logger.trace("Original chromosome {} - {}", chromosomeIndex, TreeNodeUtils.toStringTreeNode(root));
108 			}
109 
110 			final TreeNode<Operation<?>> newRoot = duplicateAndApplyRule(programTreeChromosomeSpec.program(), root);
111 			final TreeChromosome<Operation<?>> newTreeChromosome = new TreeChromosome<>(newRoot);
112 			newChromosomes[chromosomeIndex] = newTreeChromosome;
113 
114 		}
115 
116 		return new Genotype(newChromosomes);
117 	}
118 }