/// <summary>
        /// Returns a node which is swap-compatible with returntype,
        /// and whose arguments are swap-compatible with the current children of original.
        /// You need to clone this node.
        /// </summary>
        private static GPNode PickCompatibleNode(GPNode original, GPFunctionSet funcs, IEvolutionState state, GPType returntype, int thread)
        {
            // an expensive procedure: we will linearly search for a valid node
            var numValidNodes = 0;

            var  type        = returntype.Type;
            var  initializer = ((GPInitializer)state.Initializer);
            var  len         = original.Constraints(initializer).ChildTypes.Length;
            bool failed;

            if (initializer.NumAtomicTypes + initializer.NumSetTypes == 1)
            {
                // easy
                numValidNodes = funcs.NodesByArity[type][len].Length;
            }
            else
            {
                for (var x = 0; x < funcs.NodesByArity[type][len].Length; x++)
                // ugh, the hard way -- nodes swap-compatible with type, and of arity len
                {
                    failed = funcs.NodesByArity[type][len][x]
                             .Constraints(initializer).ChildTypes
                             .Where((t, y) => !t.CompatibleWith(initializer, original.Children[y]
                                                                .Constraints(initializer).ReturnType)).Any();

                    if (!failed)
                    {
                        numValidNodes++;
                    }
                }
            }

            // we must have at least success -- the node itself.  Otherwise we're
            // in deep doo-doo.

            // now pick a random node number
            var nodenum = state.Random[thread].NextInt(numValidNodes);

            // find and return that node
            var prosnode = 0;

            if (numValidNodes == funcs.NodesByArity[type][len].Length)
            {
                // easy
                return(funcs.NodesByArity[type][len][nodenum]);
            }

            for (var x = 0; x < funcs.NodesByArity[type][len].Length; x++)
            // ugh, the hard way -- nodes swap-compatible with type, and of arity len
            {
                failed = funcs.NodesByArity[type][len][x]
                         .Constraints(initializer).ChildTypes
                         .Where((t, y) => !t.CompatibleWith(initializer, original.Children[y]
                                                            .Constraints(initializer).ReturnType)).Any();

                if (failed)
                {
                    continue;
                }
                if (prosnode == nodenum)
                {
                    // got it!
                    return(funcs.NodesByArity[type][len][x]);
                }
                prosnode++;
            }

            // should never be able to get here
            throw new ApplicationException(); // whoops!
        }
 /// <summary>
 /// Determines the GPNode from the function set by the name.  If there is more than
 /// one such node (which shouldn't be the case) then only the first such node is
 /// used.  Stores the prototype.
 /// </summary>
 public GrammarFunctionNode(GPFunctionSet gpfs, String name)
     : base(name)
 {
     _prototype = ((GPNode[])gpfs.NodesByName[name])[0];
 }
Exemple #3
0
 /// <summary>
 /// Parses each of a rule's production choices.
 /// </summary>
 void ParseProductions(IEvolutionState state, GrammarRuleNode retResult, IGELexer lexer, GPFunctionSet gpfs)
 {
     do
     {
         var token = lexer.NextToken();
         if (lexer.MatchingIndex == RULE)
         {
             retResult.AddChoice(GetRule(_rules, token));
             token = lexer.NextToken();
         }
         else
         {
             if (lexer.MatchingIndex != LPAREN) //first expect '('
             {
                 state.Output.Fatal("GE Grammar Error - Unexpected token for rule: " + retResult.Head +
                                    "Expecting '('.");
             }
             token = lexer.NextToken();
             if (lexer.MatchingIndex != FUNCTION) //now expecting function
             {
                 state.Output.Fatal("GE Grammar Error - Expecting a function name after first '(' for rule: " +
                                    retResult.Head + " Error: " + token);
             }
             else
             {
                 if (!gpfs.NodesByName.ContainsKey(token))
                 {
                     state.Output.Fatal("GPNode " + token + " is not defined in the function set.");
                 }
                 var grammarfuncnode = new GrammarFunctionNode(gpfs, token);
                 token = lexer.NextToken();
                 while (lexer.MatchingIndex != RPAREN)
                 {
                     if (lexer.MatchingIndex != RULE) //this better be the name of a rule node
                     {
                         state.Output.Fatal(
                             "GE Grammar Error - Expecting a rule name as argument for function definition: "
                             + grammarfuncnode.Head + " Error on : " + token);
                     }
                     grammarfuncnode.AddArgument(GetRule(_rules, token));
                     token = lexer.NextToken();
                 }
                 retResult.AddChoice(grammarfuncnode);
             }
             //after right paren, should see either '|' or newline
             token = lexer.NextToken();
             if (lexer.MatchingIndex != PIPE && lexer.MatchingIndex != Constants.GE_LEXER_FAILURE)
             {
                 state.Output.Fatal("GE Grammar Error - Expecting either '|' delimiter or newline. Error on : " +
                                    token);
             }
         }
     } while (lexer.MatchingIndex == PIPE);
 }
