Changeset 8436
- Timestamp:
- 08/08/12 16:04:29 (12 years ago)
- Location:
- branches/HeuristicLab.TimeSeries
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.TimeSeries/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Compiler/SymbolicExpressionTreeCompiler.cs
r7989 r8436 53 53 var invokeNode = (InvokeFunctionTreeNode)instr.dynamicNode; 54 54 instr.iArg0 = entryPoint[invokeNode.Symbol.FunctionName]; 55 code[i] = instr;56 55 } 57 56 } -
branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/InterpreterState.cs
r8431 r8436 24 24 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 25 25 public class InterpreterState { 26 private double[] argumentStack;26 private readonly double[] argumentStack; 27 27 private int argumentStackPointer; 28 private Instruction[] code; 29 private int pc; 30 public int ProgramCounter { 31 get { return pc; } 32 set { pc = value; } 33 } 28 private readonly Instruction[] code; 29 30 public int ProgramCounter { get; set; } 31 public bool InLaggedContext { get; set; } 32 34 33 public InterpreterState(Instruction[] code, int argumentStackSize) { 35 34 this.code = code; 36 this.pc = 0; 35 this.ProgramCounter = 0; 36 this.InLaggedContext = false; 37 37 if (argumentStackSize > 0) { 38 38 this.argumentStack = new double[argumentStackSize]; … … 42 42 43 43 public void Reset() { 44 this. pc= 0;44 this.ProgramCounter = 0; 45 45 this.argumentStackPointer = 0; 46 this.InLaggedContext = false; 46 47 } 47 48 48 49 public Instruction NextInstruction() { 49 return code[ pc++];50 return code[ProgramCounter++]; 50 51 } 51 52 // skips a whole branch -
branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs
r8431 r8436 84 84 85 85 private static Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() { 86 { typeof(Addition), OpCodes.Add },86 { typeof(Addition), OpCodes.Add }, 87 87 { typeof(Subtraction), OpCodes.Sub }, 88 88 { typeof(Multiplication), OpCodes.Mul }, … … 127 127 { typeof(Norm), OpCodes.Norm}, 128 128 { typeof(Erf), OpCodes.Erf}, 129 { typeof(Bessel), OpCodes.Bessel} 129 { typeof(Bessel), OpCodes.Bessel} 130 130 }; 131 131 -
branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
r8432 r8436 35 35 [StorableClass] 36 36 [Item("SymbolicDataAnalysisExpressionTreeILEmittingInterpreter", "Interpreter for symbolic expression trees.")] 37 public sealed class SymbolicDataAnalysisExpressionTreeILEmittingInterpreter : ParameterizedNamedItem, 38 ISymbolicDataAnalysisExpressionTreeInterpreter { 39 private static MethodInfo listGetValue = 40 typeof(IList<double>).GetProperty("Item", new Type[] { typeof(int) }).GetGetMethod(); 37 public sealed class SymbolicDataAnalysisExpressionTreeILEmittingInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter { 38 private static readonly Type thisType = typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter); 39 internal delegate double CompiledFunction(int sampleIndex, IList<double>[] columns); 40 41 #region method infos 42 private static MethodInfo listGetValue = typeof(IList<double>).GetProperty("Item", new Type[] { typeof(int) }).GetGetMethod(); 41 43 42 44 private static MethodInfo cos = typeof(Math).GetMethod("Cos", new Type[] { typeof(double) }); … … 49 51 private static MethodInfo sqrt = typeof(Math).GetMethod("Sqrt", new Type[] { typeof(double) }); 50 52 51 internal delegate double CompiledFunction(int sampleIndex, IList<double>[] columns, IList<double>[] cachedValues, int cacheStartIndex);52 private static Type thisType = typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter);53 53 private static MethodInfo airyA = thisType.GetMethod("AiryA", new Type[] { typeof(double) }); 54 54 private static MethodInfo airyB = thisType.GetMethod("AiryB", new Type[] { typeof(double) }); … … 66 66 private static MethodInfo erf = thisType.GetMethod("Erf", new Type[] { typeof(double) }); 67 67 private static MethodInfo bessel = thisType.GetMethod("Bessel", new Type[] { typeof(double) }); 68 69 68 #endregion 70 69 71 70 private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic"; 72 71 private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions"; 73 74 #region private classes75 76 private class InterpreterState {77 private Instruction[] code;78 private int pc;79 80 public int ProgramCounter {81 get { return pc; }82 set { pc = value; }83 }84 85 private bool inLaggedContext;86 87 public bool InLaggedContext {88 get { return inLaggedContext; }89 set { inLaggedContext = value; }90 }91 92 internal InterpreterState(Instruction[] code) {93 this.inLaggedContext = false;94 this.code = code;95 this.pc = 0;96 }97 98 internal Instruction NextInstruction() {99 return code[pc++];100 }101 }102 103 private class OpCodes {104 public const byte Add = 1;105 public const byte Sub = 2;106 public const byte Mul = 3;107 public const byte Div = 4;108 109 public const byte Sin = 5;110 public const byte Cos = 6;111 public const byte Tan = 7;112 113 public const byte Log = 8;114 public const byte Exp = 9;115 116 public const byte IfThenElse = 10;117 118 public const byte GT = 11;119 public const byte LT = 12;120 121 public const byte AND = 13;122 public const byte OR = 14;123 public const byte NOT = 15;124 125 126 public const byte Average = 16;127 128 public const byte Call = 17;129 130 public const byte Variable = 18;131 public const byte LagVariable = 19;132 public const byte Constant = 20;133 public const byte Arg = 21;134 135 public const byte Power = 22;136 public const byte Root = 23;137 public const byte TimeLag = 24;138 public const byte Integral = 25;139 public const byte Derivative = 26;140 141 public const byte VariableCondition = 27;142 143 public const byte Square = 28;144 public const byte SquareRoot = 29;145 public const byte Gamma = 30;146 public const byte Psi = 31;147 public const byte Dawson = 32;148 public const byte ExponentialIntegralEi = 33;149 public const byte CosineIntegral = 34;150 public const byte SineIntegral = 35;151 public const byte HyperbolicCosineIntegral = 36;152 public const byte HyperbolicSineIntegral = 37;153 public const byte FresnelCosineIntegral = 38;154 public const byte FresnelSineIntegral = 39;155 public const byte AiryA = 40;156 public const byte AiryB = 41;157 public const byte Norm = 42;158 public const byte Erf = 43;159 public const byte Bessel = 44;160 }161 162 #endregion163 164 private Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>()165 {166 {typeof (Addition), OpCodes.Add},167 {typeof (Subtraction), OpCodes.Sub},168 {typeof (Multiplication), OpCodes.Mul},169 {typeof (Division), OpCodes.Div},170 {typeof (Sine), OpCodes.Sin},171 {typeof (Cosine), OpCodes.Cos},172 {typeof (Tangent), OpCodes.Tan},173 {typeof (Logarithm), OpCodes.Log},174 {typeof (Exponential), OpCodes.Exp},175 {typeof (IfThenElse), OpCodes.IfThenElse},176 {typeof (GreaterThan), OpCodes.GT},177 {typeof (LessThan), OpCodes.LT},178 {typeof (And), OpCodes.AND},179 {typeof (Or), OpCodes.OR},180 {typeof (Not), OpCodes.NOT},181 {typeof (Average), OpCodes.Average},182 {typeof (InvokeFunction), OpCodes.Call},183 {184 typeof (HeuristicLab.Problems.DataAnalysis.Symbolic.Variable),185 OpCodes.Variable186 },187 {typeof (LaggedVariable), OpCodes.LagVariable},188 {typeof (Constant), OpCodes.Constant},189 {typeof (Argument), OpCodes.Arg},190 {typeof (Power), OpCodes.Power},191 {typeof (Root), OpCodes.Root},192 {typeof (TimeLag), OpCodes.TimeLag},193 {typeof (Integral), OpCodes.Integral},194 {typeof (Derivative), OpCodes.Derivative},195 {typeof (VariableCondition), OpCodes.VariableCondition},196 {typeof (Square), OpCodes.Square},197 {typeof (SquareRoot), OpCodes.SquareRoot},198 {typeof (Gamma), OpCodes.Gamma},199 {typeof (Psi), OpCodes.Psi},200 {typeof (Dawson), OpCodes.Dawson},201 {typeof (ExponentialIntegralEi), OpCodes.ExponentialIntegralEi},202 {typeof (CosineIntegral), OpCodes.CosineIntegral},203 {typeof (SineIntegral), OpCodes.SineIntegral},204 {205 typeof (HyperbolicCosineIntegral),206 OpCodes.HyperbolicCosineIntegral207 },208 {209 typeof (HyperbolicSineIntegral), OpCodes.HyperbolicSineIntegral210 },211 {typeof (FresnelCosineIntegral), OpCodes.FresnelCosineIntegral},212 {typeof (FresnelSineIntegral), OpCodes.FresnelSineIntegral},213 {typeof (AiryA), OpCodes.AiryA},214 {typeof (AiryB), OpCodes.AiryB},215 {typeof (Norm), OpCodes.Norm},216 {typeof (Erf), OpCodes.Erf},217 {typeof (Bessel), OpCodes.Bessel}218 };219 72 220 73 public override bool CanChangeName { … … 254 107 255 108 [StorableConstructor] 256 private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(bool deserializing) 257 : base(deserializing) { 258 } 259 260 private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter( 261 SymbolicDataAnalysisExpressionTreeILEmittingInterpreter original, Cloner cloner) 262 : base(original, cloner) { 263 } 264 109 private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(bool deserializing) : base(deserializing) { } 110 111 private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter original, Cloner cloner) : base(original, cloner) { } 265 112 public override IDeepCloneable Clone(Cloner cloner) { 266 113 return new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(this, cloner); … … 269 116 public SymbolicDataAnalysisExpressionTreeILEmittingInterpreter() 270 117 : base("SymbolicDataAnalysisExpressionTreeILEmittingInterpreter", "Interpreter for symbolic expression trees.") { 271 Parameters.Add(new ValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, 272 "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", 273 new BoolValue(false))); 274 Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, 275 "A counter for the total number of solutions the interpreter has evaluated", 276 new IntValue(0))); 118 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))); 119 Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0))); 277 120 } 278 121 … … 280 123 private void AfterDeserialization() { 281 124 if (!Parameters.ContainsKey(EvaluatedSolutionsParameterName)) 282 Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, 283 "A counter for the total number of solutions the interpreter has evaluated", 284 new IntValue(0))); 125 Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0))); 285 126 } 286 127 … … 297 138 #endregion 298 139 299 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, 300 IEnumerable<int> rows) { 301 return GetSymbolicExpressionTreeValues(tree, dataset, new string[] { "#NOTHING#" }, rows); 302 } 303 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, string[] targetVariables, IEnumerable<int> rows) { 304 return GetSymbolicExpressionTreeValues(tree, dataset, targetVariables, rows, 1); 305 } 306 // for each row for each horizon for each target variable one value 307 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, string[] targetVariables, IEnumerable<int> rows, int horizon) { 140 public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, Dataset dataset, IEnumerable<int> rows) { 308 141 if (CheckExpressionsWithIntervalArithmetic.Value) 309 throw new NotSupportedException( 310 "Interval arithmetic is not yet supported in the symbolic data analysis interpreter."); 142 throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter."); 143 311 144 EvaluatedSolutions.Value++; // increment the evaluated solutions counter 312 var compiler = new SymbolicExpressionTreeCompiler(); 313 Instruction[] code = compiler.Compile(tree, MapSymbolToOpCode); 145 var state = PrepareInterpreterState(tree, dataset); 146 147 Type[] methodArgs = { typeof(int), typeof(IList<double>[]) }; 148 DynamicMethod testFun = new DynamicMethod("TestFun", typeof(double), methodArgs, typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter).Module); 149 150 ILGenerator il = testFun.GetILGenerator(); 151 CompileInstructions(il, state, dataset); 152 il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); 153 il.Emit(System.Reflection.Emit.OpCodes.Ret); 154 var function = (CompiledFunction)testFun.CreateDelegate(typeof(CompiledFunction)); 155 156 IList<double>[] columns = dataset.DoubleVariables.Select(v => dataset.GetReadOnlyDoubleValues(v)).ToArray(); 157 158 foreach (var row in rows) { 159 yield return function(row, columns); 160 } 161 } 162 163 private InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, Dataset dataset) { 164 Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode); 165 Dictionary<string, int> doubleVariableNames = dataset.DoubleVariables.Select((x, i) => new { x, i }).ToDictionary(e => e.x, e => e.i); 314 166 int necessaryArgStackSize = 0; 315 316 Dictionary<string, int> doubleVariableNames = 317 dataset.DoubleVariables.Select((x, i) => new { x, i }).ToDictionary(e => e.x, e => e.i); 318 319 for (int i = 0; i < code.Length; i++) { 320 Instruction instr = code[i]; 167 foreach (Instruction instr in code) { 321 168 if (instr.opCode == OpCodes.Variable) { 322 var variableTreeNode = instr.dynamicNode as VariableTreeNode;169 var variableTreeNode = (VariableTreeNode)instr.dynamicNode; 323 170 instr.iArg0 = doubleVariableNames[variableTreeNode.VariableName]; 324 code[i] = instr;325 171 } else if (instr.opCode == OpCodes.LagVariable) { 326 var variableTreeNode = instr.dynamicNode as LaggedVariableTreeNode; 327 instr.iArg0 = doubleVariableNames[variableTreeNode.VariableName]; 328 code[i] = instr; 172 var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode; 173 instr.iArg0 = doubleVariableNames[laggedVariableTreeNode.VariableName]; 329 174 } else if (instr.opCode == OpCodes.VariableCondition) { 330 var variableConditionTreeNode = instr.dynamicNode as VariableConditionTreeNode;175 var variableConditionTreeNode = (VariableConditionTreeNode)instr.dynamicNode; 331 176 instr.iArg0 = doubleVariableNames[variableConditionTreeNode.VariableName]; 332 177 } else if (instr.opCode == OpCodes.Call) { … … 334 179 } 335 180 } 336 var state = new InterpreterState(code); 337 Type[] methodArgs = { typeof(int), typeof(IList<double>[]), typeof(IList<double>[]), typeof(int) }; 338 339 CompiledFunction[] function = new CompiledFunction[targetVariables.Length]; 340 for (int i = 0; i < function.Length; i++) { 341 DynamicMethod testFun = new DynamicMethod("TestFun", typeof(double), methodArgs, typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter).Module); 342 ILGenerator il = testFun.GetILGenerator(); 343 CompileInstructions(il, state, dataset); 344 il.Emit(System.Reflection.Emit.OpCodes.Conv_R8); 345 il.Emit(System.Reflection.Emit.OpCodes.Ret); 346 function[i] = (CompiledFunction)testFun.CreateDelegate(typeof(CompiledFunction)); 347 } 348 var values = doubleVariableNames.Keys 349 .Select(v => dataset.GetReadOnlyDoubleValues(v)) 350 .ToArray(); 351 var cachedValues = (from var in doubleVariableNames.Keys 352 select new double[horizon]).ToArray(); 353 foreach (var row in rows) { 354 // init first line of cache 355 int c = 0; 356 foreach (var var in doubleVariableNames.Keys) 357 cachedValues[c++][0] = dataset.GetDoubleValue(var, row); 358 for (int horizonRow = row; horizonRow < row + horizon; horizonRow++) { 359 for (int i = 0; i < function.Length; i++) { 360 var componentProg = function[i](horizonRow, values, cachedValues, row); 361 // set cachedValues for prognosis of future values 362 if (horizon > 1) 363 cachedValues[doubleVariableNames[targetVariables[i]]][horizonRow - row] = componentProg; 364 yield return componentProg; 365 } 366 } 367 } 181 return new InterpreterState(code, necessaryArgStackSize); 368 182 } 369 183 … … 865 679 } 866 680 867 private byte MapSymbolToOpCode(ISymbolicExpressionTreeNode treeNode) {868 byte opCode;869 if (!symbolToOpcode.TryGetValue(treeNode.Symbol.GetType(), out opCode))870 throw new NotSupportedException("Symbol: " + treeNode.Symbol);871 return opCode;872 }873 874 875 681 public static double AiryA(double x) { 876 682 if (double.IsNaN(x)) return double.NaN; -
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.