Example #1
0
 /// <summary>
 /// If the given test is true, issues a warning that no terminal was found with a return type of the given type, and that an algorithm
 /// had requested one.  If fail is true, then a fatal is issued rather than a warning.  The warning takes
 /// the form of a one-time big explanatory message, followed by a one-time-per-type message. Returns the value of the test.
 /// This form makes it easy to insert warnings into if-statements.
 /// </summary>
 protected internal virtual bool WarnAboutNonterminal(bool test, GPType type, bool fail, IEvolutionState state)
 {
     if (test)
     {
         WarnAboutNonTerminalWithType(type, fail, state);
     }
     return(test);
 }
Example #2
0
        public override bool CompatibleWith(GPInitializer initializer, GPType t)
        {
            // if the type is me, then I'm compatible with it
            if (t.Type == Type)
            {
                return(true);
            }

            // if the type an atomic type, then return false
            if (t.Type < initializer.NumAtomicTypes)
            {
                return(false);
            }

            // if the type is < 0 (it's a set type), then I'm compatible
            // if I'm contained in it.  Use its sparse array.
            return(((GPSetType)t).TypesSparse[Type]);
        }
Example #3
0
        /// <summary>
        /// Assigns unique integers to each atomic type, and sets up compatibility
        /// arrays for set types.  If you add new types (heaven forbid), you
        /// should call this method again to get all the types set up properly.
        /// However, you will have to set up the function sets again as well,
        /// as their arrays are based on these type numbers.
        /// </summary>
        public virtual void  PostProcessTypes()
        {
            // assign positive integers and 0 to atomic types
            var x = 0;
            var e = TypeRepository.Values.GetEnumerator();

            while (e.MoveNext())
            {
                var t = (GPType)(e.Current);
                if (t is GPAtomicType)
                {
                    t.Type = x; x++;
                }
            }

            // at this point, x holds the number of atomic types.
            NumAtomicTypes = x;

            // assign additional positive integers to set types
            // and set up arrays for the set types
            e = TypeRepository.Values.GetEnumerator();
            while (e.MoveNext())
            {
                var t = (GPType)(e.Current);
                if (t is GPSetType)
                {
                    ((GPSetType)t).PostProcessSetType(NumAtomicTypes);
                    t.Type = x; x++;
                }
            }

            // at this point, x holds the number of set types + atomic types
            NumSetTypes = x - NumAtomicTypes;

            // make an array for convenience.  Presently rarely used.
            Types = new GPType[NumSetTypes + NumAtomicTypes];
            e     = TypeRepository.Values.GetEnumerator();
            while (e.MoveNext())
            {
                var t = (GPType)(e.Current);
                Types[t.Type] = t;
            }
        }
Example #4
0
        /// <summary>
        /// Issues a warning that no nonterminal was found with a return type of the given type, and that an algorithm
        /// had requested one.  If fail is true, then a fatal is issued rather than a warning.  The warning takes
        /// the form of a one-time big explanatory message, followed by a one-time-per-type message.
        /// </summary>
        protected internal virtual void  WarnAboutNonTerminalWithType(GPType type, bool fail, IEvolutionState state)
        {
            // big explanation -- appears only once
            state.Output.WarnOnce("A GPNodeBuilder has been requested at least once to generate a one-node tree with "
                                  + "a return value type-compatable with a certain type; but there is no NON-TERMINAL which is type-compatable "
                                  + "in this way.  As a result, the algorithm was forced to use a TERMINAL, making the tree larger than "
                                  + "requested, and exposing more child slots to fill, which if not carefully considered, could "
                                  + "recursively repeat this problem and eventually fill all memory.");

            // shorter explanation -- appears for each node builder and type combo
            if (fail)
            {
                state.Output.Fatal("" + GetType() + " can't find a terminal type-compatable with "
                                   + type + " and cannot replace it with a nonterminal.  You may need to try a different node-builder algorithm.");
            }
            else
            {
                state.Output.WarnOnce("" + GetType() + " can't find a terminal type-compatable with " + type);
            }
        }
