Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2283 added missing files (forgotten in the branch)

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