Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Algorithms.GrammaticalOptimization/SequentialDecisionPolicies/GenericGrammarPolicy.cs @ 12803

Last change on this file since 12803 was 12290, checked in by gkronber, 10 years ago

#2283 created a new branch to separate development from aballeit

File size: 6.0 KB
RevLine 
[11770]1using System;
2using System.Collections.Generic;
[11806]3using System.Diagnostics;
[11770]4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7using HeuristicLab.Common;
8using HeuristicLab.Problems.GrammaticalOptimization;
9
10namespace HeuristicLab.Algorithms.Bandits.GrammarPolicies {
11  // this represents grammar policies that use one of the available bandit policies for state selection
[11806]12  // any bandit policy can be used to select actions for states
13  // a separate datastructure is used to store visited states and to prevent revisiting of states
14  public sealed class GenericGrammarPolicy : IGrammarPolicy {
15    private Dictionary<string, IBanditPolicyActionInfo> stateInfo; // stores the necessary information for bandit policies for each state (=canonical phrase)
16    private HashSet<string> done;
17    private readonly bool useCanonicalPhrases;
[11770]18    private readonly IProblem problem;
19    private readonly IBanditPolicy banditPolicy;
20
[11806]21    public GenericGrammarPolicy(IProblem problem, IBanditPolicy banditPolicy, bool useCanonicalPhrases = false) {
22      this.useCanonicalPhrases = useCanonicalPhrases;
[11770]23      this.problem = problem;
24      this.banditPolicy = banditPolicy;
25      this.stateInfo = new Dictionary<string, IBanditPolicyActionInfo>();
[11806]26      this.done = new HashSet<string>();
[11770]27    }
28
[11806]29    private IBanditPolicyActionInfo[] activeAfterStates; // don't allocate each time
30    private int[] actionIndexMap; // don't allocate each time
31
[11793]32    public bool TrySelect(Random random, string curState, IEnumerable<string> afterStates, out int selectedStateIdx) {
33      // fail if all states are done (corresponding state infos are disabled)
[11806]34      if (afterStates.All(s => Done(s))) {
[11770]35        // fail because all follow states have already been visited => also disable the current state (if we can be sure that it has been fully explored)
[11806]36        MarkAsDone(curState);
[11792]37
[11793]38        selectedStateIdx = -1;
[11770]39        return false;
40      }
41
[11806]42      // determine active actions (not done yet) and create an array to map the selected index back to original actions
43      if (activeAfterStates == null || activeAfterStates.Length < afterStates.Count()) {
44        activeAfterStates = new IBanditPolicyActionInfo[afterStates.Count()];
45        actionIndexMap = new int[afterStates.Count()];
46      }
47      var idx = 0; int originalIdx = 0;
48      foreach (var afterState in afterStates) {
49        if (!Done(afterState)) {
50          activeAfterStates[idx] = GetStateInfo(afterState);
51          actionIndexMap[idx] = originalIdx;
52          idx++;
53        }
54        originalIdx++;
55      }
[11770]56
[11806]57      selectedStateIdx = actionIndexMap[banditPolicy.SelectAction(random, activeAfterStates.Take(idx))];
58
[11770]59      return true;
60    }
61
[11806]62
63
[11793]64    private IBanditPolicyActionInfo GetStateInfo(string state) {
[11792]65      var s = CanonicalState(state);
[11770]66      IBanditPolicyActionInfo info;
67      if (!stateInfo.TryGetValue(s, out info)) {
68        info = banditPolicy.CreateActionInfo();
69        stateInfo[s] = info;
70      }
71      return info;
72    }
73
[11806]74    public void UpdateReward(IEnumerable<string> stateTrajectory, double reward) {
[11799]75      foreach (var state in stateTrajectory) {
76        GetStateInfo(state).UpdateReward(reward);
[11770]77
[11799]78        // only the last state can be terminal
79        if (problem.Grammar.IsTerminal(state)) {
[11806]80          MarkAsDone(state);
[11799]81        }
[11770]82      }
83    }
84
[11806]85
86    public void Reset() {
[11770]87      stateInfo.Clear();
[11806]88      done.Clear();
[11770]89    }
90
[11793]91    public int GetTries(string state) {
[11792]92      var s = CanonicalState(state);
[11770]93      if (stateInfo.ContainsKey(s)) return stateInfo[s].Tries;
94      else return 0;
95    }
96
[11793]97    public double GetValue(string state) {
[11792]98      var s = CanonicalState(state);
[11770]99      if (stateInfo.ContainsKey(s)) return stateInfo[s].Value;
100      else return 0.0; // TODO: check alternatives
101    }
102
[11806]103    // the canonical states for the value function (banditInfos) and the done set must be distinguished
104    // sequences of different length could have the same canonical representation and can have the same value (banditInfo)
[12290]105    // however, if the canonical representation of a state is shorter then we must not mark the canonical state as done when all possible derivations from the initial state have been explored
[11806]106    // eg. in the ant problem the canonical representation for ...lllA is ...rA
107    // even though all possible derivations (of limited length) of lllA have been visited we must not mark the state rA as done
108    private void MarkAsDone(string state) {
109      var s = CanonicalState(state);
110      // when the lengths of the canonical string and the original string are the same we also disable the actions
111      // always disable terminals
112      Debug.Assert(s.Length <= state.Length);
113      if (s.Length == state.Length || problem.Grammar.IsTerminal(state)) {
114        Debug.Assert(!done.Contains(s));
115        done.Add(s);
116      } else {
117        // for non-terminals where the canonical string is shorter than the original string we can only disable the canonical representation for all states in the same level
118        Debug.Assert(!done.Contains(s + state.Length));
119        done.Add(s + state.Length); // encode the original length of the state, states in the same level of the tree are treated as equivalent
120      }
121    }
122
123    // symmetric to MarkDone
124    private bool Done(string state) {
125      var s = CanonicalState(state);
126      if (s.Length == state.Length || problem.Grammar.IsTerminal(state)) {
127        return done.Contains(s);
128      } else {
129        // it is not necessary to visit states if the canonical representation has already been fully explored
130        if (done.Contains(s)) return true;
131        if (done.Contains(s + state.Length)) return true;
132        for (int i = 1; i < state.Length; i++) {
133          if (done.Contains(s + i)) return true;
134        }
135        return false;
136      }
137    }
138
139    private string CanonicalState(string state) {
140      if (useCanonicalPhrases) {
[11799]141        return problem.CanonicalRepresentation(state);
[11792]142      } else
[11793]143        return state;
[11770]144    }
145  }
146}
Note: See TracBrowser for help on using the repository browser.