1 | package net.bmahe.genetics4j.gp.math; | |
2 | ||
3 | import java.util.Arrays; | |
4 | import java.util.List; | |
5 | import java.util.Objects; | |
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.chromosomes.TreeNode; | |
12 | import net.bmahe.genetics4j.gp.InputSpec; | |
13 | import net.bmahe.genetics4j.gp.Operation; | |
14 | import net.bmahe.genetics4j.gp.OperationFactories; | |
15 | import net.bmahe.genetics4j.gp.OperationFactory; | |
16 | import net.bmahe.genetics4j.gp.spec.mutation.ImmutableRule; | |
17 | import net.bmahe.genetics4j.gp.spec.mutation.Rule; | |
18 | import net.bmahe.genetics4j.gp.utils.TreeNodeUtils; | |
19 | ||
20 | public class SimplificationRules { | |
21 | final static public Logger logger = LogManager.getLogger(SimplificationRules.class); | |
22 | ||
23 | public final static double DEFAULT_EPSILON = 0.0001; | |
24 | ||
25 | protected static boolean isOperation(final TreeNode<Operation<?>> node, final String name) { | |
26 | Objects.requireNonNull(node); | |
27 | Validate.notBlank(name); | |
28 |
4
1. isOperation : removed call to java/lang/String::equals → NO_COVERAGE 2. isOperation : replaced boolean return with true for net/bmahe/genetics4j/gp/math/SimplificationRules::isOperation → NO_COVERAGE 3. isOperation : replaced boolean return with false for net/bmahe/genetics4j/gp/math/SimplificationRules::isOperation → NO_COVERAGE 4. isOperation : removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getData → NO_COVERAGE |
return name.equals(node.getData() |
29 |
1
1. isOperation : removed call to net/bmahe/genetics4j/gp/Operation::getName → NO_COVERAGE |
.getName()); |
30 | } | |
31 | ||
32 | protected static boolean hasChildOperation(final TreeNode<Operation<?>> node, final int childIndex, | |
33 | final String name) { | |
34 | Objects.requireNonNull(node); | |
35 | Validate.isTrue(childIndex >= 0); | |
36 | Validate.notBlank(name); | |
37 | ||
38 |
1
1. hasChildOperation : removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getChildren → NO_COVERAGE |
if (node.getChildren() |
39 |
5
1. hasChildOperation : removed call to java/util/List::size → NO_COVERAGE 2. hasChildOperation : negated conditional → NO_COVERAGE 3. hasChildOperation : removed conditional - replaced comparison check with false → NO_COVERAGE 4. hasChildOperation : removed conditional - replaced comparison check with true → NO_COVERAGE 5. hasChildOperation : changed conditional boundary → NO_COVERAGE |
.size() <= childIndex) { |
40 |
2
1. hasChildOperation : Substituted 0 with 1 → NO_COVERAGE 2. hasChildOperation : replaced boolean return with true for net/bmahe/genetics4j/gp/math/SimplificationRules::hasChildOperation → NO_COVERAGE |
return false; |
41 | } | |
42 | ||
43 |
2
1. hasChildOperation : replaced call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getChild with receiver → NO_COVERAGE 2. hasChildOperation : removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getChild → NO_COVERAGE |
final TreeNode<Operation<?>> child = node.getChild(childIndex); |
44 |
4
1. hasChildOperation : removed call to java/lang/String::equals → NO_COVERAGE 2. hasChildOperation : replaced boolean return with false for net/bmahe/genetics4j/gp/math/SimplificationRules::hasChildOperation → NO_COVERAGE 3. hasChildOperation : removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getData → NO_COVERAGE 4. hasChildOperation : replaced boolean return with true for net/bmahe/genetics4j/gp/math/SimplificationRules::hasChildOperation → NO_COVERAGE |
return name.equals(child.getData() |
45 |
1
1. hasChildOperation : removed call to net/bmahe/genetics4j/gp/Operation::getName → NO_COVERAGE |
.getName()); |
46 | } | |
47 | ||
48 | @SuppressWarnings("unchecked") | |
49 | protected static <T> T getChildAs(final TreeNode<Operation<?>> node, final int childIndex, final Class<T> clazz) { | |
50 |
2
1. getChildAs : removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getChild → NO_COVERAGE 2. getChildAs : replaced call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getChild with receiver → NO_COVERAGE |
final TreeNode<Operation<?>> child = node.getChild(childIndex); |
51 |
1
1. getChildAs : removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getData → NO_COVERAGE |
final Operation<?> operation = child.getData(); |
52 |
1
1. getChildAs : replaced return value with null for net/bmahe/genetics4j/gp/math/SimplificationRules::getChildAs → NO_COVERAGE |
return (T) operation; |
53 | } | |
54 | ||
55 | protected static boolean isEqual(final double v1, final double v2, final double epsilon) { | |
56 | Validate.isTrue(epsilon >= 0); | |
57 | ||
58 |
10
1. isEqual : replaced call to java/lang/Math::abs with argument → NO_COVERAGE 2. isEqual : Replaced double subtraction with addition → NO_COVERAGE 3. isEqual : changed conditional boundary → NO_COVERAGE 4. isEqual : removed call to java/lang/Math::abs → NO_COVERAGE 5. isEqual : removed conditional - replaced comparison check with false → NO_COVERAGE 6. isEqual : negated conditional → NO_COVERAGE 7. isEqual : removed conditional - replaced comparison check with true → NO_COVERAGE 8. isEqual : Substituted 0 with 1 → NO_COVERAGE 9. isEqual : replaced boolean return with true for net/bmahe/genetics4j/gp/math/SimplificationRules::isEqual → NO_COVERAGE 10. isEqual : Substituted 1 with 0 → NO_COVERAGE |
return Math.abs(v2 - v1) < epsilon; |
59 | } | |
60 | ||
61 | protected static boolean isEqual(final double v1, final double v2) { | |
62 |
4
1. isEqual : Substituted 1.0E-4 with 1.0 → NO_COVERAGE 2. isEqual : removed call to net/bmahe/genetics4j/gp/math/SimplificationRules::isEqual → NO_COVERAGE 3. isEqual : replaced boolean return with true for net/bmahe/genetics4j/gp/math/SimplificationRules::isEqual → NO_COVERAGE 4. isEqual : replaced boolean return with false for net/bmahe/genetics4j/gp/math/SimplificationRules::isEqual → NO_COVERAGE |
return isEqual(v1, v2, DEFAULT_EPSILON); |
63 | } | |
64 | ||
65 | @SuppressWarnings("unchecked") | |
66 | final public static Rule ADD_TWO_COEFFCIENTS = ImmutableRule.of((t) -> isOperation(t, Functions.NAME_ADD) | |
67 | && hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT) && hasChildOperation(t, 1, Terminals.TYPE_COEFFICIENT), | |
68 | (program, t) -> { | |
69 | ||
70 | final InputSpec inputSpec = program.inputSpec(); | |
71 | ||
72 | final CoefficientOperation<Double> firstCoefficient = getChildAs(t, 0, CoefficientOperation.class); | |
73 | final Double firstValue = firstCoefficient.value(); | |
74 | ||
75 | final CoefficientOperation<Double> secondCoefficient = getChildAs(t, 1, CoefficientOperation.class); | |
76 | final Double secondValue = secondCoefficient.value(); | |
77 | ||
78 | final OperationFactory coefficientFactory = OperationFactories | |
79 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, firstValue + secondValue); | |
80 | ||
81 | final Operation<?> newOperation = coefficientFactory.build(inputSpec); | |
82 | ||
83 | return new TreeNode<>(newOperation); | |
84 | }); | |
85 | ||
86 | @SuppressWarnings("unchecked") | |
87 | final public static Rule MUL_TWO_COEFFICIENTS = ImmutableRule.of((t) -> isOperation(t, Functions.NAME_MUL) | |
88 | && hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT) && hasChildOperation(t, 1, Terminals.TYPE_COEFFICIENT), | |
89 | (program, t) -> { | |
90 | ||
91 | final InputSpec inputSpec = program.inputSpec(); | |
92 | ||
93 | final CoefficientOperation<Double> firstCoefficient = getChildAs(t, 0, CoefficientOperation.class); | |
94 | final Double firstValue = firstCoefficient.value(); | |
95 | ||
96 | final CoefficientOperation<Double> secondCoefficient = getChildAs(t, 1, CoefficientOperation.class); | |
97 | final Double secondValue = secondCoefficient.value(); | |
98 | ||
99 | final OperationFactory coefficientFactory = OperationFactories | |
100 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, firstValue * secondValue); | |
101 | ||
102 | final Operation<?> newOperation = coefficientFactory.build(inputSpec); | |
103 | ||
104 | return new TreeNode<>(newOperation); | |
105 | }); | |
106 | ||
107 | @SuppressWarnings("unchecked") | |
108 | final public static Rule SUB_TWO_COEFFICIENTS = ImmutableRule.of((t) -> isOperation(t, Functions.NAME_SUB) | |
109 | && hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT) && hasChildOperation(t, 1, Terminals.TYPE_COEFFICIENT), | |
110 | (program, t) -> { | |
111 | ||
112 | final InputSpec inputSpec = program.inputSpec(); | |
113 | ||
114 | final CoefficientOperation<Double> firstCoefficient = getChildAs(t, 0, CoefficientOperation.class); | |
115 | final Double firstValue = firstCoefficient.value(); | |
116 | ||
117 | final CoefficientOperation<Double> secondCoefficient = getChildAs(t, 1, CoefficientOperation.class); | |
118 | final Double secondValue = secondCoefficient.value(); | |
119 | ||
120 | final OperationFactory coefficientFactory = OperationFactories | |
121 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, firstValue - secondValue); | |
122 | ||
123 | final Operation<?> newOperation = coefficientFactory.build(inputSpec); | |
124 | ||
125 | return new TreeNode<>(newOperation); | |
126 | }); | |
127 | ||
128 | @SuppressWarnings("unchecked") | |
129 | final public static Rule SUB_INPUT_FROM_SAME_INPUT = ImmutableRule.of((t) -> { | |
130 | if (isOperation(t, Functions.NAME_SUB) == false) { | |
131 | return false; | |
132 | } | |
133 | ||
134 | if (hasChildOperation(t, 0, Terminals.TYPE_INPUT) == false) { | |
135 | return false; | |
136 | } | |
137 | ||
138 | if (hasChildOperation(t, 1, Terminals.TYPE_INPUT) == false) { | |
139 | return false; | |
140 | } | |
141 | ||
142 | final InputOperation<?> firstInput = (InputOperation<Double>) t.getChild(0) | |
143 | .getData(); | |
144 | ||
145 | final InputOperation<?> secondInput = (InputOperation<Double>) t.getChild(1) | |
146 | .getData(); | |
147 | ||
148 | return firstInput.index() == secondInput.index(); | |
149 | }, (program, t) -> { | |
150 | ||
151 | final InputSpec inputSpec = program.inputSpec(); | |
152 | ||
153 | final OperationFactory coefficientFactory = OperationFactories | |
154 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, 0.0d); | |
155 | ||
156 | final Operation<?> newOperation = coefficientFactory.build(inputSpec); | |
157 | ||
158 | return new TreeNode<>(newOperation); | |
159 | }); | |
160 | ||
161 | @SuppressWarnings("unchecked") | |
162 | final public static Rule SUB_ZERO_FROM_INPUT = ImmutableRule.of((t) -> { | |
163 | if (isOperation(t, Functions.NAME_SUB) == false) { | |
164 | return false; | |
165 | } | |
166 | ||
167 | if (hasChildOperation(t, 0, Terminals.TYPE_INPUT) == false) { | |
168 | return false; | |
169 | } | |
170 | ||
171 | if (hasChildOperation(t, 1, Terminals.TYPE_INPUT) == false) { | |
172 | return false; | |
173 | } | |
174 | ||
175 | if (hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT) == false) { | |
176 | return false; | |
177 | } | |
178 | ||
179 | if (hasChildOperation(t, 1, Terminals.TYPE_COEFFICIENT) == false) { | |
180 | return false; | |
181 | } | |
182 | ||
183 | final CoefficientOperation<Double> firstCoefficient = (CoefficientOperation<Double>) t.getChild(0) | |
184 | .getData(); | |
185 | ||
186 | return isEqual(firstCoefficient.value(), 0.0d); | |
187 | }, (program, t) -> { | |
188 | ||
189 | final InputSpec inputSpec = program.inputSpec(); | |
190 | ||
191 | final OperationFactory coefficientFactory = OperationFactories | |
192 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, 0.0d); | |
193 | ||
194 | final Operation<?> newOperation = coefficientFactory.build(inputSpec); | |
195 | ||
196 | return new TreeNode<>(newOperation); | |
197 | }); | |
198 | ||
199 | @SuppressWarnings("unchecked") | |
200 | final public static Rule DIV_TWO_COEFFICIENT_FINITE = ImmutableRule.of((t) -> { | |
201 | if (isOperation(t, Functions.NAME_DIV) == false) { | |
202 | return false; | |
203 | } | |
204 | ||
205 | if (hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT) == false) { | |
206 | return false; | |
207 | } | |
208 | ||
209 | if (hasChildOperation(t, 1, Terminals.TYPE_COEFFICIENT) == false) { | |
210 | return false; | |
211 | } | |
212 | ||
213 | final CoefficientOperation<Double> firstCoefficient = (CoefficientOperation<Double>) t.getChild(0) | |
214 | .getData(); | |
215 | ||
216 | final CoefficientOperation<Double> secondCoefficient = (CoefficientOperation<Double>) t.getChild(1) | |
217 | .getData(); | |
218 | ||
219 | return Double.isFinite(firstCoefficient.value() / secondCoefficient.value()); | |
220 | }, (program, t) -> { | |
221 | ||
222 | final InputSpec inputSpec = program.inputSpec(); | |
223 | ||
224 | final CoefficientOperation<Double> firstCoefficient = getChildAs(t, 0, CoefficientOperation.class); | |
225 | final Double firstValue = firstCoefficient.value(); | |
226 | ||
227 | final CoefficientOperation<Double> secondCoefficient = getChildAs(t, 1, CoefficientOperation.class); | |
228 | final Double secondValue = secondCoefficient.value(); | |
229 | ||
230 | final OperationFactory coefficientFactory = OperationFactories | |
231 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, firstValue / secondValue); | |
232 | ||
233 | final Operation<?> newOperation = coefficientFactory.build(inputSpec); | |
234 | ||
235 | return new TreeNode<>(newOperation); | |
236 | }); | |
237 | ||
238 | @SuppressWarnings("unchecked") | |
239 | final public static Rule ADD_INPUT_TO_SAME_INPUT = ImmutableRule.of((t) -> { | |
240 | boolean result = isOperation(t, Functions.NAME_ADD) && hasChildOperation(t, 0, Terminals.TYPE_INPUT) | |
241 | && hasChildOperation(t, 1, Terminals.TYPE_INPUT); | |
242 | ||
243 | if (result == false) { | |
244 | return false; | |
245 | } | |
246 | ||
247 | final InputOperation<?> firstInput = getChildAs(t, 0, InputOperation.class); | |
248 | final InputOperation<?> secondInput = getChildAs(t, 1, InputOperation.class); | |
249 | ||
250 | return firstInput.index() == secondInput.index(); | |
251 | }, (program, t) -> { | |
252 | ||
253 | final InputSpec inputSpec = program.inputSpec(); | |
254 | ||
255 | final TreeNode<Operation<?>> multBaseTreeNode = new TreeNode<Operation<?>>(Functions.MUL.build(inputSpec)); | |
256 | ||
257 | final OperationFactory coefficientFactory = OperationFactories | |
258 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, 2.0d); | |
259 | final TreeNode<Operation<?>> timesTwoTreeNode = new TreeNode<Operation<?>>(coefficientFactory.build(inputSpec)); | |
260 | multBaseTreeNode.addChild(timesTwoTreeNode); | |
261 | ||
262 | final InputOperation<?> firstInput = (InputOperation<Double>) t.getChild(0) | |
263 | .getData(); | |
264 | final TreeNode<Operation<?>> firstInputTreeNode = new TreeNode<Operation<?>>(firstInput); | |
265 | multBaseTreeNode.addChild(firstInputTreeNode); | |
266 | ||
267 | return multBaseTreeNode; | |
268 | }); | |
269 | ||
270 | @SuppressWarnings("unchecked") | |
271 | final public static Rule MULTIPLY_INPUT_WITH_SAME_INPUT = ImmutableRule.of((t) -> { | |
272 | ||
273 | if (isOperation(t, Functions.NAME_MUL) == false) { | |
274 | return false; | |
275 | } | |
276 | ||
277 | if (hasChildOperation(t, 0, Terminals.TYPE_INPUT) == false) { | |
278 | return false; | |
279 | } | |
280 | if (hasChildOperation(t, 1, Terminals.TYPE_INPUT) == false) { | |
281 | return false; | |
282 | } | |
283 | ||
284 | final InputOperation<?> firstInput = (InputOperation<Double>) t.getChild(0) | |
285 | .getData(); | |
286 | ||
287 | final InputOperation<?> secondInput = (InputOperation<Double>) t.getChild(1) | |
288 | .getData(); | |
289 | ||
290 | return firstInput.index() == secondInput.index(); | |
291 | }, (program, t) -> { | |
292 | ||
293 | final InputSpec inputSpec = program.inputSpec(); | |
294 | ||
295 | final TreeNode<Operation<?>> expBaseTreeNode = new TreeNode<Operation<?>>(Functions.EXP.build(inputSpec)); | |
296 | ||
297 | final InputOperation<?> firstInput = (InputOperation<Double>) t.getChild(0) | |
298 | .getData(); | |
299 | final TreeNode<Operation<?>> firstInputTreeNode = new TreeNode<Operation<?>>(firstInput); | |
300 | expBaseTreeNode.addChild(firstInputTreeNode); | |
301 | ||
302 | final OperationFactory coefficientFactory = OperationFactories | |
303 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, 2.0d); | |
304 | final TreeNode<Operation<?>> twoTreeNode = new TreeNode<Operation<?>>(coefficientFactory.build(inputSpec)); | |
305 | expBaseTreeNode.addChild(twoTreeNode); | |
306 | ||
307 | return expBaseTreeNode; | |
308 | }); | |
309 | ||
310 | @SuppressWarnings("unchecked") | |
311 | final public static Rule MULTIPLY_INPUT_WITH_EXP_SAME_INPUT_COEFF = ImmutableRule.of((t) -> { | |
312 | // ex: MULT( EXP( INPUT[0], 3), INPUT[0]) ==> EXP( INPUT[0], 4) | |
313 | ||
314 | if (isOperation(t, Functions.NAME_MUL) == false) { | |
315 | return false; | |
316 | } | |
317 | if (hasChildOperation(t, 0, Functions.NAME_EXP) == false) { | |
318 | return false; | |
319 | } | |
320 | if (hasChildOperation(t, 1, Terminals.TYPE_INPUT) == false) { | |
321 | return false; | |
322 | } | |
323 | ||
324 | final TreeNode<Operation<?>> expTreeNode = t.getChild(0); | |
325 | if (hasChildOperation(expTreeNode, 0, Terminals.TYPE_INPUT) == false) { | |
326 | return false; | |
327 | } | |
328 | if (hasChildOperation(expTreeNode, 1, Terminals.TYPE_COEFFICIENT) == false) { | |
329 | return false; | |
330 | } | |
331 | ||
332 | final InputOperation<?> expInput = getChildAs(expTreeNode, 0, InputOperation.class); | |
333 | final InputOperation<?> secondInput = getChildAs(t, 1, InputOperation.class); | |
334 | ||
335 | return expInput.index() == secondInput.index(); | |
336 | }, (program, t) -> { | |
337 | ||
338 | final InputSpec inputSpec = program.inputSpec(); | |
339 | final TreeNode<Operation<?>> originalExpTreeNode = t.getChild(0); | |
340 | final CoefficientOperation<Double> originalCoefficientExp = getChildAs(originalExpTreeNode, | |
341 | 1, | |
342 | CoefficientOperation.class); | |
343 | ||
344 | final TreeNode<Operation<?>> expBaseTreeNode = new TreeNode<Operation<?>>(Functions.EXP.build(inputSpec)); | |
345 | ||
346 | final InputOperation<?> firstInput = (InputOperation<Double>) t.getChild(0) | |
347 | .getData(); | |
348 | final TreeNode<Operation<?>> firstInputTreeNode = new TreeNode<Operation<?>>(firstInput); | |
349 | expBaseTreeNode.addChild(firstInputTreeNode); | |
350 | ||
351 | final OperationFactory coefficientFactory = OperationFactories | |
352 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, originalCoefficientExp.value() + 1.0d); | |
353 | final TreeNode<Operation<?>> newCoeffTreeNode = new TreeNode<Operation<?>>(coefficientFactory.build(inputSpec)); | |
354 | expBaseTreeNode.addChild(newCoeffTreeNode); | |
355 | ||
356 | return expBaseTreeNode; | |
357 | }); | |
358 | ||
359 | @SuppressWarnings("unchecked") | |
360 | final public static Rule MUL_1_WITH_ANYTHING = ImmutableRule.of((t) -> { | |
361 | if (isOperation(t, Functions.NAME_MUL) == false) { | |
362 | return false; | |
363 | } | |
364 | ||
365 | if (hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT) == false) { | |
366 | return false; | |
367 | } | |
368 | ||
369 | final CoefficientOperation<Double> firstCoefficient = (CoefficientOperation<Double>) t.getChild(0) | |
370 | .getData(); | |
371 | ||
372 | return firstCoefficient.value() < 1 + 0.0001 && firstCoefficient.value() > 1 - .0001; | |
373 | }, (program, t) -> { | |
374 | ||
375 | return t.getChild(1); | |
376 | }); | |
377 | ||
378 | @SuppressWarnings("unchecked") | |
379 | final public static Rule MUL_ANYTHING_WITH_1 = ImmutableRule.of((t) -> { | |
380 | if (isOperation(t, Functions.NAME_MUL) == false) { | |
381 | return false; | |
382 | } | |
383 | ||
384 | if (hasChildOperation(t, 1, Terminals.TYPE_COEFFICIENT) == false) { | |
385 | return false; | |
386 | } | |
387 | ||
388 | final CoefficientOperation<Double> secondCoefficient = (CoefficientOperation<Double>) t.getChild(1) | |
389 | .getData(); | |
390 | ||
391 | return isEqual(secondCoefficient.value(), 1); | |
392 | }, (program, t) -> { | |
393 | ||
394 | return t.getChild(0); | |
395 | }); | |
396 | ||
397 | @SuppressWarnings("unchecked") | |
398 | final public static Rule ADD_0_WITH_ANYTHING = ImmutableRule.of((t) -> { | |
399 | if (isOperation(t, Functions.NAME_ADD) == false) { | |
400 | return false; | |
401 | } | |
402 | ||
403 | if (hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT) == false) { | |
404 | return false; | |
405 | } | |
406 | ||
407 | final CoefficientOperation<Double> firstCoefficient = (CoefficientOperation<Double>) t.getChild(0) | |
408 | .getData(); | |
409 | ||
410 | return isEqual(firstCoefficient.value(), 0.0d); | |
411 | }, (program, t) -> { | |
412 | ||
413 | return t.getChild(1); | |
414 | }); | |
415 | ||
416 | @SuppressWarnings("unchecked") | |
417 | final public static Rule ADD_ANYTHING_WITH_0 = ImmutableRule.of((t) -> { | |
418 | if (isOperation(t, Functions.NAME_ADD) == false) { | |
419 | return false; | |
420 | } | |
421 | ||
422 | if (hasChildOperation(t, 1, Terminals.TYPE_COEFFICIENT) == false) { | |
423 | return false; | |
424 | } | |
425 | ||
426 | final CoefficientOperation<Double> secondCoefficient = (CoefficientOperation<Double>) t.getChild(1) | |
427 | .getData(); | |
428 | ||
429 | return isEqual(secondCoefficient.value(), 0.0d); | |
430 | }, (program, t) -> { | |
431 | ||
432 | return t.getChild(0); | |
433 | }); | |
434 | ||
435 | @SuppressWarnings("unchecked") | |
436 | final public static Rule MUL_0_WITH_ANYTHING = ImmutableRule.of((t) -> { | |
437 | if (isOperation(t, Functions.NAME_MUL) == false) { | |
438 | return false; | |
439 | } | |
440 | ||
441 | if (hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT) == false) { | |
442 | return false; | |
443 | } | |
444 | ||
445 | final CoefficientOperation<Double> firstCoefficient = (CoefficientOperation<Double>) t.getChild(0) | |
446 | .getData(); | |
447 | ||
448 | return isEqual(firstCoefficient.value(), 0.0d); | |
449 | }, (program, t) -> { | |
450 | ||
451 | final InputSpec inputSpec = program.inputSpec(); | |
452 | ||
453 | final OperationFactory zeroFactory = OperationFactories | |
454 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, 0.0d); | |
455 | ||
456 | return new TreeNode<>(zeroFactory.build(inputSpec)); | |
457 | }); | |
458 | ||
459 | @SuppressWarnings("unchecked") | |
460 | final public static Rule MUL_ANYTHING_WITH_0 = ImmutableRule.of((t) -> { | |
461 | if (isOperation(t, Functions.NAME_MUL) == false) { | |
462 | return false; | |
463 | } | |
464 | ||
465 | if (hasChildOperation(t, 1, Terminals.TYPE_COEFFICIENT) == false) { | |
466 | return false; | |
467 | } | |
468 | ||
469 | final CoefficientOperation<Double> secondCoefficient = (CoefficientOperation<Double>) t.getChild(1) | |
470 | .getData(); | |
471 | ||
472 | return secondCoefficient.value() < 1 + 0.0001 && secondCoefficient.value() > 1 - .0001; | |
473 | }, (program, t) -> { | |
474 | final InputSpec inputSpec = program.inputSpec(); | |
475 | ||
476 | final OperationFactory zeroFactory = OperationFactories | |
477 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, 0.0d); | |
478 | ||
479 | return new TreeNode<>(zeroFactory.build(inputSpec)); | |
480 | }); | |
481 | ||
482 | @SuppressWarnings("unchecked") | |
483 | final public static Rule POW_0 = ImmutableRule.of((t) -> { | |
484 | if (isOperation(t, Functions.NAME_POW) == false) { | |
485 | return false; | |
486 | } | |
487 | ||
488 | if (hasChildOperation(t, 1, Terminals.TYPE_COEFFICIENT) == false) { | |
489 | return false; | |
490 | } | |
491 | ||
492 | final CoefficientOperation<Double> secondCoefficient = (CoefficientOperation<Double>) t.getChild(1) | |
493 | .getData(); | |
494 | ||
495 | return isEqual(secondCoefficient.value(), 0); | |
496 | }, (program, t) -> { | |
497 | final InputSpec inputSpec = program.inputSpec(); | |
498 | ||
499 | final OperationFactory oneFactory = OperationFactories | |
500 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, 1.0d); | |
501 | ||
502 | return new TreeNode<>(oneFactory.build(inputSpec)); | |
503 | }); | |
504 | ||
505 | @SuppressWarnings("unchecked") | |
506 | final public static Rule POW_1 = ImmutableRule.of((t) -> { | |
507 | if (isOperation(t, Functions.NAME_POW) == false) { | |
508 | return false; | |
509 | } | |
510 | ||
511 | if (hasChildOperation(t, 1, Terminals.TYPE_COEFFICIENT) == false) { | |
512 | return false; | |
513 | } | |
514 | ||
515 | final CoefficientOperation<Double> secondCoefficient = (CoefficientOperation<Double>) t.getChild(1) | |
516 | .getData(); | |
517 | ||
518 | return isEqual(secondCoefficient.value(), 1); | |
519 | }, (program, t) -> { | |
520 | ||
521 | return t.getChild(0); | |
522 | }); | |
523 | ||
524 | @SuppressWarnings("unchecked") | |
525 | final public static Rule COS_OF_COEFFICIENT = ImmutableRule.of((t) -> { | |
526 | if (isOperation(t, Functions.NAME_COS) == false) { | |
527 | return false; | |
528 | } | |
529 | ||
530 | return hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT); | |
531 | }, (program, t) -> { | |
532 | ||
533 | final InputSpec inputSpec = program.inputSpec(); | |
534 | ||
535 | final CoefficientOperation<Double> cosCoefficient = (CoefficientOperation<Double>) t.getChild(0) | |
536 | .getData(); | |
537 | ||
538 | final double cosValue = Math.cos(cosCoefficient.value()); | |
539 | ||
540 | final OperationFactory cosValueOperationFactory = OperationFactories | |
541 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, cosValue); | |
542 | ||
543 | return new TreeNode<>(cosValueOperationFactory.build(inputSpec)); | |
544 | }); | |
545 | ||
546 | @SuppressWarnings("unchecked") | |
547 | final public static Rule SIN_OF_COEFFICIENT = ImmutableRule.of((t) -> { | |
548 | if (isOperation(t, Functions.NAME_SIN) == false) { | |
549 | return false; | |
550 | } | |
551 | ||
552 | return hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT); | |
553 | }, (program, t) -> { | |
554 | ||
555 | final InputSpec inputSpec = program.inputSpec(); | |
556 | ||
557 | final CoefficientOperation<Double> sinCoefficient = (CoefficientOperation<Double>) t.getChild(0) | |
558 | .getData(); | |
559 | ||
560 | final double sinValue = Math.sin(sinCoefficient.value()); | |
561 | ||
562 | final OperationFactory sinValueOperationFactory = OperationFactories | |
563 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, sinValue); | |
564 | ||
565 | return new TreeNode<>(sinValueOperationFactory.build(inputSpec)); | |
566 | }); | |
567 | ||
568 | final public static Rule SUB_SAME_BRANCHES = ImmutableRule.of((t) -> { | |
569 | if (isOperation(t, Functions.NAME_SUB) == false) { | |
570 | return false; | |
571 | } | |
572 | ||
573 | return TreeNodeUtils.areSame(t.getChild(0), t.getChild(1)); | |
574 | }, (program, t) -> { | |
575 | ||
576 | final InputSpec inputSpec = program.inputSpec(); | |
577 | ||
578 | final OperationFactory zeroFactory = OperationFactories | |
579 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, 0.0d); | |
580 | ||
581 | return new TreeNode<>(zeroFactory.build(inputSpec)); | |
582 | }); | |
583 | ||
584 | final public static Rule ADD_SAME_BRANCHES = ImmutableRule.of((t) -> { | |
585 | if (isOperation(t, Functions.NAME_ADD) == false) { | |
586 | return false; | |
587 | } | |
588 | ||
589 | return TreeNodeUtils.areSame(t.getChild(0), t.getChild(1)); | |
590 | }, (program, t) -> { | |
591 | ||
592 | final InputSpec inputSpec = program.inputSpec(); | |
593 | ||
594 | final TreeNode<Operation<?>> baseAdd = new TreeNode<>(Functions.ADD.build(inputSpec)); | |
595 | ||
596 | final OperationFactory twoFactory = OperationFactories | |
597 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, 2.0d); | |
598 | baseAdd.addChild(new TreeNode<>(twoFactory.build(inputSpec))); | |
599 | ||
600 | baseAdd.addChild(t.getChild(0)); // TODO copy it instead? | |
601 | ||
602 | return baseAdd; | |
603 | }); | |
604 | ||
605 | final public static Rule DIV_SAME_BRANCHES = ImmutableRule.of((t) -> { | |
606 | if (isOperation(t, Functions.NAME_DIV) == false) { | |
607 | return false; | |
608 | } | |
609 | ||
610 | return TreeNodeUtils.areSame(t.getChild(0), t.getChild(1)); | |
611 | }, (program, t) -> { | |
612 | ||
613 | final InputSpec inputSpec = program.inputSpec(); | |
614 | ||
615 | final OperationFactory oneFactory = OperationFactories | |
616 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, 1.0d); | |
617 | ||
618 | return new TreeNode<>(oneFactory.build(inputSpec)); | |
619 | }); | |
620 | ||
621 | @SuppressWarnings("unchecked") | |
622 | final public static Rule EXP_OF_COEFFICIENT = ImmutableRule.of((t) -> { | |
623 | if (isOperation(t, Functions.NAME_EXP) == false) { | |
624 | return false; | |
625 | } | |
626 | ||
627 | return hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT); | |
628 | }, (program, t) -> { | |
629 | ||
630 | final InputSpec inputSpec = program.inputSpec(); | |
631 | ||
632 | final CoefficientOperation<Double> expCoefficient = (CoefficientOperation<Double>) t.getChild(0) | |
633 | .getData(); | |
634 | ||
635 | final double expValue = Math.exp(expCoefficient.value()); | |
636 | ||
637 | final OperationFactory expValueOperationFactory = OperationFactories | |
638 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, expValue); | |
639 | ||
640 | return new TreeNode<>(expValueOperationFactory.build(inputSpec)); | |
641 | }); | |
642 | ||
643 | @SuppressWarnings("unchecked") | |
644 | final public static Rule POW_TWO_COEFFICIENTS = ImmutableRule.of((t) -> isOperation(t, Functions.NAME_POW) | |
645 | && hasChildOperation(t, 0, Terminals.TYPE_COEFFICIENT) && hasChildOperation(t, 1, Terminals.TYPE_COEFFICIENT), | |
646 | (program, t) -> { | |
647 | ||
648 | final InputSpec inputSpec = program.inputSpec(); | |
649 | ||
650 | final CoefficientOperation<Double> firstCoefficient = getChildAs(t, 0, CoefficientOperation.class); | |
651 | final Double firstValue = firstCoefficient.value(); | |
652 | ||
653 | final CoefficientOperation<Double> secondCoefficient = getChildAs(t, 1, CoefficientOperation.class); | |
654 | final Double secondValue = secondCoefficient.value(); | |
655 | ||
656 | final OperationFactory coefficientFactory = OperationFactories | |
657 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, Math.pow(firstValue, secondValue)); | |
658 | ||
659 | final Operation<?> newOperation = coefficientFactory.build(inputSpec); | |
660 | ||
661 | return new TreeNode<>(newOperation); | |
662 | }); | |
663 | ||
664 | /** | |
665 | * multiplication of the same branch -> square of the first branch | |
666 | */ | |
667 | final public static Rule MUL_SAME_BRANCHES = ImmutableRule.of((t) -> { | |
668 | if (isOperation(t, Functions.NAME_MUL) == false) { | |
669 | return false; | |
670 | } | |
671 | ||
672 | return TreeNodeUtils.areSame(t.getChild(0), t.getChild(1)); | |
673 | }, (program, t) -> { | |
674 | ||
675 | final InputSpec inputSpec = program.inputSpec(); | |
676 | ||
677 | final TreeNode<Operation<?>> powNode = new TreeNode<>(Functions.POW.build(inputSpec)); | |
678 | ||
679 | powNode.addChild(t.getChild(0)); | |
680 | powNode.addChild(new TreeNode<>(OperationFactories.ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, 2.0d) | |
681 | .build(inputSpec))); | |
682 | ||
683 | return powNode; | |
684 | }); | |
685 | ||
686 | final public static Rule COS_PI = ImmutableRule.of((t) -> { | |
687 | if (isOperation(t, Functions.NAME_COS) == false) { | |
688 | return false; | |
689 | } | |
690 | ||
691 | return hasChildOperation(t, 0, Terminals.NAME_PI); | |
692 | }, (program, t) -> { | |
693 | ||
694 | final InputSpec inputSpec = program.inputSpec(); | |
695 | ||
696 | final OperationFactory minusOneFactory = OperationFactories | |
697 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, -1.0d); | |
698 | ||
699 | return new TreeNode<>(minusOneFactory.build(inputSpec)); | |
700 | }); | |
701 | ||
702 | final public static Rule SIN_PI = ImmutableRule.of((t) -> { | |
703 | if (isOperation(t, Functions.NAME_SIN) == false) { | |
704 | return false; | |
705 | } | |
706 | ||
707 | return hasChildOperation(t, 0, Terminals.NAME_PI); | |
708 | }, (program, t) -> { | |
709 | ||
710 | final InputSpec inputSpec = program.inputSpec(); | |
711 | ||
712 | final OperationFactory zeroFactory = OperationFactories | |
713 | .ofCoefficient(Terminals.TYPE_COEFFICIENT, Double.class, -0.0d); | |
714 | ||
715 | return new TreeNode<>(zeroFactory.build(inputSpec)); | |
716 | }); | |
717 | ||
718 | final public static List<Rule> SIMPLIFY_RULES = Arrays.asList(MUL_SAME_BRANCHES, | |
719 | ADD_TWO_COEFFCIENTS, | |
720 | MUL_TWO_COEFFICIENTS, | |
721 | SUB_TWO_COEFFICIENTS, | |
722 | SUB_INPUT_FROM_SAME_INPUT, | |
723 | SUB_ZERO_FROM_INPUT, | |
724 | DIV_TWO_COEFFICIENT_FINITE, | |
725 | ADD_INPUT_TO_SAME_INPUT, | |
726 | MULTIPLY_INPUT_WITH_SAME_INPUT, | |
727 | MUL_1_WITH_ANYTHING, | |
728 | MUL_ANYTHING_WITH_1, | |
729 | MUL_0_WITH_ANYTHING, | |
730 | MUL_ANYTHING_WITH_0, | |
731 | POW_0, | |
732 | POW_1, | |
733 | COS_OF_COEFFICIENT, | |
734 | SIN_OF_COEFFICIENT, | |
735 | SUB_SAME_BRANCHES, | |
736 | ADD_SAME_BRANCHES, | |
737 | DIV_SAME_BRANCHES, | |
738 | EXP_OF_COEFFICIENT, | |
739 | POW_TWO_COEFFICIENTS, | |
740 | ADD_0_WITH_ANYTHING, | |
741 | ADD_ANYTHING_WITH_0, | |
742 | COS_PI, | |
743 | SIN_PI); | |
744 | ||
745 | } | |
Mutations | ||
28 |
1.1 2.2 3.3 4.4 |
|
29 |
1.1 |
|
38 |
1.1 |
|
39 |
1.1 2.2 3.3 4.4 5.5 |
|
40 |
1.1 2.2 |
|
43 |
1.1 2.2 |
|
44 |
1.1 2.2 3.3 4.4 |
|
45 |
1.1 |
|
50 |
1.1 2.2 |
|
51 |
1.1 |
|
52 |
1.1 |
|
58 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 10.10 |
|
62 |
1.1 2.2 3.3 4.4 |