예제 #1
0
파일: concat.cpp 프로젝트: cfpperche/casadi
 void Concat::propagateSparsity(DMatrixPtrV& input, DMatrixPtrV& output, bool fwd) {
   bvec_t *res_ptr = get_bvec_t(output[0]->data());
   for (int i=0; i<input.size(); ++i) {
     vector<double>& arg_i = input[i]->data();
     bvec_t *arg_i_ptr = get_bvec_t(arg_i);
     if (fwd) {
       copy(arg_i_ptr, arg_i_ptr+arg_i.size(), res_ptr);
       res_ptr += arg_i.size();
     } else {
       for (int k=0; k<arg_i.size(); ++k) {
         *arg_i_ptr++ |= *res_ptr;
         *res_ptr++ = 0;
       }
     }
   }
 }
예제 #2
0
void EvaluationMX::propagateSparsity(DMatrixPtrV& arg, DMatrixPtrV& res,bool use_fwd) {
  if (fcn_.spCanEvaluate(use_fwd)) {
    // Propagating sparsity pattern supported
    
    // Pass/clear forward seeds/adjoint sensitivities
    for (int iind = 0; iind < fcn_.getNumInputs(); ++iind) {
      // Input vector
      vector<double> &v = fcn_.input(iind).data();
      if (v.empty()) continue; // FIXME: remove?

      if (arg[iind] == 0) {
        // Set to zero if not used
        fill_n(get_bvec_t(v), v.size(), bvec_t(0));
      } else {
        // Copy output
        fcn_.input(iind).sparsity().set(
          get_bvec_t(fcn_.input(iind).data()),
          get_bvec_t(arg[iind]->data()),
          arg[iind]->sparsity());
      }
    }

    // Pass/clear adjoint seeds/forward sensitivities
    for (int oind = 0; oind < fcn_.getNumOutputs(); ++oind) {
      // Output vector
      vector<double> &v = fcn_.output(oind).data();
      if (v.empty()) continue; // FIXME: remove?

      if (res[oind] == 0) {
        // Set to zero if not used
        fill_n(get_bvec_t(v), v.size(), bvec_t(0));
      } else {
        // Copy output
        fcn_.output(oind).sparsity().set(
            get_bvec_t(fcn_.output(oind).data()),
            get_bvec_t(res[oind]->data()),
            res[oind]->sparsity());
      }
    }

    // Propagate seedsfcn_.
    fcn_.spInit(use_fwd); // NOTE: should only be done once
    fcn_.spEvaluate(use_fwd);

    // Get the sensitivities
    if (use_fwd) {
      for (int oind = 0; oind < res.size(); ++oind) {
        if (res[oind] != 0) {
          res[oind]->sparsity().set(
              get_bvec_t(res[oind]->data()),
              get_bvec_t(fcn_.output(oind).data()),
              fcn_.output(oind).sparsity());
        }
      }
    } else {
      for (int iind = 0; iind < arg.size(); ++iind) {
        if (arg[iind] != 0) {
          arg[iind]->sparsity().bor(
              get_bvec_t(arg[iind]->data()),
              get_bvec_t(fcn_.input(iind).data()),
              fcn_.input(iind).sparsity());
        }
      }
    }

    // Clear seeds and sensitivities
    for (int iind = 0; iind < arg.size(); ++iind) {
      vector<double> &v = fcn_.input(iind).data();
      fill(v.begin(), v.end(), 0);
    }
    for (int oind = 0; oind < res.size(); ++oind) {
      vector<double> &v = fcn_.output(oind).data();
      fill(v.begin(), v.end(), 0);
    }

  } else {
    // Propagating sparsity pattern not supported

    if (use_fwd) {
      // Clear the outputs
      for (int oind = 0; oind < res.size(); ++oind) {
        // Skip of not used
        if (res[oind] == 0)
          continue;

        // Get data array for output and clear it
        bvec_t *outputd = get_bvec_t(res[oind]->data());
        fill_n(outputd, res[oind]->size(), 0);
      }
    }

    // Loop over inputs
    for (int iind = 0; iind < arg.size(); ++iind) {
      // Skip of not used
      if (arg[iind] == 0)
        continue;

      // Skip if no seeds
      if (use_fwd && arg[iind]->empty())
        continue;

      // Get data array for input
      bvec_t *inputd = get_bvec_t(arg[iind]->data());

      // Loop over outputs
      for (int oind = 0; oind < res.size(); ++oind) {

        // Skip of not used
        if (res[oind] == 0)
          continue;

        // Skip if no seeds
        if (!use_fwd && res[oind]->empty())
          continue;

        // Get the sparsity of the Jacobian block
        CRSSparsity& sp = fcn_.jacSparsity(iind, oind, true);
        if (sp.isNull() || sp.size() == 0)
          continue; // Skip if zero
        const int d1 = sp.size1();
        //const int d2 = sp.size2();
        const vector<int>& rowind = sp.rowind();
        const vector<int>& col = sp.col();

        // Get data array for output
        bvec_t *outputd = get_bvec_t(res[oind]->data());

        // Carry out the sparse matrix-vector multiplication
        for (int i = 0; i < d1; ++i) {
          for (int el = rowind[i]; el < rowind[i + 1]; ++el) {
            // Get column
            int j = col[el];

            // Propagate dependencies
            if (use_fwd) {
              outputd[i] |= inputd[j];
            } else {
              inputd[j] |= outputd[i];
            }
          }
        }
      }
    }
  }
}