source: stable/HeuristicLab.Algorithms.DataAnalysis/3.4/MctsSymbolicRegression/SymbolicExpressionGenerator.cs @ 15060

Last change on this file since 15060 was 15060, checked in by gkronber, 2 years ago

#2581: merged r13645,r13648,r13650,r13651,r13652,r13654,r13657,r13658,r13659,r13661,r13662,r13669,r13708,r14142 from trunk to stable (to be deleted in the next commit)

File size: 7.1 KB
RevLine 
[13645]1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21using System;
22using System.Diagnostics.Contracts;
23using System.Linq;
24
25using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
26using HeuristicLab.Problems.DataAnalysis.Symbolic;
27
28namespace HeuristicLab.Algorithms.DataAnalysis.MctsSymbolicRegression {
29
30  // translates byte code to a symbolic expression tree
31  internal class SymbolicExpressionTreeGenerator {
32    const int MaxStackSize = 100;
33    private readonly ISymbolicExpressionTreeNode[] stack;
34    private readonly ConstantTreeNode const0;
35    private readonly ConstantTreeNode const1;
36    private readonly Addition addSy;
37    private readonly Multiplication mulSy;
38    private readonly Exponential expSy;
39    private readonly Logarithm logSy;
40    private readonly Division divSy;
41    private readonly VariableTreeNode varNode;
42    private readonly string[] variableNames;
43    private readonly StartSymbol startSy;
44    private readonly ProgramRootSymbol progRootSy;
45
46    public SymbolicExpressionTreeGenerator(string[] variableNames) {
47      stack = new ISymbolicExpressionTreeNode[MaxStackSize];
48      var grammar = new TypeCoherentExpressionGrammar();
49      this.variableNames = variableNames;
50
51      grammar.ConfigureAsDefaultRegressionGrammar();
52      const0 = (ConstantTreeNode)grammar.Symbols.OfType<Constant>().First().CreateTreeNode();
53      const0.Value = 0;
54      const1 = (ConstantTreeNode)grammar.Symbols.OfType<Constant>().First().CreateTreeNode();
55      const1.Value = 1;
56      varNode = (VariableTreeNode)grammar.Symbols.OfType<Variable>().First().CreateTreeNode();
57
58      addSy = grammar.AllowedSymbols.OfType<Addition>().First();
59      mulSy = grammar.AllowedSymbols.OfType<Multiplication>().First();
60      logSy = grammar.AllowedSymbols.OfType<Logarithm>().First();
61      expSy = grammar.AllowedSymbols.OfType<Exponential>().First();
62      divSy = grammar.AllowedSymbols.OfType<Division>().First();
63
64      progRootSy = grammar.AllowedSymbols.OfType<ProgramRootSymbol>().First();
65      startSy = grammar.AllowedSymbols.OfType<StartSymbol>().First();
66    }
67
68    public ISymbolicExpressionTreeNode Exec(byte[] code, double[] consts, int nParams, double[] scalingFactor, double[] scalingOffset) {
69      int topOfStack = -1;
70      int pc = 0;
71      int nextParamIdx = -1;
72      OpCodes op;
73      short arg;
74      while (true) {
75        ReadNext(code, ref pc, out op, out arg);
76        switch (op) {
77          case OpCodes.Nop: break;
78          case OpCodes.LoadConst0: {
79              ++topOfStack;
80              stack[topOfStack] = (ISymbolicExpressionTreeNode)const0.Clone();
81              break;
82            }
83          case OpCodes.LoadConst1: {
84              ++topOfStack;
85              stack[topOfStack] = (ISymbolicExpressionTreeNode)const1.Clone();
86              break;
87            }
88          case OpCodes.LoadParamN: {
89              ++topOfStack;
90              var p = (ConstantTreeNode)const1.Clone(); // value will be tuned later (evaluator and tree generator both use 1 as initial values)
91              p.Value = consts[++nextParamIdx];
92              stack[topOfStack] = p;
93              break;
94            }
95          case OpCodes.LoadVar:
96            ++topOfStack;
97            if (scalingOffset != null) {
98              var sumNode = addSy.CreateTreeNode();
99              var varNode = (VariableTreeNode)this.varNode.Clone();
100              var constNode = (ConstantTreeNode)const0.Clone();
101              varNode.Weight = scalingFactor[arg];
102              varNode.VariableName = variableNames[arg];
103              constNode.Value = scalingOffset[arg];
104              sumNode.AddSubtree(varNode);
105              sumNode.AddSubtree(constNode);
106              stack[topOfStack] = sumNode;
107            } else {
108              var varNode = (VariableTreeNode)this.varNode.Clone();
109              varNode.Weight = 1.0;
110              varNode.VariableName = variableNames[arg];
111              stack[topOfStack] = varNode;
112            }
113            break;
114          case OpCodes.Add: {
[15060]115              var t1 = stack[topOfStack - 1];
116              var t2 = stack[topOfStack];
[13645]117              topOfStack--;
[15060]118              if (t1.Symbol is Addition) {
119                t1.AddSubtree(t2);
[13645]120              } else {
121                var addNode = addSy.CreateTreeNode();
122                addNode.AddSubtree(t1);
123                addNode.AddSubtree(t2);
124                stack[topOfStack] = addNode;
125              }
126              break;
127            }
128          case OpCodes.Mul: {
[15060]129              var t1 = stack[topOfStack - 1];
130              var t2 = stack[topOfStack];
[13645]131              topOfStack--;
[15060]132              if (t1.Symbol is Multiplication) {
133                t1.AddSubtree(t2);
[13645]134              } else {
135                var mulNode = mulSy.CreateTreeNode();
136                mulNode.AddSubtree(t1);
137                mulNode.AddSubtree(t2);
138                stack[topOfStack] = mulNode;
139              }
140              break;
141            }
142          case OpCodes.Log: {
143              var v1 = stack[topOfStack];
144              var logNode = logSy.CreateTreeNode();
145              logNode.AddSubtree(v1);
146              stack[topOfStack] = logNode;
147              break;
148            }
149          case OpCodes.Exp: {
150              var v1 = stack[topOfStack];
151              var expNode = expSy.CreateTreeNode();
152              expNode.AddSubtree(v1);
153              stack[topOfStack] = expNode;
154              break;
155            }
156          case OpCodes.Inv: {
157              var v1 = stack[topOfStack];
158              var divNode = divSy.CreateTreeNode();
159              divNode.AddSubtree(v1);
160              stack[topOfStack] = divNode;
161              break;
162            }
163          case OpCodes.Exit:
164            Contract.Assert(topOfStack == 0);
165            var rootNode = progRootSy.CreateTreeNode();
166            var startNode = startSy.CreateTreeNode();
167            startNode.AddSubtree(stack[topOfStack]);
168            rootNode.AddSubtree(startNode);
169            return rootNode;
170        }
171      }
172    }
173
174    private void ReadNext(byte[] code, ref int pc, out OpCodes op, out short s) {
175      op = (OpCodes)Enum.ToObject(typeof(OpCodes), code[pc++]);
176      s = 0;
177      if (op == OpCodes.LoadVar) {
[15060]178        s = (short)((code[pc] << 8) | code[pc + 1]);
[13645]179        pc += 2;
180      }
181    }
182  }
183}
Note: See TracBrowser for help on using the repository browser.