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