Exemple #4
0
        /// <summary>
        /// This function parses the dyck word and puts random nodes into their slots.
        /// </summary>
        private static GPNode BuildTree(IEvolutionState state, int thread,
                                        IGPNodeParent parent, int argPosition, GPFunctionSet funcs, string dyckWord)
        {
            var s = new List <GPNode>();

            // Parsing dyck word from left to right and building tree
            for (var counter = 0; counter < dyckWord.Length; counter++)
            {
                char nextChar;
                if (counter < dyckWord.Length - 1)
                {
                    nextChar = dyckWord[counter + 1];
                }
                else
                {
                    nextChar = '*';
                }
                if ((nextChar == 'x') || (nextChar == '*'))
                /* terminal node */
                {
                    var nn = funcs.Terminals[0];
                    var n  = nn[state.Random[thread].NextInt(nn.Length)].LightClone();
                    n.ResetNode(state, thread); // give ERCs a chance to randomize
                    s.Add(n);
                }
                else if (nextChar == 'y')
                /* non-terminal */
                {
                    // finding arity of connection
                    var ycount    = 0; /* arity */
                    var nextCharY = (nextChar == 'y');
                    counter++;
                    while ((counter < dyckWord.Length) && (nextCharY))
                    {
                        if (dyckWord[counter] == 'y')
                        {
                            ycount++;
                        }
                        if (counter < dyckWord.Length - 1)
                        {
                            nextCharY = (dyckWord[counter + 1] == 'y');
                        }
                        counter++;
                    }

                    //Arity found.  Now just choose non terminal at random.
                    var nonTerms = funcs.NodesByArity[0][ycount];
                    var nT       = nonTerms[state.Random[thread].NextInt(nonTerms.Length)].LightClone();
                    // Non terminal chosen, now attaching children
                    var childcount = ycount;
                    while (childcount > 0)
                    {
                        childcount--;
                        if (s.Count == 0)
                        {
                            state.Output.Fatal("Stack underflow when building tree.");
                        }
                        var child = Pop(s);
                        child.Parent            = nT;
                        child.ArgPosition       = (sbyte)childcount;
                        nT.Children[childcount] = child;
                    }
                    nT.ArgPosition = 0;
                    nT.Parent      = null;
                    s.Add(nT);
                    if (counter != dyckWord.Length)
                    {
                        counter--;
                    }
                }
            }
            return(Pop(s));
        }
Exemple #5
0
        /// <summary>
        /// A private function which recursively returns a GROW tree to NewRootedTree(...)
        /// </summary>
        protected internal virtual GPNode GrowNode(IEvolutionState state, int current, int max, GPType type, int thread,
                                                   IGPNodeParent parent, int argPosition, GPFunctionSet funcs)
        {
            // growNode can mess up if there are no available terminals for a given type.  If this occurs,
            // and we find ourselves unable to pick a terminal when we want to do so, we will issue a warning,
            // and pick a nonterminal, violating the maximum-depth contract.  This can lead to pathological situations
            // where the system will continue to go on and on unable to stop because it can't pick a terminal,
            // resulting in running out of memory or some such.  But there are cases where we'd want to let
            // this work itself out.
            var triedTerminals = false;

            var t = type.Type;

            GPNode[] terminals = funcs.Terminals[t];
            //GPNode[] nonterminals = funcs.Nonterminals[t];
            GPNode[] nodes = funcs.Nodes[t];

            if (nodes.Length == 0)
            {
                ErrorAboutNoNodeWithType(type, state); // total failure
            }
            // pick a terminal when we're at max depth or if there are NO nonterminals
            if (current + 1 >= max
                // this will freak out the static checkers
                && (triedTerminals = true) && // [first set triedTerminals]
                terminals.Length != 0)     // AND if there are available terminals
            {
                var n = terminals[state.Random[thread].NextInt(terminals.Length)].LightClone();
                n.ResetNode(state, thread); // give ERCs a chance to randomize
                n.ArgPosition = (sbyte)argPosition;
                n.Parent      = parent;
                return(n);
            }
            // else pick a random node
            else
            {
                if (triedTerminals)
                {
                    WarnAboutNoTerminalWithType(type, false, state); // we tried terminals and we're here because there were none!
                }
                var n = nodes[state.Random[thread].NextInt(nodes.Length)].LightClone();
                n.ResetNode(state, thread); // give ERCs a chance to randomize
                n.ArgPosition = (sbyte)argPosition;
                n.Parent      = parent;

                // Populate the node...
                var childtypes = n.Constraints(((GPInitializer)state.Initializer)).ChildTypes;
                for (var x = 0; x < childtypes.Length; x++)
                {
                    n.Children[x] = GrowNode(state, current + 1, max, childtypes[x], thread, n, x, funcs);
                }

                return(n);
            }
        }
