/// <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); }
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]); }
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); }
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)); }
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++; } } } }
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; }
/// <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! }
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); }