Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GrammaticalOptimization-gkr/HeuristicLab.Problems.GrammaticalOptimization/PartialExpressionInterpreter.cs @ 12298

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

#2283: experiments with q-learning

File size: 4.8 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Security.Policy;
5using HeuristicLab.Common;
6
7namespace HeuristicLab.Problems.GrammaticalOptimization {
8  public class PartialExpressionInterpreter {
9    private static readonly double[] emptyErc = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
10    private string sentence;
11    private int syIdx;
12    private HashSet<double> intermediateValues = new HashSet<double>();
13    private Stack<double> stack = new Stack<double>();
14    // interprets sentences from L(G(Expr)):
15    // Expr -> Term { ('+' | '-' | '^' ) Term }
16    // Term -> Fact { ('*' | '%') Fact }
17    // Fact -> '!' Expr | '(' Expr ')' | Var | const
18    // Var -> 'a'..'z'
19    // const -> '0' .. '9'
20
21    // uses protected division symbol %
22    // constants are Koza-style ephemeral random constants (ERC). for now we only allow up to 10 constants.
23    // The constant symbols '0' .. '9' are treated as ERC indices
24
25    public IEnumerable<double> Interpret(string sentence, double[] vars) {
26      return Interpret(sentence, vars, emptyErc);
27    }
28
29    public IEnumerable<double> Interpret(string sentence, double[] vars, double[] erc) {
30      InitLex(sentence);
31      intermediateValues.Clear();
32      stack.Clear();
33      Expr(vars, erc);
34      return intermediateValues;
35    }
36
37
38    private void InitLex(string sentence) {
39      this.sentence = sentence;
40      this.syIdx = 0;
41    }
42
43    private char CurSy() {
44      if (syIdx >= sentence.Length) return '\0';
45      return sentence[syIdx];
46    }
47    private void NewSy() {
48      if (syIdx < sentence.Length) syIdx++;
49    }
50
51    // helper for xor
52    private double Not(double x) {
53      return DoubleExtensions.IsAlmost(x, 0) ? 1.0 : 0.0;
54    }
55
56    private bool Expr(double[] d, double[] erc) {
57      if (!Term(d, erc)) return false;
58      var curSy = CurSy();
59      while (curSy == '+' || curSy == '-' || curSy == '^') {
60        if (curSy == '+') {
61          NewSy();
62          if (!Term(d, erc)) { return false; }
63          stack.Push(stack.Pop() + stack.Pop());
64          intermediateValues.Add(stack.Peek());
65        } else if (curSy == '-') {
66          NewSy();
67          if (!Term(d, erc)) {  return false; }
68          stack.Push(-stack.Pop() + stack.Pop());
69          intermediateValues.Add(stack.Peek());
70        } else {
71          NewSy();
72          if (!Term(d, erc)) { return false; }
73          var e = stack.Pop();
74          var r = stack.Pop();
75          stack.Push(Not(r) * e + r * Not(e)); // xor = (!x AND y) OR (x AND !y)
76          intermediateValues.Add(stack.Peek());
77        }
78        curSy = CurSy();
79      }
80      return true;
81    }
82
83    private bool Term(double[] d, double[] erc) {
84      if (!Fact(d, erc)) { return false; }
85      var curSy = CurSy();
86      while (curSy == '*' || curSy == '%') {
87        if (curSy == '*') {
88          NewSy();
89          if (!Fact(d, erc)) { return false; }
90          stack.Push(stack.Pop() * stack.Pop());
91          intermediateValues.Add(stack.Peek());
92        } else {
93          NewSy();
94          if (!Fact(d, erc)) { return false; }
95          var nom = stack.Pop();
96          var r = stack.Pop();
97          if (HeuristicLab.Common.Extensions.IsAlmost(nom, 0.0)) nom = 1.0;
98          stack.Push(r / nom);
99          intermediateValues.Add(stack.Peek());
100        }
101        curSy = CurSy();
102      }
103      return true;
104    }
105
106    private bool Fact(double[] d, double[] erc) {
107      var curSy = CurSy();
108      if (curSy == '!') {
109        //NewSy();
110        //if (!Expr(d, erc)) { stack.Push(-7.0); return false; }
111        //stack.Push(Not(stack.Pop()));
112      } else if (curSy == '(') {
113        //NewSy();
114        //if (!Expr(d, erc)) { stack.Push(-8.0); return false; }
115        //if (CurSy() != ')') throw new ArgumentException();
116        //NewSy();
117      } else if (curSy >= 'a' && curSy <= 'z') {
118        int o = (byte)curSy - (byte)'a';
119        //int o = Convert.ToByte(CurSy()) - Convert.ToByte('a');
120        if (o < 0 || o >= d.Length) throw new ArgumentException();
121        stack.Push(d[o]);
122        intermediateValues.Add(stack.Peek());
123        NewSy();
124      } else if (curSy == '/') {
125        // /-symbol is used in the expressionextender to represent inverse (1/x).
126        // this is necessary because we also use symbols 0..9 as indices for ERCs
127        //NewSy();
128        //if (!Fact(d, erc)) { stack.Push(-9.0); return false; }
129        //stack.Push(1.0 / stack.Pop());
130      } else if (curSy >= '0' && curSy <= '9') {
131        int o = (byte)curSy - (byte)'0';
132        //int o = Convert.ToByte(CurSy()) - Convert.ToByte('a');
133        if (o < 0 || o >= 10) throw new ArgumentException();
134        stack.Push(erc[o]);
135        intermediateValues.Add(stack.Peek());
136        NewSy();
137      } else {
138        return false;
139      }
140      return true;
141    }
142
143  }
144}
Note: See TracBrowser for help on using the repository browser.