Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Algorithms.IteratedSentenceConstruction/HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction/3.3/Policies/SymbolicExpressionConstructionPolicyBase.cs @ 12923

Last change on this file since 12923 was 12923, checked in by gkronber, 9 years ago

#2471

  • refactoring to use state value function V(s) instead of state/action value function Q(s,a)
  • added test case for artificial ant problem
File size: 6.9 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Diagnostics.Contracts;
4using System.Linq;
5using System.Net.NetworkInformation;
6using System.Text;
7using System.Threading.Tasks;
8using HeuristicLab.Common;
9using HeuristicLab.Core;
10using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
11using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
12
13namespace HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction {
14  // this class is a base class for symbolic expression construction policies
15  // it filters allowed actions based on tree length constraint
16  // and keeps all visited derivation paths in memory to prevent sampling of duplicates
17  [StorableClass]
18  public abstract class SymbolicExpressionConstructionPolicyBase : ParameterizedNamedItem, ISymbolicExpressionConstructionPolicy {
19    [Storable]
20    public SymbolicExpressionTreeProblem Problem { get; private set; }
21    [Storable]
22    public IRandom Random { get; private set; }
23    private SearchTree<ISymbol> searchTree; // tree of replacement symbols
24
25    private class Slot {
26      public ISymbolicExpressionTreeNode parent;
27      public int childIdx;
28      public int minSize;
29    }
30
31    [StorableHook(HookType.AfterDeserialization)]
32    private void AfterDeserialization() {
33      searchTree = new SearchTree<ISymbol>();
34    }
35    protected SymbolicExpressionConstructionPolicyBase(SymbolicExpressionConstructionPolicyBase original, Cloner cloner)
36      : base(original, cloner) {
37      this.Problem = cloner.Clone(original.Problem);
38      this.Random = cloner.Clone(original.Random);
39
40      // search tree is not cloned or stored
41      searchTree = new SearchTree<ISymbol>();
42    }
43
44    [StorableConstructor]
45    protected SymbolicExpressionConstructionPolicyBase(bool deserializing) : base(deserializing) { }
46
47    protected SymbolicExpressionConstructionPolicyBase() {
48
49    }
50
51    public virtual void Initialize(SymbolicExpressionTreeProblem problem, IRandom random) {
52      this.Problem = problem;
53      this.Random = random;
54      this.searchTree = new SearchTree<ISymbol>(); // represents all realized actionSequences as a prefix tree
55    }
56
57    public ISymbolicExpressionTree Sample(out IEnumerable<object> stateSequence) {
58      var actions = new List<ISymbol>();
59      var states = new List<object>();
60
61      var openSlots = new Stack<Slot>();
62      var g = Problem.Encoding.Grammar;
63      var root = g.ProgramRootSymbol.CreateTreeNode();
64      int maxDepth = Problem.Encoding.TreeDepthParameter.Value.Value;
65      int maxLen = Problem.Encoding.TreeLengthParameter.Value.Value;
66
67
68      Contract.Assert(Problem.Encoding.FunctionDefinitions == 0);
69      openSlots.Push(new Slot() { parent = root, childIdx = 0, minSize = g.GetMinimumExpressionLength(root.Symbol) - 1 }); // at least two nodes are necessary below root
70
71      // tree size lower bound is the current tree size + the sum of the minimal size for all open slots
72      int treeSize = 1;
73
74      searchTree.ResetPosition();
75
76      while (openSlots.Any()) {
77        var next = openSlots.Pop();
78        var parent = next.parent;
79        var childIdx = next.childIdx;
80
81        if (searchTree.IsLeafNode()) {
82          var allowedChildSymbols = g.GetAllowedChildSymbols(parent.Symbol, childIdx)
83            .Where(a => a.Enabled)
84            .Where(a => treeSize + g.GetMinimumExpressionLength(a) + openSlots.Select(e => e.minSize).Sum() <= maxLen);
85
86          searchTree.ExpandCurrentNode(allowedChildSymbols);
87        }
88
89        if (!searchTree.ChildValues.Any()) {
90          throw new InvalidProgramException(string.Format("Couldn't construct a valid tree of maximum length {0} or all possible trees have been visited", maxLen));
91        }
92
93        var alternatives = searchTree.ChildValues.ToArray(); // TODO perf
94
95        // generate follow states
96        var followStates = new object[alternatives.Length];
97        for (int i = 0; i < followStates.Length; i++) {
98          // temporarily make the replacement and create the followState object
99          var childNode = alternatives[i].CreateTreeNode();
100          if (childNode.HasLocalParameters) {
101            throw new NotSupportedException("Symbols with parameters are not supported by construction policies for symbolic expressions. " +
102                                            "Try to reformulate the problem so that only discrete actions are necessary");
103            // childNode.ResetLocalParameters(Random);
104          }
105          parent.AddSubtree(childNode);
106          actions.Add(alternatives[i]);
107
108          // states might be defined differently be different policies
109          // this allows policies to calculate the state as a function of the current tree and the position where it is changed,
110          // or as a function of the list of actions so far,
111          // or as a function of both
112          followStates[i] = CreateState(root, actions, parent, childIdx);
113
114          // roll back the change
115          parent.RemoveSubtree(parent.SubtreeCount - 1);
116          actions.RemoveAt(actions.Count - 1);
117        }
118
119        // select one of the follow states and prepare for the next step
120        var selectedIdx = Select(followStates, Random);
121        actions.Add(alternatives[selectedIdx]);
122        states.Add(followStates[selectedIdx]);
123
124        {
125          // and add child node to parent
126          var childNode = alternatives[selectedIdx].CreateTreeNode();
127
128          Contract.Assert(parent.SubtreeCount == childIdx); // enforce left-canonical derivation
129          parent.AddSubtree(childNode);
130          treeSize++;
131
132          // push new slots
133          for (int chIdx = g.GetMinimumSubtreeCount(childNode.Symbol) - 1; chIdx >= 0; chIdx--) {
134            int minForChild = g.GetAllowedChildSymbols(childNode.Symbol, chIdx)
135              .Min(a => g.GetMinimumExpressionLength(a)); // min length of all possible alts for the slot
136            openSlots.Push(new Slot() { parent = childNode, childIdx = chIdx, minSize = minForChild });
137          }
138        }
139
140        // if this is the last slot we never have to revisit selectedIdx
141        if (!openSlots.Any()) {
142          searchTree.RemoveBranch(alternatives[selectedIdx]);
143        } else {
144          searchTree.Follow(alternatives[selectedIdx]);
145        }
146      }
147
148      stateSequence = states;
149      return new SymbolicExpressionTree(root);
150    }
151
152    /// <summary>
153    /// Choose one of the follow states
154    /// </summary>
155    /// <param name="followStates"></param>
156    /// <param name="random"></param>
157    /// <returns>The index of the selected follow state</returns>
158    protected abstract int Select(IReadOnlyList<object> followStates, IRandom random);
159    public abstract void Update(IEnumerable<object> stateSequence, double quality);
160
161    protected abstract object CreateState(ISymbolicExpressionTreeNode root, List<ISymbol> actions, ISymbolicExpressionTreeNode parent, int childIdx);
162  }
163}
Note: See TracBrowser for help on using the repository browser.