Esempio n. 1
0
  void Horzcat::evaluateMX(const MXPtrV& input, MXPtrV& output, const MXPtrVV& fwdSeed,
                           MXPtrVV& fwdSens, const MXPtrVV& adjSeed, MXPtrVV& adjSens,
                           bool output_given) {
    int nfwd = fwdSens.size();
    int nadj = adjSeed.size();

    // Non-differentiated output
    if (!output_given) {
      *output[0] = horzcat(getVector(input));
    }

    // Forward sensitivities
    for (int d = 0; d<nfwd; ++d) {
      *fwdSens[d][0] = horzcat(getVector(fwdSeed[d]));
    }

    // Quick return?
    if (nadj==0) return;

    // Get offsets for each column
    vector<int> col_offset(ndep()+1, 0);
    for (int i=0; i<ndep(); ++i) {
      int ncol = dep(i).sparsity().size2();
      col_offset[i+1] = col_offset[i] + ncol;
    }

    // Adjoint sensitivities
    for (int d=0; d<nadj; ++d) {
      MX& aseed = *adjSeed[d][0];
      vector<MX> s = horzsplit(aseed, col_offset);
      aseed = MX();
      for (int i=0; i<ndep(); ++i) {
        adjSens[d][i]->addToSum(s[i]);
      }
    }
  }
  void ImplicitFunctionInternal::evaluateMX(
      MXNode* node, const MXPtrV& arg, MXPtrV& res,
      const MXPtrVV& fseed, MXPtrVV& fsens, const MXPtrVV& aseed, MXPtrVV& asens,
      bool output_given) {
    // Evaluate non-differentiated
    vector<MX> argv = MXNode::getVector(arg);
    MX z; // the solution to the system of equations
    if (output_given) {
      z = *res[iout_];
    } else {
      vector<MX> resv = callSelf(argv);
      for (int i=0; i<resv.size(); ++i) {
        if (res[i]!=0) *res[i] = resv[i];
      }
      z = resv[iout_];
    }

    // Quick return if no derivatives
    int nfwd = fsens.size();
    int nadj = aseed.size();
    if (nfwd==0 && nadj==0) return;

    // Temporaries
    vector<int> col_offset(1, 0);
    vector<MX> rhs;
    vector<int> rhs_loc;

    // Arguments when calling f/f_der
    vector<MX> v;
    v.reserve(getNumInputs()*(1+nfwd) + nadj);
    v.insert(v.end(), argv.begin(), argv.end());
    v[iin_] = z;

    // Get an expression for the Jacobian
    MX J = jac_.call(v).front();

    // Directional derivatives of f
    Function f_der = f_.derivative(nfwd, nadj);

    // Forward sensitivities, collect arguments for calling f_der
    for (int d=0; d<nfwd; ++d) {
      argv = MXNode::getVector(fseed[d]);
      argv[iin_] = MX::zeros(input(iin_).sparsity());
      v.insert(v.end(), argv.begin(), argv.end());
    }

    // Adjoint sensitivities, solve to get arguments for calling f_der
    if (nadj>0) {
      for (int d=0; d<nadj; ++d) {
        for (int i=0; i<getNumOutputs(); ++i) {
          if (aseed[d][i]!=0) {
            if (i==iout_) {
              rhs.push_back(*aseed[d][i]);
              col_offset.push_back(col_offset.back()+1);
              rhs_loc.push_back(v.size()); // where to store it
              v.push_back(MX());
            } else {
              v.push_back(*aseed[d][i]);
            }
          }
          *aseed[d][i] = MX();
        }
      }

      // Solve for all right-hand-sides at once
      rhs = horzsplit(J->getSolve(horzcat(rhs), true, linsol_), col_offset);
      for (int d=0; d<rhs.size(); ++d) {
        v[rhs_loc[d]] = rhs[d];
      }
      col_offset.resize(1);
      rhs.clear();
    }

    // Propagate through the implicit function
    v = f_der.call(v);
    vector<MX>::const_iterator v_it = v.begin();

    // Discard non-differentiated evaluation (change?)
    v_it += getNumOutputs();

    // Forward directional derivatives
    if (nfwd>0) {
      for (int d=0; d<nfwd; ++d) {
        for (int i=0; i<getNumOutputs(); ++i) {
          if (i==iout_) {
            // Collect the arguments
            rhs.push_back(*v_it++);
            col_offset.push_back(col_offset.back()+1);
          } else {
            // Auxiliary output
            if (fsens[d][i]!=0) {
              *fsens[d][i] = *v_it++;
            }
          }
        }
      }

      // Solve for all the forward derivatives at once
      rhs = horzsplit(J->getSolve(horzcat(rhs), false, linsol_), col_offset);
      for (int d=0; d<nfwd; ++d) {
        if (fsens[d][iout_]!=0) {
          *fsens[d][iout_] = -rhs[d];
        }
      }

      col_offset.resize(1);
      rhs.clear();
    }

    // Collect adjoint sensitivities
    for (int d=0; d<nadj; ++d) {
      for (int i=0; i<asens[d].size(); ++i, ++v_it) {
        if (i!=iin_ && asens[d][i]!=0 && !v_it->isNull()) {
          *asens[d][i] += - *v_it;
        }
      }
    }
    casadi_assert(v_it==v.end());
  }