Beispiel #1
0
 /// <summary>
 /// This very expensive method (for types) might be improved in various ways I guess.
 /// </summary>
 private static bool Swappable(GPInitializer initializer, GPNode node)
 {
     if (node.Children.Length < 2)
     {
         return(false); // fast check
     }
     if (initializer.NumAtomicTypes + initializer.NumSetTypes == 1)
     {
         return(true); // next fast check
     }
     // we're typed, so now we have to check our type compatibility
     for (var x = 0; x < node.Constraints(initializer).ChildTypes.Length - 1; x++)
     {
         for (var y = x + 1; y < node.Constraints(initializer).ChildTypes.Length; y++)
         {
             if (node.Children[x].Constraints(initializer).ReturnType
                 .CompatibleWith(initializer, node.Constraints(initializer).ChildTypes[y]) &&
                 node.Children[y].Constraints(initializer).ReturnType
                 .CompatibleWith(initializer, node.Constraints(initializer).ChildTypes[x]))
             {
                 // whew!
                 return(true);
             }
         }
     }
     return(false);
 }
Beispiel #2
0
        public virtual BigInteger NumChildPermutations(GPInitializer initializer, int functionset, GPNode parent, int size, int outof, int pickchild)
        {
            if (NUMCHILDPERMUTATIONS[functionset][IntForNode(parent)][size][outof][pickchild] == 0)
            {
                var count = BigInteger.Zero;
                if (pickchild == parent.Children.Length - 1 && size == outof)
                {
                    count = NumTreesOfType(initializer, functionset, parent.Constraints(initializer).ChildTypes[pickchild].Type, size);
                }

                else if (pickchild < parent.Children.Length - 1 && outof - size >= (parent.Children.Length - pickchild - 1))
                {
                    var cval = NumTreesOfType(initializer, functionset, parent.Constraints(initializer).ChildTypes[pickchild].Type, size);
                    var tot  = BigInteger.Zero;
                    for (var s = 1; s <= outof - size; s++)
                    {
                        tot = BigInteger.Add(tot, NumChildPermutations(initializer, functionset, parent, s, outof - size, pickchild + 1));
                    }
                    count = BigInteger.Multiply(cval, tot);
                }
                // out.PrintLn("Parent: " + parent + " Size: " + size + " OutOf: " + outof +
                //       " PickChild: " + pickchild + " Count: " +count);
                NUMCHILDPERMUTATIONS[functionset][IntForNode(parent)][size][outof][pickchild] = count;
            }
            return(NUMCHILDPERMUTATIONS[functionset][IntForNode(parent)][size][outof][pickchild]);
        }
Beispiel #3
0
        private static bool Demotable(GPInitializer initializer, GPNode node, GPFunctionSet funcs)
        {
            GPType t;

            if (node.Parent is GPNode)
            {
                // ugh, expensive
                t = ((GPNode)(node.Parent)).Constraints(initializer).ChildTypes[node.ArgPosition];
            }
            else
            {
                t = ((GPTree)(node.Parent)).Constraints(initializer).TreeType;
            }

            // Now, out of the nonterminals compatible with that return type,
            // do any also have a child compatible with that return type?  This
            // will be VERY expensive

            for (var x = 0; x < funcs.Nonterminals[t.Type].Length; x++)
            {
                if (funcs.Nonterminals[t.Type][x].Constraints(initializer).ChildTypes
                    .Any(t1 => t1.CompatibleWith(initializer, node.Constraints(initializer).ReturnType)))
                {
                    return(true);
                }
            }
            return(false);
        }
Beispiel #4
0
        private static bool Promotable(GPInitializer initializer, GPNode node)
        {
            // A node is promotable if:
            // 1: its parent is a GPNode
            if (!(node.Parent is GPNode))
            {
                return(false);
            }
            var parent = (GPNode)(node.Parent);

            GPType t;

            if (parent.Parent is GPNode)
            {
                // ugh, expensive
                t = ((GPNode)parent.Parent).Constraints(initializer).ChildTypes[parent.ArgPosition];
            }
            else
            {
                t = ((GPTree)parent.Parent).Constraints(initializer).TreeType;
            }

            // 2: the node's returntype is type-compatible with its GRANDparent's return slot
            return(node.Constraints(initializer).ReturnType.CompatibleWith(initializer, t));
        }
