示例#1
0
  void UnaryMX::evaluateD(const DMatrixPtrV& input, DMatrixPtrV& output, const DMatrixPtrVV& fwdSeed, DMatrixPtrVV& fwdSens, const DMatrixPtrVV& adjSeed, DMatrixPtrVV& adjSens){
    double nan = numeric_limits<double>::quiet_NaN();
    vector<double> &outputd = output[0]->data();
    const vector<double> &inputd = input[0]->data();
    int nfwd = fwdSens.size();
    int nadj = adjSeed.size();
  
    if(nfwd==0 && nadj==0){
      // No sensitivities
      for(int i=0; i<size(); ++i)
        casadi_math<double>::fun(op_,inputd[i],nan,outputd[i]);
    
    } else {
      // Sensitivities
      double f, tmp[2];  // temporary variable to hold value and partial derivatives of the function
      for(int i=0; i<size(); ++i){
        // Evaluate and get partial derivatives
        casadi_math<double>::fun(op_,inputd[i],nan,f);
        casadi_math<double>::der(op_,inputd[i],nan,f,tmp);
        outputd[i] = f;

        // Propagate forward seeds
        for(int d=0; d<nfwd; ++d){
          fwdSens[d][0]->data()[i] = tmp[0]*fwdSeed[d][0]->data()[i];
        }

        // Propagate adjoint seeds
        for(int d=0; d<nadj; ++d){
          double s = adjSeed[d][0]->data()[i];
          adjSeed[d][0]->data()[i] = 0;
          adjSens[d][0]->data()[i] += s*tmp[0];
        }
      }
    }
  }
示例#2
0
void Densification::evaluateD(const DMatrixPtrV& input, DMatrixPtrV& output, const DMatrixPtrVV& fwdSeed, DMatrixPtrVV& fwdSens, const DMatrixPtrVV& adjSeed, DMatrixPtrVV& adjSens){
  int nfwd = fwdSens.size();
  int nadj = adjSeed.size();

  // Propate values
  input[0]->get(output[0]->data(),DENSE);
  
  // Propagate forward seeds
  for(int d=0; d<nfwd; ++d){
    fwdSeed[d][0]->get(fwdSens[d][0]->data(),DENSE);
  }

  // Propagate adjoint seeds
  for(int d=0; d<nadj; ++d){
    adjSens[d][0]->set(adjSeed[d][0]->data(),DENSE);
  }
}
示例#3
0
void Multiplication::evaluateD(const DMatrixPtrV& input, DMatrixPtrV& output, const DMatrixPtrVV& fwdSeed, DMatrixPtrVV& fwdSens, const DMatrixPtrVV& adjSeed, DMatrixPtrVV& adjSens){
  int nfwd = fwdSens.size();
  int nadj = adjSeed.size();

  fill(output[0]->begin(),output[0]->end(),0);
  DMatrix::mul_no_alloc(*input[0],*input[1],*output[0]);

  // Forward sensitivities: dot(Z) = dot(X)*Y + X*dot(Y)
  for(int d=0; d<nfwd; ++d){
    fill(fwdSens[d][0]->begin(),fwdSens[d][0]->end(),0);
    DMatrix::mul_no_alloc(*fwdSeed[d][0],*input[1],*fwdSens[d][0]);
    DMatrix::mul_no_alloc(*input[0],*fwdSeed[d][1],*fwdSens[d][0]);
  }

  // Adjoint sensitivities
  for(int d=0; d<nadj; ++d){
    DMatrix::mul_no_alloc1(*adjSens[d][0],*input[1],*adjSeed[d][0]);
    DMatrix::mul_no_alloc2(*input[0],*adjSens[d][1],*adjSeed[d][0]);
  }
}
示例#4
0
void EvaluationMX::evaluateD(const DMatrixPtrV& arg, DMatrixPtrV& res,
    const DMatrixPtrVV& fseed, DMatrixPtrVV& fsens,
    const DMatrixPtrVV& aseed, DMatrixPtrVV& asens) {
  
  // Number of inputs and outputs
  int num_in = fcn_.getNumInputs();
  int num_out = fcn_.getNumOutputs();

  // Number of derivative directions to calculate
  int nfdir = fsens.size();
  int nadir = aseed.size();

  // Number of derivative directions supported by the function
  int max_nfdir = fcn_.numAllocFwd();
  int max_nadir = fcn_.numAllocAdj();

  // Current forward and adjoint direction
  int offset_nfdir = 0, offset_nadir = 0;

  // Has the function been evaluated once
  bool fcn_evaluated = false;

  // Pass the inputs to the function
  for (int i = 0; i < num_in; ++i) {
    DMatrix *a = arg[i];
    if(a != 0){
      fcn_.setInput(*a, i);
    } else {
      fcn_.setInput(0., i);
    }
  }
  
  // Evaluate until everything has been determinated
  while (!fcn_evaluated || offset_nfdir < nfdir || offset_nadir < nadir) {

    // Number of forward and adjoint directions in the current "batch"
    int nfdir_f_batch = std::min(nfdir - offset_nfdir, max_nfdir);
    int nadir_f_batch = std::min(nadir - offset_nadir, max_nadir);

    // Pass the forward seeds to the function
    for(int d = 0; d < nfdir_f_batch; ++d){
      for(int i = 0; i < num_in; ++i){
        DMatrix *a = fseed[offset_nfdir + d][i];
        if(a != 0){
          fcn_.setFwdSeed(*a, i, d);
        } else {
          fcn_.setFwdSeed(0., i, d);
        }
      }
    }

    // Pass the adjoint seed to the function
    for(int d = 0; d < nadir_f_batch; ++d){
      for(int i = 0; i < num_out; ++i) {
        DMatrix *a = aseed[offset_nadir + d][i];
        if(a != 0){
          fcn_.setAdjSeed(*a, i, d);
        } else {
          fcn_.setAdjSeed(0., i, d);
        }
      }
    }

    // Evaluate
    fcn_.evaluate(nfdir_f_batch, nadir_f_batch);
    
    // Get the outputs if first evaluation
    if(!fcn_evaluated){
      for(int i = 0; i < num_out; ++i) {
        if(res[i] != 0) fcn_.getOutput(*res[i], i);
      }
    }

    // Marked as evaluated
    fcn_evaluated = true;

    // Get the forward sensitivities
    for(int d = 0; d < nfdir_f_batch; ++d){
      for(int i = 0; i < num_out; ++i) {
        DMatrix *a = fsens[offset_nfdir + d][i];
        if(a != 0) fcn_.getFwdSens(*a, i, d);
      }
    }

    // Get the adjoint sensitivities
    for (int d = 0; d < nadir_f_batch; ++d) {
      for (int i = 0; i < num_in; ++i) {
        DMatrix *a = asens[offset_nadir + d][i];
        if(a != 0){
          a->sparsity().add(a->ptr(),fcn_.adjSens(i,d).ptr(),fcn_.adjSens(i,d).sparsity());
        }
      }
    }

    // Update direction offsets
    offset_nfdir += nfdir_f_batch;
    offset_nadir += nadir_f_batch;
  }
}