Exemple #6
0
        public override GPNode NewRootedTree(IEvolutionState state, GPType type, int thread, IGPNodeParent parent,
                                             GPFunctionSet funcs, int argPosition, int requestedSize)
        {
            var initializer = ((GPInitializer)state.Initializer);

            if (requestedSize == NOSIZEGIVEN)
            // pick from the distribution
            {
                var BOUNDARY = 20; // if we try 20 times and fail, check to see if it's possible to succeed
                var bound    = 0;

                var fset = (int)FunctionSetsHash[funcs];
                var siz  = PickSize(state, thread, fset, type.Type);
                var typ  = type.Type;

                // this code is confusing.  The idea is:
                // if the number of trees of our arbitrarily-picked size is zero, we try BOUNDARY
                // number of times to find a tree which will work, picking new sizes each
                // time.  If we still haven't found anything, we will continue to search
                // for a working tree only if we know for sure that one exists in the distribution.

                var checkState = false; // BRS : Can't call this "checked" as in ECJ because of the compiler keyword
                while (ROOT_D_ZERO[fset][typ][siz])
                {
                    if (++bound == BOUNDARY)
                    {
                        if (!checkState)
                        {
                            checkState = true;
                            for (var x = 0; x < ROOT_D_ZERO[fset][typ].Length; x++)
                            {
                                if (!ROOT_D_ZERO[fset][typ][x])
                                {
                                    goto check_brk; // BRS : TODO : This is different from ECJ "break check;" Is it equivalent?
                                } // found a non-zero
                            }
                            // uh oh, we're all zeroes
                            state.Output.Fatal("ec.gp.build.Uniform was asked to build a tree with functionset " + funcs
                                               + " rooted with type " + type + ", but cannot because for some reason there are no trees"
                                               + " of any valid size (within the specified size range) which exist for this function set and type.");
                        }
                        check_brk :;
                    }
                    siz = PickSize(state, thread, fset, typ);
                }

                // okay, now we have a valid size.
                var n = CreateTreeOfType(state, thread, initializer, fset, typ, siz, state.Random[thread]);
                n.Parent      = parent;
                n.ArgPosition = (sbyte)argPosition;
                return(n);
            }
            else if (requestedSize < 1)
            {
                state.Output.Fatal("ec.gp.build.Uniform requested to build a tree, but a requested size was given that is < 1.");
                return(null); // never happens
            }
            else
            {
                var fset = (int)FunctionSetsHash[funcs];
                var typ  = type.Type;
                var siz  = requestedSize;

                // if the number of trees of the requested size is zero, we first march up until we
                // find a tree size with non-zero numbers of trees.  Failing that, we march down to
                // find one.  If that still fails, we issue an error.  Otherwise we use the size
                // we discovered.

                if (ROOT_D_ZERO[fset][typ][siz])
                {
                    // march up
                    for (var x = siz + 1; x < ROOT_D_ZERO[fset][typ].Length; x++)
                    {
                        if (ROOT_D_ZERO[fset][typ][siz])
                        {
                            siz = x;
                            goto determineSize_brk;
                        }
                    }
                    // march down
                    for (var x = siz - 1; x >= 0; x--)
                    {
                        if (ROOT_D_ZERO[fset][typ][siz])
                        {
                            siz = x;
                            goto determineSize_brk;
                        }
                    }
                    // issue an error
                    state.Output.Fatal("ec.gp.build.Uniform was asked to build a tree with functionset " + funcs + " rooted with type "
                                       + type + ", and of size " + requestedSize + ", but cannot because for some reason there are no trees of any"
                                       + " valid size (within the specified size range) which exist for this function set and type.");
                }

                determineSize_brk :;


                var n = CreateTreeOfType(state, thread, initializer, fset, typ, siz, state.Random[thread]);
                n.Parent      = parent;
                n.ArgPosition = (sbyte)argPosition;
                return(n);
            }
        }
