Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Grammar.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Grammar.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Grammar.cs	(revision 12893)
@@ -184,5 +184,13 @@
         Debug.Assert(maxLenOfReplacement > 0);
 
-        var alts = GetTerminalAlternatives(nt).Where(alt => MinPhraseLength(alt) <= maxLenOfReplacement);
+
+        IEnumerable<Sequence> alts;
+        if (random.NextDouble() < 0.005) {
+          alts = GetTerminalAlternatives(nt).Where(alt => MinPhraseLength(alt) <= maxLenOfReplacement);
+        } else {
+          alts = GetNonTerminalAlternatives(nt).Where(alt => MinPhraseLength(alt) <= maxLenOfReplacement);
+          if (!alts.Any())
+            alts = GetTerminalAlternatives(nt).Where(alt => MinPhraseLength(alt) <= maxLenOfReplacement);
+        }
         Debug.Assert(alts.Any());
 
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/HeuristicLab.Problems.GrammaticalOptimization.csproj
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/HeuristicLab.Problems.GrammaticalOptimization.csproj	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/HeuristicLab.Problems.GrammaticalOptimization.csproj	(revision 12893)
@@ -32,4 +32,5 @@
     <WarningLevel>4</WarningLevel>
     <Prefer32Bit>false</Prefer32Bit>
+    <UseVSHostingProcess>true</UseVSHostingProcess>
   </PropertyGroup>
   <ItemGroup>
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Interfaces/IProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Interfaces/IProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Interfaces/IProblem.cs	(revision 12893)
@@ -12,4 +12,5 @@
     IGrammar Grammar { get; }
     double Evaluate(string sentence);
+    bool IsOptimalPhrase(string phrase); // determines if the phrase can be derived to an optimal solution
     string CanonicalRepresentation(string phrase); // canonical state must use correct syntax (must be a valid input for evaluate)
     IEnumerable<Feature> GetFeatures(string phrase);
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/EvenParityProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/EvenParityProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/EvenParityProblem.cs	(revision 12893)
@@ -63,4 +63,8 @@
     }
 
+    public bool IsOptimalPhrase(string phrase) {
+      throw new NotImplementedException();
+    }
+
     public string CanonicalRepresentation(string phrase) {
       throw new NotImplementedException();
@@ -68,7 +72,6 @@
     }
 
-    public IEnumerable<Feature> GetFeatures(string phrase)
-    {
-      return new[] {new Feature(phrase, 1.0)};
+    public IEnumerable<Feature> GetFeatures(string phrase) {
+      return new[] { new Feature(phrase, 1.0) };
     }
 
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/FindPhrasesProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/FindPhrasesProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/FindPhrasesProblem.cs	(revision 12893)
@@ -169,4 +169,7 @@
       return new Feature[] {new Feature(phrase, 1.0),};
     }
+    public bool IsOptimalPhrase(string phrase) {
+      throw new NotImplementedException();
+    }
 
     public override string ToString() {
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/HardPalindromeProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/HardPalindromeProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/HardPalindromeProblem.cs	(revision 12893)
@@ -55,4 +55,7 @@
       throw new NotImplementedException();
     }
+    public bool IsOptimalPhrase(string phrase) {
+      throw new NotImplementedException();
+    }
 
     public IGrammar TreeBasedGPGrammar { get; private set; }
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/PalindromeProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/PalindromeProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/PalindromeProblem.cs	(revision 12893)
@@ -96,4 +96,7 @@
       throw new NotImplementedException();
     }
+    public bool IsOptimalPhrase(string phrase) {
+      throw new NotImplementedException();
+    }
 
     public IGrammar TreeBasedGPGrammar { get; private set; }
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/PermutationProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/PermutationProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/PermutationProblem.cs	(revision 12893)
@@ -47,4 +47,8 @@
       throw new NotImplementedException();
     }
+    public bool IsOptimalPhrase(string phrase) {
+      throw new NotImplementedException();
+    }
+
     public IGrammar TreeBasedGPGrammar { get; private set; }
     public string ConvertTreeToSentence(ISymbolicExpressionTree tree) {
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/PrimePolynomialProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/PrimePolynomialProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/PrimePolynomialProblem.cs	(revision 12893)
@@ -215,4 +215,8 @@
       return sb.ToString();
     }
