All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ec.gp.ADF Maven / Gradle / Ivy

Go to download

ECJ, A Java-based Evolutionary Computation Research System. ECJ is a research EC system written in Java. It was designed to be highly flexible, with nearly all classes (and all of their settings) dynamically determined at runtime by a user-provided parameter file. All structures in the system are arranged to be easily modifiable. Even so, the system was designed with an eye toward efficiency. ECJ is developed at George Mason University's ECLab Evolutionary Computation Laboratory. The software has nothing to do with its initials' namesake, Evolutionary Computation Journal. ECJ's sister project is MASON, a multi-agent simulation system which dovetails with ECJ nicely.

The newest version!
/*
  Copyright 2006 by Sean Luke
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/


package ec.gp;
import ec.*;
import ec.util.*;
import java.io.*;

/* 
 * ADF.java
 * 
 * Created: Mon Oct 25 18:42:09 1999
 * By: Sean Luke
 */

/**
 * An ADF is a GPNode which implements an "Automatically Defined Function",
 * as described in Koza II.  
 *
 * 

In this system, the ADF facility consists of several classes: ADF, * ADM, ADFStack, ADFContext, and ADFArgument. ADFs, and their cousins * ADMs ("Automatically Defined Macros [Lee Spector]"), appear as * typical function nodes in a GP tree. However, they have a special * associated tree in the individual's tree forest which * they evaluate as a kind of a "subfunction". * *

When an ADF is evaluated, it first evaluates all of its children * and stores away their results. It then evaluates its associated tree. * In the associated tree may exist one or more ADF Argument Terminals, * defined by the ADFArgument class. These terminal nodes are associated * with a single number which represents the "argument" in the original ADF * which evaluated their tree. When an Argument Terminal is evaluated, * it returns the stored result for that child number in the parent ADF. * Ultimately, when the associated tree completes its evaluation, the ADF * returns that value. * *

ADMs work slightly differently. When an ADM is evaluated, it * immediately evaluates its associated tree without first evaluating * any children. When an Argument Terminal is evaluated, it evaluates * the subtree of the appropriate child number in the parent ADM and returns * that result. These subtrees can be evaluated many times. When the * associated tree completes its evaluation, the ADM returns that value. * *

Obviously, if you have Argument Terminals in a tree, that tree must * be only callable by ADFs and ADMs, otherwise the Argument Terminals * won't have anything to return. Furthermore, you must make sure that * you don't have an Argument Terminal in a tree whose number is higher * than the smallest arity (number of arguments) of a calling ADF or ADM. * *

The mechanism behind ADFs and ADMs is complex, requiring two specially- * stored stacks (contained in the ADFStack object) of ADFContexts. For * information on how this mechanism works, see ADFStack. * *

Parameters

base.tree
int >= 0
(The "associated tree" of the ADF)
base.name
String, can be undefined
(A simple "name" of the ADF to distinguish it from other ADF functions in your function set. Use only letters, numbers, hyphens, and underscores. Lowercase is best.)

Default Base
gp.adf * @see ec.gp.ADFStack * @author Sean Luke * @version 1.0 */ public class ADF extends GPNode { public static final String P_ADF = "adf"; public static final String P_ASSOCIATEDTREE = "tree"; public static final String P_FUNCTIONNAME = "name"; /** The ADF's associated tree */ public int associatedTree; /** The "function name" of the ADF, to distinguish it from other GP functions you might provide. */ public String name; public String name() { return name; } public Parameter defaultBase() { return GPDefaults.base().push(P_ADF); } public void writeNode(final EvolutionState state, final DataOutput dataOutput) throws IOException { dataOutput.writeInt(associatedTree); dataOutput.writeUTF(name); } public void readNode(final EvolutionState state, final DataInput dataInput) throws IOException { associatedTree = dataInput.readInt(); name = dataInput.readUTF(); } /** Returns name.hashCode() + class.hashCode() + associatedTree. Hope that's reasonably random. */ public int nodeHashCode() { return (this.getClass().hashCode() + name.hashCode() + associatedTree); } /** Determines node equality by comparing the class, associated tree, and function name of the nodes. */ public boolean nodeEquals(final GPNode node) { if (!this.getClass().equals(node.getClass()) || children.length != node.children.length) return false; ADF adf = (ADF)node; return (associatedTree==adf.associatedTree && name.equals(adf.name)); } /** Checks type-compatibility constraints between the ADF, its argument terminals, and the tree type of its associated tree, and also checks to make sure the tree exists, there aren't invalid argument terminals in it, and there are sufficient argument terminals (a warning). Whew! */ public void checkConstraints(final EvolutionState state, final int tree, final GPIndividual typicalIndividual, final Parameter individualBase) { super.checkConstraints(state,tree,typicalIndividual,individualBase); // does the associated tree exist? if (associatedTree < 0 || associatedTree >= typicalIndividual.trees.length) state.output.error("The node " + toStringForError() + " of individual " + individualBase + " must have an associated tree that is >= 0 and < " + typicalIndividual.trees.length + ". Value provided was: " + associatedTree); else { // is the associated tree of the correct type? Issue an error. GPInitializer initializer = ((GPInitializer)state.initializer); if (!constraints(initializer).returntype.compatibleWith(initializer, typicalIndividual.trees[associatedTree].constraints(initializer).treetype)) state.output.error("The return type of the node " + toStringForError() + " of individual " + individualBase + "is not type-compatible with the tree type of its associated tree."); GPNode[][] funcs = typicalIndividual.trees[associatedTree]. constraints(initializer).functionset.nodes; ADFArgument validArgument[] = new ADFArgument[children.length]; for(int w=0;w= children.length) // uh oh state.output.error("The node " + toStringForError() + " in individual " + individualBase + " would call its associated tree, which has an argument terminal with an argument number (" + arg + ") >= the ADF/ADM's arity (" + children.length +"). The argument terminal in question is " + gpfi[x].toStringForError()); else { if (validArgument[arg]!=null && validArgument[arg]!=argument) // got one already state.output.warning("There exists more than one Argument terminal for argument #" + arg + " for the node " + toStringForError() + " in individual " + individualBase); else validArgument[arg] = argument; // is the argument terminal of the correct return type? Issue an error. if (!gpfi[x].constraints(initializer).returntype.compatibleWith(initializer, constraints(initializer).childtypes[arg])) state.output.error("The node " + toStringForError() + " in individual " + individualBase + " would call its associated tree, which has an argument terminal which is not type-compatible with the related argument position of the ADF/ADM. The argument terminal in question is " + gpfi[x].toStringForError()); } } } // does the tree's function set have fewer argument terminals // than I can provide? (issue a warning) for (int x=0;x





© 2015 - 2024 Weber Informatics LLC | Privacy Policy