Index: /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction-3.3.csproj
===================================================================
--- /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction-3.3.csproj	(revision 12966)
+++ /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction-3.3.csproj	(revision 12967)
@@ -179,4 +179,5 @@
     </Compile>
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="QualityFunctions\SparseLinearApproximateStateValueFunction.cs" />
     <Compile Include="QualityFunctions\GbtApproximateStateValueFunction.cs" />
     <Compile Include="QualityFunctions\TabularStateValueFunctionBase.cs" />
@@ -184,4 +185,5 @@
     <Compile Include="QualityFunctions\TabularMaxStateValueFunction.cs" />
     <Compile Include="SearchTree.cs" />
+    <Compile Include="StateFunctions\SymbolicExpressionTermsStateFunction.cs" />
     <Compile Include="StateFunctions\ParentChildStateFunction.cs" />
     <Compile Include="StateFunctions\DefaultStateFunction.cs" />
Index: /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/Policies/BoltzmannExplorationSymbolicExpressionConstructionPolicy.cs
===================================================================
--- /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/Policies/BoltzmannExplorationSymbolicExpressionConstructionPolicy.cs	(revision 12966)
+++ /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/Policies/BoltzmannExplorationSymbolicExpressionConstructionPolicy.cs	(revision 12967)
@@ -20,9 +20,9 @@
     }
 