Beispiel #5
0
        private static void SwapSomethingDirtyWork(GPNode node, IEvolutionState state, int thread)
        {
            var numSwappable = 0;
            var initializer  = ((GPInitializer)state.Initializer);

            for (var x = 0; x < node.Constraints(initializer).ChildTypes.Length - 1; x++)
            {
                for (var y = x + 1; y < node.Constraints(initializer).ChildTypes.Length; y++)
                {
                    if (node.Children[x].Constraints(initializer).ReturnType
                        .CompatibleWith(initializer, node.Constraints(initializer).ChildTypes[y]) &&
                        node.Children[y].Constraints(initializer).ReturnType
                        .CompatibleWith(initializer, node.Constraints(initializer).ChildTypes[x]))
                    {
                        // whew!
                        numSwappable++;
                    }
                }
            }

            // pick a random item to swap -- numSwappable is assumed to be > 0
            var swapItem = state.Random[thread].NextInt(numSwappable);

            numSwappable = 0;
            // find it

            for (var x = 0; x < node.Constraints(initializer).ChildTypes.Length - 1; x++)
            {
                for (var y = x + 1; y < node.Constraints(initializer).ChildTypes.Length; y++)
                {
                    if (node.Children[x].Constraints(initializer).ReturnType
                        .CompatibleWith(initializer, node.Constraints(initializer).ChildTypes[y]) &&
                        node.Children[y].Constraints(initializer).ReturnType
                        .CompatibleWith(initializer, node.Constraints(initializer).ChildTypes[x]))
                    {
                        if (numSwappable == swapItem)
                        // found it
                        {
                            // swap the children
                            var tmp = node.Children[x];
                            node.Children[x]             = node.Children[y];
                            node.Children[y]             = tmp;
                            node.Children[x].ArgPosition = (sbyte)x;
                            node.Children[y].ArgPosition = (sbyte)y;
                            // no need to set parent -- it's the same parent of course
                            return;
                        }
                        numSwappable++;
                    }
                }
            }
        }
Beispiel #6
0
        internal virtual void FillNodeWithChildren(IEvolutionState state, int thread, GPInitializer initializer, int functionset,
                                                   GPNode parent, GPNode parentc, int pickchild, int outof, IMersenneTwister mt)
        {
            if (pickchild == parent.Children.Length - 1)
            {
                parent.Children[pickchild] = CreateTreeOfType(state, thread, initializer, functionset,
                                                              parent.Constraints(initializer).ChildTypes[pickchild].Type, outof, mt);
            }
            else
            {
                var size = RandomChoice.PickFromDistribution(CHILD_D[functionset][IntForNode(parentc)][outof][pickchild], mt.NextDouble());

                parent.Children[pickchild] = CreateTreeOfType(state, thread, initializer, functionset,
                                                              parent.Constraints(initializer).ChildTypes[pickchild].Type, size, mt);

                FillNodeWithChildren(state, thread, initializer, functionset, parent, parentc, pickchild + 1, outof - size, mt);
            }
            parent.Children[pickchild].Parent      = parent;
            parent.Children[pickchild].ArgPosition = (sbyte)pickchild;
        }
Beispiel #7
0
        /// <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("Invalid execution path!"); // whoops!
        }
