/// <summary>Copies this program to another.</summary> /// <param name="inOther">The program to receive the copy of this program</param> public void CopyTo(Psh.Program inOther) { for (int n = 0; n < _size; n++) { inOther.Push(this[n]); } }
/// <summary>Replaces a subtree of this Program with a new object.</summary> /// <param name="inIndex">The index of the subtree to replace.</param> /// <param name="inReplacement">The replacement for the subtree</param> /// <returns>True if a replacement was made (the index was valid).</returns> public bool ReplaceSubtree(int inIndex, object inReplacement) { if (_size == 0) { this.Push(inReplacement); return(true); } if (inIndex < _size) { this[inIndex] = Cloneforprogram(inReplacement); return(true); } else { int startIndex = _size; for (int n = 0; n < _size; n++) { object o = this[n]; if (o is Psh.Program) { Psh.Program sub = (Psh.Program)o; int length = sub.ProgramSize(); if (inIndex - startIndex < length) { return(sub.ReplaceSubtree(inIndex - startIndex, inReplacement)); } startIndex += length; } } } return(false); }
/// <summary>Returns a subtree of the program.</summary> /// <param name="inIndex">The index of the requested subtree.</param> /// <returns>The program subtree.</returns> public object Subtree(int inIndex) { if (inIndex < _size) { return(this[inIndex]); } else { int startIndex = _size; for (int n = 0; n < _size; n++) { object o = this[n]; if (o is Psh.Program) { Psh.Program sub = (Psh.Program)o; int length = sub.ProgramSize(); if (inIndex - startIndex < length) { return(sub.Subtree(inIndex - startIndex)); } startIndex += length; } } } return(null); }
public void Flatten(int inIndex) { if (inIndex < _size) { // If here, the index to be flattened is in this program. So, push // the rest of the program onto a new program, and replace this with // that new program. Psh.Program replacement = new Psh.Program(this); Clear(); for (int i = 0; i < replacement._size; i++) { if (inIndex == i) { if (replacement[i] is Psh.Program) { Psh.Program p = (Psh.Program)replacement[i]; for (int j = 0; j < p._size; j++) { this.Push(p[j]); } } else { this.Push(replacement[i]); } } else { this.Push(replacement[i]); } } } else { int startIndex = _size; for (int n = 0; n < _size; n++) { object o = this[n]; if (o is Psh.Program) { Psh.Program sub = (Psh.Program)o; int length = sub.ProgramSize(); if (inIndex - startIndex < length) { sub.Flatten(inIndex - startIndex); break; } startIndex += length; } } } }
/// <exception cref="System.Exception"/> private int Parse(string[] inTokens, int inStart) { bool first = (inStart == 0); for (int n = inStart; n < inTokens.Length; n++) { string token = inTokens[n]; if (!token.Equals(string.Empty)) { if (token.Equals("(")) { // Found an open paren -- begin a recursive Parse, though // the very first // token in the list is a special case -- no need to create // a sub-program if (!first) { Psh.Program p = new Psh.Program(); n = p.Parse(inTokens, n + 1); Push(p); } } else { if (token.Equals(")")) { // End of the program -- return the advanced token index to // the caller return(n); } else { if (char.IsLetter(token[0])) { Push(token); } else { // This makes printing stacks very ugly. For now, will store // program instructions as strings, as was done before. /* * Instruction i = _interpreter._instructions.get(token); * if (i != null) * push(i); * else * push(token); */ try { object number; if (token.IndexOf('.') != -1) { number = float.Parse(token); } else { number = System.Convert.ToInt32(token); } Push(number); } catch (FormatException fe) { throw new Exception("Could not convert '" + token + "' to number.", fe); } } } } first = false; } } // If we're here, there was no closing brace for one of the programs throw new Exception("No closing brace found for program"); }
/// <summary>Constructs a copy of an existing Program.</summary> /// <param name="inOther">The Push program to copy.</param> public Program(Psh.Program inOther) { inOther.CopyTo(this); }
public void Evaluate(IEvolutionState state, Individual ind, int subpopulation, int threadnum) { if (!ind.Evaluated) // don't bother reevaluating { int hits = 0; double sum = 0.0; Interpreter interpreter = GetInterpreter(state, (GPIndividual)ind, threadnum); Psh.Program program = GetProgram(state, (GPIndividual)ind); for (int y = 0; y < TrainingSetSize; y++) { if (y > 0) // need to reset first { ResetInterpreter(interpreter); } // load it up and run it PushOntoFloatStack(interpreter, (float)(Inputs[y])); ExecuteProgram(program, interpreter, MaxSteps); // It's possible to get NaN because cos(infinity) and // sin(infinity) are undefined (hence cos(exp(3000)) zings ya!) // So since NaN is NOT =,<,>,etc. any other number, including // NaN, we're CAREFULLY wording our cutoff to include NaN. // Interesting that this has never been reported before to // my knowledge. double HIT_LEVEL = 0.01; double PROBABLY_ZERO = 1E-6; // The Psh interpreter seems less accurate, not sure why double BIG_NUMBER = 1.0e15; // the same as lilgp uses var result = Math.Abs(Outputs[y] - TopOfFloatStack(interpreter)); if (!(result < BIG_NUMBER)) // *NOT* (input.x >= BIG_NUMBER) { result = BIG_NUMBER; } if (IsFloatStackEmpty(interpreter)) // uh oh, invalid value { result = BIG_NUMBER; } // very slight math errors can creep in when evaluating // two equivalent by differently-ordered functions, like // x * (x*x*x + x*x) vs. x*x*x*x + x*x else if (result < PROBABLY_ZERO) // slightly off { result = 0.0; } if (result <= HIT_LEVEL) { hits++; // whatever! } sum += result; } // the fitness better be KozaFitness! var f = (KozaFitness)ind.Fitness; f.SetStandardizedFitness(state, (float)sum); f.Hits = hits; ind.Evaluated = true; } }