Example #5
0
        public override bool CompatibleWith(GPInitializer initializer, GPType t)
        {
            // if the type is me, then I'm compatible with it.
            if (t.Type == Type)
            {
                return(true);
            }

            // if the type is an atomic type, then I'm compatible with it if I contain it.
            // Use the sparse array.
            if (t.Type < initializer.NumAtomicTypes)
            {
                // atomic type, faster than doing instanceof
                return(TypesSparse[t.Type]);
            }

            // else the type is a set type.  I'm compatible with it if we contain
            // an atomic type in common.   Use the sorted packed array.

            var s = (GPSetType)t;
            var x = 0;
            var y = 0;

            for (; x < TypesPacked.Length && y < s.TypesPacked.Length;)
            {
                if (TypesPacked[x] == s.TypesPacked[y])
                {
                    return(true);
                }
                if (TypesPacked[x] < s.TypesPacked[y])
                {
                    x++;
                }
                else
                {
                    y++;
                }
            }
            return(false);
        }
Example #6
0
        /// <summary>
        /// When completed, done will hold all the types which are needed
        /// in the function set -- you can then check to make sure that
        /// they contain at least one terminal and (hopefully) at least
        /// one nonterminal.
        /// </summary>
        private void CheckFunctionSetValidity(IEvolutionState state, Hashtable done, GPType type)
        {
            // put type in the hashtable -- it's being used
            done[type] = type;

            // Grab the array in nodes
            var i = FunctionSet.Nodes[type.Type];

            // For each argument type in a node in i, if it's not in done,
            // then add it to done and call me on it
            var initializer = ((GPInitializer)state.Initializer);

            foreach (var node in i)
            {
                foreach (var t in node.Constraints(initializer).ChildTypes)
                {
                    if (done[t] == null)
                    {
                        CheckFunctionSetValidity(state, done, t);
                    }
                }
            }
        }
Example #7
0
 /// <summary>
 /// Issues a fatal error that no node (nonterminal or terminal)
 /// was found with a return type of the given type, and that an algorithm
 /// had requested one.
 /// </summary>
 protected internal virtual void  ErrorAboutNoNodeWithType(GPType type, IEvolutionState state)
 {
     state.Output.Fatal("" + GetType() + " could find no terminal or nonterminal type-compatable with " + type);
 }
Example #8
0
 /// <summary>
 /// Produces a new rooted tree of GPNodes whose root's return type is
 /// swap-compatible with <i>type</i>.  When you build a brand-new
 /// tree out of GPNodes cloned from the
 /// prototypes stored in the GPNode[] arrays, you must remember
 /// to call resetNode() on each cloned GPNode.  This gives ERCs a chance
 /// to randomize themselves and set themselves up.
 /// <p/>requestedSize is an
 /// optional argument which differs based on the GPNodeBuilder used.
 /// Typically it is set to a tree size that the calling method wants
 /// the GPNodeBuilder to produce; the GPNodeBuilder is not obligated to
 /// produce a tree of this size, but it should attempt to interpret this
 /// argument as appropriate for the given algorithm.  To indicate that
 /// you don't care what size the tree should be, you can pass NOSIZEGIVEN.
 /// However if the algorithm <i>requires</i> you to provide a size, it
 /// will generate a fatal error to let you know.
 /// </summary>
 public abstract GPNode NewRootedTree(IEvolutionState state, GPType type, int thread,
                                      IGPNodeParent parent, GPFunctionSet funcs, int argPosition, int requestedSize);
Example #9
0
 /// <summary>
 /// Am I compatible with ("fit" with) <i>t</i>?  For two atomic
 /// types, this is done by direct pointer equality.  For
 /// two set types, this is done by determining if the intersection
 /// is nonempty.  A set type is compatible with an atomic type
 /// if it contains the atomic type in its set.
 /// </summary>
 public abstract bool CompatibleWith(GPInitializer initializer, GPType t);
