Changeset 7120 for branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeInterpreter.cs
- Timestamp:
- 12/05/11 08:22:36 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeInterpreter.cs
r6860 r7120 22 22 using System; 23 23 using System.Collections.Generic; 24 using System.Linq; 24 25 using HeuristicLab.Common; 25 26 using HeuristicLab.Core; … … 32 33 [StorableClass] 33 34 [Item("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.")] 34 public sealed class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter { 35 public sealed class SymbolicDataAnalysisExpressionTreeInterpreter : ParameterizedNamedItem, 36 ISymbolicDataAnalysisExpressionTreeInterpreter, ISymbolicTimeSeriesPrognosisExpressionTreeInterpreter { 35 37 private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic"; 36 38 #region private classes … … 199 201 200 202 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) { 203 return from prog in GetSymbolicExpressionTreeValues(tree, dataset, new string[] { "#NOTHING#" }, rows, 1) 204 select prog.First().First(); 205 } 206 207 // for each row for each target variable one prognosis (=enumerable of future values) 208 public IEnumerable<IEnumerable<IEnumerable<double>>> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, string[] targetVariables, IEnumerable<int> rows, int horizon) { 201 209 if (CheckExpressionsWithIntervalArithmetic.Value) 202 210 throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter."); … … 223 231 var state = new InterpreterState(code, necessaryArgStackSize); 224 232 233 int nComponents = tree.Root.GetSubtree(0).SubtreeCount; 234 // produce a n-step forecast for each target variable for all rows 235 var cachedPrognosedValues = new Dictionary<string, double[]>(); 236 foreach (var targetVariable in targetVariables) 237 cachedPrognosedValues[targetVariable] = new double[horizon]; 225 238 foreach (var rowEnum in rows) { 226 239 int row = rowEnum; 227 state.Reset(); 228 yield return Evaluate(dataset, ref row, state); 229 } 230 } 231 232 private double Evaluate(Dataset dataset, ref int row, InterpreterState state) { 240 List<double[]> vProgs = new List<double[]>(); 241 foreach (var horizonRow in Enumerable.Range(row, horizon)) { 242 int localRow = horizonRow; // create a local variable for the ref parameter 243 var vPrognosis = from i in Enumerable.Range(0, nComponents) 244 select Evaluate(dataset, ref localRow, row - 1, state, cachedPrognosedValues); 245 246 var vPrognosisArr = vPrognosis.ToArray(); 247 vProgs.Add(vPrognosisArr); 248 // set cachedValues for prognosis of future values 249 for (int i = 0; i < vPrognosisArr.Length; i++) 250 cachedPrognosedValues[targetVariables[i]][horizonRow - row] = vPrognosisArr[i]; 251 252 state.Reset(); 253 } 254 255 yield return from component in Enumerable.Range(0, nComponents) 256 select from prognosisStep in Enumerable.Range(0, vProgs.Count) 257 select vProgs[prognosisStep][component]; 258 } 259 } 260 261 private double Evaluate(Dataset dataset, ref int row, int lastObservedRow, InterpreterState state, Dictionary<string, double[]> cachedPrognosedValues) { 233 262 Instruction currentInstr = state.NextInstruction(); 234 263 switch (currentInstr.opCode) { 235 264 case OpCodes.Add: { 236 double s = Evaluate(dataset, ref row, state);237 for (int i = 1; i < currentInstr.nArguments; i++) { 238 s += Evaluate(dataset, ref row, state);265 double s = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 266 for (int i = 1; i < currentInstr.nArguments; i++) { 267 s += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 239 268 } 240 269 return s; 241 270 } 242 271 case OpCodes.Sub: { 243 double s = Evaluate(dataset, ref row, state);244 for (int i = 1; i < currentInstr.nArguments; i++) { 245 s -= Evaluate(dataset, ref row, state);272 double s = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 273 for (int i = 1; i < currentInstr.nArguments; i++) { 274 s -= Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 246 275 } 247 276 if (currentInstr.nArguments == 1) s = -s; … … 249 278 } 250 279 case OpCodes.Mul: { 251 double p = Evaluate(dataset, ref row, state);252 for (int i = 1; i < currentInstr.nArguments; i++) { 253 p *= Evaluate(dataset, ref row, state);280 double p = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 281 for (int i = 1; i < currentInstr.nArguments; i++) { 282 p *= Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 254 283 } 255 284 return p; 256 285 } 257 286 case OpCodes.Div: { 258 double p = Evaluate(dataset, ref row, state);259 for (int i = 1; i < currentInstr.nArguments; i++) { 260 p /= Evaluate(dataset, ref row, state);287 double p = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 288 for (int i = 1; i < currentInstr.nArguments; i++) { 289 p /= Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 261 290 } 262 291 if (currentInstr.nArguments == 1) p = 1.0 / p; … … 264 293 } 265 294 case OpCodes.Average: { 266 double sum = Evaluate(dataset, ref row, state);267 for (int i = 1; i < currentInstr.nArguments; i++) { 268 sum += Evaluate(dataset, ref row, state);295 double sum = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 296 for (int i = 1; i < currentInstr.nArguments; i++) { 297 sum += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 269 298 } 270 299 return sum / currentInstr.nArguments; 271 300 } 272 301 case OpCodes.Cos: { 273 return Math.Cos(Evaluate(dataset, ref row, state));302 return Math.Cos(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues)); 274 303 } 275 304 case OpCodes.Sin: { 276 return Math.Sin(Evaluate(dataset, ref row, state));305 return Math.Sin(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues)); 277 306 } 278 307 case OpCodes.Tan: { 279 return Math.Tan(Evaluate(dataset, ref row, state));308 return Math.Tan(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues)); 280 309 } 281 310 case OpCodes.Power: { 282 double x = Evaluate(dataset, ref row, state);283 double y = Math.Round(Evaluate(dataset, ref row, state));311 double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 312 double y = Math.Round(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues)); 284 313 return Math.Pow(x, y); 285 314 } 286 315 case OpCodes.Root: { 287 double x = Evaluate(dataset, ref row, state);288 double y = Math.Round(Evaluate(dataset, ref row, state));316 double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 317 double y = Math.Round(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues)); 289 318 return Math.Pow(x, 1 / y); 290 319 } 291 320 case OpCodes.Exp: { 292 return Math.Exp(Evaluate(dataset, ref row, state));321 return Math.Exp(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues)); 293 322 } 294 323 case OpCodes.Log: { 295 return Math.Log(Evaluate(dataset, ref row, state));324 return Math.Log(Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues)); 296 325 } 297 326 case OpCodes.IfThenElse: { 298 double condition = Evaluate(dataset, ref row, state);327 double condition = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 299 328 double result; 300 329 if (condition > 0.0) { 301 result = Evaluate(dataset, ref row, state); SkipInstructions(state);330 result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); SkipInstructions(state); 302 331 } else { 303 SkipInstructions(state); result = Evaluate(dataset, ref row, state);332 SkipInstructions(state); result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 304 333 } 305 334 return result; 306 335 } 307 336 case OpCodes.AND: { 308 double result = Evaluate(dataset, ref row, state);309 for (int i = 1; i < currentInstr.nArguments; i++) { 310 if (result > 0.0) result = Evaluate(dataset, ref row, state);337 double result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 338 for (int i = 1; i < currentInstr.nArguments; i++) { 339 if (result > 0.0) result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 311 340 else { 312 341 SkipInstructions(state); … … 316 345 } 317 346 case OpCodes.OR: { 318 double result = Evaluate(dataset, ref row, state);319 for (int i = 1; i < currentInstr.nArguments; i++) { 320 if (result <= 0.0) result = Evaluate(dataset, ref row, state);347 double result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 348 for (int i = 1; i < currentInstr.nArguments; i++) { 349 if (result <= 0.0) result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 321 350 else { 322 351 SkipInstructions(state); … … 326 355 } 327 356 case OpCodes.NOT: { 328 return Evaluate(dataset, ref row, state) > 0.0 ? -1.0 : 1.0;357 return Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues) > 0.0 ? -1.0 : 1.0; 329 358 } 330 359 case OpCodes.GT: { 331 double x = Evaluate(dataset, ref row, state);332 double y = Evaluate(dataset, ref row, state);360 double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 361 double y = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 333 362 if (x > y) return 1.0; 334 363 else return -1.0; 335 364 } 336 365 case OpCodes.LT: { 337 double x = Evaluate(dataset, ref row, state);338 double y = Evaluate(dataset, ref row, state);366 double x = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 367 double y = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 339 368 if (x < y) return 1.0; 340 369 else return -1.0; … … 343 372 var timeLagTreeNode = (LaggedTreeNode)currentInstr.dynamicNode; 344 373 row += timeLagTreeNode.Lag; 345 double result = Evaluate(dataset, ref row, state);374 double result = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 346 375 row -= timeLagTreeNode.Lag; 347 376 return result; … … 353 382 for (int i = 0; i < Math.Abs(timeLagTreeNode.Lag); i++) { 354 383 row += Math.Sign(timeLagTreeNode.Lag); 355 sum += Evaluate(dataset, ref row, state);384 sum += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 356 385 state.ProgramCounter = savedPc; 357 386 } 358 387 row -= timeLagTreeNode.Lag; 359 sum += Evaluate(dataset, ref row, state);388 sum += Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 360 389 return sum; 361 390 } … … 367 396 case OpCodes.Derivative: { 368 397 int savedPc = state.ProgramCounter; 369 double f_0 = Evaluate(dataset, ref row, state); row--;398 double f_0 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); row--; 370 399 state.ProgramCounter = savedPc; 371 double f_1 = Evaluate(dataset, ref row, state); row -= 2;400 double f_1 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); row -= 2; 372 401 state.ProgramCounter = savedPc; 373 double f_3 = Evaluate(dataset, ref row, state); row--;402 double f_3 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); row--; 374 403 state.ProgramCounter = savedPc; 375 double f_4 = Evaluate(dataset, ref row, state);404 double f_4 = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 376 405 row += 4; 377 406 … … 382 411 double[] argValues = new double[currentInstr.nArguments]; 383 412 for (int i = 0; i < currentInstr.nArguments; i++) { 384 argValues[i] = Evaluate(dataset, ref row, state);413 argValues[i] = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 385 414 } 386 415 // push on argument values on stack … … 392 421 state.ProgramCounter = (ushort)currentInstr.iArg0; 393 422 // evaluate the function 394 double v = Evaluate(dataset, ref row, state);423 double v = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 395 424 396 425 // delete the stack frame … … 408 437 return double.NaN; 409 438 var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode; 410 return ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight; 439 if (row <= lastObservedRow || !cachedPrognosedValues.ContainsKey(variableTreeNode.VariableName)) return ((IList<double>)currentInstr.iArg0)[row] * variableTreeNode.Weight; 440 else return cachedPrognosedValues[variableTreeNode.VariableName][row - lastObservedRow - 1] * variableTreeNode.Weight; 411 441 } 412 442 case OpCodes.LagVariable: { … … 415 445 if (actualRow < 0 || actualRow >= dataset.Rows) 416 446 return double.NaN; 417 return ((IList<double>)currentInstr.iArg0)[actualRow] * laggedVariableTreeNode.Weight; 447 if (actualRow <= lastObservedRow || !cachedPrognosedValues.ContainsKey(laggedVariableTreeNode.VariableName)) return ((IList<double>)currentInstr.iArg0)[actualRow] * laggedVariableTreeNode.Weight; 448 else return cachedPrognosedValues[laggedVariableTreeNode.VariableName][actualRow - lastObservedRow - 1] * laggedVariableTreeNode.Weight; 418 449 } 419 450 case OpCodes.Constant: { … … 428 459 return double.NaN; 429 460 var variableConditionTreeNode = (VariableConditionTreeNode)currentInstr.dynamicNode; 430 double variableValue = ((IList<double>)currentInstr.iArg0)[row]; 461 double variableValue; 462 if (row <= lastObservedRow || !cachedPrognosedValues.ContainsKey(variableConditionTreeNode.VariableName)) 463 variableValue = ((IList<double>)currentInstr.iArg0)[row]; 464 else 465 variableValue = cachedPrognosedValues[variableConditionTreeNode.VariableName][row - lastObservedRow - 1]; 466 431 467 double x = variableValue - variableConditionTreeNode.Threshold; 432 468 double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x)); 433 469 434 double trueBranch = Evaluate(dataset, ref row, state);435 double falseBranch = Evaluate(dataset, ref row, state);470 double trueBranch = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 471 double falseBranch = Evaluate(dataset, ref row, lastObservedRow, state, cachedPrognosedValues); 436 472 437 473 return trueBranch * p + falseBranch * (1 - p);
Note: See TracChangeset
for help on using the changeset viewer.