Beispiel #8
0
        private static void DemoteSomethingDirtyWork(GPNode node, IEvolutionState state, int thread, GPFunctionSet funcs)
        {
            var numDemotable = 0;

            GPType t;
            var    initializer = ((GPInitializer)state.Initializer);

            if (node.Parent is GPNode)
            {
                // ugh, expensive
                t = ((GPNode)(node.Parent)).Constraints(initializer).ChildTypes[node.ArgPosition];
            }
            else
            {
                t = ((GPTree)(node.Parent)).Constraints(initializer).TreeType;
            }

            // Now, determine how many nodes we can demote this under --
            // note this doesn't select based on the total population
            // of "available child positions", but on the total population
            // of *nodes* regardless of if they have more than one possible
            // valid "child position".

            for (var x = 0; x < funcs.Nonterminals[t.Type].Length; x++)
            {
                if (funcs.Nonterminals[t.Type][x].Constraints(initializer).ChildTypes
                    .Any(t1 => t1.CompatibleWith(initializer, node.Constraints(initializer).ReturnType)))
                {
                    numDemotable++;
                }
            }

            // pick a random item to demote -- numDemotable is assumed to be > 0
            var demoteItem = state.Random[thread].NextInt(numDemotable);

            numDemotable = 0;
            // find it

            for (var x = 0; x < funcs.Nonterminals[t.Type].Length; x++)
            {
                if (funcs.Nonterminals[t.Type][x].Constraints(initializer).ChildTypes
                    .Any(t1 => t1.CompatibleWith(initializer, node.Constraints(initializer).ReturnType)))
                {
                    if (numDemotable == demoteItem)
                    {
                        // clone the node
                        var cnode = funcs.Nonterminals[t.Type][x].LightClone();

                        // choose a spot to hang the old parent under
                        var retyp  = node.Constraints(initializer).ReturnType;
                        var chityp = cnode.Constraints(initializer).ChildTypes;

                        var numSpots = cnode.Children.Where((t1, z) => chityp[z].CompatibleWith(initializer, retyp)).Count();
                        var choice   = state.Random[thread].NextInt(numSpots);

                        numSpots = 0;
                        for (var z = 0; z < cnode.Children.Length; z++)
                        {
                            if (chityp[z].CompatibleWith(initializer, retyp))
                            {
                                if (numSpots == choice)
                                {
                                    // demote the parent, inserting cnode
                                    cnode.Parent      = node.Parent;
                                    cnode.ArgPosition = node.ArgPosition;
                                    cnode.Children[z] = node;
                                    node.Parent       = cnode;
                                    node.ArgPosition  = (sbyte)z;
                                    if (cnode.Parent is GPNode)
                                    {
                                        ((GPNode)(cnode.Parent)).Children[cnode.ArgPosition] = cnode;
                                    }
                                    else
                                    {
                                        ((GPTree)(cnode.Parent)).Child = cnode;
                                    }

                                    // this is important to ensure that the
                                    // demotion only happens once!  Otherwise
                                    // you'll get really nasty bugs
                                    numSpots++; // notice no break
                                }
                                else
                                {
                                    // hang a randomly-generated terminal off of cnode
                                    var term = funcs.Terminals
                                               [chityp[z].Type][state.Random[thread].NextInt(funcs.Terminals[chityp[z].Type].Length)].LightClone();

                                    cnode.Children[z] = term;
                                    term.Parent       = cnode;     // just in case
                                    term.ArgPosition  = (sbyte)z;  // just in case
                                    term.ResetNode(state, thread); // let it randomize itself if necessary

                                    // increase numSpots
                                    numSpots++; // notice no break
                                }
                            }
                            else
                            {
                                // hang a randomly-generated terminal off of cnode
                                var term = funcs.Terminals
                                           [chityp[z].Type][state.Random[thread].NextInt(funcs.Terminals[chityp[z].Type].Length)].LightClone();

                                cnode.Children[z] = term;
                                term.Parent       = cnode;     // just in case
                                term.ArgPosition  = (sbyte)z;  // just in case
                                term.ResetNode(state, thread); // let it randomize itself if necessary
                            }
                        }
                        return;
                    }
                    numDemotable++;
                }
            }
            // should never reach here
            throw new ApplicationException("Bug in demoteSomething -- should never be able to reach the end of the function");
        }
        /// <summary>
        /// Returns a brand-new tree which is swap-compatible with returntype,
        /// created by making nodes "compatible" with the equivalent nodes in the tree rooted at original.
        /// You need to set the parent and argumentposition of the root yourself.
        /// </summary>
        private static GPNode GenerateCompatibleTree(GPNode original, GPFunctionSet funcs, IEvolutionState state, GPType returntype, int thread)
        {
            // pick a new node and clone it
            var node = PickCompatibleNode(original, funcs, state, returntype, thread).LightClone();

            // reset it
            node.ResetNode(state, thread);

            // fill in its children
            var initializer = ((GPInitializer)state.Initializer);

            for (var x = 0; x < node.Children.Length; x++)
            {
                node.Children[x]             = GenerateCompatibleTree(original.Children[x], funcs, state, original.Constraints(initializer).ChildTypes[x], thread);
                node.Children[x].Parent      = node;
                node.Children[x].ArgPosition = (sbyte)x;
            }
            return(node);
        }