Example #10
0
        /// <summary>
        /// This must be called <i>after</i> the GPTypes and GPFunctionSets
        /// have been set up.
        /// </summary>
        public void Setup(IEvolutionState state, IParameter paramBase)
        {
            // What's my name?
            Name = state.Parameters.GetString(paramBase.Push(P_NAME), null);
            if (Name == null)
            {
                state.Output.Fatal("No name was given for this function set.", paramBase.Push(P_NAME));
            }

            // Register me
            var tempObject = ((GPInitializer)state.Initializer).TreeConstraintRepository[Name];

            ((GPInitializer)state.Initializer).TreeConstraintRepository[Name] = this;

            var oldConstraints = (GPTreeConstraints)(tempObject);

            if (oldConstraints != null)
            {
                state.Output.Fatal("The GP tree constraint \"" + Name + "\" has been defined multiple times.", paramBase.Push(P_NAME));
            }

            // Load my initializing builder
            Init = (GPNodeBuilder)(state.Parameters.GetInstanceForParameter(paramBase.Push(P_INIT), null, typeof(GPNodeBuilder)));
            Init.Setup(state, paramBase.Push(P_INIT));

            // Load my return type
            var s = state.Parameters.GetString(paramBase.Push(P_RETURNS), null);

            if (s == null)
            {
                state.Output.Fatal("No return type given for the GPTreeConstraints " + Name, paramBase.Push(P_RETURNS));
            }

            TreeType = GPType.TypeFor(s, state);

            // Load my function set
            s = state.Parameters.GetString(paramBase.Push(P_FUNCTIONSET), null);
            if (s == null)
            {
                state.Output.Fatal("No function set given for the GPTreeConstraints " + Name, paramBase.Push(P_RETURNS));
            }

            FunctionSet = GPFunctionSet.FunctionSetFor(s, state);
            state.Output.ExitIfErrors(); // otherwise checkFunctionSetValidity might crash below

            // Determine the validity of the function set
            // the way we do that is by gathering all the types that
            // are transitively used, starting with treetype, as in:
            var typ = Hashtable.Synchronized(new Hashtable());

            CheckFunctionSetValidity(state, typ, TreeType);

            // next we make sure that for every one of these types,
            // there's a terminal with that return type, and *maybe*
            // a nonterminal
            var e = typ.Values.GetEnumerator();

            while (e.MoveNext())
            {
                var t = (GPType)(e.Current);
                var i = FunctionSet.Nodes[t.Type];
                if (i.Length == 0) // yeesh
                {
                    state.Output.Error("In function set " + FunctionSet + " for the GPTreeConstraints "
                                       + this + ", no nodes at all are given with the return type "
                                       + t + " which is required by other functions in the function set or by the tree's return type."
                                       + " This almost certainly indicates a serious typing error.", paramBase);
                }
                else
                {
                    i = FunctionSet.Terminals[t.Type];
                    if (i.Length == 0)
                    // uh oh
                    {
                        state.Output.Warning("In function set " + FunctionSet + " for the GPTreeConstraints "
                                             + this + ", no terminals are given with the return type "
                                             + t + " which is required by other functions in the function set or by the tree's return type."
                                             + " Nearly all tree-builders in ECJ require the ability to add a terminal of any type for which "
                                             + " there is a nonterminal, and at any time.  Without terminals, your code may not work."
                                             + " One common indication that a tree-builder has failed due to this problem is if you get"
                                             + " the MersenneTwister error 'n must be positive'.", paramBase);
                    }
                    i = FunctionSet.Nonterminals[t.Type];
                    if (i.Length == 0)
                    // uh oh
                    {
                        state.Output.Warning("In function set " + FunctionSet + " for the GPTreeConstraints "
                                             + this + ", no *nonterminals* are given with the return type "
                                             + t + " which is required by other functions in the function set or by the tree's return type."
                                             + " This may or may not be a problem for you.", paramBase);
                    }
                }
            }
            state.Output.ExitIfErrors();
        }