+    public bool IsOptimalPhrase(string phrase) {
+      // throw new NotImplementedException();
+      return false; // TODO
+    }
 
 
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalPairProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalPairProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalPairProblem.cs	(revision 12893)
@@ -76,4 +76,7 @@
 
     }
+    public bool IsOptimalPhrase(string phrase) {
+      throw new NotImplementedException();
+    }
 
     public IGrammar TreeBasedGPGrammar { get; private set; }
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalPhraseSequenceProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalPhraseSequenceProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalPhraseSequenceProblem.cs	(revision 12893)
@@ -153,4 +153,7 @@
       return new Feature[] {new Feature(phrase, 1.0)};
     }
+    public bool IsOptimalPhrase(string phrase) {
+      throw new NotImplementedException();
+    }
 
     public IGrammar TreeBasedGPGrammar { get; private set; }
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalRoadProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalRoadProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalRoadProblem.cs	(revision 12893)
@@ -33,4 +33,7 @@
       return phrase;
     }
+    public bool IsOptimalPhrase(string phrase) {
+      throw new NotImplementedException();
+    }
 
     public IEnumerable<Feature> GetFeatures(string phrase)
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalSequenceProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalSequenceProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalSequenceProblem.cs	(revision 12893)
@@ -104,4 +104,7 @@
       throw new NotImplementedException();
     }
+    public bool IsOptimalPhrase(string phrase) {
+      throw new NotImplementedException();
+    }
 
     public IGrammar TreeBasedGPGrammar { get; private set; }
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalSymbolProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalSymbolProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalSymbolProblem.cs	(revision 12893)
@@ -51,4 +51,7 @@
       throw new NotImplementedException();
     }
+    public bool IsOptimalPhrase(string phrase) {
+      throw new NotImplementedException();
+    }
 
     public IGrammar TreeBasedGPGrammar { get; private set; }
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalTreeProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalTreeProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/RoyalTreeProblem.cs	(revision 12893)
@@ -263,4 +263,7 @@
       throw new NotImplementedException();
     }
+    public bool IsOptimalPhrase(string phrase) {
+      throw new NotImplementedException();
+    }
 
     public IGrammar TreeBasedGPGrammar { get; private set; }
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/SantaFeAntProblem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/SantaFeAntProblem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/SantaFeAntProblem.cs	(revision 12893)
@@ -30,4 +30,23 @@
     // here we use a modified grammar which has only one syntax tree for each sentence
 
+    public IEnumerable<string> OptimalSentences {
+      get {
+        return new string[]
+        {
+          "?(m)(ll?(m)(r))mr",
+          "?(m)(rr?(m)(l))ml",
+          "r?(m)(ll?(m)(r))m",
+          "l?(m)(rr?(m)(l))m",
+          "mr?(m)(ll?(m)(r))",
+          "ml?(m)(rr?(m)(l))",
+          "?(m)(ll?(m)(l))ml",
+          "?(m)(rr?(m)(r))mr",
+          "l?(m)(ll?(m)(l))m",
+          "r?(m)(rr?(m)(r))m",
+          "ml?(m)(ll?(m)(l))",
+          "mr?(m)(rr?(m)(r))",
+        };
+      }
+    }
 
     private readonly IGrammar grammar;
@@ -138,5 +157,8 @@
 
     public IEnumerable<Feature> GetFeatures(string phrase) {
-      yield return new Feature(phrase, 1.0);
+      for (int idx = 0; idx < 15; idx++) {
+        foreach (var t in Grammar.TerminalSymbols)
+          yield return new Feature(t.ToString(), phrase.Length > idx ? phrase[idx] == t ? 1 : 0 : 0);
+      }
       //var ant = new Ant(false);
       //int p = 0;
@@ -166,4 +188,10 @@
       }
     }
+    public bool IsOptimalPhrase(string phrase) {
+      var firstNonTerminalIdx = new Sequence(phrase).FirstNonTerminalIndex;
+      if (firstNonTerminalIdx == -1) firstNonTerminalIdx = phrase.Length;
+      return OptimalSentences.Any(s => s.Substring(0, firstNonTerminalIdx) == phrase.Substring(0, firstNonTerminalIdx));
+    }
+
   }
 
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/SymbolicRegressionPoly10Problem.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/SymbolicRegressionPoly10Problem.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/Problems/SymbolicRegressionPoly10Problem.cs	(revision 12893)
@@ -6,4 +6,5 @@
 using System.Linq;
 using System.Net;
