SimplificationRules.java

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

Mutations

28

1.1
Location : isOperation
Killed by : none
removed call to java/lang/String::equals → NO_COVERAGE

2.2
Location : isOperation
Killed by : none
replaced boolean return with true for net/bmahe/genetics4j/gp/math/SimplificationRules::isOperation → NO_COVERAGE

3.3
Location : isOperation
Killed by : none
removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getData → NO_COVERAGE

4.4
Location : isOperation
Killed by : none
replaced boolean return with false for net/bmahe/genetics4j/gp/math/SimplificationRules::isOperation → NO_COVERAGE

5.5
Location : isOperation
Killed by : none
removed call to net/bmahe/genetics4j/gp/Operation::getName → NO_COVERAGE

37

1.1
Location : hasChildOperation
Killed by : none
removed call to java/util/List::size → NO_COVERAGE

2.2
Location : hasChildOperation
Killed by : none
changed conditional boundary → NO_COVERAGE

3.3
Location : hasChildOperation
Killed by : none
removed conditional - replaced comparison check with false → NO_COVERAGE

4.4
Location : hasChildOperation
Killed by : none
removed conditional - replaced comparison check with true → NO_COVERAGE

5.5
Location : hasChildOperation
Killed by : none
negated conditional → NO_COVERAGE

6.6
Location : hasChildOperation
Killed by : none
removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getChildren → NO_COVERAGE

38

1.1
Location : hasChildOperation
Killed by : none
Substituted 0 with 1 → NO_COVERAGE

2.2
Location : hasChildOperation
Killed by : none
replaced boolean return with true for net/bmahe/genetics4j/gp/math/SimplificationRules::hasChildOperation → NO_COVERAGE

41

1.1
Location : hasChildOperation
Killed by : none
replaced call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getChild with receiver → NO_COVERAGE

2.2
Location : hasChildOperation
Killed by : none
removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getChild → NO_COVERAGE

42

1.1
Location : hasChildOperation
Killed by : none
removed call to java/lang/String::equals → NO_COVERAGE

2.2
Location : hasChildOperation
Killed by : none
replaced boolean return with false for net/bmahe/genetics4j/gp/math/SimplificationRules::hasChildOperation → NO_COVERAGE

3.3
Location : hasChildOperation
Killed by : none
removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getData → NO_COVERAGE

4.4
Location : hasChildOperation
Killed by : none
removed call to net/bmahe/genetics4j/gp/Operation::getName → NO_COVERAGE

5.5
Location : hasChildOperation
Killed by : none
replaced boolean return with true for net/bmahe/genetics4j/gp/math/SimplificationRules::hasChildOperation → NO_COVERAGE

47

1.1
Location : getChildAs
Killed by : none
removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getChild → NO_COVERAGE

2.2
Location : getChildAs
Killed by : none
replaced call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getChild with receiver → NO_COVERAGE

48

1.1
Location : getChildAs
Killed by : none
removed call to net/bmahe/genetics4j/core/chromosomes/TreeNode::getData → NO_COVERAGE

49

1.1
Location : getChildAs
Killed by : none
replaced return value with null for net/bmahe/genetics4j/gp/math/SimplificationRules::getChildAs → NO_COVERAGE

55

1.1
Location : isEqual
Killed by : none
replaced call to java/lang/Math::abs with argument → NO_COVERAGE

2.2
Location : isEqual
Killed by : none
Replaced double subtraction with addition → NO_COVERAGE

3.3
Location : isEqual
Killed by : none
changed conditional boundary → NO_COVERAGE

4.4
Location : isEqual
Killed by : none
removed call to java/lang/Math::abs → NO_COVERAGE

5.5
Location : isEqual
Killed by : none
removed conditional - replaced comparison check with false → NO_COVERAGE

6.6
Location : isEqual
Killed by : none
negated conditional → NO_COVERAGE

7.7
Location : isEqual
Killed by : none
removed conditional - replaced comparison check with true → NO_COVERAGE

8.8
Location : isEqual
Killed by : none
Substituted 0 with 1 → NO_COVERAGE

9.9
Location : isEqual
Killed by : none
replaced boolean return with true for net/bmahe/genetics4j/gp/math/SimplificationRules::isEqual → NO_COVERAGE

10.10
Location : isEqual
Killed by : none
Substituted 1 with 0 → NO_COVERAGE

59

1.1
Location : isEqual
Killed by : none
Substituted 1.0E-4 with 1.0 → NO_COVERAGE

2.2
Location : isEqual
Killed by : none
removed call to net/bmahe/genetics4j/gp/math/SimplificationRules::isEqual → NO_COVERAGE

3.3
Location : isEqual
Killed by : none
replaced boolean return with true for net/bmahe/genetics4j/gp/math/SimplificationRules::isEqual → NO_COVERAGE

4.4
Location : isEqual
Killed by : none
replaced boolean return with false for net/bmahe/genetics4j/gp/math/SimplificationRules::isEqual → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.25.7 support