Exemple #7
0
        public virtual void  Preprocess(IEvolutionState state, int maxTreeSize)
        {
            state.Output.Message("Determining Tree Sizes");

            MaxTreeSize = maxTreeSize;

            var functionSetRepository = ((GPInitializer)state.Initializer).FunctionSetRepository;

            // Put each function set into the arrays
            FunctionSets     = new GPFunctionSet[functionSetRepository.Count];
            FunctionSetsHash = Hashtable.Synchronized(new Hashtable());
            var e     = functionSetRepository.Values.GetEnumerator();
            var count = 0;

            while (e.MoveNext())
            {
                var funcs = (GPFunctionSet)e.Current;
                FunctionSetsHash[funcs] = count;
                FunctionSets[count++]   = funcs;
            }

            // For each function set, assign each GPNode to a unique integer
            // so we can keep track of it (ick, this will be inefficient!)
            FuncNodesHash = Hashtable.Synchronized(new Hashtable());
            var t_nodes = Hashtable.Synchronized(new Hashtable());

            count    = 0;
            MaxArity = 0;
            for (var x = 0; x < FunctionSets.Length; x++)
            {
                GPNode n;
                // hash all the nodes so we can remove duplicates
                for (var typ = 0; typ < FunctionSets[x].Nodes.Length; typ++)
                {
                    for (var nod = 0; nod < FunctionSets[x].Nodes[typ].Length; nod++)
                    {
                        t_nodes[n = FunctionSets[x].Nodes[typ][nod]] = n;
                    }
                }

                // rehash with Integers, yuck
                e = t_nodes.Values.GetEnumerator();
                GPNode tmpn;
                while (e.MoveNext())
                {
                    tmpn = (GPNode)e.Current;
                    if (MaxArity < tmpn.Children.Length)
                    {
                        MaxArity = tmpn.Children.Length;
                    }
                    if (!FuncNodesHash.ContainsKey(tmpn))  // don't remap the node; it'd make holes
                    {
                        FuncNodesHash[tmpn] = count++;
                    }
                }
            }

            NumFuncNodes = FuncNodesHash.Count;

            var initializer        = (GPInitializer)state.Initializer;
            var numAtomicTypes     = initializer.NumAtomicTypes;
            var numSetTypes        = initializer.NumSetTypes;
            var functionSetsLength = FunctionSets.Length;
            var atomicPlusSetTypes = numAtomicTypes + numSetTypes;
            var maxTreeSizePlusOne = MaxTreeSize + 1;

            // set up the arrays

            // NUMTREESOFTYPE
            NUMTREESOFTYPE = TensorFactory.Create <BigInteger>(functionSetsLength, atomicPlusSetTypes, maxTreeSizePlusOne);

            // NUMTREESROOTEDBYNODE
            NUMTREESROOTEDBYNODE = TensorFactory.Create <BigInteger>(functionSetsLength, NumFuncNodes, maxTreeSizePlusOne);

            // NUMCHILDPERMUTATIONS
            NUMCHILDPERMUTATIONS = TensorFactory.Create <BigInteger>(functionSetsLength,
                                                                     NumFuncNodes,
                                                                     maxTreeSizePlusOne,
                                                                     maxTreeSizePlusOne,
                                                                     MaxArity);

            // ROOT_D
            ROOT_D = TensorFactory.CreateOpenEnded <UniformGPNodeStorage>(functionSetsLength,
                                                                          atomicPlusSetTypes,
                                                                          maxTreeSizePlusOne); // 4D OpenEnded

            // ROOT_D_ZERO
            ROOT_D_ZERO = TensorFactory.Create <bool>(functionSetsLength,
                                                      atomicPlusSetTypes,
                                                      maxTreeSizePlusOne);

            // CHILD_D
            CHILD_D = TensorFactory.CreateOpenEnded <double>(functionSetsLength,
                                                             NumFuncNodes,
                                                             maxTreeSizePlusOne,
                                                             maxTreeSizePlusOne); // 5D OpenEnded

            var types = ((GPInitializer)(state.Initializer)).Types;

            // _TrueSizesBigInt
            TrueSizesBigInt = TensorFactory.Create <BigInteger>(functionSetsLength,
                                                                atomicPlusSetTypes,
                                                                maxTreeSizePlusOne);

            // Go through each function set and determine numbers
            // (this will take quite a while!  Thankfully it's offline)

            for (var x = 0; x < FunctionSets.Length; x++)
            {
                for (var y = 0; y < numAtomicTypes + numSetTypes; y++)
                {
                    for (var z = 1; z <= MaxTreeSize; z++)
                    {
                        state.Output.Message("FunctionSet: " + FunctionSets[x].Name + ", Type: " + types[y].Name
                                             + ", Size: " + z + " num: " + (TrueSizesBigInt[x][y][z] = NumTreesOfType(initializer, x, y, z)));
                    }
                }
            }

            state.Output.Message("Compiling Distributions");

            TrueSizes = TensorFactory.Create <double>(functionSetsLength,
                                                      atomicPlusSetTypes,
                                                      maxTreeSizePlusOne);

            // convert to doubles and organize distribution
            for (var x = 0; x < FunctionSets.Length; x++)
            {
                for (var y = 0; y < numAtomicTypes + numSetTypes; y++)
                {
                    for (var z = 1; z <= MaxTreeSize; z++)
                    {
                        TrueSizes[x][y][z] = (double)TrueSizesBigInt[x][y][z]; // BRS : DOES THIS TRUNCATE ANYTHING ???
                    }
                    // and if this is all zero (a possibility) we should be forgiving (hence the 'true') -- I *think*
                    RandomChoice.OrganizeDistribution(TrueSizes[x][y], true);
                }
            }

            // compute our percentages
            ComputePercentages();
        }
