1 package net.bmahe.genetics4j.gp.math;
2
3 import java.util.List;
4 import java.util.Objects;
5 import java.util.random.RandomGenerator;
6 import java.util.stream.Collectors;
7 import java.util.stream.IntStream;
8
9 import org.apache.commons.lang3.Validate;
10
11 import net.bmahe.genetics4j.gp.OperationFactories;
12 import net.bmahe.genetics4j.gp.OperationFactory;
13
14 public class Terminals {
15
16 public static final String TYPE_COEFFICIENT = "Coefficient";
17 public static final String TYPE_COEFFICIENT_INT = "CoefficientInt";
18 public static final String TYPE_INPUT = "Input";
19
20 public static final String NAME_PI = "PI";
21 public static final String NAME_E = "E";
22
23 public static OperationFactory PI = OperationFactories.ofTerminal(NAME_PI, Double.class, () -> Math.PI);
24
25 public static OperationFactory E = OperationFactories.ofTerminal(NAME_E, Double.class, () -> Math.E);
26
27 public static OperationFactory Coefficient(final RandomGenerator randomGenerator, final double min,
28 final double max) {
29 return OperationFactories.ofOperationSupplier(new Class[] {}, Double.class, () -> {
30
31 final double value = randomGenerator.nextDouble() * (max - min) + min;
32
33 final var operationBuilder = ImmutableCoefficientOperation.builder();
34
35 operationBuilder.name(TYPE_COEFFICIENT)
36 .prettyName(TYPE_COEFFICIENT + "[" + value + "]")
37 .returnedType(Double.class)
38 .value(value);
39
40 return operationBuilder.build();
41 });
42 }
43
44 public static OperationFactory CoefficientRounded(final RandomGenerator randomGenerator, final int min,
45 final int max) {
46 return OperationFactories.ofOperationSupplier(new Class[] {}, Double.class, () -> {
47
48 final double value = randomGenerator.nextInt(max - min) + min;
49
50 final var operationBuilder = ImmutableCoefficientOperation.builder();
51 operationBuilder.name(TYPE_COEFFICIENT)
52 .prettyName("CoefficientRounded[" + value + "]")
53 .returnedType(Double.class)
54 .value(value);
55
56 return operationBuilder.build();
57 });
58 }
59
60 public static OperationFactory CoefficientInt(final RandomGenerator randomGenerator, final int min, final int max) {
61 return OperationFactories.ofOperationSupplier(new Class[] {}, Integer.class, () -> {
62
63 final int value = randomGenerator.nextInt(max - min) + min;
64
65 final var operationBuilder = ImmutableCoefficientOperation.builder();
66 operationBuilder.name(TYPE_COEFFICIENT_INT)
67 .prettyName("CoefficientInt[" + value + "]")
68 .returnedType(Integer.class)
69 .value(value);
70
71 return operationBuilder.build();
72 });
73 }
74
75 @SuppressWarnings({ "unchecked", "rawtypes" })
76 public static <T> OperationFactory Input(final int inputIndex, final Class<T> clazz) {
77 Validate.isTrue(inputIndex >= 0);
78 Objects.requireNonNull(clazz);
79
80 return OperationFactories.of(new Class[] {}, clazz, inputSpec -> {
81 final List<Class> types = inputSpec.types();
82 Validate.isTrue(types.get(inputIndex).isAssignableFrom(clazz));
83
84 final var operationBuilder = ImmutableInputOperation.builder();
85 operationBuilder.name(TYPE_INPUT)
86 .prettyName(TYPE_INPUT + "[" + inputIndex + "]")
87 .returnedType(clazz)
88 .index(inputIndex);
89
90 return operationBuilder.build();
91 });
92 }
93
94 @SuppressWarnings({ "unchecked", "rawtypes" })
95 public static <T> OperationFactory Input(final RandomGenerator randomGenerator, final Class<T> clazz) {
96 Objects.requireNonNull(randomGenerator);
97 Objects.requireNonNull(clazz);
98
99 return OperationFactories.of(new Class[] {}, clazz, inputSpec -> {
100 final List<Class> types = inputSpec.types();
101 final List<Integer> candidates = IntStream.range(0, types.size())
102 .filter(i -> types.get(i).isAssignableFrom(clazz))
103 .boxed()
104 .collect(Collectors.toList());
105
106 if (candidates.isEmpty()) {
107 throw new IllegalArgumentException("No input with type " + clazz + " found");
108 }
109
110 final Integer inputIdx = candidates.get(randomGenerator.nextInt(candidates.size()));
111
112 final var operationBuilder = ImmutableInputOperation.builder();
113 operationBuilder.name(TYPE_INPUT)
114 .prettyName(TYPE_INPUT + "[" + inputIdx + "]")
115 .returnedType(clazz)
116 .index(inputIdx);
117
118 return operationBuilder.build();
119 });
120 }
121
122 public static OperationFactory InputDouble(final RandomGenerator randomGenerator) {
123 return Input(randomGenerator, Double.class);
124 }
125
126 public static OperationFactory InputString(final RandomGenerator randomGenerator) {
127 return Input(randomGenerator, String.class);
128 }
129 }