Changeset 18086 for branches/2521_ProblemRefactoring/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter
- Timestamp:
- 11/19/21 16:07:45 (3 years ago)
- Location:
- branches/2521_ProblemRefactoring/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter
- Files:
-
- 4 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/2521_ProblemRefactoring/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithBoundsEstimator.cs
r17903 r18086 53 53 private IntervalArithBoundsEstimator(StorableConstructorFlag _) : base(_) { } 54 54 55 pr ivateIntervalArithBoundsEstimator(IntervalArithBoundsEstimator original, Cloner cloner) : base(original, cloner) { }55 protected IntervalArithBoundsEstimator(IntervalArithBoundsEstimator original, Cloner cloner) : base(original, cloner) { } 56 56 57 57 public IntervalArithBoundsEstimator() : base("Interval Arithmetic Bounds Estimator", … … 223 223 break; 224 224 } 225 case OpCodes.Power: { 226 var a = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 227 var b = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 228 // support only integer powers 229 if (b.LowerBound == b.UpperBound && Math.Truncate(b.LowerBound) == b.LowerBound) { 230 result = Interval.Power(a, (int)b.LowerBound); 231 } else { 232 throw new NotSupportedException("Interval is only supported for integer powers"); 233 } 234 break; 235 } 225 236 case OpCodes.Absolute: { 226 237 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); … … 232 243 for (var i = 1; i < currentInstr.nArguments; i++) { 233 244 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 234 result = Interval.Analytic alQuotient(result, argumentInterval);245 result = Interval.AnalyticQuotient(result, argumentInterval); 235 246 } 236 247 … … 329 340 !(n.Symbol is Cube) && 330 341 !(n.Symbol is CubeRoot) && 342 !(n.Symbol is Power) && 331 343 !(n.Symbol is Absolute) && 332 344 !(n.Symbol is AnalyticQuotient) -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalArithCompiledExpressionBoundsEstimator.cs
r17903 r18086 75 75 76 76 [StorableConstructor] 77 pr ivateIntervalArithCompiledExpressionBoundsEstimator(StorableConstructorFlag _) : base(_) { }78 79 pr ivateIntervalArithCompiledExpressionBoundsEstimator(IntervalArithCompiledExpressionBoundsEstimator original, Cloner cloner) : base(original, cloner) { }77 protected IntervalArithCompiledExpressionBoundsEstimator(StorableConstructorFlag _) : base(_) { } 78 79 protected IntervalArithCompiledExpressionBoundsEstimator(IntervalArithCompiledExpressionBoundsEstimator original, Cloner cloner) : base(original, cloner) { } 80 80 81 81 public override IDeepCloneable Clone(Cloner cloner) { … … 194 194 return Expression.Divide(e1, e2); 195 195 } 196 case OpCodes.AnalyticQuotient: { 197 var a = expr(node.GetSubtree(0)); 198 var b = expr(node.GetSubtree(1)); 199 var fun = typeof(Interval).GetMethod(methodName[opCode], new[] { a.Type, b.Type }); 200 return Expression.Call(fun, a, b); 201 } 196 202 // all these cases share the same code: get method info by name, emit call expression 197 203 case OpCodes.Exp: … … 205 211 case OpCodes.SquareRoot: 206 212 case OpCodes.CubeRoot: 207 case OpCodes.Absolute: 208 case OpCodes.AnalyticQuotient: { 213 case OpCodes.Absolute: { 209 214 var arg = expr(node.GetSubtree(0)); 210 215 var fun = typeof(Interval).GetMethod(methodName[opCode], new[] { arg.Type }); -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs
r17586 r18086 1 1 #region License Information 2 2 3 /* HeuristicLab 3 4 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) … … 18 19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 20 */ 21 20 22 #endregion 21 23 … … 32 34 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 33 35 [StorableType("DE6C1E1E-D7C1-4070-847E-63B68562B10C")] 34 [Item("IntervalInterpreter", "Int perter for calculation of intervals of symbolic models.")]36 [Item("IntervalInterpreter", "Interpreter for calculation of intervals of symbolic models.")] 35 37 public sealed class IntervalInterpreter : ParameterizedNamedItem, IStatefulItem { 36 37 38 private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions"; 38 39 public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter { 40 get { return (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; } 41 } 39 public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter => 40 (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; 42 41 43 42 public int EvaluatedSolutions { 44 get { return EvaluatedSolutionsParameter.Value.Value; }45 set { EvaluatedSolutionsParameter.Value.Value = value; }43 get => EvaluatedSolutionsParameter.Value.Value; 44 set => EvaluatedSolutionsParameter.Value.Value = value; 46 45 } 47 46 48 47 [StorableConstructor] 49 48 private IntervalInterpreter(StorableConstructorFlag _) : base(_) { } 49 50 50 private IntervalInterpreter(IntervalInterpreter original, Cloner cloner) 51 51 : base(original, cloner) { } 52 52 53 53 public IntervalInterpreter() 54 : base("IntervalInterpreter", "Intperter for calculation of intervals of symbolic models.") { 55 Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0))); 54 : base("IntervalInterpreter", "Interpreter for calculation of intervals of symbolic models.") { 55 Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, 56 "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0))); 56 57 } 57 58 … … 63 64 64 65 #region IStatefulItem Members 66 65 67 public void InitializeState() { 66 68 EvaluatedSolutions = 0; 67 69 } 70 68 71 public void ClearState() { } 72 69 73 #endregion 70 74 71 public Interval GetSymbolicExpressionTreeInterval(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows = null) { 75 public Interval GetSymbolicExpressionTreeInterval( 76 ISymbolicExpressionTree tree, IDataset dataset, 77 IEnumerable<int> rows = null) { 72 78 var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows); 73 79 return GetSymbolicExpressionTreeInterval(tree, variableRanges); 74 80 } 75 81 76 public Interval GetSymbolicExpressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset, 77 out IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals, IEnumerable<int> rows = null) { 82 public Interval GetSymbolicExpressionTreeIntervals( 83 ISymbolicExpressionTree tree, IDataset dataset, 84 out IDictionary<ISymbolicExpressionTreeNode, Interval> 85 nodeIntervals, IEnumerable<int> rows = null) { 78 86 var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows); 79 87 return GetSymbolicExpressionTreeIntervals(tree, variableRanges, out nodeIntervals); 80 88 } 81 89 82 public Interval GetSymbolicExpressionTreeInterval(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges) { 90 public Interval GetSymbolicExpressionTreeInterval( 91 ISymbolicExpressionTree tree, 92 IReadOnlyDictionary<string, Interval> variableRanges) { 83 93 lock (syncRoot) { 84 94 EvaluatedSolutions++; 85 95 } 86 int instructionCount = 0; 96 97 Interval outputInterval; 98 99 var instructionCount = 0; 87 100 var instructions = PrepareInterpreterState(tree, variableRanges); 88 var outputInterval = Evaluate(instructions, ref instructionCount); 89 90 // because of numerical errors the bounds might be incorrect 91 if (outputInterval.LowerBound <= outputInterval.UpperBound) 92 return outputInterval; 93 else 94 return new Interval(outputInterval.UpperBound, outputInterval.LowerBound); 95 } 96 97 98 public Interval GetSymbolicExpressionTreeIntervals(ISymbolicExpressionTree tree, 99 IReadOnlyDictionary<string, Interval> variableRanges, out IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals) { 101 outputInterval = Evaluate(instructions, ref instructionCount); 102 103 return outputInterval.LowerBound <= outputInterval.UpperBound 104 ? outputInterval 105 : new Interval(outputInterval.UpperBound, outputInterval.LowerBound); 106 } 107 108 109 public Interval GetSymbolicExpressionTreeIntervals( 110 ISymbolicExpressionTree tree, 111 IReadOnlyDictionary<string, Interval> variableRanges, 112 out IDictionary<ISymbolicExpressionTreeNode, Interval> 113 nodeIntervals) { 100 114 lock (syncRoot) { 101 115 EvaluatedSolutions++; 102 116 } 103 int instructionCount = 0; 117 104 118 var intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>(); 105 119 var instructions = PrepareInterpreterState(tree, variableRanges); 106 var outputInterval = Evaluate(instructions, ref instructionCount, intervals); 107 108 // fix incorrect intervals if necessary (could occur because of numerical errors) 120 121 Interval outputInterval; 122 var instructionCount = 0; 123 outputInterval = Evaluate(instructions, ref instructionCount, intervals); 124 109 125 nodeIntervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>(); 110 126 foreach (var kvp in intervals) { … … 119 135 if (outputInterval.IsInfiniteOrUndefined || outputInterval.LowerBound <= outputInterval.UpperBound) 120 136 return outputInterval; 121 else 122 return new Interval(outputInterval.UpperBound, outputInterval.LowerBound); 123 } 124 125 126 private static Instruction[] PrepareInterpreterState(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges) { 137 138 return new Interval(outputInterval.UpperBound, outputInterval.LowerBound); 139 } 140 141 142 private static Instruction[] PrepareInterpreterState( 143 ISymbolicExpressionTree tree, 144 IReadOnlyDictionary<string, Interval> variableRanges) { 127 145 if (variableRanges == null) 128 146 throw new ArgumentNullException("No variablew ranges are present!", nameof(variableRanges)); 129 147 130 //Check if all variables used in the tree are present in the dataset 131 foreach (var variable in tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(n => n.VariableName).Distinct()) { 132 if (!variableRanges.ContainsKey(variable)) throw new InvalidOperationException($"No ranges for variable {variable} is present"); 133 } 134 135 Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode); 136 foreach (Instruction instr in code.Where(i => i.opCode == OpCodes.Variable)) { 148 // Check if all variables used in the tree are present in the dataset 149 foreach (var variable in tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(n => n.VariableName) 150 .Distinct()) 151 if (!variableRanges.ContainsKey(variable)) 152 throw new InvalidOperationException($"No ranges for variable {variable} is present"); 153 154 var code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode); 155 foreach (var instr in code.Where(i => i.opCode == OpCodes.Variable)) { 137 156 var variableTreeNode = (VariableTreeNode)instr.dynamicNode; 138 157 instr.data = variableRanges[variableTreeNode.VariableName]; 139 158 } 159 140 160 return code; 141 161 } 142 162 143 private Interval Evaluate(Instruction[] instructions, ref int instructionCounter, IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null) { 144 Instruction currentInstr = instructions[instructionCounter]; 145 //Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side 146 //Update instructionCounter, whenever Evaluate is called 163 // Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side 164 // Update instructionCounter, whenever Evaluate is called 165 public static Interval Evaluate( 166 Instruction[] instructions, ref int instructionCounter, 167 IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null, 168 IReadOnlyDictionary<string, Interval> variableIntervals = null) { 169 var currentInstr = instructions[instructionCounter]; 170 147 171 instructionCounter++; 148 Interval result = null;172 Interval result; 149 173 150 174 switch (currentInstr.opCode) { 151 //Variables, Constants, ...152 175 case OpCodes.Variable: { 153 176 var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode; 154 177 var weightInterval = new Interval(variableTreeNode.Weight, variableTreeNode.Weight); 155 var variableInterval = (Interval)currentInstr.data; 178 179 Interval variableInterval; 180 if (variableIntervals != null && variableIntervals.ContainsKey(variableTreeNode.VariableName)) 181 variableInterval = variableIntervals[variableTreeNode.VariableName]; 182 else 183 variableInterval = (Interval)currentInstr.data; 156 184 157 185 result = Interval.Multiply(variableInterval, weightInterval); … … 163 191 break; 164 192 } 165 //Elementary arithmetic rules166 193 case OpCodes.Add: { 167 result = Evaluate(instructions, ref instructionCounter, nodeIntervals );168 for ( inti = 1; i < currentInstr.nArguments; i++) {169 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );194 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 195 for (var i = 1; i < currentInstr.nArguments; i++) { 196 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 170 197 result = Interval.Add(result, argumentInterval); 171 198 } 199 172 200 break; 173 201 } 174 202 case OpCodes.Sub: { 175 result = Evaluate(instructions, ref instructionCounter, nodeIntervals );203 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 176 204 if (currentInstr.nArguments == 1) 177 205 result = Interval.Multiply(new Interval(-1, -1), result); 178 206 179 for ( inti = 1; i < currentInstr.nArguments; i++) {180 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );207 for (var i = 1; i < currentInstr.nArguments; i++) { 208 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 181 209 result = Interval.Subtract(result, argumentInterval); 182 210 } 211 183 212 break; 184 213 } 185 214 case OpCodes.Mul: { 186 result = Evaluate(instructions, ref instructionCounter, nodeIntervals );187 for ( inti = 1; i < currentInstr.nArguments; i++) {188 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );215 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 216 for (var i = 1; i < currentInstr.nArguments; i++) { 217 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 189 218 result = Interval.Multiply(result, argumentInterval); 190 219 } 220 191 221 break; 192 222 } 193 223 case OpCodes.Div: { 194 result = Evaluate(instructions, ref instructionCounter, nodeIntervals );224 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 195 225 if (currentInstr.nArguments == 1) 196 226 result = Interval.Divide(new Interval(1, 1), result); 197 227 198 for ( inti = 1; i < currentInstr.nArguments; i++) {199 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );228 for (var i = 1; i < currentInstr.nArguments; i++) { 229 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 200 230 result = Interval.Divide(result, argumentInterval); 201 231 } 202 break; 203 }204 //Trigonometric functions232 233 break; 234 } 205 235 case OpCodes.Sin: { 206 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );236 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 207 237 result = Interval.Sine(argumentInterval); 208 238 break; 209 239 } 210 240 case OpCodes.Cos: { 211 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );241 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 212 242 result = Interval.Cosine(argumentInterval); 213 243 break; 214 244 } 215 245 case OpCodes.Tan: { 216 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );246 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 217 247 result = Interval.Tangens(argumentInterval); 218 248 break; 219 249 } 220 250 case OpCodes.Tanh: { 221 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );251 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 222 252 result = Interval.HyperbolicTangent(argumentInterval); 223 253 break; 224 254 } 225 //Exponential functions226 255 case OpCodes.Log: { 227 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );256 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 228 257 result = Interval.Logarithm(argumentInterval); 229 258 break; 230 259 } 231 260 case OpCodes.Exp: { 232 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );261 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 233 262 result = Interval.Exponential(argumentInterval); 234 263 break; 235 264 } 236 265 case OpCodes.Square: { 237 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );266 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 238 267 result = Interval.Square(argumentInterval); 239 268 break; 240 269 } 241 270 case OpCodes.SquareRoot: { 242 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );271 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 243 272 result = Interval.SquareRoot(argumentInterval); 244 273 break; 245 274 } 246 275 case OpCodes.Cube: { 247 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );276 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 248 277 result = Interval.Cube(argumentInterval); 249 278 break; 250 279 } 251 280 case OpCodes.CubeRoot: { 252 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );281 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 253 282 result = Interval.CubicRoot(argumentInterval); 254 283 break; 255 284 } 285 case OpCodes.Power: { 286 var a = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 287 var b = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 288 // support only integer powers 289 if (b.LowerBound == b.UpperBound && Math.Truncate(b.LowerBound) == b.LowerBound) { 290 result = Interval.Power(a, (int)b.LowerBound); 291 } else { 292 throw new NotSupportedException("Interval is only supported for integer powers"); 293 } 294 break; 295 } 296 256 297 case OpCodes.Absolute: { 257 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );298 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 258 299 result = Interval.Absolute(argumentInterval); 259 300 break; 260 301 } 261 302 case OpCodes.AnalyticQuotient: { 262 result = Evaluate(instructions, ref instructionCounter, nodeIntervals );263 for (var i = 1; i < currentInstr.nArguments; i++) { 264 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );265 result = Interval.Analytic alQuotient(result, argumentInterval);303 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 304 for (var i = 1; i < currentInstr.nArguments; i++) { 305 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 306 result = Interval.AnalyticQuotient(result, argumentInterval); 266 307 } 267 308 … … 272 313 } 273 314 274 if ( nodeIntervals != null)315 if (!(nodeIntervals == null || nodeIntervals.ContainsKey(currentInstr.dynamicNode))) 275 316 nodeIntervals.Add(currentInstr.dynamicNode, result); 276 317 … … 278 319 } 279 320 321 280 322 public static bool IsCompatible(ISymbolicExpressionTree tree) { 281 var containsUnknownSyumbol = ( 282 from n in tree.Root.GetSubtree(0).IterateNodesPrefix() 283 where 284 !(n.Symbol is Problems.DataAnalysis.Symbolic.Variable) && 323 foreach (var n in tree.Root.GetSubtree(0).IterateNodesPrefix()) { 324 if ( 325 !(n.Symbol is Variable) && 285 326 !(n.Symbol is Constant) && 286 327 !(n.Symbol is StartSymbol) && … … 292 333 !(n.Symbol is Cosine) && 293 334 !(n.Symbol is Tangent) && 335 !(n.Symbol is HyperbolicTangent) && 294 336 !(n.Symbol is Logarithm) && 295 337 !(n.Symbol is Exponential) && … … 298 340 !(n.Symbol is Cube) && 299 341 !(n.Symbol is CubeRoot) && 342 !(n.Symbol is Power) && 300 343 !(n.Symbol is Absolute) && 301 !(n.Symbol is AnalyticQuotient) 302 select n).Any(); 303 return !containsUnknownSyumbol; 344 !(n.Symbol is AnalyticQuotient)) return false; 345 346 else if (n.Symbol is Power) { 347 // only integer exponents are supported 348 var exp = n.GetSubtree(1) as ConstantTreeNode; 349 if (exp == null || exp.Value != Math.Truncate(exp.Value)) return false; 350 } 351 } 352 return true; 304 353 } 305 354 } -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs
r17226 r18086 144 144 { typeof(Cosine), OpCodes.Cos }, 145 145 { typeof(Tangent), OpCodes.Tan }, 146 { typeof 146 { typeof(HyperbolicTangent), OpCodes.Tanh}, 147 147 { typeof(Logarithm), OpCodes.Log }, 148 148 { typeof(Exponential), OpCodes.Exp }, -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs
r17457 r18086 222 222 223 223 private double[] GetValues(ISymbolicExpressionTree tree, IDataset dataset, int[] rows) { 224 if (cachedData == null || cachedDataset != dataset ) {224 if (cachedData == null || cachedDataset != dataset || cachedDataset is ModifiableDataset) { 225 225 InitCache(dataset); 226 226 } -
branches/2521_ProblemRefactoring/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs
r17457 r18086 127 127 if (!rows.Any()) return Enumerable.Empty<double>(); 128 128 129 if (cachedData == null || cachedDataset != dataset ) {129 if (cachedData == null || cachedDataset != dataset || cachedDataset is ModifiableDataset) { 130 130 InitCache(dataset); 131 131 }
Note: See TracChangeset
for help on using the changeset viewer.