Example #1
0
        public override object Clone()
        {
            SizeFairCrossoverPipeline c = (SizeFairCrossoverPipeline)(base.Clone());

            // deep-cloned stuff
            c.NodeSelect1 = (IGPNodeSelector)NodeSelect1.Clone();
            c.NodeSelect2 = (IGPNodeSelector)NodeSelect2.Clone();
            c.Parents     = Parents.ToList();

            return(c);
        }
Example #2
0
        public void Setup(IEvolutionState state, Parameter paramBase)
        {
            base.Setup(state, paramBase);

            IParameter def = DefaultBase;
            IParameter p   = paramBase.Push(P_NODESELECTOR).Push("0");
            IParameter d   = def.Push(P_NODESELECTOR).Push("0");

            NodeSelect1 = (IGPNodeSelector)state.Parameters.GetInstanceForParameter(p, d, typeof(IGPNodeSelector));
            NodeSelect1.Setup(state, p);

            p = paramBase.Push(P_NODESELECTOR).Push("1");
            d = def.Push(P_NODESELECTOR).Push("1");

            if (state.Parameters.ParameterExists(p, d) && state.Parameters.GetString(p, d).Equals(V_SAME))
            {
                // can't just copy it this time; the selectors
                // use internal caches. So we have to clone it no matter what
                NodeSelect2 = (IGPNodeSelector)NodeSelect1.Clone();
            }
            else
            {
                NodeSelect2 = (IGPNodeSelector)state.Parameters.GetInstanceForParameter(p, d, typeof(IGPNodeSelector));
                NodeSelect2.Setup(state, p);
            }

            NumTries = state.Parameters.GetInt(paramBase.Push(P_NUM_TRIES), def.Push(P_NUM_TRIES), 1);
            if (NumTries == 0)
            {
                state.Output.Fatal("GPCrossover Pipeline has an invalid number of tries (it must be >= 1).",
                                   paramBase.Push(P_NUM_TRIES), def.Push(P_NUM_TRIES));
            }

            MaxDepth = state.Parameters.GetInt(paramBase.Push(P_MAXDEPTH), def.Push(P_MAXDEPTH), 1);
            if (MaxDepth == 0)
            {
                state.Output.Fatal("GPCrossover Pipeline has an invalid maximum depth (it must be >= 1).",
                                   paramBase.Push(P_MAXDEPTH), def.Push(P_MAXDEPTH));
            }

            Tree1 = TREE_UNFIXED;
            if (state.Parameters.ParameterExists(paramBase.Push(P_TREE).Push("" + 0), def.Push(P_TREE).Push("" + 0)))
            {
                Tree1 = state.Parameters.GetInt(paramBase.Push(P_TREE).Push("" + 0), def.Push(P_TREE).Push("" + 0), 0);
                if (Tree1 == -1)
                {
                    state.Output.Fatal("Tree fixed value, if defined, must be >= 0");
                }
            }

            Tree2 = TREE_UNFIXED;
            if (state.Parameters.ParameterExists(paramBase.Push(P_TREE).Push("" + 1), def.Push(P_TREE).Push("" + 1)))
            {
                Tree2 = state.Parameters.GetInt(paramBase.Push(P_TREE).Push("" + 1), def.Push(P_TREE).Push("" + 1), 0);
                if (Tree2 == -1)
                {
                    state.Output.Fatal("Tree fixed value, if defined, must be >= 0");
                }
            }
            TossSecondParent = state.Parameters.GetBoolean(paramBase.Push(P_TOSS), def.Push(P_TOSS), false);
            if (state.Parameters.ParameterExists(paramBase.Push(P_HOMOLOGOUS), null))
            {
                //get the parameter
                Homologous = state.Parameters.GetBoolean(paramBase.Push(P_HOMOLOGOUS), null, false);
            }
        }
