View Javadoc
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.
13   * Operations can be either functions (with arguments) or terminals (without arguments). Each operation
14   * has a defined signature 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
51  	 * for each argument position. The list 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
81  	 * overridden to provide more 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 }