Changeset 8436 for branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
- Timestamp:
- 08/08/12 16:04:29 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
r8432 r8436 22 22 using System; 23 23 using System.Collections.Generic; 24 using System.Linq;25 24 using HeuristicLab.Common; 26 25 using HeuristicLab.Core; … … 33 32 [StorableClass] 34 33 [Item("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.")] 35 public sealed class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem, 36 ISymbolicDataAnalysisExpressionTreeInterpreter, ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter { 34 public class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter { 37 35 private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic"; 38 36 private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions"; 39 #region private classes 40 private class InterpreterState { 41 private double[] argumentStack; 42 private int argumentStackPointer; 43 private Instruction[] code; 44 private int pc; 45 public int ProgramCounter { 46 get { return pc; } 47 set { pc = value; } 48 } 49 internal InterpreterState(Instruction[] code, int argumentStackSize) { 50 this.code = code; 51 this.pc = 0; 52 if (argumentStackSize > 0) { 53 this.argumentStack = new double[argumentStackSize]; 54 } 55 this.argumentStackPointer = 0; 56 } 57 58 internal void Reset() { 59 this.pc = 0; 60 this.argumentStackPointer = 0; 61 } 62 63 internal Instruction NextInstruction() { 64 return code[pc++]; 65 } 66 private void Push(double val) { 67 argumentStack[argumentStackPointer++] = val; 68 } 69 private double Pop() { 70 return argumentStack[--argumentStackPointer]; 71 } 72 73 internal void CreateStackFrame(double[] argValues) { 74 // push in reverse order to make indexing easier 75 for (int i = argValues.Length - 1; i >= 0; i--) { 76 argumentStack[argumentStackPointer++] = argValues[i]; 77 } 78 Push(argValues.Length); 79 } 80 81 internal void RemoveStackFrame() { 82 int size = (int)Pop(); 83 argumentStackPointer -= size; 84 } 85 86 internal double GetStackFrameValue(ushort index) { 87 // layout of stack: 88 // [0] <- argumentStackPointer 89 // [StackFrameSize = N + 1] 90 // [Arg0] <- argumentStackPointer - 2 - 0 91 // [Arg1] <- argumentStackPointer - 2 - 1 92 // [...] 93 // [ArgN] <- argumentStackPointer - 2 - N 94 // <Begin of stack frame> 95 return argumentStack[argumentStackPointer - index - 2]; 96 } 97 } 98 private class OpCodes { 99 public const byte Add = 1; 100 public const byte Sub = 2; 101 public const byte Mul = 3; 102 public const byte Div = 4; 103 104 public const byte Sin = 5; 105 public const byte Cos = 6; 106 public const byte Tan = 7; 107 108 public const byte Log = 8; 109 public const byte Exp = 9; 110 111 public const byte IfThenElse = 10; 112 113 public const byte GT = 11; 114 public const byte LT = 12; 115 116 public const byte AND = 13; 117 public const byte OR = 14; 118 public const byte NOT = 15; 119 120 121 public const byte Average = 16; 122 123 public const byte Call = 17; 124 125 public const byte Variable = 18; 126 public const byte LagVariable = 19; 127 public const byte Constant = 20; 128 public const byte Arg = 21; 129 130 public const byte Power = 22; 131 public const byte Root = 23; 132 public const byte TimeLag = 24; 133 public const byte Integral = 25; 134 public const byte Derivative = 26; 135 136 public const byte VariableCondition = 27; 137 138 public const byte Square = 28; 139 public const byte SquareRoot = 29; 140 public const byte Gamma = 30; 141 public const byte Psi = 31; 142 public const byte Dawson = 32; 143 public const byte ExponentialIntegralEi = 33; 144 public const byte CosineIntegral = 34; 145 public const byte SineIntegral = 35; 146 public const byte HyperbolicCosineIntegral = 36; 147 public const byte HyperbolicSineIntegral = 37; 148 public const byte FresnelCosineIntegral = 38; 149 public const byte FresnelSineIntegral = 39; 150 public const byte AiryA = 40; 151 public const byte AiryB = 41; 152 public const byte Norm = 42; 153 public const byte Erf = 43; 154 public const byte Bessel = 44; 155 } 156 #endregion 157 158 private Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() { 159 { typeof(Addition), OpCodes.Add }, 160 { typeof(Subtraction), OpCodes.Sub }, 161 { typeof(Multiplication), OpCodes.Mul }, 162 { typeof(Division), OpCodes.Div }, 163 { typeof(Sine), OpCodes.Sin }, 164 { typeof(Cosine), OpCodes.Cos }, 165 { typeof(Tangent), OpCodes.Tan }, 166 { typeof(Logarithm), OpCodes.Log }, 167 { typeof(Exponential), OpCodes.Exp }, 168 { typeof(IfThenElse), OpCodes.IfThenElse }, 169 { typeof(GreaterThan), OpCodes.GT }, 170 { typeof(LessThan), OpCodes.LT }, 171 { typeof(And), OpCodes.AND }, 172 { typeof(Or), OpCodes.OR }, 173 { typeof(Not), OpCodes.NOT}, 174 { typeof(Average), OpCodes.Average}, 175 { typeof(InvokeFunction), OpCodes.Call }, 176 { typeof(Variable), OpCodes.Variable }, 177 { typeof(LaggedVariable), OpCodes.LagVariable }, 178 { typeof(Constant), OpCodes.Constant }, 179 { typeof(Argument), OpCodes.Arg }, 180 { typeof(Power),OpCodes.Power}, 181 { typeof(Root),OpCodes.Root}, 182 { typeof(TimeLag), OpCodes.TimeLag}, 183 { typeof(Integral), OpCodes.Integral}, 184 { typeof(Derivative), OpCodes.Derivative}, 185 { typeof(VariableCondition),OpCodes.VariableCondition}, 186 { typeof(Square),OpCodes.Square}, 187 { typeof(SquareRoot),OpCodes.SquareRoot}, 188 { typeof(Gamma), OpCodes.Gamma }, 189 { typeof(Psi), OpCodes.Psi }, 190 { typeof(Dawson), OpCodes.Dawson}, 191 { typeof(ExponentialIntegralEi), OpCodes.ExponentialIntegralEi }, 192 { typeof(CosineIntegral), OpCodes.CosineIntegral }, 193 { typeof(SineIntegral), OpCodes.SineIntegral }, 194 { typeof(HyperbolicCosineIntegral), OpCodes.HyperbolicCosineIntegral }, 195 { typeof(HyperbolicSineIntegral), OpCodes.HyperbolicSineIntegral }, 196 { typeof(FresnelCosineIntegral), OpCodes.FresnelCosineIntegral }, 197 { typeof(FresnelSineIntegral), OpCodes.FresnelSineIntegral }, 198 { typeof(AiryA), OpCodes.AiryA }, 199 { typeof(AiryB), OpCodes.AiryB }, 200 { typeof(Norm), OpCodes.Norm}, 201 { typeof(Erf), OpCodes.Erf}, 202 { typeof(Bessel), OpCodes.Bessel} 203 }; 204 205 public override bool CanChangeName { 206 get { return false; } 207 } 208 public override bool CanChangeDescription { 209 get { return false; } 210 } 37 38 public override bool CanChangeName { get { return false; } } 39 public override bool CanChangeDescription { get { return false; } } 211 40 212 41 #region parameter properties … … 233 62 234 63 [StorableConstructor] 235 pr ivateSymbolicDataAnalysisExpressionTreeInterpreter(bool deserializing) : base(deserializing) { }236 pr ivateSymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original, Cloner cloner) : base(original, cloner) { }64 protected SymbolicDataAnalysisExpressionTreeInterpreter(bool deserializing) : base(deserializing) { } 65 protected SymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original, Cloner cloner) : base(original, cloner) { } 237 66 public override IDeepCloneable Clone(Cloner cloner) { 238 67 return new SymbolicDataAnalysisExpressionTreeInterpreter(this, cloner); … … 245 74 } 246 75 76 protected SymbolicDataAnalysisExpressionTreeInterpreter(string name, string description) 77 : 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))); 80 } 81 247 82 [StorableHook(HookType.AfterDeserialization)] 248 83 private void AfterDeserialization() { … … 261 96 262 97 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) { 263 return GetSymbolicExpressionTreeValues(tree, dataset, new string[] { "#NOTHING#" }, rows);264 }265 266 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, string[] targetVariables, IEnumerable<int> rows) {267 return GetSymbolicExpressionTreeValues(tree, dataset, targetVariables, rows, 1);268 }269 270 271 // for each row for each horizon for each target variable one value272 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, string[] targetVariables, IEnumerable<int> rows, int horizon) {273 98 if (CheckExpressionsWithIntervalArithmetic.Value) 274 99 throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter."); 100 275 101 EvaluatedSolutions.Value++; // increment the evaluated solutions counter 276 var compiler = new SymbolicExpressionTreeCompiler(); 277 Instruction[] code = compiler.Compile(tree, MapSymbolToOpCode); 102 var state = PrepareInterpreterState(tree, dataset); 103 104 foreach (var rowEnum in rows) { 105 int row = rowEnum; 106 yield return Evaluate(dataset, ref row, state); 107 state.Reset(); 108 } 109 } 110 111 private InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, Dataset dataset) { 112 Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode); 278 113 int necessaryArgStackSize = 0; 279 for (int i = 0; i < code.Length; i++) { 280 Instruction instr = code[i]; 114 foreach (Instruction instr in code) { 281 115 if (instr.opCode == OpCodes.Variable) { 282 var variableTreeNode = instr.dynamicNode as VariableTreeNode;116 var variableTreeNode = (VariableTreeNode)instr.dynamicNode; 283 117 instr.iArg0 = dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName); 284 code[i] = instr;285 118 } else if (instr.opCode == OpCodes.LagVariable) { 286 var laggedVariableTreeNode = instr.dynamicNode as LaggedVariableTreeNode;119 var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode; 287 120 instr.iArg0 = dataset.GetReadOnlyDoubleValues(laggedVariableTreeNode.VariableName); 288 code[i] = instr;289 121 } else if (instr.opCode == OpCodes.VariableCondition) { 290 var variableConditionTreeNode = instr.dynamicNode as VariableConditionTreeNode;122 var variableConditionTreeNode = (VariableConditionTreeNode)instr.dynamicNode; 291 123 instr.iArg0 = dataset.GetReadOnlyDoubleValues(variableConditionTreeNode.VariableName); 292 124 } else if (instr.opCode == OpCodes.Call) { … … 294 126 } 295 127 } 296 var state = new InterpreterState(code, necessaryArgStackSize); 297 298 int nComponents = tree.Root.GetSubtree(0).SubtreeCount; 299 // produce a n-step forecast for each target variable for all rows 300 var cachedPrognosedValues = new Dictionary<string, double[]>(); 301 foreach (var targetVariable in targetVariables) 302 cachedPrognosedValues[targetVariable] = new double[horizon]; 303 foreach (var rowEnum in rows) { 304 int row = rowEnum; 305 foreach (var horizonRow in Enumerable.Range(row, horizon)) { 306 int localRow = horizonRow; // create a local variable for the ref parameter 307 for (int c = 0; c < nComponents; c++) { 308 var prog = Evaluate(dataset, ref localRow, row - 1, state, cachedPrognosedValues); 309 yield return prog; 310 cachedPrognosedValues[targetVariables[c]][horizonRow - row] = prog; 311 } 312 313 state.Reset(); 314 } 315 } 316 } 317 318 private double Evaluate(Dataset dataset, ref int row, int lastObservedRow, InterpreterState state, Dictionary<string, double[]> cachedPrognosedValues) { 128 return new InterpreterState(code, necessaryArgStackSize); 129 } 130 131 132 protected virtual double Evaluate(Dataset dataset, ref int row, InterpreterState state) { 319 133 Instruction currentInstr = state.NextInstruction(); 320 134 switch (currentInstr.opCode) { 321 135 case OpCodes.Add: { 322 double s = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);323 for (int i = 1; i < currentInstr.nArguments; i++) { 324 s += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);136 double s = Evaluate(dataset, ref row, state); 137 for (int i = 1; i < currentInstr.nArguments; i++) { 138 s += Evaluate(dataset, ref row, state); 325 139 } 326 140 return s; 327 141 } 328 142 case OpCodes.Sub: { 329 double s = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);330 for (int i = 1; i < currentInstr.nArguments; i++) { 331 s -= Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);143 double s = Evaluate(dataset, ref row, state); 144 for (int i = 1; i < currentInstr.nArguments; i++) { 145 s -= Evaluate(dataset, ref row, state); 332 146 } 333 147 if (currentInstr.nArguments == 1) s = -s; … … 335 149 } 336 150 case OpCodes.Mul: { 337 double p = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);338 for (int i = 1; i < currentInstr.nArguments; i++) { 339 p *= Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);151 double p = Evaluate(dataset, ref row, state); 152 for (int i = 1; i < currentInstr.nArguments; i++) { 153 p *= Evaluate(dataset, ref row, state); 340 154 } 341 155 return p; 342 156 } 343 157 case OpCodes.Div: { 344 double p = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);345 for (int i = 1; i < currentInstr.nArguments; i++) { 346 p /= Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);158 double p = Evaluate(dataset, ref row, state); 159 for (int i = 1; i < currentInstr.nArguments; i++) { 160 p /= Evaluate(dataset, ref row, state); 347 161 } 348 162 if (currentInstr.nArguments == 1) p = 1.0 / p; … … 350 164 } 351 165 case OpCodes.Average: { 352 double sum = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);353 for (int i = 1; i < currentInstr.nArguments; i++) { 354 sum += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);166 double sum = Evaluate(dataset, ref row, state); 167 for (int i = 1; i < currentInstr.nArguments; i++) { 168 sum += Evaluate(dataset, ref row, state); 355 169 } 356 170 return sum / currentInstr.nArguments; 357 171 } 358 172 case OpCodes.Cos: { 359 return Math.Cos(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));173 return Math.Cos(Evaluate(dataset, ref row, state)); 360 174 } 361 175 case OpCodes.Sin: { 362 return Math.Sin(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));176 return Math.Sin(Evaluate(dataset, ref row, state)); 363 177 } 364 178 case OpCodes.Tan: { 365 return Math.Tan(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));179 return Math.Tan(Evaluate(dataset, ref row, state)); 366 180 } 367 181 case OpCodes.Square: { 368 return Math.Pow(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues), 2);182 return Math.Pow(Evaluate(dataset, ref row, state), 2); 369 183 } 370 184 case OpCodes.Power: { 371 double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);372 double y = Math.Round(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));185 double x = Evaluate(dataset, ref row, state); 186 double y = Math.Round(Evaluate(dataset, ref row, state)); 373 187 return Math.Pow(x, y); 374 188 } 375 189 case OpCodes.SquareRoot: { 376 return Math.Sqrt(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));190 return Math.Sqrt(Evaluate(dataset, ref row, state)); 377 191 } 378 192 case OpCodes.Root: { 379 double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);380 double y = Math.Round(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));193 double x = Evaluate(dataset, ref row, state); 194 double y = Math.Round(Evaluate(dataset, ref row, state)); 381 195 return Math.Pow(x, 1 / y); 382 196 } 383 197 case OpCodes.Exp: { 384 return Math.Exp(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));198 return Math.Exp(Evaluate(dataset, ref row, state)); 385 199 } 386 200 case OpCodes.Log: { 387 return Math.Log(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues));201 return Math.Log(Evaluate(dataset, ref row, state)); 388 202 } 389 203 case OpCodes.Gamma: { 390 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);204 var x = Evaluate(dataset, ref row, state); 391 205 if (double.IsNaN(x)) return double.NaN; 392 206 else return alglib.gammafunction(x); 393 207 } 394 208 case OpCodes.Psi: { 395 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);209 var x = Evaluate(dataset, ref row, state); 396 210 if (double.IsNaN(x)) return double.NaN; 397 211 else if (x <= 0 && (Math.Floor(x) - x).IsAlmost(0)) return double.NaN; … … 399 213 } 400 214 case OpCodes.Dawson: { 401 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);215 var x = Evaluate(dataset, ref row, state); 402 216 if (double.IsNaN(x)) return double.NaN; 403 217 return alglib.dawsonintegral(x); 404 218 } 405 219 case OpCodes.ExponentialIntegralEi: { 406 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);220 var x = Evaluate(dataset, ref row, state); 407 221 if (double.IsNaN(x)) return double.NaN; 408 222 return alglib.exponentialintegralei(x); … … 410 224 case OpCodes.SineIntegral: { 411 225 double si, ci; 412 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);226 var x = Evaluate(dataset, ref row, state); 413 227 if (double.IsNaN(x)) return double.NaN; 414 228 else { … … 419 233 case OpCodes.CosineIntegral: { 420 234 double si, ci; 421 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);235 var x = Evaluate(dataset, ref row, state); 422 236 if (double.IsNaN(x)) return double.NaN; 423 237 else { … … 428 242 case OpCodes.HyperbolicSineIntegral: { 429 243 double shi, chi; 430 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);244 var x = Evaluate(dataset, ref row, state); 431 245 if (double.IsNaN(x)) return double.NaN; 432 246 else { … … 437 251 case OpCodes.HyperbolicCosineIntegral: { 438 252 double shi, chi; 439 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);253 var x = Evaluate(dataset, ref row, state); 440 254 if (double.IsNaN(x)) return double.NaN; 441 255 else { … … 446 260 case OpCodes.FresnelCosineIntegral: { 447 261 double c = 0, s = 0; 448 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);262 var x = Evaluate(dataset, ref row, state); 449 263 if (double.IsNaN(x)) return double.NaN; 450 264 else { … … 455 269 case OpCodes.FresnelSineIntegral: { 456 270 double c = 0, s = 0; 457 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);271 var x = Evaluate(dataset, ref row, state); 458 272 if (double.IsNaN(x)) return double.NaN; 459 273 else { … … 464 278 case OpCodes.AiryA: { 465 279 double ai, aip, bi, bip; 466 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);280 var x = Evaluate(dataset, ref row, state); 467 281 if (double.IsNaN(x)) return double.NaN; 468 282 else { … … 473 287 case OpCodes.AiryB: { 474 288 double ai, aip, bi, bip; 475 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);289 var x = Evaluate(dataset, ref row, state); 476 290 if (double.IsNaN(x)) return double.NaN; 477 291 else { … … 481 295 } 482 296 case OpCodes.Norm: { 483 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);297 var x = Evaluate(dataset, ref row, state); 484 298 if (double.IsNaN(x)) return double.NaN; 485 299 else return alglib.normaldistribution(x); 486 300 } 487 301 case OpCodes.Erf: { 488 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);302 var x = Evaluate(dataset, ref row, state); 489 303 if (double.IsNaN(x)) return double.NaN; 490 304 else return alglib.errorfunction(x); 491 305 } 492 306 case OpCodes.Bessel: { 493 var x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);307 var x = Evaluate(dataset, ref row, state); 494 308 if (double.IsNaN(x)) return double.NaN; 495 309 else return alglib.besseli0(x); 496 310 } 497 311 case OpCodes.IfThenElse: { 498 double condition = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);312 double condition = Evaluate(dataset, ref row, state); 499 313 double result; 500 314 if (condition > 0.0) { 501 result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); SkipInstructions(state);315 result = Evaluate(dataset, ref row, state); state.SkipInstructions(); 502 316 } else { 503 SkipInstructions(state); result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);317 state.SkipInstructions(); result = Evaluate(dataset, ref row, state); 504 318 } 505 319 return result; 506 320 } 507 321 case OpCodes.AND: { 508 double result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);509 for (int i = 1; i < currentInstr.nArguments; i++) { 510 if (result > 0.0) result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);322 double result = Evaluate(dataset, ref row, state); 323 for (int i = 1; i < currentInstr.nArguments; i++) { 324 if (result > 0.0) result = Evaluate(dataset, ref row, state); 511 325 else { 512 SkipInstructions(state);326 state.SkipInstructions(); 513 327 } 514 328 } … … 516 330 } 517 331 case OpCodes.OR: { 518 double result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);519 for (int i = 1; i < currentInstr.nArguments; i++) { 520 if (result <= 0.0) result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);332 double result = Evaluate(dataset, ref row, state); 333 for (int i = 1; i < currentInstr.nArguments; i++) { 334 if (result <= 0.0) result = Evaluate(dataset, ref row, state); 521 335 else { 522 SkipInstructions(state);336 state.SkipInstructions(); 523 337 } 524 338 } … … 526 340 } 527 341 case OpCodes.NOT: { 528 return Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues) > 0.0 ? -1.0 : 1.0;342 return Evaluate(dataset, ref row, state) > 0.0 ? -1.0 : 1.0; 529 343 } 530 344 case OpCodes.GT: { 531 double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);532 double y = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);345 double x = Evaluate(dataset, ref row, state); 346 double y = Evaluate(dataset, ref row, state); 533 347 if (x > y) return 1.0; 534 348 else return -1.0; 535 349 } 536 350 case OpCodes.LT: { 537 double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);538 double y = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);351 double x = Evaluate(dataset, ref row, state); 352 double y = Evaluate(dataset, ref row, state); 539 353 if (x < y) return 1.0; 540 354 else return -1.0; … … 543 357 var timeLagTreeNode = (LaggedTreeNode)currentInstr.dynamicNode; 544 358 row += timeLagTreeNode.Lag; 545 double result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);359 double result = Evaluate(dataset, ref row, state); 546 360 row -= timeLagTreeNode.Lag; 547 361 return result; … … 553 367 for (int i = 0; i < Math.Abs(timeLagTreeNode.Lag); i++) { 554 368 row += Math.Sign(timeLagTreeNode.Lag); 555 sum += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);369 sum += Evaluate(dataset, ref row, state); 556 370 state.ProgramCounter = savedPc; 557 371 } 558 372 row -= timeLagTreeNode.Lag; 559 sum += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);373 sum += Evaluate(dataset, ref row, state); 560 374 return sum; 561 375 } … … 567 381 case OpCodes.Derivative: { 568 382 int savedPc = state.ProgramCounter; 569 double f_0 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); row--;383 double f_0 = Evaluate(dataset, ref row, state); row--; 570 384 state.ProgramCounter = savedPc; 571 double f_1 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); row -= 2;385 double f_1 = Evaluate(dataset, ref row, state); row -= 2; 572 386 state.ProgramCounter = savedPc; 573 double f_3 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); row--;387 double f_3 = Evaluate(dataset, ref row, state); row--; 574 388 state.ProgramCounter = savedPc; 575 double f_4 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);389 double f_4 = Evaluate(dataset, ref row, state); 576 390 row += 4; 577 391 … … 582 396 double[] argValues = new double[currentInstr.nArguments]; 583 397 for (int i = 0; i < currentInstr.nArguments; i++) { 584 argValues[i] = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);398 argValues[i] = Evaluate(dataset, ref row, state); 585 399 } 586 400 // push on argument values on stack … … 592 406 state.ProgramCounter = (ushort)currentInstr.iArg0; 593 407 // evaluate the function 594 double v = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);408 double v = Evaluate(dataset, ref row, state); 595 409 596 410 // delete the stack frame … … 608 422 return double.NaN; 609 423 var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode; 610 if (row <= lastObservedRow || !cachedPrognosedValues.ContainsKey(variableTreeNode.VariableName)) return ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight; 611 else return cachedPrognosedValues[variableTreeNode.VariableName][row - lastObservedRow - 1] * variableTreeNode.Weight; 424 return ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight; 612 425 } 613 426 case OpCodes.LagVariable: { … … 616 429 if (actualRow < 0 || actualRow >= dataset.Rows) 617 430 return double.NaN; 618 if (actualRow <= lastObservedRow || !cachedPrognosedValues.ContainsKey(laggedVariableTreeNode.VariableName)) return ((IList<double>)currentInstr.iArg0)[actualRow] * laggedVariableTreeNode.Weight; 619 else return cachedPrognosedValues[laggedVariableTreeNode.VariableName][actualRow - lastObservedRow - 1] * laggedVariableTreeNode.Weight; 431 return ((IList<double>)currentInstr.iArg0)[actualRow] * laggedVariableTreeNode.Weight; 620 432 } 621 433 case OpCodes.Constant: { 622 var constTreeNode = currentInstr.dynamicNode as ConstantTreeNode;434 var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode; 623 435 return constTreeNode.Value; 624 436 } … … 630 442 return double.NaN; 631 443 var variableConditionTreeNode = (VariableConditionTreeNode)currentInstr.dynamicNode; 632 double variableValue; 633 if (row <= lastObservedRow || !cachedPrognosedValues.ContainsKey(variableConditionTreeNode.VariableName)) 634 variableValue = ((IList<double>)currentInstr.iArg0)[row]; 635 else 636 variableValue = cachedPrognosedValues[variableConditionTreeNode.VariableName][row - lastObservedRow - 1]; 637 444 double variableValue = ((IList<double>)currentInstr.iArg0)[row]; 638 445 double x = variableValue - variableConditionTreeNode.Threshold; 639 446 double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x)); 640 447 641 double trueBranch = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);642 double falseBranch = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues);448 double trueBranch = Evaluate(dataset, ref row, state); 449 double falseBranch = Evaluate(dataset, ref row, state); 643 450 644 451 return trueBranch * p + falseBranch * (1 - p); … … 647 454 } 648 455 } 649 650 private byte MapSymbolToOpCode(ISymbolicExpressionTreeNode treeNode) {651 byte opCode;652 if (!symbolToOpcode.TryGetValue(treeNode.Symbol.GetType(), out opCode))653 throw new NotSupportedException("Symbol: " + treeNode.Symbol);654 return opCode;655 }656 657 // skips a whole branch658 private void SkipInstructions(InterpreterState state) {659 int i = 1;660 while (i > 0) {661 i += state.NextInstruction().nArguments;662 i--;663 }664 }665 456 } 666 457 }
Note: See TracChangeset
for help on using the changeset viewer.