1 package net.bmahe.genetics4j.gp;
2
3 import java.util.List;
4 import java.util.function.BiFunction;
5
6 import org.immutables.value.Value;
7 import org.immutables.value.Value.Parameter;
8
9 /**
10 * Represents an operation (function or terminal) in genetic programming.
11 *
12 * <p>An operation defines a computational unit that can be used as a node in genetic programming trees. Operations can
13 * be either functions (with arguments) or terminals (without arguments). Each operation has a defined signature
14 * including the types it accepts as input and the type it returns.
15 *
16 * <p>Operations are the building blocks of genetic programming expressions and define:
17 * <ul>
18 * <li>The computation to perform</li>
19 * <li>Type constraints for strongly-typed GP</li>
20 * <li>Arity (number of arguments)</li>
21 * <li>Whether it's a terminal or function</li>
22 * </ul>
23 *
24 * <p>Common operation types include:
25 * <ul>
26 * <li><strong>Mathematical functions</strong>: +, -, *, /, sin, cos, exp</li>
27 * <li><strong>Logical functions</strong>: AND, OR, NOT, IF-THEN-ELSE</li>
28 * <li><strong>Terminals</strong>: constants, variables, input values</li>
29 * <li><strong>Domain-specific</strong>: problem-specific functions and operators</li>
30 * </ul>
31 *
32 * @param <T> the base type used for computation in this operation
33 * @see OperationFactory
34 * @see net.bmahe.genetics4j.gp.program.Program
35 */
36 @Value.Immutable
37 public abstract class Operation<T> {
38
39 /**
40 * Returns the name of this operation.
41 *
42 * @return the operation name, used for identification and display
43 */
44 @Parameter
45 public abstract String getName();
46
47 /**
48 * Returns the list of types that this operation accepts as arguments.
49 *
50 * <p>For strongly-typed genetic programming, this defines the type constraints for each argument position. The list
51 * size determines the operation's arity.
52 *
53 * @return the list of accepted argument types, empty for terminals
54 */
55 @SuppressWarnings("rawtypes")
56 @Parameter
57 public abstract List<Class> acceptedTypes();
58
59 /**
60 * Returns the type that this operation returns.
61 *
62 * @return the return type of this operation
63 */
64 @SuppressWarnings("rawtypes")
65 @Parameter
66 public abstract Class returnedType();
67
68 /**
69 * Returns the computation function for this operation.
70 *
71 * @return a function that takes input arguments and parameters and returns the computed result
72 */
73 @Parameter
74 @Value.Auxiliary
75 public abstract BiFunction<T[], Object[], Object> compute();
76
77 /**
78 * Returns a human-readable name for this operation.
79 *
80 * <p>By default, this returns the same value as {@link #getName()}, but can be overridden to provide more
81 * descriptive names for display purposes.
82 *
83 * @return the pretty name for display purposes
84 */
85 @Value.Default
86 public String getPrettyName() {
87 return getName();
88 }
89
90 /**
91 * Applies this operation to the given input and parameters.
92 *
93 * @param input the input arguments to the operation
94 * @param parameters additional parameters for the operation
95 * @return the result of applying this operation
96 */
97 public Object apply(final T[] input, final Object[] parameters) {
98 final BiFunction<T[], Object[], Object> function = compute();
99 return function.apply(input, parameters);
100 }
101
102 /**
103 * Returns the arity (number of arguments) of this operation.
104 *
105 * @return the number of arguments this operation accepts
106 */
107 public int getArity() {
108 return acceptedTypes().size();
109 }
110
111 /**
112 * Checks if this operation is a terminal (has no arguments).
113 *
114 * @return {@code true} if this operation takes no arguments, {@code false} otherwise
115 */
116 public boolean isTerminal() {
117 return getArity() == 0;
118 }
119 }