+using System.Runtime.InteropServices;
 using System.Security;
 using System.Security.AccessControl;
@@ -60,9 +61,9 @@
     public string Name { get { return "SymbolicRegressionPoly10"; } }
 
-    public SymbolicRegressionPoly10Problem() {
+    public SymbolicRegressionPoly10Problem(int n = 500) {
       this.grammar = new Grammar(grammarString);
       this.TreeBasedGPGrammar = new Grammar(hlGrammarString);
 
-      this.N = 500;
+      this.N = n;
       this.x = new double[N][];
       this.y = new double[N];
@@ -99,7 +100,8 @@
     }
 
+    private static double[] erc = new double[] { 0.0, 1.0 };
     public double Evaluate(string sentence) {
       var interpreter = new ExpressionInterpreter();
-      return HeuristicLab.Common.Extensions.RSq(y, Enumerable.Range(0, N).Select(i => interpreter.Interpret(sentence, x[i])).ToArray());
+      return Math.Round(HeuristicLab.Common.Extensions.RSq(y, Enumerable.Range(0, N).Select(i => interpreter.Interpret(sentence, x[i], erc)).ToArray()), 3);
     }
 
@@ -166,5 +168,5 @@
 
 
-      if (phrase.EndsWith("E")) phrase = phrase.TrimEnd('*', '+', 'E');
+      //if (phrase.EndsWith("E")) phrase = phrase.TrimEnd('*', '+', 'E');
       //var len = 5;
       //var start = Math.Max(0, phrase.Length - len);
@@ -174,10 +176,18 @@
       //
 
-      var terms = phrase.Split('+');
-      foreach (var t in terms.Distinct()) yield return new Feature(t, 1.0);
-
-      for (int i = 0; i < terms.Length; i++) {
-        for (int j = i + 1; j < terms.Length; j++) {
-          yield return new Feature(terms[i] + " " + terms[j], 1.0);
+      //var terms = phrase.Split('+');
+      //foreach (var t in terms.Distinct()) yield return new Feature(t, 1.0);
+      //
+      //for (int i = 0; i < terms.Length; i++) {
+      //  for (int j = i + 1; j < terms.Length; j++) {
+      //    yield return new Feature(terms[i] + " " + terms[j], 1.0);
+      //  }
+      //}
+      var t = new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" };
+      for (int t0Idx = 0; t0Idx < t.Length - 1; t0Idx++) {
+        for (int t1Idx = t0Idx; t1Idx < t.Length; t1Idx++) {
+          var a = t[t0Idx] + "*" + t[t1Idx];
+          var b = t[t1Idx] + "*" + t[t0Idx];
+          yield return new Feature(a, phrase.Contains(a) || phrase.Contains(b) ? 1 : 0);
         }
       }
@@ -225,4 +235,165 @@
     }
 
+    private static string[][] optimalTerms = new string[][]
+      {
+        new string[] { "a*b","b*a",},
+        new string[] { "c*d","d*c",},
+        new string[] { "e*f","f*e",},
+        new string[] { "a*g*i","a*i*g","g*a*i","g*i*a","i*a*g","i*g*a"},
+        new string[] { "c*j*f","c*f*j","j*c*f","j*f*c","f*c*j","f*j*c"},
+      };
+
+    private static int[][] permute5 = new int[][]
+      {
+        new int[] { 4, 3, 2, 0, 1 },
+        new int[] { 4, 3, 2, 1, 0 },
+        new int[] { 4, 3, 0, 2, 1 },
+        new int[] { 4, 3, 1, 2, 0 },
+        new int[] { 4, 3, 0, 1, 2 },
+        new int[] { 4, 3, 1, 0, 2 },
+        new int[] { 4, 2, 3, 0, 1 },
+        new int[] { 4, 2, 3, 1, 0 },
+        new int[] { 4, 0, 3, 2, 1 },
+        new int[] { 4, 1, 3, 2, 0 },
+        new int[] { 4, 0, 3, 1, 2 },
+        new int[] { 4, 1, 3, 0, 2 },
+        new int[] { 4, 2, 0, 3, 1 },
+        new int[] { 4, 2, 1, 3, 0 },
+        new int[] { 4, 0, 2, 3, 1 },
+        new int[] { 4, 1, 2, 3, 0 },
+        new int[] { 4, 0, 1, 3, 2 },
+        new int[] { 4, 1, 0, 3, 2 },
+        new int[] { 4, 2, 0, 1, 3 },
+        new int[] { 4, 2, 1, 0, 3 },
+        new int[] { 4, 0, 2, 1, 3 },
+        new int[] { 4, 1, 2, 0, 3 },
+        new int[] { 4, 0, 1, 2, 3 },
+        new int[] { 4, 1, 0, 2, 3 },
+        new int[] { 3, 4, 2, 0, 1 },
+        new int[] { 3, 4, 2, 1, 0 },
+        new int[] { 3, 4, 0, 2, 1 },
+        new int[] { 3, 4, 1, 2, 0 },
+        new int[] { 3, 4, 0, 1, 2 },
+        new int[] { 3, 4, 1, 0, 2 },
+        new int[] { 2, 4, 3, 0, 1 },
+        new int[] { 2, 4, 3, 1, 0 },
+        new int[] { 0, 4, 3, 2, 1 },
+        new int[] { 1, 4, 3, 2, 0 },
+        new int[] { 0, 4, 3, 1, 2 },
+        new int[] { 1, 4, 3, 0, 2 },
+        new int[] { 2, 4, 0, 3, 1 },
+        new int[] { 2, 4, 1, 3, 0 },
+        new int[] { 0, 4, 2, 3, 1 },
+        new int[] { 1, 4, 2, 3, 0 },
+        new int[] { 0, 4, 1, 3, 2 },
+        new int[] { 1, 4, 0, 3, 2 },
+        new int[] { 2, 4, 0, 1, 3 },
+        new int[] { 2, 4, 1, 0, 3 },
+        new int[] { 0, 4, 2, 1, 3 },
+        new int[] { 1, 4, 2, 0, 3 },
+        new int[] { 0, 4, 1, 2, 3 },
+        new int[] { 1, 4, 0, 2, 3 },
+        new int[] { 3, 2, 4, 0, 1 },
+        new int[] { 3, 2, 4, 1, 0 },
+        new int[] { 3, 0, 4, 2, 1 },
+        new int[] { 3, 1, 4, 2, 0 },
+        new int[] { 3, 0, 4, 1, 2 },
+        new int[] { 3, 1, 4, 0, 2 },
+        new int[] { 2, 3, 4, 0, 1 },
+        new int[] { 2, 3, 4, 1, 0 },
+        new int[] { 0, 3, 4, 2, 1 },
+        new int[] { 1, 3, 4, 2, 0 },
+        new int[] { 0, 3, 4, 1, 2 },
+        new int[] { 1, 3, 4, 0, 2 },
+        new int[] { 2, 0, 4, 3, 1 },
+        new int[] { 2, 1, 4, 3, 0 },
+        new int[] { 0, 2, 4, 3, 1 },
+        new int[] { 1, 2, 4, 3, 0 },
+        new int[] { 0, 1, 4, 3, 2 },
+        new int[] { 1, 0, 4, 3, 2 },
+        new int[] { 2, 0, 4, 1, 3 },
+        new int[] { 2, 1, 4, 0, 3 },
+        new int[] { 0, 2, 4, 1, 3 },
+        new int[] { 1, 2, 4, 0, 3 },
+        new int[] { 0, 1, 4, 2, 3 },
+        new int[] { 1, 0, 4, 2, 3 },
+        new int[] { 3, 2, 0, 4, 1 },
+        new int[] { 3, 2, 1, 4, 0 },
+        new int[] { 3, 0, 2, 4, 1 },
+        new int[] { 3, 1, 2, 4, 0 },
+        new int[] { 3, 0, 1, 4, 2 },
+        new int[] { 3, 1, 0, 4, 2 },
+        new int[] { 2, 3, 0, 4, 1 },
+        new int[] { 2, 3, 1, 4, 0 },
+        new int[] { 0, 3, 2, 4, 1 },
+        new int[] { 1, 3, 2, 4, 0 },
+        new int[] { 0, 3, 1, 4, 2 },
+        new int[] { 1, 3, 0, 4, 2 },
+        new int[] { 2, 0, 3, 4, 1 },
+        new int[] { 2, 1, 3, 4, 0 },
+        new int[] { 0, 2, 3, 4, 1 },
+        new int[] { 1, 2, 3, 4, 0 },
+        new int[] { 0, 1, 3, 4, 2 },
+        new int[] { 1, 0, 3, 4, 2 },
+        new int[] { 2, 0, 1, 4, 3 },
+        new int[] { 2, 1, 0, 4, 3 },
+        new int[] { 0, 2, 1, 4, 3 },
+        new int[] { 1, 2, 0, 4, 3 },
+        new int[] { 0, 1, 2, 4, 3 },
+        new int[] { 1, 0, 2, 4, 3 },
+        new int[] { 3, 2, 0, 1, 4 },
+        new int[] { 3, 2, 1, 0, 4 },
+        new int[] { 3, 0, 2, 1, 4 },
+        new int[] { 3, 1, 2, 0, 4 },
+        new int[] { 3, 0, 1, 2, 4 },
+        new int[] { 3, 1, 0, 2, 4 },
+        new int[] { 2, 3, 0, 1, 4 },
+        new int[] { 2, 3, 1, 0, 4 },
+        new int[] { 0, 3, 2, 1, 4 },
+        new int[] { 1, 3, 2, 0, 4 },
+        new int[] { 0, 3, 1, 2, 4 },
+        new int[] { 1, 3, 0, 2, 4 },
+        new int[] { 2, 0, 3, 1, 4 },
+        new int[] { 2, 1, 3, 0, 4 },
+        new int[] { 0, 2, 3, 1, 4 },
+        new int[] { 1, 2, 3, 0, 4 },
+        new int[] { 0, 1, 3, 2, 4 },
+        new int[] { 1, 0, 3, 2, 4 },
+        new int[] { 2, 0, 1, 3, 4 },
+        new int[] { 2, 1, 0, 3, 4 },
+        new int[] { 0, 2, 1, 3, 4 },
+        new int[] { 1, 2, 0, 3, 4 },
+        new int[] { 0, 1, 2, 3, 4 },
+        new int[] { 1, 0, 2, 3, 4 },
+      };
+
+
+    private static HashSet<string>[] optimalSentences;
+    static SymbolicRegressionPoly10Problem() {
+      optimalSentences = Enumerable.Range(0, 24).Select(i => new HashSet<string>()).ToArray();
+
+      foreach (var t0Idx in new[] { 0, 1 })
+        foreach (var t1Idx in new[] { 0, 1 })
+          foreach (var t2Idx in new[] { 0, 1 })
+            foreach (var t3Idx in new[] { 0, 1, 2, 3, 4, 5 })
+              foreach (var t4Idx in new[] { 0, 1, 2, 3, 4, 5 }) {
+                foreach (var p in permute5) {
+                  int[] idx = new int[] { t0Idx, t1Idx, t2Idx, t3Idx, t4Idx };
+                  optimalSentences[23].Add(string.Join("+", p.Select(pi => optimalTerms[pi][idx[pi]])));
+                }
+              }
+      for (int i = 0; i < 23; i += 2) {
+        var newElements = new HashSet<string>();
+        foreach (var sentence in optimalSentences[23]) {
+          newElements.Add(sentence.Substring(0, i) + "E");
+        }
+        foreach (var e in newElements) optimalSentences[i + 1].Add(e);
+      }
+    }
+
+    public bool IsOptimalPhrase(string phrase) {
+      return optimalSentences[phrase.Length].Contains(phrase);
+    }
+
     private void TreeToSentence(ISymbolicExpressionTreeNode treeNode, StringBuilder sb) {
       if (treeNode.SubtreeCount == 0) {
Index: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/SentenceSetStatistics.cs
===================================================================
--- branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/SentenceSetStatistics.cs	(revision 12876)
+++ branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/SentenceSetStatistics.cs	(revision 12893)
@@ -23,4 +23,8 @@
     public SentenceSetStatistics(double bestKnownQuality = 1.0) {
       this.bestKnownQuality = bestKnownQuality;
+      Clear();
+    }
+
+    public void Clear() {
       BestSentenceQuality = double.NegativeInfinity;
       BestSentence = string.Empty;
@@ -55,5 +59,5 @@
       BestSentenceIndex, TrimToSize(BestSentence, 30),
       LastSentenceQuality, TrimToSize(LastSentence, 20)
-      //LastSentenceQuality, TrimToSize(LastSentence, 20)
+        //LastSentenceQuality, TrimToSize(LastSentence, 20)
      );
     }
