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. *

* 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. *

* 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. *

* 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 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 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(); for (int i = 0; i < functionList.length; i++) { allowedFunctions.add(i); } } }