Free cookie consent management tool by TermsFeed Policy Generator

Changeset 9758


Ignore:
Timestamp:
07/25/13 17:04:27 (11 years ago)
Author:
bburlacu
Message:

#2021:

  • Derived the LinearInstruction class from Instruction.
  • Added missing symbols to the linear interpreter
  • Changed description for the linear interpreter
  • Added more helpful exception message when a symbol is not supported.
  • Added evaluation test for the linear interpreter
Location:
branches/HeuristicLab.DataAnalysis.Symbolic.LinearInterpreter
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.DataAnalysis.Symbolic.LinearInterpreter/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Compiler/LinearInstruction.cs

    r9738 r9758  
    2323namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
    2424  // total size of this class should be small to improve cache access while executing the code
    25   public class LinearInstruction {
    26     // the tree node can hold additional data that is necessary for the execution of this instruction
    27     public ISymbolicExpressionTreeNode dynamicNode;
    28     // op code of the function that determines what operation should be executed
    29     public byte opCode;
    30     // number of arguments of the current instruction
    31     public byte nArguments;
    32     // an optional object value (addresses for calls, argument index for arguments)
    33     public object iArg0;
    34 
     25  public class LinearInstruction : Instruction {
    3526    public double value;
    36 
    37     public int childIndex;
     27    public byte childIndex;
    3828  }
    3929}
  • branches/HeuristicLab.DataAnalysis.Symbolic.LinearInterpreter/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Compiler/SymbolicExpressionTreeLinearCompiler.cs

    r9739 r9758  
    3434      var nodes = root.IterateNodesBreadth().ToArray();
    3535      for (int i = 0; i != nodes.Length; ++i) {
    36         code[i].childIndex = code.Count;
    37         code.AddRange(nodes[i].Subtrees.Select(s => new LinearInstruction {
    38           dynamicNode = s, nArguments = (byte)s.SubtreeCount, opCode = opCodeMapper(s)
    39         }));
     36        code[i].childIndex = (byte)code.Count;
     37        code.AddRange(nodes[i].Subtrees.Select(s => new LinearInstruction { dynamicNode = s, nArguments = (byte)s.SubtreeCount, opCode = opCodeMapper(s) }));
    4038      }
    4139
  • branches/HeuristicLab.DataAnalysis.Symbolic.LinearInterpreter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs

    r9739 r9758  
    3232namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
    3333  [StorableClass]
    34   [Item("SymbolicDataAnalysisExpressionTreeLinearInterpreter", "Linear (non-recursive) interpreter for symbolic expression trees (does not support ADFs).")]
    35   public class SymbolicDataAnalysisExpressionTreeLinearInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
     34  [Item("SymbolicDataAnalysisExpressionTreeLinearInterpreter", "Linear (non-recursive) interpreter for symbolic expression trees. This interpreter is faster but does not support Integral, Derivative, TimeLag or ADF function nodes.")]
     35  public sealed class SymbolicDataAnalysisExpressionTreeLinearInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
    3636    private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
    3737    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
     
    4646
    4747    #region parameter properties
    48 
    4948    public IValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
    5049      get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
     
    5453      get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
    5554    }
    56 
    5755    #endregion
    5856
    5957    #region properties
    60 
    6158    public BoolValue CheckExpressionsWithIntervalArithmetic {
    6259      get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
    6360      set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
    6461    }
    65 
    6662    public IntValue EvaluatedSolutions {
    6763      get { return EvaluatedSolutionsParameter.Value; }
    6864      set { EvaluatedSolutionsParameter.Value = value; }
    6965    }
    70 
    7166    #endregion
    7267
    7368    [StorableConstructor]
    74     protected SymbolicDataAnalysisExpressionTreeLinearInterpreter(bool deserializing)
     69    private SymbolicDataAnalysisExpressionTreeLinearInterpreter(bool deserializing)
    7570      : base(deserializing) {
    7671    }
    7772
    78     protected SymbolicDataAnalysisExpressionTreeLinearInterpreter(
     73    private SymbolicDataAnalysisExpressionTreeLinearInterpreter(
    7974      SymbolicDataAnalysisExpressionTreeLinearInterpreter original, Cloner cloner)
    8075      : base(original, cloner) {
     
    8681
    8782    public SymbolicDataAnalysisExpressionTreeLinearInterpreter()
    88       : base("SymbolicDataAnalysisExpressionTreeLinearInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.") {
     83      : base("SymbolicDataAnalysisExpressionTreeLinearInterpreter", "Linear (non-recursive) interpreter for symbolic expression trees (does not support ADFs).") {
    8984      Parameters.Add(new ValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
    9085      Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
    9186    }
    9287
    93     protected SymbolicDataAnalysisExpressionTreeLinearInterpreter(string name, string description)
     88    private SymbolicDataAnalysisExpressionTreeLinearInterpreter(string name, string description)
    9489      : base(name, description) {
    9590      Parameters.Add(new ValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
     
    123118
    124119      var code = SymbolicExpressionTreeLinearCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
    125       PrepareInterpreterState(code, dataset);
     120      PrepareInstructions(code, dataset);
    126121      return rows.Select(row => Evaluate(dataset, ref row, code));
    127122    }
    128123
    129     private static void PrepareInterpreterState(LinearInstruction[] code, Dataset dataset) {
     124    private static void PrepareInstructions(LinearInstruction[] code, Dataset dataset) {
    130125      for (int i = code.Length - 1; i >= 0; --i) {
    131126        var instr = code[i];
     
    159154    private static double Evaluate(Dataset dataset, ref int row, LinearInstruction[] code) {
    160155      for (int i = code.Length - 1; i >= 0; --i) {
     156        if (code[i].opCode == OpCodes.Constant) continue;
     157        #region opcode switch
    161158        var instr = code[i];
    162         if (instr.opCode == OpCodes.Constant) continue;
    163         #region opcode switch
    164159        switch (instr.opCode) {
    165160          case OpCodes.Variable: {
     
    241236          case OpCodes.Tan: {
    242237              instr.value = Math.Tan(code[instr.childIndex].value);
     238            }
     239            break;
     240          case OpCodes.Square: {
     241              instr.value = Math.Pow(code[instr.childIndex].value, 2);
     242            }
     243            break;
     244          case OpCodes.Power: {
     245              double x = code[instr.childIndex].value;
     246              double y = Math.Round(code[instr.childIndex + 1].value);
     247              instr.value = Math.Pow(x, y);
     248            }
     249            break;
     250          case OpCodes.SquareRoot: {
     251              instr.value = Math.Sqrt(code[instr.childIndex].value);
    243252            }
    244253            break;
     
    422431            }
    423432            break;
    424           case OpCodes.TimeLag: {
    425               throw new NotSupportedException();
    426             }
    427           case OpCodes.Integral: {
    428               throw new NotSupportedException();
    429             }
    430           case OpCodes.Derivative: {
    431               throw new NotSupportedException();
    432             }
    433           case OpCodes.Arg: {
    434               throw new NotSupportedException();
    435             }
    436433          default:
    437             throw new NotSupportedException();
     434            var errorText = string.Format("The {0} symbol is not supported by the linear interpreter. To support this symbol, please use another interpreter.", instr.dynamicNode.Symbol.Name);
     435            throw new NotSupportedException(errorText);
    438436        }
    439437        #endregion
  • branches/HeuristicLab.DataAnalysis.Symbolic.LinearInterpreter/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeInterpreterTest.cs

    r9735 r9758  
    149149    [TestMethod]
    150150    public void SymbolicDataAnalysisExpressionTreeInterpreterEvaluateTest() {
     151      var interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
    151152      Dataset ds = new Dataset(new string[] { "Y", "A", "B" }, new double[,] {
    152153        { 1.0, 1.0, 1.0 },
     
    164165      });
    165166
    166       var interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
    167167      EvaluateTerminals(interpreter, ds);
    168168      EvaluateOperations(interpreter, ds);
     169      EvaluateTimeSymbols(interpreter, ds);
    169170      EvaluateAdf(interpreter, ds);
     171    }
     172
     173    [TestMethod]
     174    public void SymbolicDataAnalysisExpressionTreeLinearInterpreterEvaluateTest() {
     175      var interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter();
     176      Dataset ds = new Dataset(new string[] { "Y", "A", "B" }, new double[,] {
     177        { 1.0, 1.0, 1.0 },
     178        { 2.0, 2.0, 2.0 },
     179        { 3.0, 1.0, 2.0 },
     180        { 4.0, 1.0, 1.0 },
     181        { 5.0, 2.0, 2.0 },
     182        { 6.0, 1.0, 2.0 },
     183        { 7.0, 1.0, 1.0 },
     184        { 8.0, 2.0, 2.0 },
     185        { 9.0, 1.0, 2.0 },
     186        { 10.0, 1.0, 1.0 },
     187        { 11.0, 2.0, 2.0 },
     188        { 12.0, 1.0, 2.0 }
     189      });
     190      //time symbols and ADFs not supported by the linear interpreter
     191      EvaluateTerminals(interpreter, ds);
     192      EvaluateOperations(interpreter, ds);
    170193    }
    171194
     
    190213      EvaluateTerminals(interpreter, ds);
    191214      EvaluateOperations(interpreter, ds);
     215    }
     216
     217    private void EvaluateTimeSymbols(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, Dataset ds) {
     218      // integral
     219      Evaluate(interpreter, ds, "(integral -1.0 (variable 1.0 a)) ", 1, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1));
     220      Evaluate(interpreter, ds, "(integral -1.0 (lagVariable 1.0 a 1)) ", 1, ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
     221      Evaluate(interpreter, ds, "(integral -2.0 (variable 1.0 a)) ", 2, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
     222      Evaluate(interpreter, ds, "(integral -1.0 (* (variable 1.0 a) (variable 1.0 b)))", 1, ds.GetDoubleValue("A", 0) * ds.GetDoubleValue("B", 0) + ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1));
     223      Evaluate(interpreter, ds, "(integral -2.0 3.0)", 1, 9.0);
     224
     225      // derivative
     226      // (f_0 + 2 * f_1 - 2 * f_3 - f_4) / 8; // h = 1
     227      Evaluate(interpreter, ds, "(diff (variable 1.0 a)) ", 5, (ds.GetDoubleValue("A", 5) + 2 * ds.GetDoubleValue("A", 4) - 2 * ds.GetDoubleValue("A", 2) - ds.GetDoubleValue("A", 1)) / 8.0);
     228      Evaluate(interpreter, ds, "(diff (variable 1.0 b)) ", 5, (ds.GetDoubleValue("B", 5) + 2 * ds.GetDoubleValue("B", 4) - 2 * ds.GetDoubleValue("B", 2) - ds.GetDoubleValue("B", 1)) / 8.0);
     229      Evaluate(interpreter, ds, "(diff (* (variable 1.0 a) (variable 1.0 b)))", 5, +
     230        (ds.GetDoubleValue("A", 5) * ds.GetDoubleValue("B", 5) +
     231        2 * ds.GetDoubleValue("A", 4) * ds.GetDoubleValue("B", 4) -
     232        2 * ds.GetDoubleValue("A", 2) * ds.GetDoubleValue("B", 2) -
     233        ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1)) / 8.0);
     234      Evaluate(interpreter, ds, "(diff -2.0 3.0)", 5, 0.0);
     235
     236      // timelag
     237      Evaluate(interpreter, ds, "(lag -1.0 (lagVariable 1.0 a 2)) ", 1, ds.GetDoubleValue("A", 2));
     238      Evaluate(interpreter, ds, "(lag -2.0 (lagVariable 1.0 a 2)) ", 2, ds.GetDoubleValue("A", 2));
     239      Evaluate(interpreter, ds, "(lag -1.0 (* (lagVariable 1.0 a 1) (lagVariable 1.0 b 2)))", 1, ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 2));
     240      Evaluate(interpreter, ds, "(lag -2.0 3.0)", 1, 3.0);
    192241    }
    193242
     
    358407      Evaluate(interpreter, ds, "(lagVariable 1.0 a 1) ", 0, ds.GetDoubleValue("A", 1));
    359408
    360       // integral
    361       Evaluate(interpreter, ds, "(integral -1.0 (variable 1.0 a)) ", 1, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1));
    362       Evaluate(interpreter, ds, "(integral -1.0 (lagVariable 1.0 a 1)) ", 1, ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
    363       Evaluate(interpreter, ds, "(integral -2.0 (variable 1.0 a)) ", 2, ds.GetDoubleValue("A", 0) + ds.GetDoubleValue("A", 1) + ds.GetDoubleValue("A", 2));
    364       Evaluate(interpreter, ds, "(integral -1.0 (* (variable 1.0 a) (variable 1.0 b)))", 1, ds.GetDoubleValue("A", 0) * ds.GetDoubleValue("B", 0) + ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1));
    365       Evaluate(interpreter, ds, "(integral -2.0 3.0)", 1, 9.0);
    366 
    367       // derivative
    368       // (f_0 + 2 * f_1 - 2 * f_3 - f_4) / 8; // h = 1
    369       Evaluate(interpreter, ds, "(diff (variable 1.0 a)) ", 5, (ds.GetDoubleValue("A", 5) + 2 * ds.GetDoubleValue("A", 4) - 2 * ds.GetDoubleValue("A", 2) - ds.GetDoubleValue("A", 1)) / 8.0);
    370       Evaluate(interpreter, ds, "(diff (variable 1.0 b)) ", 5, (ds.GetDoubleValue("B", 5) + 2 * ds.GetDoubleValue("B", 4) - 2 * ds.GetDoubleValue("B", 2) - ds.GetDoubleValue("B", 1)) / 8.0);
    371       Evaluate(interpreter, ds, "(diff (* (variable 1.0 a) (variable 1.0 b)))", 5, +
    372         (ds.GetDoubleValue("A", 5) * ds.GetDoubleValue("B", 5) +
    373         2 * ds.GetDoubleValue("A", 4) * ds.GetDoubleValue("B", 4) -
    374         2 * ds.GetDoubleValue("A", 2) * ds.GetDoubleValue("B", 2) -
    375         ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 1)) / 8.0);
    376       Evaluate(interpreter, ds, "(diff -2.0 3.0)", 5, 0.0);
    377 
    378       // timelag
    379       Evaluate(interpreter, ds, "(lag -1.0 (lagVariable 1.0 a 2)) ", 1, ds.GetDoubleValue("A", 2));
    380       Evaluate(interpreter, ds, "(lag -2.0 (lagVariable 1.0 a 2)) ", 2, ds.GetDoubleValue("A", 2));
    381       Evaluate(interpreter, ds, "(lag -1.0 (* (lagVariable 1.0 a 1) (lagVariable 1.0 b 2)))", 1, ds.GetDoubleValue("A", 1) * ds.GetDoubleValue("B", 2));
    382       Evaluate(interpreter, ds, "(lag -2.0 3.0)", 1, 3.0);
    383 
    384409      {
    385410        // special functions
     
    434459          Evaluate(interpreter, ds, "(expint " + x + ")", 0, alglib.exponentialintegralei(x));
    435460        };
    436 
    437 
    438461
    439462        foreach (var e in new[] { -2.0, -1.0, 0.0, 1.0, 2.0 }) {
Note: See TracChangeset for help on using the changeset viewer.