- Timestamp:
- 03/16/21 14:23:41 (4 years ago)
- Location:
- trunk/HeuristicLab.Problems.DataAnalysis.Symbolic
- Files:
-
- 2 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/HeuristicLab.Problems.DataAnalysis.Symbolic
- Property svn:mergeinfo changed
-
trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs
r17579 r17902 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 148 //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)) { 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); … … 165 193 //Elementary arithmetic rules 166 194 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 );195 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 196 for (var i = 1; i < currentInstr.nArguments; i++) { 197 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 170 198 result = Interval.Add(result, argumentInterval); 171 199 } 200 172 201 break; 173 202 } 174 203 case OpCodes.Sub: { 175 result = Evaluate(instructions, ref instructionCounter, nodeIntervals );204 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 176 205 if (currentInstr.nArguments == 1) 177 206 result = Interval.Multiply(new Interval(-1, -1), result); 178 207 179 for ( inti = 1; i < currentInstr.nArguments; i++) {180 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );208 for (var i = 1; i < currentInstr.nArguments; i++) { 209 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 181 210 result = Interval.Subtract(result, argumentInterval); 182 211 } 212 183 213 break; 184 214 } 185 215 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 );216 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 217 for (var i = 1; i < currentInstr.nArguments; i++) { 218 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 189 219 result = Interval.Multiply(result, argumentInterval); 190 220 } 221 191 222 break; 192 223 } 193 224 case OpCodes.Div: { 194 result = Evaluate(instructions, ref instructionCounter, nodeIntervals );225 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 195 226 if (currentInstr.nArguments == 1) 196 227 result = Interval.Divide(new Interval(1, 1), result); 197 228 198 for ( inti = 1; i < currentInstr.nArguments; i++) {199 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );229 for (var i = 1; i < currentInstr.nArguments; i++) { 230 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 200 231 result = Interval.Divide(result, argumentInterval); 201 232 } 202 break; 203 }204 //Trigonometric functions233 234 break; 235 } 205 236 case OpCodes.Sin: { 206 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );237 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 207 238 result = Interval.Sine(argumentInterval); 208 239 break; 209 240 } 210 241 case OpCodes.Cos: { 211 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );242 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 212 243 result = Interval.Cosine(argumentInterval); 213 244 break; 214 245 } 215 246 case OpCodes.Tan: { 216 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );247 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 217 248 result = Interval.Tangens(argumentInterval); 218 249 break; 219 250 } 220 251 case OpCodes.Tanh: { 221 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );252 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 222 253 result = Interval.HyperbolicTangent(argumentInterval); 223 254 break; 224 255 } 225 //Exponential functions226 256 case OpCodes.Log: { 227 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );257 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 228 258 result = Interval.Logarithm(argumentInterval); 229 259 break; 230 260 } 231 261 case OpCodes.Exp: { 232 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );262 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 233 263 result = Interval.Exponential(argumentInterval); 234 264 break; 235 265 } 236 266 case OpCodes.Square: { 237 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );267 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 238 268 result = Interval.Square(argumentInterval); 239 269 break; 240 270 } 241 271 case OpCodes.SquareRoot: { 242 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );272 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 243 273 result = Interval.SquareRoot(argumentInterval); 244 274 break; 245 275 } 246 276 case OpCodes.Cube: { 247 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );277 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 248 278 result = Interval.Cube(argumentInterval); 249 279 break; 250 280 } 251 281 case OpCodes.CubeRoot: { 252 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );282 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 253 283 result = Interval.CubicRoot(argumentInterval); 254 284 break; 255 285 } 256 286 case OpCodes.Absolute: { 257 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals );287 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 258 288 result = Interval.Absolute(argumentInterval); 259 289 break; 260 290 } 261 291 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 );292 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 293 for (var i = 1; i < currentInstr.nArguments; i++) { 294 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 265 295 result = Interval.AnalyticalQuotient(result, argumentInterval); 266 296 } … … 272 302 } 273 303 274 if ( nodeIntervals != null)304 if (!(nodeIntervals == null || nodeIntervals.ContainsKey(currentInstr.dynamicNode))) 275 305 nodeIntervals.Add(currentInstr.dynamicNode, result); 276 306 … … 278 308 } 279 309 310 280 311 public static bool IsCompatible(ISymbolicExpressionTree tree) { 281 var containsUnknownSy umbol= (312 var containsUnknownSymbols = ( 282 313 from n in tree.Root.GetSubtree(0).IterateNodesPrefix() 283 314 where 284 !(n.Symbol is Problems.DataAnalysis.Symbolic.Variable) &&315 !(n.Symbol is Variable) && 285 316 !(n.Symbol is Constant) && 286 317 !(n.Symbol is StartSymbol) && … … 292 323 !(n.Symbol is Cosine) && 293 324 !(n.Symbol is Tangent) && 325 !(n.Symbol is HyperbolicTangent) && 294 326 !(n.Symbol is Logarithm) && 295 327 !(n.Symbol is Exponential) && … … 301 333 !(n.Symbol is AnalyticQuotient) 302 334 select n).Any(); 303 return !containsUnknownSy umbol;335 return !containsUnknownSymbols; 304 336 } 305 337 }
Note: See TracChangeset
for help on using the changeset viewer.