Changeset 13222 for branches/HeuristicLab.LinqExpressionTreeInterpreter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
- Timestamp:
- 11/17/15 16:21:29 (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.LinqExpressionTreeInterpreter/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
r13141 r13222 32 32 [StorableClass] 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 … … 54 61 set { CheckExpressionsWithIntervalArithmeticParameter.Value.Value = value; } 55 62 } 63 56 64 public int EvaluatedSolutions { 57 65 get { return EvaluatedSolutionsParameter.Value.Value; } … … 62 70 [StorableConstructor] 63 71 protected SymbolicDataAnalysisExpressionTreeInterpreter(bool deserializing) : base(deserializing) { } 64 protected SymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original, Cloner cloner) : base(original, cloner) { } 72 73 protected SymbolicDataAnalysisExpressionTreeInterpreter(SymbolicDataAnalysisExpressionTreeInterpreter original, 74 Cloner cloner) : base(original, cloner) { } 75 65 76 public override IDeepCloneable Clone(Cloner cloner) { 66 77 return new SymbolicDataAnalysisExpressionTreeInterpreter(this, cloner); … … 69 80 public SymbolicDataAnalysisExpressionTreeInterpreter() 70 81 : base("SymbolicDataAnalysisExpressionTreeInterpreter", "Interpreter for symbolic expression trees including automatically defined functions.") { 71 Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, 72 "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false))); 82 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))); 73 83 Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0))); 74 84 } … … 76 86 protected SymbolicDataAnalysisExpressionTreeInterpreter(string name, string description) 77 87 : base(name, description) { 78 Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, 79 "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false))); 88 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))); 80 89 Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0))); 81 90 } … … 83 92 [StorableHook(HookType.AfterDeserialization)] 84 93 private void AfterDeserialization() { 85 Parameters.Remove(EvaluatedSolutionsParameterName); 86 Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0))); 87 88 Parameters.Remove(CheckExpressionsWithIntervalArithmeticParameterName); 89 Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, 90 "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false))); 94 var evaluatedSolutions = new IntValue(0); 95 var checkExpressionsWithIntervalArithmetic = new BoolValue(false); 96 if (Parameters.ContainsKey(EvaluatedSolutionsParameterName)) { 97 var evaluatedSolutionsParameter = (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; 98 evaluatedSolutions = evaluatedSolutionsParameter.Value; 99 Parameters.Remove(EvaluatedSolutionsParameterName); 100 } 101 Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", evaluatedSolutions)); 102 if (Parameters.ContainsKey(CheckExpressionsWithIntervalArithmeticParameterName)) { 103 var checkExpressionsWithIntervalArithmeticParameter = (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; 104 Parameters.Remove(CheckExpressionsWithIntervalArithmeticParameterName); 105 checkExpressionsWithIntervalArithmetic = checkExpressionsWithIntervalArithmeticParameter.Value; 106 } 107 Parameters.Add(new FixedValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, CheckExpressionsWithIntervalArithmeticParameterDescription, checkExpressionsWithIntervalArithmetic)); 91 108 } 92 109 … … 96 113 } 97 114 98 public void ClearState() { 99 } 115 public void ClearState() { } 100 116 #endregion 101 117 102 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) { 103 if (CheckExpressionsWithIntervalArithmetic) 118 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, 119 IEnumerable<int> rows) { 120 if (CheckExpressionsWithIntervalArithmetic) { 104 121 throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter."); 122 } 105 123 106 124 lock (EvaluatedSolutionsParameter.Value) { … … 136 154 } 137 155 138 139 156 public virtual double Evaluate(IDataset dataset, ref int row, InterpreterState state) { 140 157 Instruction currentInstr = state.NextInstruction(); 141 158 switch (currentInstr.opCode) { 142 case OpCodes.Add: 143 { 159 case OpCodes.Add: { 144 160 double s = Evaluate(dataset, ref row, state); 145 161 for (int i = 1; i < currentInstr.nArguments; i++) { … … 148 164 return s; 149 165 } 150 case OpCodes.Sub: 151 { 166 case OpCodes.Sub: { 152 167 double s = Evaluate(dataset, ref row, state); 153 168 for (int i = 1; i < currentInstr.nArguments; i++) { 154 169 s -= Evaluate(dataset, ref row, state); 155 170 } 156 if (currentInstr.nArguments == 1) s = -s;171 if (currentInstr.nArguments == 1) { s = -s; } 157 172 return s; 158 173 } 159 case OpCodes.Mul: 160 { 174 case OpCodes.Mul: { 161 175 double p = Evaluate(dataset, ref row, state); 162 176 for (int i = 1; i < currentInstr.nArguments; i++) { … … 165 179 return p; 166 180 } 167 case OpCodes.Div: 168 { 181 case OpCodes.Div: { 169 182 double p = Evaluate(dataset, ref row, state); 170 183 for (int i = 1; i < currentInstr.nArguments; i++) { 171 184 p /= Evaluate(dataset, ref row, state); 172 185 } 173 if (currentInstr.nArguments == 1) p = 1.0 / p;186 if (currentInstr.nArguments == 1) { p = 1.0 / p; } 174 187 return p; 175 188 } 176 case OpCodes.Average: 177 { 189 case OpCodes.Average: { 178 190 double sum = Evaluate(dataset, ref row, state); 179 191 for (int i = 1; i < currentInstr.nArguments; i++) { … … 182 194 return sum / currentInstr.nArguments; 183 195 } 184 case OpCodes.Cos: 185 { 196 case OpCodes.Cos: { 186 197 return Math.Cos(Evaluate(dataset, ref row, state)); 187 198 } 188 case OpCodes.Sin: 189 { 199 case OpCodes.Sin: { 190 200 return Math.Sin(Evaluate(dataset, ref row, state)); 191 201 } 192 case OpCodes.Tan: 193 { 202 case OpCodes.Tan: { 194 203 return Math.Tan(Evaluate(dataset, ref row, state)); 195 204 } 196 case OpCodes.Square: 197 { 205 case OpCodes.Square: { 198 206 return Math.Pow(Evaluate(dataset, ref row, state), 2); 199 207 } 200 case OpCodes.Power: 201 { 208 case OpCodes.Power: { 202 209 double x = Evaluate(dataset, ref row, state); 203 210 double y = Math.Round(Evaluate(dataset, ref row, state)); 204 211 return Math.Pow(x, y); 205 212 } 206 case OpCodes.SquareRoot: 207 { 213 case OpCodes.SquareRoot: { 208 214 return Math.Sqrt(Evaluate(dataset, ref row, state)); 209 215 } 210 case OpCodes.Root: 211 { 216 case OpCodes.Root: { 212 217 double x = Evaluate(dataset, ref row, state); 213 218 double y = Math.Round(Evaluate(dataset, ref row, state)); 214 219 return Math.Pow(x, 1 / y); 215 220 } 216 case OpCodes.Exp: 217 { 221 case OpCodes.Exp: { 218 222 return Math.Exp(Evaluate(dataset, ref row, state)); 219 223 } 220 case OpCodes.Log: 221 { 224 case OpCodes.Log: { 222 225 return Math.Log(Evaluate(dataset, ref row, state)); 223 226 } 224 case OpCodes.Gamma: 225 { 226 var x = Evaluate(dataset, ref row, state); 227 if (double.IsNaN(x)) return double.NaN; 228 else return alglib.gammafunction(x); 229 } 230 case OpCodes.Psi: 231 { 227 case OpCodes.Gamma: { 228 var x = Evaluate(dataset, ref row, state); 229 if (double.IsNaN(x)) { return double.NaN; } else { return alglib.gammafunction(x); } 230 } 231 case OpCodes.Psi: { 232 232 var x = Evaluate(dataset, ref row, state); 233 233 if (double.IsNaN(x)) return double.NaN; … … 235 235 return alglib.psi(x); 236 236 } 237 case OpCodes.Dawson: 238 { 239 var x = Evaluate(dataset, ref row, state); 240 if (double.IsNaN(x)) return double.NaN; 237 case OpCodes.Dawson: { 238 var x = Evaluate(dataset, ref row, state); 239 if (double.IsNaN(x)) { return double.NaN; } 241 240 return alglib.dawsonintegral(x); 242 241 } 243 case OpCodes.ExponentialIntegralEi: 244 { 245 var x = Evaluate(dataset, ref row, state); 246 if (double.IsNaN(x)) return double.NaN; 242 case OpCodes.ExponentialIntegralEi: { 243 var x = Evaluate(dataset, ref row, state); 244 if (double.IsNaN(x)) { return double.NaN; } 247 245 return alglib.exponentialintegralei(x); 248 246 } 249 case OpCodes.SineIntegral: 250 { 247 case OpCodes.SineIntegral: { 251 248 double si, ci; 252 249 var x = Evaluate(dataset, ref row, state); … … 257 254 } 258 255 } 259 case OpCodes.CosineIntegral: 260 { 256 case OpCodes.CosineIntegral: { 261 257 double si, ci; 262 258 var x = Evaluate(dataset, ref row, state); … … 267 263 } 268 264 } 269 case OpCodes.HyperbolicSineIntegral: 270 { 265 case OpCodes.HyperbolicSineIntegral: { 271 266 double shi, chi; 272 267 var x = Evaluate(dataset, ref row, state); … … 277 272 } 278 273 } 279 case OpCodes.HyperbolicCosineIntegral: 280 { 274 case OpCodes.HyperbolicCosineIntegral: { 281 275 double shi, chi; 282 276 var x = Evaluate(dataset, ref row, state); … … 287 281 } 288 282 } 289 case OpCodes.FresnelCosineIntegral: 290 { 283 case OpCodes.FresnelCosineIntegral: { 291 284 double c = 0, s = 0; 292 285 var x = Evaluate(dataset, ref row, state); … … 297 290 } 298 291 } 299 case OpCodes.FresnelSineIntegral: 300 { 292 case OpCodes.FresnelSineIntegral: { 301 293 double c = 0, s = 0; 302 294 var x = Evaluate(dataset, ref row, state); … … 307 299 } 308 300 } 309 case OpCodes.AiryA: 310 { 301 case OpCodes.AiryA: { 311 302 double ai, aip, bi, bip; 312 303 var x = Evaluate(dataset, ref row, state); … … 317 308 } 318 309 } 319 case OpCodes.AiryB: 320 { 310 case OpCodes.AiryB: { 321 311 double ai, aip, bi, bip; 322 312 var x = Evaluate(dataset, ref row, state); … … 327 317 } 328 318 } 329 case OpCodes.Norm: 330 { 319 case OpCodes.Norm: { 331 320 var x = Evaluate(dataset, ref row, state); 332 321 if (double.IsNaN(x)) return double.NaN; 333 322 else return alglib.normaldistribution(x); 334 323 } 335 case OpCodes.Erf: 336 { 324 case OpCodes.Erf: { 337 325 var x = Evaluate(dataset, ref row, state); 338 326 if (double.IsNaN(x)) return double.NaN; 339 327 else return alglib.errorfunction(x); 340 328 } 341 case OpCodes.Bessel: 342 { 329 case OpCodes.Bessel: { 343 330 var x = Evaluate(dataset, ref row, state); 344 331 if (double.IsNaN(x)) return double.NaN; 345 332 else return alglib.besseli0(x); 346 333 } 347 case OpCodes.IfThenElse: 348 { 334 case OpCodes.IfThenElse: { 349 335 double condition = Evaluate(dataset, ref row, state); 350 336 double result; … … 356 342 return result; 357 343 } 358 case OpCodes.AND: 359 { 344 case OpCodes.AND: { 360 345 double result = Evaluate(dataset, ref row, state); 361 346 for (int i = 1; i < currentInstr.nArguments; i++) { … … 367 352 return result > 0.0 ? 1.0 : -1.0; 368 353 } 369 case OpCodes.OR: 370 { 354 case OpCodes.OR: { 371 355 double result = Evaluate(dataset, ref row, state); 372 356 for (int i = 1; i < currentInstr.nArguments; i++) { … … 378 362 return result > 0.0 ? 1.0 : -1.0; 379 363 } 380 case OpCodes.NOT: 381 { 364 case OpCodes.NOT: { 382 365 return Evaluate(dataset, ref row, state) > 0.0 ? -1.0 : 1.0; 383 366 } 384 case OpCodes.XOR: 385 { 367 case OpCodes.XOR: { 386 368 //mkommend: XOR on multiple inputs is defined as true if the number of positive signals is odd 387 369 // this is equal to a consecutive execution of binary XOR operations. 388 370 int positiveSignals = 0; 389 371 for (int i = 0; i < currentInstr.nArguments; i++) { 390 if (Evaluate(dataset, ref row, state) > 0.0) positiveSignals++;372 if (Evaluate(dataset, ref row, state) > 0.0) { positiveSignals++; } 391 373 } 392 374 return positiveSignals % 2 != 0 ? 1.0 : -1.0; 393 375 } 394 case OpCodes.GT: 395 { 376 case OpCodes.GT: { 396 377 double x = Evaluate(dataset, ref row, state); 397 378 double y = Evaluate(dataset, ref row, state); 398 if (x > y) return 1.0; 399 else return -1.0; 400 } 401 case OpCodes.LT: 402 { 379 if (x > y) { return 1.0; } else { return -1.0; } 380 } 381 case OpCodes.LT: { 403 382 double x = Evaluate(dataset, ref row, state); 404 383 double y = Evaluate(dataset, ref row, state); 405 if (x < y) return 1.0; 406 else return -1.0; 407 } 408 case OpCodes.TimeLag: 409 { 384 if (x < y) { return 1.0; } else { return -1.0; } 385 } 386 case OpCodes.TimeLag: { 410 387 var timeLagTreeNode = (LaggedTreeNode)currentInstr.dynamicNode; 411 388 row += timeLagTreeNode.Lag; … … 414 391 return result; 415 392 } 416 case OpCodes.Integral: 417 { 393 case OpCodes.Integral: { 418 394 int savedPc = state.ProgramCounter; 419 395 var timeLagTreeNode = (LaggedTreeNode)currentInstr.dynamicNode; … … 433 409 //one sided smooth differentiatior, N = 4 434 410 // y' = 1/8h (f_i + 2f_i-1, -2 f_i-3 - f_i-4) 435 case OpCodes.Derivative: 436 { 411 case OpCodes.Derivative: { 437 412 int savedPc = state.ProgramCounter; 438 413 double f_0 = Evaluate(dataset, ref row, state); row--; … … 447 422 return (f_0 + 2 * f_1 - 2 * f_3 - f_4) / 8; // h = 1 448 423 } 449 case OpCodes.Call: 450 { 424 case OpCodes.Call: { 451 425 // evaluate sub-trees 452 426 double[] argValues = new double[currentInstr.nArguments]; … … 471 445 return v; 472 446 } 473 case OpCodes.Arg: 474 { 447 case OpCodes.Arg: { 475 448 return state.GetStackFrameValue((ushort)currentInstr.data); 476 449 } 477 case OpCodes.Variable: 478 { 450 case OpCodes.Variable: { 479 451 if (row < 0 || row >= dataset.Rows) return double.NaN; 480 452 var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode; 481 453 return ((IList<double>)currentInstr.data)[row] * variableTreeNode.Weight; 482 454 } 483 case OpCodes.LagVariable: 484 { 455 case OpCodes.LagVariable: { 485 456 var laggedVariableTreeNode = (LaggedVariableTreeNode)currentInstr.dynamicNode; 486 457 int actualRow = row + laggedVariableTreeNode.Lag; 487 if (actualRow < 0 || actualRow >= dataset.Rows) return double.NaN;458 if (actualRow < 0 || actualRow >= dataset.Rows) { return double.NaN; } 488 459 return ((IList<double>)currentInstr.data)[actualRow] * laggedVariableTreeNode.Weight; 489 460 } 490 case OpCodes.Constant: 491 { 461 case OpCodes.Constant: { 492 462 var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode; 493 463 return constTreeNode.Value; … … 496 466 //mkommend: this symbol uses the logistic function f(x) = 1 / (1 + e^(-alpha * x) ) 497 467 //to determine the relative amounts of the true and false branch see http://en.wikipedia.org/wiki/Logistic_function 498 case OpCodes.VariableCondition: 499 { 468 case OpCodes.VariableCondition: { 500 469 if (row < 0 || row >= dataset.Rows) return double.NaN; 501 470 var variableConditionTreeNode = (VariableConditionTreeNode)currentInstr.dynamicNode; … … 509 478 return trueBranch * p + falseBranch * (1 - p); 510 479 } 511 default: throw new NotSupportedException(); 480 default: 481 throw new NotSupportedException(); 512 482 } 513 483 }
Note: See TracChangeset
for help on using the changeset viewer.