Changeset 17928 for branches/3026_IntegrationIntoSymSpace/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter
- Timestamp:
- 04/06/21 13:13:32 (4 years ago)
- Location:
- branches/3026_IntegrationIntoSymSpace
- Files:
-
- 6 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3026_IntegrationIntoSymSpace
- Property svn:mergeinfo changed
-
branches/3026_IntegrationIntoSymSpace/HeuristicLab.Problems.DataAnalysis.Symbolic
- Property svn:mergeinfo changed
-
branches/3026_IntegrationIntoSymSpace/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs
r17180 r17928 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 … … 23 25 using System.Collections.Generic; 24 26 using System.Linq; 27 using HEAL.Attic; 25 28 using HeuristicLab.Common; 26 29 using HeuristicLab.Core; 27 30 using HeuristicLab.Data; 28 31 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 29 using HEAL.Attic;30 32 using HeuristicLab.Parameters; 31 33 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, IDictionary<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 IDictionary<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, IDictionary<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 case OpCodes.Power: {237 result = Evaluate(instructions, ref instructionCounter, nodeIntervals);238 for (int i = 1; i < currentInstr.nArguments; i++) {239 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);240 result = Interval.Power(result, argumentInterval);241 }242 break;243 }244 265 case OpCodes.Square: { 245 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );266 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 246 267 result = Interval.Square(argumentInterval); 247 268 break; 248 269 } 249 case OpCodes.Root: {250 result = Evaluate(instructions, ref instructionCounter, nodeIntervals);251 for (int i = 1; i < currentInstr.nArguments; i++) {252 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);253 result = Interval.Root(result, argumentInterval);254 }255 break;256 }257 270 case OpCodes.SquareRoot: { 258 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );271 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 259 272 result = Interval.SquareRoot(argumentInterval); 273 break; 274 } 275 case OpCodes.Cube: { 276 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 277 result = Interval.Cube(argumentInterval); 278 break; 279 } 280 case OpCodes.CubeRoot: { 281 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 282 result = Interval.CubicRoot(argumentInterval); 283 break; 284 } 285 case OpCodes.Absolute: { 286 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 287 result = Interval.Absolute(argumentInterval); 288 break; 289 } 290 case OpCodes.AnalyticQuotient: { 291 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 292 for (var i = 1; i < currentInstr.nArguments; i++) { 293 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 294 result = Interval.AnalyticQuotient(result, argumentInterval); 295 } 296 260 297 break; 261 298 } … … 264 301 } 265 302 266 if ( nodeIntervals != null)303 if (!(nodeIntervals == null || nodeIntervals.ContainsKey(currentInstr.dynamicNode))) 267 304 nodeIntervals.Add(currentInstr.dynamicNode, result); 268 305 … … 270 307 } 271 308 309 272 310 public static bool IsCompatible(ISymbolicExpressionTree tree) { 273 var containsUnknownSy umbol= (311 var containsUnknownSymbols = ( 274 312 from n in tree.Root.GetSubtree(0).IterateNodesPrefix() 275 313 where 314 !(n.Symbol is Variable) && 315 !(n.Symbol is Constant) && 276 316 !(n.Symbol is StartSymbol) && 277 317 !(n.Symbol is Addition) && … … 282 322 !(n.Symbol is Cosine) && 283 323 !(n.Symbol is Tangent) && 324 !(n.Symbol is HyperbolicTangent) && 284 325 !(n.Symbol is Logarithm) && 285 326 !(n.Symbol is Exponential) && 286 !(n.Symbol is Power) &&287 327 !(n.Symbol is Square) && 288 !(n.Symbol is Root) &&289 328 !(n.Symbol is SquareRoot) && 290 !(n.Symbol is Problems.DataAnalysis.Symbolic.Variable) && 291 !(n.Symbol is Constant) 329 !(n.Symbol is Cube) && 330 !(n.Symbol is CubeRoot) && 331 !(n.Symbol is Absolute) && 332 !(n.Symbol is AnalyticQuotient) 292 333 select n).Any(); 293 return !containsUnknownSy umbol;334 return !containsUnknownSymbols; 294 335 } 295 336 } -
branches/3026_IntegrationIntoSymSpace/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs
r17180 r17928 52 52 private static readonly MethodInfo Log = typeof(Math).GetMethod("Log", new[] { typeof(double) }); 53 53 private static readonly MethodInfo IsNaN = typeof(double).GetMethod("IsNaN"); 54 private static readonly MethodInfo IsAlmost = typeof(DoubleExtensions).GetMethod("IsAlmost" );54 private static readonly MethodInfo IsAlmost = typeof(DoubleExtensions).GetMethod("IsAlmost", new Type[] { typeof(double), typeof(double)}); 55 55 private static readonly MethodInfo Gamma = typeof(alglib).GetMethod("gammafunction", new[] { typeof(double) }); 56 56 private static readonly MethodInfo Psi = typeof(alglib).GetMethod("psi", new[] { typeof(double) }); -
branches/3026_IntegrationIntoSymSpace/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeBatchInterpreter.cs
r16768 r17928 1 using System; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System; 2 23 using System.Collections.Generic; 3 24 using System.Linq; … … 181 202 182 203 [ThreadStatic] 183 private Dictionary<string, double[]> cachedData;204 private static Dictionary<string, double[]> cachedData; 184 205 185 206 [ThreadStatic] 186 private IDataset dataset;207 private static IDataset cachedDataset; 187 208 188 209 private void InitCache(IDataset dataset) { 189 this.dataset = dataset;210 cachedDataset = dataset; 190 211 cachedData = new Dictionary<string, double[]>(); 191 212 foreach (var v in dataset.DoubleVariables) { … … 196 217 public void InitializeState() { 197 218 cachedData = null; 198 dataset = null;219 cachedDataset = null; 199 220 EvaluatedSolutions = 0; 200 221 } 201 222 202 223 private double[] GetValues(ISymbolicExpressionTree tree, IDataset dataset, int[] rows) { 203 if (cachedData == null || this.dataset != dataset) {224 if (cachedData == null || cachedDataset != dataset || cachedDataset is ModifiableDataset) { 204 225 InitCache(dataset); 205 226 } -
branches/3026_IntegrationIntoSymSpace/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeNativeInterpreter.cs
r17180 r17928 99 99 100 100 [ThreadStatic] 101 private IDataset dataset;101 private static IDataset cachedDataset; 102 102 103 103 private static readonly HashSet<byte> supportedOpCodes = new HashSet<byte>() { … … 127 127 if (!rows.Any()) return Enumerable.Empty<double>(); 128 128 129 if (cachedData == null || this.dataset != dataset) {129 if (cachedData == null || cachedDataset != dataset || cachedDataset is ModifiableDataset) { 130 130 InitCache(dataset); 131 131 } … … 152 152 153 153 private void InitCache(IDataset dataset) { 154 this.dataset = dataset;154 cachedDataset = dataset; 155 155 156 156 // free handles to old data … … 178 178 cachedData = null; 179 179 } 180 dataset = null;180 cachedDataset = null; 181 181 EvaluatedSolutions = 0; 182 182 }
Note: See TracChangeset
for help on using the changeset viewer.