aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/backend/function/FunctionSet.java
blob: 6a549cd87e36678b23175f43641332f713dcccd2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package jcgp.backend.function;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;


/**
 * FunctionSet encapsulates a group of functions. This is usually done to
 * simplify the implementation of problem types.
 * <br><br>
 * FunctionSet contains a variety of useful methods for acquiring general
 * information, such as the maximum arity across all functions and the total
 * number of functions.
 * <br><br>
 * In addition, FunctionSet offers the ability to enable and disable functions.
 * Accessing the functions through {@code getAllowedFunction()} will return
 * allowed functions only, providing an easy way to control which functions
 * can be used in mutations.
 * <br><br>
 * An implementation of FunctionSet must simply set the name field and initialise
 * the functionList array with all of the functions. It is advisable to call
 * {@code enableAll()} to enable all functions once the array is initialised.
 * 
 * 
 * @author Eduardo Pedroni
 *
 */
public abstract class FunctionSet {
		protected Function[] functionList;
		protected ArrayList<Integer> allowedFunctions;
		protected String name;
		
		/**
		 * @return the number of currently allowed functions.
		 */
		public int getAllowedFunctionCount() {
			return allowedFunctions.size();
		}
		
		/**
		 * @return the total number of functions, including disabled ones.
		 */
		public int getTotalFunctionCount() {
			return functionList.length;
		}
		
		/**
		 * Returns an allowed function. This throws an
		 * ArrayIndexOutOfBoundsException if the supplied 
		 * index is beyond the count of allowed functions.
		 * 
		 * @param index the allowed function index.
		 * @return the allowed function object.
		 */
		public Function getAllowedFunction(int index) {
			return functionList[allowedFunctions.get(index)];
		}
		
		/**
		 * Returns a function from the complete collection,
		 * enabled or disabled alike. This throws an
		 * ArrayIndexOutOfBoundsException if the supplied 
		 * index is beyond the count of allowed functions.
		 * 
		 * @param index the function index.
		 * @return the function object.
		 */
		public Function getFunction(int index) {
			return functionList[index];
		}
		
		/**
		 * Computes and returns the maximum arity out of
		 * all enabled functions.
		 * 
		 * @return the problem's current maximum arity.
		 */
		public int getMaxArity(){
			int arity = 0;
			for (Integer function : allowedFunctions) {
				// if a higher arity is found, store it
				if (functionList[function].getArity() > arity) {
					arity = functionList[function].getArity();
				}
			}
			return arity;
		}
		
		/**
		 * Disables the indexed function. If the function
		 * is already disabled, this does nothing.
		 * 
		 * @param index the function to disable.
		 */
		public void disableFunction(int index) {
			/*
			 * allowedFunctions is a list of the indices of all allowed functions, 
			 * as addressed in functionList. This method iterates through the whole
			 * list of allowed functions and removes any elements which are equal
			 * to the specified index.
			 */
			if (index < functionList.length) {
				for (Iterator<Integer> iterator = allowedFunctions.iterator(); iterator.hasNext();) {
					int function = iterator.next();
					if (function == index) {
						iterator.remove();
					}
				}
			} else {
				throw new ArrayIndexOutOfBoundsException("Function " + index + " does not exist, the set only has " + functionList.length + " functions.");
			}
		}
		
		/**
		 * Disables the indexed function. If the function is
		 * already enabled, this does nothing. 
		 * 
		 * @param index the function to disable.
		 */
		public void enableFunction(int index) {
			// add the specified index to the list of allowed indices
			if (!allowedFunctions.contains(index)) {
				allowedFunctions.add(index);
				Collections.sort(allowedFunctions);
			}
		}
		
		@Override
		public String toString() {
			return name;
		}
		
		/**
		 * Checks if a specified function is enabled. If the function
		 * does not belong in the FunctionSet, this returns false.
		 * 
		 * @param function the function to check.
		 * @return true if the function is enabled.
		 */
		public boolean isEnabled(Function function) {
			for (int i = 0; i < allowedFunctions.size(); i++) {
				if (functionList[allowedFunctions.get(i)] == function) {
					return true;
				}
			}
			return false;
		}
		
		/**
		 * Enables all functions. 
		 */
		public void enableAll() {
			allowedFunctions = new ArrayList<Integer>();
			for (int i = 0; i < functionList.length; i++) {
				allowedFunctions.add(i);
			}
		}
	}