Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
06/24/20 16:12:03 (4 years ago)
Author:
chaider
Message:

#3073

  • Added splitting parameter in IntervalInterpreter
  • Added methods for spitting in Interval class
  • Fixed some typos and other minor changes
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs

    r17628 r17631  
    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
     
    2325using System.Collections.Generic;
    2426using System.Linq;
     27using System.Runtime.Remoting.Contexts;
    2528using HEAL.Attic;
    2629using HeuristicLab.Common;
     
    3235namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
    3336  [StorableType("DE6C1E1E-D7C1-4070-847E-63B68562B10C")]
    34   [Item("IntervalInterpreter", "Intperter for calculation of intervals of symbolic models.")]
     37  [Item("IntervalInterpreter", "Interpreter for calculation of intervals of symbolic models.")]
    3538  public sealed class IntervalInterpreter : ParameterizedNamedItem, IStatefulItem {
    36 
    3739    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
    38 
    39     public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter => (IFixedValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName];
     40    private const string MinSplittingWidthParameterName = "MinSplittingWidth";
     41    private const string MaxSplittingDepthParameterName = "MaxSplittingDepth";
     42    private const string UseIntervalSplittingParameterName = "UseIntervalSplitting";
     43
     44    public IFixedValueParameter<IntValue> EvaluatedSolutionsParameter =>
     45      (IFixedValueParameter<IntValue>) Parameters[EvaluatedSolutionsParameterName];
     46
     47    public IFixedValueParameter<IntValue> MinSplittingWithParameter =>
     48      (IFixedValueParameter<IntValue>) Parameters[MinSplittingWidthParameterName];
     49
     50    public IFixedValueParameter<IntValue> MaxSplittingDepthParameter =>
     51      (IFixedValueParameter<IntValue>) Parameters[MaxSplittingDepthParameterName];
     52
     53    public IFixedValueParameter<BoolValue> UseIntervalSplittingParameter =>
     54      (IFixedValueParameter<BoolValue>) Parameters[UseIntervalSplittingParameterName];
     55
     56    public int MinSplittingWidth {
     57      get => MinSplittingWithParameter.Value.Value;
     58      set => MinSplittingWithParameter.Value.Value = value;
     59    }
     60
     61    public int MaxSplittingDepth {
     62      get => MaxSplittingDepthParameter.Value.Value;
     63      set => MaxSplittingDepthParameter.Value.Value = value;
     64    }
     65
     66    public bool UseIntervalSplitting {
     67      get => UseIntervalSplittingParameter.Value.Value;
     68      set => UseIntervalSplittingParameter.Value.Value = value;
     69    }
    4070
    4171    public int EvaluatedSolutions {
     
    4676    [StorableConstructor]
    4777    private IntervalInterpreter(StorableConstructorFlag _) : base(_) { }
     78
    4879    private IntervalInterpreter(IntervalInterpreter original, Cloner cloner)
    49         : base(original, cloner) { }
     80      : base(original, cloner) { }
    5081
    5182    public IntervalInterpreter()
    52         : base("IntervalInterpreter", "Intperter for calculation of intervals of symbolic models.") {
    53       Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     83      : base("IntervalInterpreter", "Interpreter for calculation of intervals of symbolic models.") {
     84      Parameters.Add(new FixedValueParameter<IntValue>(EvaluatedSolutionsParameterName,
     85        "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
     86      Parameters.Add(new FixedValueParameter<IntValue>(MinSplittingWidthParameterName, "Minimum interval width until splitting is stopped", new IntValue(0)));
     87      Parameters.Add(new FixedValueParameter<IntValue>(MaxSplittingDepthParameterName, "Maximum recursion depth of the splitting", new IntValue(5)));
     88      Parameters.Add(new FixedValueParameter<BoolValue>(UseIntervalSplittingParameterName, "", new BoolValue(false)));
    5489    }
    5590
     
    6196
    6297    #region IStatefulItem Members
     98
    6399    public void InitializeState() {
    64100      EvaluatedSolutions = 0;
    65101    }
     102
    66103    public void ClearState() { }
     104
    67105    #endregion
    68106
    69     public Interval GetSymbolicExpressionTreeInterval(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows = null) {
     107    public Interval GetSymbolicExpressionTreeInterval(
     108      ISymbolicExpressionTree tree, IDataset dataset,
     109      IEnumerable<int> rows = null, bool splitting = true) {
    70110      var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
    71       return GetSymbolicExpressionTreeInterval(tree, variableRanges);
    72     }
    73 
    74     public Interval GetSymbolicExpressionTreeIntervals(ISymbolicExpressionTree tree, IDataset dataset,
    75       out IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals, IEnumerable<int> rows = null) {
     111      return GetSymbolicExpressionTreeInterval(tree, variableRanges, splitting);
     112    }
     113
     114    public Interval GetSymbolicExpressionTreeIntervals(
     115      ISymbolicExpressionTree tree, IDataset dataset,
     116      out IDictionary<ISymbolicExpressionTreeNode, Interval>
     117        nodeIntervals, IEnumerable<int> rows = null, bool splitting = true) {
    76118      var variableRanges = DatasetUtil.GetVariableRanges(dataset, rows);
    77       return GetSymbolicExpressionTreeIntervals(tree, variableRanges, out nodeIntervals);
    78     }
    79 
    80     public Interval GetSymbolicExpressionTreeInterval(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges) {
     119      return GetSymbolicExpressionTreeIntervals(tree, variableRanges, out nodeIntervals, splitting);
     120    }
     121
     122    public Interval GetSymbolicExpressionTreeInterval(
     123      ISymbolicExpressionTree tree,
     124      IDictionary<string, Interval> variableRanges, bool splitting = true) {
    81125      lock (syncRoot) {
    82126        EvaluatedSolutions++;
    83127      }
    84       int instructionCount = 0;
    85       var instructions = PrepareInterpreterState(tree, variableRanges);
    86       var outputInterval = Evaluate(instructions, ref instructionCount);
    87 
    88       // because of numerical errors the bounds might be incorrect
    89       return outputInterval.LowerBound <= outputInterval.UpperBound ? outputInterval : new Interval(outputInterval.UpperBound, outputInterval.LowerBound);
    90     }
    91 
    92 
    93     public Interval GetSymbolicExpressionTreeIntervals(ISymbolicExpressionTree tree,
    94       IReadOnlyDictionary<string, Interval> variableRanges, out IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals) {
     128
     129      Interval outputInterval;
     130
     131      if (splitting) {
     132        outputInterval = GetSymbolicExpressionTreeIntervals(tree, variableRanges,
     133          out var nodeIntervals);
     134      } else {
     135        var instructionCount = 0;
     136        var instructions = PrepareInterpreterState(tree, variableRanges);
     137        outputInterval = Evaluate(instructions, ref instructionCount);
     138      }
     139
     140      return outputInterval.LowerBound <= outputInterval.UpperBound
     141        ? outputInterval
     142        : new Interval(outputInterval.UpperBound, outputInterval.LowerBound);
     143    }
     144
     145
     146    public Interval GetSymbolicExpressionTreeIntervals(
     147      ISymbolicExpressionTree tree,
     148      IDictionary<string, Interval> variableRanges,
     149      out IDictionary<ISymbolicExpressionTreeNode, Interval>
     150        nodeIntervals, bool splitting = true) {
    95151      lock (syncRoot) {
    96152        EvaluatedSolutions++;
    97153      }
    98       int instructionCount = 0;
     154
    99155      var intervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
    100156      var instructions = PrepareInterpreterState(tree, variableRanges);
    101       var outputInterval = Evaluate(instructions, ref instructionCount, intervals);
    102 
    103       // fix incorrect intervals if necessary (could occur because of numerical errors)
     157
     158      Interval outputInterval;
     159      if (splitting) {
     160        var variables = tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(x => x.VariableName).Distinct()
     161                            .ToList();
     162        var containsDependencyProblem = ContainsVariableMultipleTimes(tree);
     163
     164        if (variables.Count > 1 && containsDependencyProblem) {
     165          var currIndex = 0;
     166          var currDepth = 0;
     167          outputInterval = EvaluateRecursive(instructions, intervals, variableRanges, variables, MinSplittingWidth, MaxSplittingDepth,
     168            ref currIndex, ref currDepth, tree);
     169        } else {
     170          var instructionCount = 0;
     171          outputInterval = Evaluate(instructions, ref instructionCount, intervals);
     172        }
     173      } else {
     174        var instructionCount = 0;
     175        outputInterval = Evaluate(instructions, ref instructionCount, intervals);
     176      }
     177
    104178      nodeIntervals = new Dictionary<ISymbolicExpressionTreeNode, Interval>();
    105179      foreach (var kvp in intervals) {
     
    114188      if (outputInterval.IsInfiniteOrUndefined || outputInterval.LowerBound <= outputInterval.UpperBound)
    115189        return outputInterval;
    116       else
    117         return new Interval(outputInterval.UpperBound, outputInterval.LowerBound);
    118     }
    119 
    120 
    121     private static Instruction[] PrepareInterpreterState(ISymbolicExpressionTree tree, IReadOnlyDictionary<string, Interval> variableRanges) {
     190
     191      return new Interval(outputInterval.UpperBound, outputInterval.LowerBound);
     192    }
     193
     194
     195    private static Instruction[] PrepareInterpreterState(
     196      ISymbolicExpressionTree tree,
     197      IDictionary<string, Interval> variableRanges) {
    122198      if (variableRanges == null)
    123199        throw new ArgumentNullException("No variablew ranges are present!", nameof(variableRanges));
    124200
    125201      //Check if all variables used in the tree are present in the dataset
    126       foreach (var variable in tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(n => n.VariableName).Distinct()) {
    127         if (!variableRanges.ContainsKey(variable)) throw new InvalidOperationException($"No ranges for variable {variable} is present");
    128       }
    129 
    130       Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
    131       foreach (Instruction instr in code.Where(i => i.opCode == OpCodes.Variable)) {
    132         var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
     202      foreach (var variable in tree.IterateNodesPrefix().OfType<VariableTreeNode>().Select(n => n.VariableName).Distinct())
     203        if (!variableRanges.ContainsKey(variable))
     204          throw new InvalidOperationException($"No ranges for variable {variable} is present");
     205
     206      var code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
     207      foreach (var instr in code.Where(i => i.opCode == OpCodes.Variable)) {
     208        var variableTreeNode = (VariableTreeNode) instr.dynamicNode;
    133209        instr.data = variableRanges[variableTreeNode.VariableName];
    134210      }
     211
    135212      return code;
    136213    }
    137214
    138     private Interval Evaluate(Instruction[] instructions, ref int instructionCounter, IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null) {
    139       Instruction currentInstr = instructions[instructionCounter];
     215    public static Interval EvaluateRecursive(
     216      Instruction[] instructions,
     217      IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals,
     218      IDictionary<string, Interval> variableIntervals, IList<string> variables,
     219      double minWidth, int maxDepth, ref int currIndex, ref int currDepth,
     220      ISymbolicExpressionTree tree) {
     221      Interval evaluate() {
     222        var ic = 0;
     223        return Evaluate(instructions, ref ic, nodeIntervals, variableIntervals);
     224      }
     225
     226      Interval recurse(ref int idx, ref int depth) {
     227        return EvaluateRecursive(instructions, nodeIntervals, variableIntervals, variables, minWidth, maxDepth, ref idx,
     228          ref depth, tree);
     229      }
     230
     231
     232      var v = variables[currIndex];
     233      var x = variableIntervals[v];
     234      if (x.Width < minWidth || currDepth == maxDepth || !MultipleTimes(tree, v)) {
     235        if (currIndex + 1 < variables.Count) {
     236          currDepth = 0;
     237          currIndex++;
     238          var z = recurse(ref currIndex, ref currDepth);
     239          currIndex--;
     240          return z;
     241        }
     242
     243        return evaluate();
     244      }
     245
     246      var t  = x.Split();
     247      var xa = t.Item1;
     248      var xb = t.Item2;
     249      var d  = currDepth;
     250      currDepth            = d + 1;
     251      variableIntervals[v] = xa;
     252      var ya = recurse(ref currIndex, ref currDepth);
     253      currDepth            = d + 1;
     254      variableIntervals[v] = xb;
     255      var yb = recurse(ref currIndex, ref currDepth);
     256      variableIntervals[v] = x; // restore interval
     257      return ya | yb;
     258    }
     259
     260    public static Interval Evaluate(
     261      Instruction[] instructions, ref int instructionCounter,
     262      IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null,
     263      IDictionary<string, Interval> variableIntervals = null) {
     264      var currentInstr = instructions[instructionCounter];
    140265      //Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side
    141266      //Update instructionCounter, whenever Evaluate is called
     
    146271        //Variables, Constants, ...
    147272        case OpCodes.Variable: {
    148             var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode;
    149             var weightInterval = new Interval(variableTreeNode.Weight, variableTreeNode.Weight);
    150             var variableInterval = (Interval)currentInstr.data;
    151 
    152             result = Interval.Multiply(variableInterval, weightInterval);
    153             break;
    154           }
     273          var variableTreeNode = (VariableTreeNode) currentInstr.dynamicNode;
     274          var weightInterval   = new Interval(variableTreeNode.Weight, variableTreeNode.Weight);
     275          //var variableInterval = (Interval)currentInstr.data;
     276
     277          Interval variableInterval;
     278          if (variableIntervals != null && variableIntervals.ContainsKey(variableTreeNode.VariableName))
     279            variableInterval = variableIntervals[variableTreeNode.VariableName];
     280          else
     281            variableInterval = (Interval) currentInstr.data;
     282
     283          result = Interval.Multiply(variableInterval, weightInterval);
     284          break;
     285        }
    155286        case OpCodes.Constant: {
    156             var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode;
    157             result = new Interval(constTreeNode.Value, constTreeNode.Value);
    158             break;
    159           }
     287          var constTreeNode = (ConstantTreeNode) currentInstr.dynamicNode;
     288          result = new Interval(constTreeNode.Value, constTreeNode.Value);
     289          break;
     290        }
    160291        //Elementary arithmetic rules
    161292        case OpCodes.Add: {
    162             result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    163             for (int i = 1; i < currentInstr.nArguments; i++) {
    164               var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    165               result = Interval.Add(result, argumentInterval);
    166             }
    167             break;
     293          //result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     294          result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     295          for (var i = 1; i < currentInstr.nArguments; i++) {
     296            //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     297            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     298            result = Interval.Add(result, argumentInterval);
    168299          }
     300
     301          break;
     302        }
    169303        case OpCodes.Sub: {
    170             result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    171             if (currentInstr.nArguments == 1)
    172               result = Interval.Multiply(new Interval(-1, -1), result);
    173 
    174             for (int i = 1; i < currentInstr.nArguments; i++) {
    175               var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    176               result = Interval.Subtract(result, argumentInterval);
    177             }
    178             break;
     304          //result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     305          result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     306          if (currentInstr.nArguments == 1)
     307            result = Interval.Multiply(new Interval(-1, -1), result);
     308
     309          for (var i = 1; i < currentInstr.nArguments; i++) {
     310            //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     311            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     312            result = Interval.Subtract(result, argumentInterval);
    179313          }
     314
     315          break;
     316        }
    180317        case OpCodes.Mul: {
    181             result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    182             for (int i = 1; i < currentInstr.nArguments; i++) {
    183               var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    184               result = Interval.Multiply(result, argumentInterval);
    185             }
    186             break;
     318          //result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     319          result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     320          for (var i = 1; i < currentInstr.nArguments; i++) {
     321            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     322            //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     323            result = Interval.Multiply(result, argumentInterval);
    187324          }
     325
     326          break;
     327        }
    188328        case OpCodes.Div: {
    189             result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    190             if (currentInstr.nArguments == 1)
    191               result = Interval.Divide(new Interval(1, 1), result);
    192 
    193             for (int i = 1; i < currentInstr.nArguments; i++) {
    194               var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    195               result = Interval.Divide(result, argumentInterval);
    196             }
    197             break;
     329          //result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     330          result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     331          if (currentInstr.nArguments == 1)
     332            result = Interval.Divide(new Interval(1, 1), result);
     333
     334          for (var i = 1; i < currentInstr.nArguments; i++) {
     335            //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     336            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     337            result = Interval.Divide(result, argumentInterval);
    198338          }
     339
     340          break;
     341        }
    199342        //Trigonometric functions
    200343        case OpCodes.Sin: {
    201             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    202             result = Interval.Sine(argumentInterval);
    203             break;
    204           }
     344          //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     345          var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     346          result = Interval.Sine(argumentInterval);
     347          break;
     348        }
    205349        case OpCodes.Cos: {
    206             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    207             result = Interval.Cosine(argumentInterval);
    208             break;
    209           }
     350          //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     351          var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     352          result = Interval.Cosine(argumentInterval);
     353          break;
     354        }
    210355        case OpCodes.Tan: {
    211             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    212             result = Interval.Tangens(argumentInterval);
    213             break;
    214           }
     356          //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     357          var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     358          result = Interval.Tangens(argumentInterval);
     359          break;
     360        }
    215361        case OpCodes.Tanh: {
    216             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    217             result = Interval.HyperbolicTangent(argumentInterval);
    218             break;
    219           }
     362          //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     363          var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     364          result = Interval.HyperbolicTangent(argumentInterval);
     365          break;
     366        }
    220367        //Exponential functions
    221368        case OpCodes.Log: {
    222             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    223             result = Interval.Logarithm(argumentInterval);
    224             break;
     369          //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     370          var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     371          result = Interval.Logarithm(argumentInterval);
     372          break;
     373        }
     374        case OpCodes.Exp: {
     375          //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     376          var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     377          result = Interval.Exponential(argumentInterval);
     378          break;
     379        }
     380        case OpCodes.Square: {
     381          //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     382          var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     383          result = Interval.Square(argumentInterval);
     384          break;
     385        }
     386        case OpCodes.SquareRoot: {
     387          //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     388          var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     389          result = Interval.SquareRoot(argumentInterval);
     390          break;
     391        }
     392        case OpCodes.Cube: {
     393          //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     394          var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     395          result = Interval.Cube(argumentInterval);
     396          break;
     397        }
     398        case OpCodes.CubeRoot: {
     399          //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     400          var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     401          result = Interval.CubicRoot(argumentInterval);
     402          break;
     403        }
     404        case OpCodes.Absolute: {
     405          //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     406          var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     407          result = Interval.Absolute(argumentInterval);
     408          break;
     409        }
     410        case OpCodes.AnalyticQuotient: {
     411          //result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     412          result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     413          for (var i = 1; i < currentInstr.nArguments; i++) {
     414            //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
     415            var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals);
     416            result = Interval.AnalyticalQuotient(result, argumentInterval);
    225417          }
    226         case OpCodes.Exp: {
    227             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    228             result = Interval.Exponential(argumentInterval);
    229             break;
    230           }
    231         case OpCodes.Square: {
    232             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    233             result = Interval.Square(argumentInterval);
    234             break;
    235           }
    236         case OpCodes.SquareRoot: {
    237             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    238             result = Interval.SquareRoot(argumentInterval);
    239             break;
    240           }
    241         case OpCodes.Cube: {
    242             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    243             result = Interval.Cube(argumentInterval);
    244             break;
    245           }
    246         case OpCodes.CubeRoot: {
    247             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    248             result = Interval.CubicRoot(argumentInterval);
    249             break;
    250           }
    251         case OpCodes.Absolute: {
    252             var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    253             result = Interval.Absolute(argumentInterval);
    254             break;
    255           }
    256         case OpCodes.AnalyticQuotient: {
    257             result = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    258             for (var i = 1; i < currentInstr.nArguments; i++) {
    259               var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals);
    260               result = Interval.AnalyticalQuotient(result, argumentInterval);
    261             }
    262 
    263             break;
    264           }
     418
     419          break;
     420        }
    265421        default:
    266422          throw new NotSupportedException($"The tree contains the unknown symbol {currentInstr.dynamicNode.Symbol}");
    267423      }
    268424
    269       if (nodeIntervals != null)
     425      if (!(nodeIntervals == null || nodeIntervals.ContainsKey(currentInstr.dynamicNode)))
    270426        nodeIntervals.Add(currentInstr.dynamicNode, result);
    271427
    272428      return result;
    273429    }
     430
     431    private static bool MultipleTimes(ISymbolicExpressionTree tree, string variable) {
     432      var varlist = tree.IterateNodesPrefix().OfType<VariableTreeNode>().GroupBy(x => x.VariableName);
     433      var group   = varlist.Select(x => x.Key == variable).Count();
     434
     435      return group > 1;
     436    }
     437
     438    private static bool ContainsVariableMultipleTimes(ISymbolicExpressionTree tree) {
     439      var varlist = tree.IterateNodesPrefix().OfType<VariableTreeNode>().GroupBy(x => x.VariableName);
     440      return varlist.Any(@group => @group.Count() > 1);
     441    }
     442
    274443
    275444    public static bool IsCompatible(ISymbolicExpressionTree tree) {
     
    277446        from n in tree.Root.GetSubtree(0).IterateNodesPrefix()
    278447        where
    279           !(n.Symbol is Problems.DataAnalysis.Symbolic.Variable) &&
     448          !(n.Symbol is Variable) &&
    280449          !(n.Symbol is Constant) &&
    281450          !(n.Symbol is StartSymbol) &&
Note: See TracChangeset for help on using the changeset viewer.