-    public ITabularStateValueFunction StateValueFunction {
+    public IStateValueFunction StateValueFunction {
       get {
-        return ((IValueParameter<ITabularStateValueFunction>)Parameters["Quality function"]).Value;
+        return ((IValueParameter<IStateValueFunction>)Parameters["Quality function"]).Value;
       }
-      set { ((IValueParameter<ITabularStateValueFunction>)Parameters["Quality function"]).Value = value; }
+      set { ((IValueParameter<IStateValueFunction>)Parameters["Quality function"]).Value = value; }
     }
 
@@ -39,13 +39,9 @@
       : base() {
       Parameters.Add(new FixedValueParameter<DoubleValue>("Beta", "The weighting factor beta", new DoubleValue(1.0)));
-      Parameters.Add(new ValueParameter<ITabularStateValueFunction>("Quality function", "The quality function to use", new TabularAvgStateValueFunction()));
+      Parameters.Add(new ValueParameter<IStateValueFunction>("Quality function", "The quality function to use", new TabularAvgStateValueFunction()));
     }
 
     protected sealed override int Select(IReadOnlyList<object> followStates, IRandom random) {
       var idxs = Enumerable.Range(0, followStates.Count);
-      // find best action
-      if (followStates.Any(s => StateValueFunction.Tries(s) == 0)) {
-        return idxs.Where(idx => StateValueFunction.Tries(followStates[idx]) == 0).SampleRandom(random);
-      }
 
       // windowing
@@ -72,5 +68,5 @@
     }
 
-    public override IDeepCloneable Clone(HeuristicLab.Common.Cloner cloner) {
+    public override IDeepCloneable Clone(Cloner cloner) {
       return new BoltzmannExplorationSymbolicExpressionConstructionPolicy(this, cloner);
     }
Index: /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/QualityFunctions/SparseLinearApproximateStateValueFunction.cs
===================================================================
--- /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/QualityFunctions/SparseLinearApproximateStateValueFunction.cs	(revision 12967)
+++ /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/QualityFunctions/SparseLinearApproximateStateValueFunction.cs	(revision 12967)
@@ -0,0 +1,77 @@
+﻿using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Parameters;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction {
+  [StorableClass]
+  public class SparseLinearApproximateStateValueFunction : ParameterizedNamedItem, IStateValueFunction, IStatefulItem {
+
+    private readonly Dictionary<string, double> w = new Dictionary<string, double>();
+
+    public IStateFunction StateFunction {
+      get {
+        return ((IValueParameter<IStateFunction>)Parameters["Feature function"]).Value;
+      }
+      private set { ((IValueParameter<IStateFunction>)Parameters["Feature function"]).Value = value; }
+    }
+
+    public SparseLinearApproximateStateValueFunction()
+      : base() {
+      Parameters.Add(new ValueParameter<IStateFunction>("Feature function", "The function that generates features for value approximation"));
+    }
+
+    public double Value(object state) {
+      var features = state as IEnumerable<Tuple<string, double>>;
+      if (features == null) throw new InvalidProgramException();
+
+      return features.Select(t => t.Item2 * GetWeight(t.Item1)).Sum();
+    }
+
+    private double GetWeight(string featureId) {
+      double w;
+      this.w.TryGetValue(featureId, out w);
+      return w;
+    }
+
+    public void Update(object state, double observedQuality) {
+      var features = state as IEnumerable<Tuple<string, double>>;
+      if (features == null) throw new InvalidProgramException();
+
+      var delta = observedQuality - Value(state);
+      const double alpha = 0.01;
+
+      foreach (var t in features) {
+        var featureId = t.Item1;
+        var w = t.Item2;
+
+        this.w[featureId] = GetWeight(featureId) + alpha * delta;
+      }
+    }
+
+    #region item
+    [StorableConstructor]
+    protected SparseLinearApproximateStateValueFunction(bool deserializing) : base(deserializing) { }
+    protected SparseLinearApproximateStateValueFunction(SparseLinearApproximateStateValueFunction original, Cloner cloner)
+      : base(original, cloner) {
+      w = new Dictionary<string, double>(original.w);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SparseLinearApproximateStateValueFunction(this, cloner);
+    }
+    #endregion
+
+    public void InitializeState() {
+      w.Clear();
+    }
+
+    public void ClearState() {
+      w.Clear();
+    }
+  }
+}
Index: /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/StateFunctions/SymbolicExpressionTermsStateFunction.cs
===================================================================
--- /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/StateFunctions/SymbolicExpressionTermsStateFunction.cs	(revision 12967)
+++ /branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/StateFunctions/SymbolicExpressionTermsStateFunction.cs	(revision 12967)
@@ -0,0 +1,51 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using System.Text;
+using System.Threading.Tasks;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction {
+  [StorableClass]
+  [Item("SymbolicExpressionTermsStateFunction", "")]
+  public class SymbolicExpressionTermsStateFunction : Item, IStateFunction {
+    public SymbolicExpressionTermsStateFunction()
+      : base() {
+    }
+
+    public object CreateState(ISymbolicExpressionTreeNode root, List<ISymbol> actions, ISymbolicExpressionTreeNode parentNode, int childIdx) {
+      var terms = new List<Tuple<string, double>>();
+      var formatter = new HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.SymbolicExpressionTreeStringFormatter();
+      var t = new SymbolicExpressionTree();
+      terms.Add(Tuple.Create("const", 1.0));
+      foreach (var n in root.IterateNodesPrefix()) {
+        if (n.Symbol is StartSymbol && n.SubtreeCount > 0) {
+          t.Root = n;
+          terms.Add(Tuple.Create("start-" + n.GetSubtree(0).Symbol.Name, 1.0));
+        } else if (n.Symbol.Name == "+" || n.Symbol.Name == "-") {
+          foreach (var child in n.Subtrees.OrderBy(c => c.Symbol.Name)) {
+            if (child.Symbol.Name == "+" || n.Symbol.Name == "-") continue; // skip (+ (+ ...) ...), only non-decomposable terms are relevant for us
+            t.Root = child;
+            terms.Add(Tuple.Create(formatter.Format(t), 1.0));
+          }
+        }
+      }
+      return terms;
+    }
+
+    #region item
+    [StorableConstructor]
+    protected SymbolicExpressionTermsStateFunction(bool deserializing) : base(deserializing) { }
+    protected SymbolicExpressionTermsStateFunction(SymbolicExpressionTermsStateFunction original, Cloner cloner)
+      : base(original, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new SymbolicExpressionTermsStateFunction(this, cloner);
+    }
+    #endregion
+  }
+}
