Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
10/03/19 12:30:19 (5 years ago)
Author:
gkronber
Message:

#2994 continued refactoring and extended unit tests. Interval calculation still fails for some edge cases (mainly for undefined behaviour). VectorEvaluator and VectorAutoDiffEvaluator produce the same results as the LinearInterpreter. TODO: check gradient calculation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2994-AutoDiffForIntervals/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/VectorAutoDiffEvaluator.cs

    r17296 r17303  
    55
    66namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
    7   public sealed class VectorAutoDiffEvaluator : InterpreterBase<MultivariateDual<AlgebraicDoubleVector>> {
     7  public sealed class VectorAutoDiffEvaluator : InterpreterBase<VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>> {
    88    private const int BATCHSIZE = 128;
    99    [ThreadStatic]
     
    5757      for (rowIndex = 0; rowIndex < roundedTotal; rowIndex += BATCHSIZE) {
    5858        Evaluate(code);
    59         code[0].value.Value.CopyTo(fi, rowIndex, BATCHSIZE);
    6059
    61         // TRANSPOSE into JAC
    62         var g = code[0].value.Gradient;
    63         for (int j = 0; j < nParams; ++j) {
    64           if (g.Elements.TryGetValue(j, out AlgebraicDoubleVector v)) {
    65             v.CopyColumnTo(jac, j, rowIndex, BATCHSIZE);
    66           } else {
    67             for (int r = 0; r < BATCHSIZE; r++) jac[rowIndex + r, j] = 0.0;
     60        // code[0].value.Value.CopyTo(fi, rowIndex, BATCHSIZE);
     61        var v = code[0].value;
     62        for (int k = 0; k < BATCHSIZE; k++) {
     63          fi[rowIndex + k] = v[k].Value.Value;
     64
     65          // copy gradient to Jacobian
     66          var g = v[k].Gradient;
     67          for (int j = 0; j < nParams; ++j) {
     68            if (g.Elements.TryGetValue(j, out AlgebraicDouble gj)) {
     69              jac[rowIndex + k, j] = gj.Value;
     70            } else {
     71              jac[rowIndex + k, j] = 0.0;
     72            }
    6873          }
    6974        }
     
    7277      if (remainingRows > 0) {
    7378        Evaluate(code);
    74         code[0].value.Value.CopyTo(fi, roundedTotal, remainingRows);
     79        // code[0].value.Value.CopyTo(fi, roundedTotal, remainingRows);
     80        var v = code[0].value;
     81        for (int k = 0; k < remainingRows; k++) {
     82          fi[roundedTotal + k] = v[k].Value.Value;
    7583
    76         var g = code[0].value.Gradient;
    77         for (int j = 0; j < nParams; ++j)
    78           if (g.Elements.TryGetValue(j, out AlgebraicDoubleVector v)) {
    79             v.CopyColumnTo(jac, j, roundedTotal, remainingRows);
    80           } else {
    81             for (int r = 0; r < remainingRows; r++) jac[roundedTotal + r, j] = 0.0;
     84          var g = v[k].Gradient;
     85          for (int j = 0; j < nParams; ++j) {
     86            if (g.Elements.TryGetValue(j, out AlgebraicDouble gj)) {
     87              jac[roundedTotal + k, j] = gj.Value;
     88            } else {
     89              jac[roundedTotal + k, j] = 0.0;
     90            }
    8291          }
     92        }
    8393      }
    8494    }
    8595
    8696    protected override void InitializeInternalInstruction(ref Instruction instruction, ISymbolicExpressionTreeNode node) {
    87       var zero = new AlgebraicDoubleVector(BATCHSIZE);
    88       instruction.value = new MultivariateDual<AlgebraicDoubleVector>(zero);
     97      instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE).Zero; // XXX zero needed?
    8998    }
    9099
    91100    protected override void InitializeTerminalInstruction(ref Instruction instruction, ConstantTreeNode constant) {
    92       var g_arr = new double[BATCHSIZE];
    93101      if (node2paramIdx.TryGetValue(constant, out var paramIdx)) {
    94         for (int i = 0; i < BATCHSIZE; i++) g_arr[i] = 1.0;
    95         var g = new AlgebraicDoubleVector(g_arr);
    96         instruction.value = new MultivariateDual<AlgebraicDoubleVector>(new AlgebraicDoubleVector(BATCHSIZE), paramIdx, g); // only a single column for the gradient
     102        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
     103        for (int k = 0; k < BATCHSIZE; k++) {
     104          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(constant.Value, paramIdx, 1.0); // gradient is 1.0 for all elements
     105        }
    97106      } else {
    98         instruction.value = new MultivariateDual<AlgebraicDoubleVector>(new AlgebraicDoubleVector(BATCHSIZE));
     107        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
     108        for (int k = 0; k < BATCHSIZE; k++) {
     109          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(constant.Value); // zero gradient
     110        }
    99111      }
    100112
    101       instruction.dblVal = constant.Value;
    102       instruction.value.Value.AssignConstant(instruction.dblVal);
     113      instruction.dblVal = constant.Value; // also store the parameter value in the instruction (not absolutely necessary, will not be used)
    103114    }
    104115
     
    115126      if (node2paramIdx.ContainsKey(variable)) {
    116127        paramIdx = node2paramIdx[variable];
    117         var f = new AlgebraicDoubleVector(BATCHSIZE);
    118         var g = new AlgebraicDoubleVector(BATCHSIZE);
    119         instruction.value = new MultivariateDual<AlgebraicDoubleVector>(f, paramIdx, g);
     128        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
     129        for(int k=0;k<BATCHSIZE;k++) {
     130          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(0.0, paramIdx, 0.0); // values are set in LoadVariable()
     131        }
    120132      } else {
    121133        var f = new AlgebraicDoubleVector(BATCHSIZE);
    122         instruction.value = new MultivariateDual<AlgebraicDoubleVector>(f);
     134        instruction.value = new VectorOfAlgebraic<MultivariateDual<AlgebraicDouble>>(BATCHSIZE);
     135        for (int k = 0; k < BATCHSIZE; k++) {
     136          instruction.value[k] = new MultivariateDual<AlgebraicDouble>(0.0); // values are set in LoadVariable()
     137        }
    123138      }
    124139
    125       instruction.dblVal = variable.Weight;
     140      instruction.dblVal = variable.Weight; 
    126141      instruction.data = new object[] { data, paramIdx };
    127142    }
     
    131146      var data = (double[])((object[])a.data)[0];
    132147
    133       for (int i = rowIndex; i < rows.Length && i - rowIndex < BATCHSIZE; i++) a.value.Value[i - rowIndex] = data[rows[i]];
    134       a.value.Scale(a.dblVal);
     148      for (int i = rowIndex; i < rows.Length && i - rowIndex < BATCHSIZE; i++) {
     149        a.value[i - rowIndex].Value.Assign(a.dblVal * data[rows[i]]);
     150      }
    135151
    136152      if (paramIdx >= 0) {
    137153        // update gradient with variable values
    138         var g = a.value.Gradient.Elements[paramIdx];
    139154        for (int i = rowIndex; i < rows.Length && i - rowIndex < BATCHSIZE; i++) {
    140           g[i - rowIndex] = data[rows[i]];
     155          a.value[i - rowIndex].Gradient.Elements[paramIdx].Assign(data[rows[i]]);
    141156        }
    142157      }
Note: See TracChangeset for help on using the changeset viewer.