View Javadoc
1   package net.bmahe.genetics4j.gp.mutation;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   import java.util.Objects;
6   import java.util.Optional;
7   
8   import org.apache.commons.lang3.Validate;
9   import org.apache.logging.log4j.LogManager;
10  import org.apache.logging.log4j.Logger;
11  
12  import net.bmahe.genetics4j.core.Genotype;
13  import net.bmahe.genetics4j.core.chromosomes.Chromosome;
14  import net.bmahe.genetics4j.core.chromosomes.TreeChromosome;
15  import net.bmahe.genetics4j.core.chromosomes.TreeNode;
16  import net.bmahe.genetics4j.core.mutation.Mutator;
17  import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration;
18  import net.bmahe.genetics4j.core.spec.chromosome.ChromosomeSpec;
19  import net.bmahe.genetics4j.gp.Operation;
20  import net.bmahe.genetics4j.gp.program.Program;
21  import net.bmahe.genetics4j.gp.spec.chromosome.ProgramTreeChromosomeSpec;
22  import net.bmahe.genetics4j.gp.spec.mutation.Rule;
23  import net.bmahe.genetics4j.gp.utils.TreeNodeUtils;
24  
25  public class ProgramRulesApplicatorMutator implements Mutator {
26  	final static public Logger logger = LogManager.getLogger(ProgramRulesApplicatorMutator.class);
27  
28  	private final List<Rule> rules;
29  	private final AbstractEAConfiguration eaConfiguration;
30  
31  	public ProgramRulesApplicatorMutator(final List<Rule> _rules, final AbstractEAConfiguration _eaConfiguration) {
32  		Objects.requireNonNull(_rules);
33  		Validate.isTrue(_rules.isEmpty() == false);
34  		Objects.requireNonNull(_eaConfiguration);
35  
36  		this.rules = _rules;
37  		this.eaConfiguration = _eaConfiguration;
38  	}
39  
40  	protected TreeNode<Operation<?>> duplicateAndApplyRule(final Program program, final TreeNode<Operation<?>> root) {
41  		Objects.requireNonNull(root);
42  
43  		logger.trace("A - {}", TreeNodeUtils.toStringTreeNode(root));
44  
45  		final Operation<?> rootOperation = root.getData();
46  		final List<TreeNode<Operation<?>>> children = root.getChildren();
47  
48  		TreeNode<Operation<?>> currentRoot = new TreeNode<Operation<?>>(rootOperation);
49  
50  		if (children.size() > 0) {
51  			final List<TreeNode<Operation<?>>> newChildren = new ArrayList<>();
52  			for (int i = 0; i < children.size(); i++) {
53  				final TreeNode<Operation<?>> childNode = children.get(i);
54  
55  				final TreeNode<Operation<?>> childCopy = duplicateAndApplyRule(program, childNode);
56  				newChildren.add(childCopy);
57  
58  			}
59  			currentRoot.addChildren(newChildren);
60  		}
61  
62  		boolean done = false;
63  		while (done == false) {
64  			final TreeNode<Operation<?>> localRoot = currentRoot;
65  
66  			logger.trace("B - {}", TreeNodeUtils.toStringTreeNode(localRoot));
67  
68  			final Optional<Rule> applicableRule = rules.stream()
69  					.filter((rule) -> rule.test(localRoot))
70  					.findFirst();
71  			final Optional<TreeNode<Operation<?>>> newRootOpt = applicableRule.map(x -> x.apply(program, localRoot));
72  
73  			done = newRootOpt.map(newRoot -> TreeNodeUtils.areSame(newRoot, localRoot))
74  					.orElse(true);
75  
76  			if (newRootOpt.isPresent()) {
77  				currentRoot = newRootOpt.get();
78  			}
79  		}
80  
81  		return currentRoot;
82  	}
83  
84  	@Override
85  	public Genotype mutate(final long generation, final Genotype original) {
86  		Objects.requireNonNull(original);
87  
88  		logger.trace("Mutating genotype: {}", original);
89  
90  		final Chromosome[] newChromosomes = new Chromosome[original.getSize()];
91  		final Chromosome[] chromosomes = original.getChromosomes();
92  		for (int chromosomeIndex = 0; chromosomeIndex < chromosomes.length; chromosomeIndex++) {
93  			final ChromosomeSpec chromosomeSpec = eaConfiguration.getChromosomeSpec(chromosomeIndex);
94  			final Chromosome chromosome = chromosomes[chromosomeIndex];
95  
96  			if (chromosomeSpec instanceof ProgramTreeChromosomeSpec == false) {
97  				throw new IllegalArgumentException("This mutator does not support chromosome specs " + chromosomeSpec);
98  			}
99  
100 			if (chromosome instanceof TreeChromosome<?> == false) {
101 				throw new IllegalArgumentException(
102 						"This mutator does not support chromosome of type " + chromosome.getClass()
103 								.getSimpleName());
104 			}
105 
106 			final ProgramTreeChromosomeSpec programTreeChromosomeSpec = (ProgramTreeChromosomeSpec) chromosomeSpec;
107 
108 			final TreeChromosome<Operation<?>> treeChromosome = (TreeChromosome<Operation<?>>) chromosome;
109 			final TreeNode<Operation<?>> root = treeChromosome.getRoot();
110 
111 			if (logger.isTraceEnabled()) {
112 				logger.trace("Original chromosome {} - {}", chromosomeIndex, TreeNodeUtils.toStringTreeNode(root));
113 			}
114 
115 			final TreeNode<Operation<?>> newRoot = duplicateAndApplyRule(programTreeChromosomeSpec.program(), root);
116 			final TreeChromosome<Operation<?>> newTreeChromosome = new TreeChromosome<>(newRoot);
117 			newChromosomes[chromosomeIndex] = newTreeChromosome;
118 
119 		}
120 
121 		return new Genotype(newChromosomes);
122 	}
123 }