Example #3
0
        public override int Produce(
            int min,
            int max,
            int subpop,
            IList <Individual> inds,
            IEvolutionState state,
            int thread,
            IDictionary <string, object> misc)
        {
            int start = inds.Count;

            // how many individuals should we make?
            var n = TypicalIndsProduced;

            if (n < min)
            {
                n = min;
            }
            if (n > max)
            {
                n = max;
            }

            // should we bother?
            if (!state.Random[thread].NextBoolean(Likelihood))
            {
                // just load from source 0 and clone 'em
                Sources[0].Produce(n, n, subpop, inds, state, thread, misc);
                return(n);
            }

            IntBag[] parentparents   = null;
            IntBag[] preserveParents = null;
            if (misc != null && misc.ContainsKey(KEY_PARENTS))
            {
                preserveParents   = (IntBag[])misc[KEY_PARENTS];
                parentparents     = new IntBag[2];
                misc[KEY_PARENTS] = parentparents;
            }

            var initializer = (GPInitializer)state.Initializer;

            for (var q = start; q < n + start;)  // keep on going until we're filled up
            {
                Parents.Clear();

                // grab two individuals from our sources
                if (Sources[0] == Sources[1])
                {
                    // grab from the same source
                    Sources[0].Produce(2, 2, subpop, Parents, state, thread, misc);
                }
                // grab from different sources
                else
                {
                    Sources[0].Produce(1, 1, subpop, Parents, state, thread, misc);
                    Sources[1].Produce(1, 1, subpop, Parents, state, thread, misc);
                }

                // at this point, Parents[] contains our two selected individuals

                // are our tree values valid?
                if (Tree1 != TREE_UNFIXED && (Tree1 < 0 || Tree1 >= ((GPIndividual)Parents[0]).Trees.Length))
                {
                    // uh oh
                    state.Output.Fatal("GP Crossover Pipeline attempted to fix tree.0 to a value which was out of bounds"
                                       + " of the array of the individual's trees.  Check the pipeline's fixed tree values"
                                       + " -- they may be negative or greater than the number of trees in an individual");
                }

                if (Tree2 != TREE_UNFIXED && (Tree2 < 0 || Tree2 >= ((GPIndividual)Parents[1]).Trees.Length))
                {
                    // uh oh
                    state.Output.Fatal("GP Crossover Pipeline attempted to fix tree.1 to a value which was out of bounds"
                                       + " of the array of the individual's trees.  Check the pipeline's fixed tree values"
                                       + " -- they may be negative or greater than the number of trees in an individual");
                }

                var t1 = 0;
                var t2 = 0;
                if (Tree1 == TREE_UNFIXED || Tree2 == TREE_UNFIXED)
                {
                    do
                    // pick random trees  -- their GPTreeConstraints must be the same
                    {
                        if (Tree1 == TREE_UNFIXED)
                        {
                            if (((GPIndividual)Parents[0]).Trees.Length > 1)
                            {
                                t1 = state.Random[thread].NextInt(((GPIndividual)Parents[0]).Trees.Length);
                            }
                            else
                            {
                                t1 = 0;
                            }
                        }
                        else
                        {
                            t1 = Tree1;
                        }

                        if (Tree2 == TREE_UNFIXED)
                        {
                            if (((GPIndividual)Parents[1]).Trees.Length > 1)
                            {
                                t2 = state.Random[thread].NextInt(((GPIndividual)Parents[1]).Trees.Length);
                            }
                            else
                            {
                                t2 = 0;
                            }
                        }
                        else
                        {
                            t2 = Tree2;
                        }
                    }while (((GPIndividual)Parents[0]).Trees[t1].Constraints(initializer) != ((GPIndividual)Parents[1]).Trees[t2].Constraints(initializer));
                }
                else
                {
                    t1 = Tree1;
                    t2 = Tree2;
                    // make sure the constraints are okay
                    if (((GPIndividual)Parents[0]).Trees[t1].Constraints(initializer) != ((GPIndividual)Parents[1]).Trees[t2].Constraints(initializer))
                    {
                        // uh oh
                        state.Output.Fatal("GP Crossover Pipeline's two tree choices are both specified by the user"
                                           + " -- but their GPTreeConstraints are not the same");
                    }
                }

                // validity results...
                var res1 = false;
                var res2 = false;

                // prepare the nodeselectors
                NodeSelect1.Reset();
                NodeSelect2.Reset();

                // pick some nodes

                GPNode p1 = null;
                GPNode p2 = null;

                for (var x = 0; x < NumTries; x++)
                {
                    // pick a node in individual 1
                    p1 = NodeSelect1.PickNode(state, subpop, thread, (GPIndividual)Parents[0], ((GPIndividual)Parents[0]).Trees[t1]);

                    // pick a node in individual 2
                    p2 = NodeSelect2.PickNode(state, subpop, thread, (GPIndividual)Parents[1], ((GPIndividual)Parents[1]).Trees[t2]);

                    // check for depth and swap-compatibility limits
                    res1 = VerifyPoints(initializer, p2, p1); // p2 can fill p1's spot -- order is important!
                    if (n - (q - start) < 2 || TossSecondParent)
                    {
                        res2 = true;
                    }
                    else
                    {
                        res2 = VerifyPoints(initializer, p1, p2); // p1 can fill p2's spot -- order is important!
                    }
                    // did we get something that had both nodes verified?
                    // we reject if EITHER of them is invalid.  This is what lil-gp does.
                    // Koza only has NumTries set to 1, so it's compatible as well.
                    if (res1 && res2)
                    {
                        break;
                    }
                }

                // at this point, res1 AND res2 are valid, OR either res1
                // OR res2 is valid and we ran out of tries, OR neither is
                // valid and we ran out of tries.  So now we will transfer
                // to a tree which has res1 or res2 valid, otherwise it'll
                // just get replicated.  This is compatible with both Koza
                // and lil-gp.

                // at this point I could check to see if my sources were breeding
                // pipelines -- but I'm too lazy to write that code (it's a little
                // complicated) to just swap one individual over or both over,
                // -- it might still entail some copying.  Perhaps in the future.
                // It would make things faster perhaps, not requiring all that
                // cloning.

                // Create some new individuals based on the old ones -- since
                // GPTree doesn't deep-clone, this should be just fine.  Perhaps we
                // should change this to proto off of the main species prototype, but
                // we have to then copy so much stuff over; it's not worth it.

                var          j1 = ((GPIndividual)Parents[0]).LightClone();
                GPIndividual j2 = null;

                if (n - (q - start) >= 2 && !TossSecondParent)
                {
                    j2 = ((GPIndividual)Parents[1]).LightClone();
                }

                // Fill in various tree information that didn't get filled in there
                j1.Trees = new GPTree[((GPIndividual)Parents[0]).Trees.Length];
                if (n - (q - start) >= 2 && !TossSecondParent)
                {
                    j2.Trees = new GPTree[((GPIndividual)Parents[1]).Trees.Length];
                }

                // at this point, p1 or p2, or both, may be null.
                // If not, swap one in.  Else just copy the parent.

                for (var x = 0; x < j1.Trees.Length; x++)
                {
                    if (x == t1 && res1)
                    // we've got a tree with a kicking cross position!
                    {
                        j1.Trees[x]                   = ((GPIndividual)Parents[0]).Trees[x].LightClone();
                        j1.Trees[x].Owner             = j1;
                        j1.Trees[x].Child             = ((GPIndividual)Parents[0]).Trees[x].Child.CloneReplacing(p2, p1);
                        j1.Trees[x].Child.Parent      = j1.Trees[x];
                        j1.Trees[x].Child.ArgPosition = 0;
                        j1.Evaluated                  = false;
                    }
                    // it's changed
                    else
                    {
                        j1.Trees[x]                   = ((GPIndividual)Parents[0]).Trees[x].LightClone();
                        j1.Trees[x].Owner             = j1;
                        j1.Trees[x].Child             = (GPNode)((GPIndividual)Parents[0]).Trees[x].Child.Clone();
                        j1.Trees[x].Child.Parent      = j1.Trees[x];
                        j1.Trees[x].Child.ArgPosition = 0;
                    }
                }

                if (n - (q - start) >= 2 && !TossSecondParent)
                {
                    for (var x = 0; x < j2.Trees.Length; x++)
                    {
                        if (x == t2 && res2)
                        // we've got a tree with a kicking cross position!
                        {
                            j2.Trees[x]                   = ((GPIndividual)Parents[1]).Trees[x].LightClone();
                            j2.Trees[x].Owner             = j2;
                            j2.Trees[x].Child             = ((GPIndividual)Parents[1]).Trees[x].Child.CloneReplacing(p1, p2);
                            j2.Trees[x].Child.Parent      = j2.Trees[x];
                            j2.Trees[x].Child.ArgPosition = 0;
                            j2.Evaluated                  = false;
                        }
                        // it's changed
                        else
                        {
                            j2.Trees[x]                   = ((GPIndividual)Parents[1]).Trees[x].LightClone();
                            j2.Trees[x].Owner             = j2;
                            j2.Trees[x].Child             = (GPNode)((GPIndividual)Parents[1]).Trees[x].Child.Clone();
                            j2.Trees[x].Child.Parent      = j2.Trees[x];
                            j2.Trees[x].Child.ArgPosition = 0;
                        }
                    }
                }

                // add the individuals to the population
                inds.Add(j1);
                q++;
                if (q < n + start && !TossSecondParent)
                {
                    inds.Add(j2);
                    if (preserveParents != null)
                    {
                        parentparents[0].AddAll(parentparents[1]);
                        preserveParents[q] = parentparents[0];
                    }
                    q++;
                }
            }
            return(n);
        }