Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
04/30/21 12:18:19 (4 years ago)
Author:
gkronber
Message:

#3106 merged r17856:17969 from trunk to branch

Location:
branches/3106_AnalyticContinuedFractionsRegression
Files:
4 edited
2 copied

Legend:

Unmodified
Added
Removed
  • branches/3106_AnalyticContinuedFractionsRegression

  • branches/3106_AnalyticContinuedFractionsRegression/HeuristicLab.Problems.DataAnalysis.Symbolic

  • branches/3106_AnalyticContinuedFractionsRegression/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs

    r17579 r17970  
    11#region License Information
     2
    23/* HeuristicLab
    34 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     
    1819 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
    1920 */
     21
    2022#endregion
    2123
     
    3234namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
    3335  [StorableType("DE6C1E1E-D7C1-4070-847E-63B68562B10C")]
    34   [Item("IntervalInterpreter", "Intperter for calculation of intervals of symbolic models.")]
     36  [Item("IntervalInterpreter", "Interpreter for calculation of intervals of symbolic models.")]
    3537  public sealed class IntervalInterpreter : ParameterizedNamedItem, IStatefulItem {
    36 
    3738    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];
    4241
    4342    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;
    4645    }
    4746
    4847    [StorableConstructor]
    4948    private IntervalInterpreter(StorableConstructorFlag _) : base(_) { }
     49
    5050    private IntervalInterpreter(IntervalInterpreter original, Cloner cloner)
    51         : base(original, cloner) { }
     51      : base(original, cloner) { }
    5252
    5353    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)));
    5657    }
    5758
     
    6364
    6465    #region IStatefulItem Members
     66
    6567    public void InitializeState() {
    6668      EvaluatedSolutions = 0;
    6769    }
     70
    6871    public void ClearState() { }
     72
    6973    #endregion
    7074
    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) {
    7278      var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
    7379      return GetSymbolicExpressionTreeInterval(tree, variableRanges);
    7480    }
    7581
    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) {
    7886      var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
    7987      return GetSymbolicExpressionTreeIntervals(tree, variableRanges, out nodeIntervals);
    8088    }
    8189
    82     public Interval GetSymbolicExpressionTreeInterval(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges) {
     90    public Interval GetSymbolicExpressionTreeInterval(
     91      ISymbolicExpressionTree tree,
     92      IReadOnlyDictionary<string, Interval> variableRanges) {
    8393      lock (syncRoot) {
    8494        EvaluatedSolutions++;
    8595      }
    86       int instructionCount = 0;
     96
     97      Interval outputInterval;
     98
     99      var instructionCount = 0;
    87100      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) {
    100114      lock (syncRoot) {
    101115        EvaluatedSolutions++;
    102116      }
    103       int instructionCount = 0;
     117
    104118      var intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
    105119      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
    109125      nodeIntervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
    110126      foreach (var kvp in intervals) {
     
    119135      if (outputInterval.IsInfiniteOrUndefined || outputInterval.LowerBound <= outputInterval.UpperBound)
    120136        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) {
    127145      if (variableRanges == null)
    128146        throw new ArgumentNullException("No variablew ranges are present!", nameof(variableRanges));
    129147
    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)) {
    137156        var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
    138157        instr.data = variableRanges[variableTreeNode.VariableName];
    139158      }
     159
    140160      return code;
    141161    }
    142162
    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
    147171      instructionCounter++;
    148       Interval result = null;
     172      Interval result;
    149173
    150174      switch (currentInstr.opCode) {
    151         //Variables, Constants, ...
    152175        case OpCodes.Variable: {
    153176            var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode;
    154177            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;
    156184
    157185            result = Interval.Multiply(variableInterval, weightInterval);
     
    163191            break;
    164192          }
    165         //Elementary arithmetic rules
    166193        case OpCodes.Add: {
    167             result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    168             for (int i = 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);
    170197              result = Interval.Add(result, argumentInterval);
    171198            }
     199
    172200            break;
    173201          }
    174202        case OpCodes.Sub: {
    175             result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     203            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    176204            if (currentInstr.nArguments == 1)
    177205              result = Interval.Multiply(new Interval(-1, -1), result);
    178206
    179             for (int i = 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);
    181209              result = Interval.Subtract(result, argumentInterval);
    182210            }
     211
    183212            break;
    184213          }
    185214        case OpCodes.Mul: {
    186             result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    187             for (int i = 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);
    189218              result = Interval.Multiply(result, argumentInterval);
    190219            }
     220
    191221            break;
    192222          }
    193223        case OpCodes.Div: {
    194             result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     224            result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    195225            if (currentInstr.nArguments == 1)
    196226              result = Interval.Divide(new Interval(1, 1), result);
    197227
    198             for (int i = 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);
    200230              result = Interval.Divide(result, argumentInterval);
    201231            }
    202             break;
    203           }
    204         //Trigonometric functions
     232
     233            break;
     234          }
    205235        case OpCodes.Sin: {
    206             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     236            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    207237            result = Interval.Sine(argumentInterval);
    208238            break;
    209239          }
    210240        case OpCodes.Cos: {
    211             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     241            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    212242            result = Interval.Cosine(argumentInterval);
    213243            break;
    214244          }
    215245        case OpCodes.Tan: {
    216             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     246            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    217247            result = Interval.Tangens(argumentInterval);
    218248            break;
    219249          }
    220250        case OpCodes.Tanh: {
    221             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     251            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    222252            result = Interval.HyperbolicTangent(argumentInterval);
    223253            break;
    224254          }
    225         //Exponential functions
    226255        case OpCodes.Log: {
    227             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     256            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    228257            result = Interval.Logarithm(argumentInterval);
    229258            break;
    230259          }
    231260        case OpCodes.Exp: {
    232             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     261            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    233262            result = Interval.Exponential(argumentInterval);
    234263            break;
    235264          }
    236265        case OpCodes.Square: {
    237             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     266            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    238267            result = Interval.Square(argumentInterval);
    239268            break;
    240269          }
    241270        case OpCodes.SquareRoot: {
    242             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     271            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    243272            result = Interval.SquareRoot(argumentInterval);
    244273            break;
    245274          }
    246275        case OpCodes.Cube: {
    247             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     276            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    248277            result = Interval.Cube(argumentInterval);
    249278            break;
    250279          }
    251280        case OpCodes.CubeRoot: {
    252             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     281            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    253282            result = Interval.CubicRoot(argumentInterval);
    254283            break;
    255284          }
     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
    256297        case OpCodes.Absolute: {
    257             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     298            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
    258299            result = Interval.Absolute(argumentInterval);
    259300            break;
    260301          }
    261302        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.AnalyticalQuotient(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);
    266307            }
    267308
     
    272313      }
    273314
    274       if (nodeIntervals != null)
     315      if (!(nodeIntervals == null || nodeIntervals.ContainsKey(currentInstr.dynamicNode)))
    275316        nodeIntervals.Add(currentInstr.dynamicNode, result);
    276317
     
    278319    }
    279320
     321
    280322    public static bool IsCompatible(ISymbolicExpressionTree tree) {
    281       var containsUnknownSyumbol = (
     323      var containsUnknownSymbols = (
    282324        from n in tree.Root.GetSubtree(0).IterateNodesPrefix()
    283325        where
    284           !(n.Symbol is Problems.DataAnalysis.Symbolic.Variable) &&
     326          !(n.Symbol is Variable) &&
    285327          !(n.Symbol is Constant) &&
    286328          !(n.Symbol is StartSymbol) &&
     
    292334          !(n.Symbol is Cosine) &&
    293335          !(n.Symbol is Tangent) &&
     336          !(n.Symbol is HyperbolicTangent) &&
    294337          !(n.Symbol is Logarithm) &&
    295338          !(n.Symbol is Exponential) &&
     
    298341          !(n.Symbol is Cube) &&
    299342          !(n.Symbol is CubeRoot) &&
     343          !(n.Symbol is Power) &&
    300344          !(n.Symbol is Absolute) &&
    301345          !(n.Symbol is AnalyticQuotient)
    302346        select n).Any();
    303       return !containsUnknownSyumbol;
     347      return !containsUnknownSymbols;
    304348    }
    305349  }
  • branches/3106_AnalyticContinuedFractionsRegression/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs

    r17180 r17970  
    144144      { typeof(Cosine), OpCodes.Cos },
    145145      { typeof(Tangent), OpCodes.Tan },
    146       { typeof (HyperbolicTangent), OpCodes.Tanh},
     146      { typeof(HyperbolicTangent), OpCodes.Tanh},
    147147      { typeof(Logarithm), OpCodes.Log },
    148148      { typeof(Exponential), OpCodes.Exp },
Note: See TracChangeset for help on using the changeset viewer.