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]; } } } }
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); } }
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]); } }
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; } }