Exemple #8
0
        private GPNode randomBranch(IEvolutionState state, GPType type, int maxLength, int thread, IGPNodeParent parent, int argPosition, GPFunctionSet funcs)
        {
            // randomBranch can mess up if there are no available terminals for a given type.  If this occurs,
            // and we find ourselves unable to pick a terminal when we want to do so, we will issue a warning,
            // and pick a nonterminal, violating the maximum-size contract.  This can lead to pathological situations
            // where the system will continue to go on and on unable to stop because it can't pick a terminal,
            // resulting in running out of memory or some such.  But there are cases where we'd want to let
            // this work itself out.
            var triedTerminals = false;

            var t            = type.Type;
            var terminals    = funcs.Terminals[t];
            var nonterminals = funcs.Nonterminals[t];
            var nodes        = funcs.Nodes[t];

            if (nodes.Length == 0)
            {
                ErrorAboutNoNodeWithType(type, state); // total failure
            }
            // if the desired length is 1
            // OR if there are NO nonterminals!
            // [first set triedTerminals]
            // AND if there are available terminals
            if ((maxLength == 1 || WarnAboutNonterminal(nonterminals.Length == 0, type, false, state))
                // this will freak out the static checkers
                && (triedTerminals = true) &&
                terminals.Length != 0)
            {
                var n = terminals[state.Random[thread].NextInt(terminals.Length)].LightClone();
                n.ResetNode(state, thread); // give ERCs a chance to randomize
                n.ArgPosition = (sbyte)argPosition;
                n.Parent      = parent;
                return(n);
            }

            if (triedTerminals)
            {
                WarnAboutNoTerminalWithType(type, false, state); // we tried terminals and we're here because there were none!
            }
            // grab all the nodes whose arity is <= maxlength-1
            var len = funcs.NonterminalsUnderArity[type.Type].Length - 1;

            if (len > maxLength - 1)
            {
                len = maxLength - 1;
            }
            var okayNonterms = funcs.NonterminalsUnderArity[type.Type][len];

            if (okayNonterms.Length == 0)
            // no nodes, pick a terminal
            {
                if (terminals.Length == 0)
                {
                    ErrorAboutNoNodeWithType(type, state); // total failure
                }
                var n = terminals[state.Random[thread].NextInt(terminals.Length)].LightClone();
                n.ResetNode(state, thread); // give ERCs a chance to randomize
                n.ArgPosition = (sbyte)argPosition;
                n.Parent      = parent;
                return(n);
            }
            // we've got nonterminals, pick one at random
            else
            {
                var n = okayNonterms[state.Random[thread].NextInt(okayNonterms.Length)].LightClone();
                n.ResetNode(state, thread); // give ERCs a chance to randomize
                n.ArgPosition = (sbyte)argPosition;
                n.Parent      = parent;

                // Populate the node...
                var childtypes = n.Constraints((GPInitializer)state.Initializer).ChildTypes;
                for (var x = 0; x < childtypes.Length; x++)
                {
                    n.Children[x] = randomBranch(state, childtypes[x], (maxLength - 1) / childtypes.Length, thread, n, x, funcs);
                }
                return(n);
            }
        }