public override void Setup(IEvolutionState state, IParameter paramBase)
        {
            base.Setup(state, paramBase);

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

            NodeSelect0 = (IGPNodeSelector)(state.Parameters.GetInstanceForParameter(p, d, typeof(IGPNodeSelector)));
            NodeSelect0.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
                NodeSelect1 = (IGPNodeSelector)(NodeSelect0.Clone());
            }
            else
            {
                NodeSelect1 = (IGPNodeSelector)(state.Parameters.GetInstanceForParameter(p, d, typeof(IGPNodeSelector)));
                NodeSelect1.Setup(state, p);
            }

            NumTries = state.Parameters.GetInt(paramBase.Push(P_NUM_TRIES), def.Push(P_NUM_TRIES), 1);
            if (NumTries == 0)
            {
                state.Output.Fatal("InternalCrossover 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("InternalCrossover 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");
                }
            }
        }
        public override object Clone()
        {
            var c = (InternalCrossoverPipeline)(base.Clone());

            // deep-cloned stuff
            c.NodeSelect0 = (IGPNodeSelector)(NodeSelect0.Clone());
            c.NodeSelect1 = (IGPNodeSelector)(NodeSelect1.Clone());
            return(c);
        }