Changeset 17687 for branches/1837_Sliding Window GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
- Timestamp:
- 07/19/20 19:07:40 (4 years ago)
- Location:
- branches/1837_Sliding Window GP/HeuristicLab.Problems.DataAnalysis.Symbolic
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/1837_Sliding Window GP/HeuristicLab.Problems.DataAnalysis.Symbolic
- Property svn:mergeinfo changed
-
branches/1837_Sliding Window GP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
r9870 r17687 1 1 #region License Information 2 2 /* HeuristicLab 3 * Copyright (C) 2002-2013Heuristic and Evolutionary Algorithms Laboratory (HEAL)3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 4 * 5 5 * This file is part of HeuristicLab. … … 27 27 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 28 28 using HeuristicLab.Parameters; 29 using H euristicLab.Persistence.Default.CompositeSerializers.Storable;29 using HEAL.Attic; 30 30 31 31 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 32 [Storable Class]32 [StorableType("FB94F333-B32A-44FB-A561-CBDE76693D20")] 33 33 [Item("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.")] 34 public class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter { 34 public class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem, 35 ISymbolicDataAnalysisExpressionTreeInterpreter { 35 36 private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic"; 37 private const string CheckExpressionsWithIntervalArithmeticParameterDescription = "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression."; 36 38 private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions"; 37 39 38 public override bool CanChangeName { get { return false; } } 39 public override bool CanChangeDescription { get { return false; } } 40 public override bool CanChangeName { 41 get { return false; } 42 } 43 44 public override bool CanChangeDescription { 45 get { return false; } 46 } 40 47 41 48 #region parameter properties 42 public I ValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {43 get { return (I ValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }44 } 45 46 public I ValueParameter<IntValue> EvaluatedSolutionsParameter {47 get { return (I ValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }49 public IFixedValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter { 50 get { return (IFixedValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; } 51 } 52 53 public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter { 54 get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; } 48 55 } 49 56 #endregion 50 57 51 58 #region properties 52 public BoolValueCheckExpressionsWithIntervalArithmetic {53 get { return CheckExpressionsWithIntervalArithmeticParameter.Value ; }54 set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }55 } 56 57 public IntValueEvaluatedSolutions {58 get { return EvaluatedSolutionsParameter.Value ; }59 set { EvaluatedSolutionsParameter.Value = value; }59 public bool CheckExpressionsWithIntervalArithmetic { 60 get { return CheckExpressionsWithIntervalArithmeticParameter.Value.Value; } 61 set { CheckExpressionsWithIntervalArithmeticParameter.Value.Value = value; } 62 } 63 64 public int EvaluatedSolutions { 65 get { return EvaluatedSolutionsParameter.Value.Value; } 66 set { EvaluatedSolutionsParameter.Value.Value = value; } 60 67 } 61 68 #endregion 62 69 63 70 [StorableConstructor] 64 protected SymbolicDataAnalysisExpressionTreeInterpreter(bool deserializing) : base(deserializing) { } 65 protected SymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original, Cloner cloner) : base(original, cloner) { } 71 protected SymbolicDataAnalysisExpressionTreeInterpreter(StorableConstructorFlag _) : base(_) { } 72 73 protected SymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original, 74 Cloner cloner) 75 : base(original, cloner) { } 76 66 77 public override IDeepCloneable Clone(Cloner cloner) { 67 78 return new SymbolicDataAnalysisExpressionTreeInterpreter(this, cloner); … … 70 81 public SymbolicDataAnalysisExpressionTreeInterpreter() 71 82 : base("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.") { 72 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)));73 Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));83 Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false))); 84 Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0))); 74 85 } 75 86 76 87 protected SymbolicDataAnalysisExpressionTreeInterpreter(string name, string description) 77 88 : base(name, description) { 78 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)));79 Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));89 Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false))); 90 Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0))); 80 91 } 81 92 82 93 [StorableHook(HookType.AfterDeserialization)] 83 94 private void AfterDeserialization() { 84 if (!Parameters.ContainsKey(EvaluatedSolutionsParameterName)) 85 Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0))); 95 var evaluatedSolutions = new IntValue(0); 96 var checkExpressionsWithIntervalArithmetic = new BoolValue(false); 97 if (Parameters.ContainsKey(EvaluatedSolutionsParameterName)) { 98 var evaluatedSolutionsParameter = (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; 99 evaluatedSolutions = evaluatedSolutionsParameter.Value; 100 Parameters.Remove(EvaluatedSolutionsParameterName); 101 } 102 Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", evaluatedSolutions)); 103 if (Parameters.ContainsKey(CheckExpressionsWithIntervalArithmeticParameterName)) { 104 var checkExpressionsWithIntervalArithmeticParameter = (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; 105 Parameters.Remove(CheckExpressionsWithIntervalArithmeticParameterName); 106 checkExpressionsWithIntervalArithmetic = checkExpressionsWithIntervalArithmeticParameter.Value; 107 } 108 Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, checkExpressionsWithIntervalArithmetic)); 86 109 } 87 110 88 111 #region IStatefulItem 89 112 public void InitializeState() { 90 EvaluatedSolutions.Value = 0; 91 } 92 93 public void ClearState() { 94 } 113 EvaluatedSolutions = 0; 114 } 115 116 public void ClearState() { } 95 117 #endregion 96 118 97 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) { 98 if (CheckExpressionsWithIntervalArithmetic.Value) 119 private readonly object syncRoot = new object(); 120 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, 121 IEnumerable<int> rows) { 122 if (CheckExpressionsWithIntervalArithmetic) { 99 123 throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter."); 100 101 lock (EvaluatedSolutions) { 102 EvaluatedSolutions.Value++; // increment the evaluated solutions counter 124 } 125 126 lock (syncRoot) { 127 EvaluatedSolutions++; // increment the evaluated solutions counter 103 128 } 104 129 var state = PrepareInterpreterState(tree, dataset); … … 111 136 } 112 137 113 private static InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, Dataset dataset) {138 private static InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, IDataset dataset) { 114 139 Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode); 115 140 int necessaryArgStackSize = 0; … … 118 143 var variableTreeNode = (VariableTreeNode)instr.dynamicNode; 119 144 instr.data = dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName); 145 } else if (instr.opCode == OpCodes.FactorVariable) { 146 var factorTreeNode = instr.dynamicNode as FactorVariableTreeNode; 147 instr.data = dataset.GetReadOnlyStringValues(factorTreeNode.VariableName); 148 } else if (instr.opCode == OpCodes.BinaryFactorVariable) { 149 var factorTreeNode = instr.dynamicNode as BinaryFactorVariableTreeNode; 150 instr.data = dataset.GetReadOnlyStringValues(factorTreeNode.VariableName); 120 151 } else if (instr.opCode == OpCodes.LagVariable) { 121 152 var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode; … … 131 162 } 132 163 133 134 public virtual double Evaluate(Dataset dataset, ref int row, InterpreterState state) { 164 public virtual double Evaluate(IDataset dataset, ref int row, InterpreterState state) { 135 165 Instruction currentInstr = state.NextInstruction(); 136 166 switch (currentInstr.opCode) { … … 147 177 s -= Evaluate(dataset, ref row, state); 148 178 } 149 if (currentInstr.nArguments == 1) s = -s;179 if (currentInstr.nArguments == 1) { s = -s; } 150 180 return s; 151 181 } … … 162 192 p /= Evaluate(dataset, ref row, state); 163 193 } 164 if (currentInstr.nArguments == 1) p = 1.0 / p;194 if (currentInstr.nArguments == 1) { p = 1.0 / p; } 165 195 return p; 166 196 } … … 172 202 return sum / currentInstr.nArguments; 173 203 } 204 case OpCodes.Absolute: { 205 return Math.Abs(Evaluate(dataset, ref row, state)); 206 } 207 case OpCodes.Tanh: { 208 return Math.Tanh(Evaluate(dataset, ref row, state)); 209 } 174 210 case OpCodes.Cos: { 175 211 return Math.Cos(Evaluate(dataset, ref row, state)); … … 183 219 case OpCodes.Square: { 184 220 return Math.Pow(Evaluate(dataset, ref row, state), 2); 221 } 222 case OpCodes.Cube: { 223 return Math.Pow(Evaluate(dataset, ref row, state), 3); 185 224 } 186 225 case OpCodes.Power: { … … 192 231 return Math.Sqrt(Evaluate(dataset, ref row, state)); 193 232 } 233 case OpCodes.CubeRoot: { 234 var arg = Evaluate(dataset, ref row, state); 235 return arg < 0 ? -Math.Pow(-arg, 1.0 / 3.0) : Math.Pow(arg, 1.0 / 3.0); 236 } 194 237 case OpCodes.Root: { 195 238 double x = Evaluate(dataset, ref row, state); … … 205 248 case OpCodes.Gamma: { 206 249 var x = Evaluate(dataset, ref row, state); 207 if (double.IsNaN(x)) return double.NaN; 208 else return alglib.gammafunction(x); 250 if (double.IsNaN(x)) { return double.NaN; } else { return alglib.gammafunction(x); } 209 251 } 210 252 case OpCodes.Psi: { … … 216 258 case OpCodes.Dawson: { 217 259 var x = Evaluate(dataset, ref row, state); 218 if (double.IsNaN(x)) return double.NaN;260 if (double.IsNaN(x)) { return double.NaN; } 219 261 return alglib.dawsonintegral(x); 220 262 } 221 263 case OpCodes.ExponentialIntegralEi: { 222 264 var x = Evaluate(dataset, ref row, state); 223 if (double.IsNaN(x)) return double.NaN;265 if (double.IsNaN(x)) { return double.NaN; } 224 266 return alglib.exponentialintegralei(x); 225 267 } … … 310 352 if (double.IsNaN(x)) return double.NaN; 311 353 else return alglib.besseli0(x); 354 } 355 356 case OpCodes.AnalyticQuotient: { 357 var x1 = Evaluate(dataset, ref row, state); 358 var x2 = Evaluate(dataset, ref row, state); 359 return x1 / Math.Pow(1 + x2 * x2, 0.5); 312 360 } 313 361 case OpCodes.IfThenElse: { … … 344 392 return Evaluate(dataset, ref row, state) > 0.0 ? -1.0 : 1.0; 345 393 } 394 case OpCodes.XOR: { 395 //mkommend: XOR on multiple inputs is defined as true if the number of positive signals is odd 396 // this is equal to a consecutive execution of binary XOR operations. 397 int positiveSignals = 0; 398 for (int i = 0; i < currentInstr.nArguments; i++) { 399 if (Evaluate(dataset, ref row, state) > 0.0) { positiveSignals++; } 400 } 401 return positiveSignals % 2 != 0 ? 1.0 : -1.0; 402 } 346 403 case OpCodes.GT: { 347 404 double x = Evaluate(dataset, ref row, state); 348 405 double y = Evaluate(dataset, ref row, state); 349 if (x > y) return 1.0; 350 else return -1.0; 406 if (x > y) { return 1.0; } else { return -1.0; } 351 407 } 352 408 case OpCodes.LT: { 353 409 double x = Evaluate(dataset, ref row, state); 354 410 double y = Evaluate(dataset, ref row, state); 355 if (x < y) return 1.0; 356 else return -1.0; 411 if (x < y) { return 1.0; } else { return -1.0; } 357 412 } 358 413 case OpCodes.TimeLag: { … … 425 480 return ((IList<double>)currentInstr.data)[row] * variableTreeNode.Weight; 426 481 } 482 case OpCodes.BinaryFactorVariable: { 483 if (row < 0 || row >= dataset.Rows) return double.NaN; 484 var factorVarTreeNode = currentInstr.dynamicNode as BinaryFactorVariableTreeNode; 485 return ((IList<string>)currentInstr.data)[row] == factorVarTreeNode.VariableValue ? factorVarTreeNode.Weight : 0; 486 } 487 case OpCodes.FactorVariable: { 488 if (row < 0 || row >= dataset.Rows) return double.NaN; 489 var factorVarTreeNode = currentInstr.dynamicNode as FactorVariableTreeNode; 490 return factorVarTreeNode.GetValue(((IList<string>)currentInstr.data)[row]); 491 } 427 492 case OpCodes.LagVariable: { 428 493 var laggedVariableTreeNode = (LaggedVariableTreeNode)currentInstr.dynamicNode; 429 494 int actualRow = row + laggedVariableTreeNode.Lag; 430 if (actualRow < 0 || actualRow >= dataset.Rows) return double.NaN;495 if (actualRow < 0 || actualRow >= dataset.Rows) { return double.NaN; } 431 496 return ((IList<double>)currentInstr.data)[actualRow] * laggedVariableTreeNode.Weight; 432 497 } … … 441 506 if (row < 0 || row >= dataset.Rows) return double.NaN; 442 507 var variableConditionTreeNode = (VariableConditionTreeNode)currentInstr.dynamicNode; 443 double variableValue = ((IList<double>)currentInstr.data)[row]; 444 double x = variableValue - variableConditionTreeNode.Threshold; 445 double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x)); 446 447 double trueBranch = Evaluate(dataset, ref row, state); 448 double falseBranch = Evaluate(dataset, ref row, state); 449 450 return trueBranch * p + falseBranch * (1 - p); 451 } 452 default: throw new NotSupportedException(); 508 if (!variableConditionTreeNode.Symbol.IgnoreSlope) { 509 double variableValue = ((IList<double>)currentInstr.data)[row]; 510 double x = variableValue - variableConditionTreeNode.Threshold; 511 double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x)); 512 513 double trueBranch = Evaluate(dataset, ref row, state); 514 double falseBranch = Evaluate(dataset, ref row, state); 515 516 return trueBranch * p + falseBranch * (1 - p); 517 } else { 518 // strict threshold 519 double variableValue = ((IList<double>)currentInstr.data)[row]; 520 if (variableValue <= variableConditionTreeNode.Threshold) { 521 var left = Evaluate(dataset, ref row, state); 522 state.SkipInstructions(); 523 return left; 524 } else { 525 state.SkipInstructions(); 526 return Evaluate(dataset, ref row, state); 527 } 528 } 529 } 530 default: 531 throw new NotSupportedException(); 453 532 } 454 533 }
Note: See TracChangeset
for help on using the changeset viewer.