int main(){
  // Test both SX and MX
  for(int test=0; test<2; ++test){

    // Create a simple function
    FX f;
    if(test==0){
      cout << "SXFunction:" << endl;
      SXMatrix x = ssym("x",3);
      SXMatrix z = x[0]*x[0]+x[2] + 3;
      f = SXFunction(x,z);
    } else {
      cout << "MXFunction:" << endl;
      MX x = msym("x",3);
      MX z = x[0]*x[0]+x[2] + 3;
      f = MXFunction(x,z);
    }
    f.init();
    
    // Get arrays for the inputs and outputs, reinterpreting the vector of double as an array of unsigned integers
    bvec_t* f_in = get_bvec_t(f.input().data());
    bvec_t* f_out = get_bvec_t(f.output().data());
    
    // Propagate from input to output (forward mode)
    cout << "forward mode" << endl;
    int fwd = true;
    
    // Make sure that the class is able to support the dependency propagation
    casadi_assert(f.spCanEvaluate(fwd));
    
    // Pass seeds
    f_in[0] = bvec_t(1) << 0; // seed in direction 0
    f_in[1] = bvec_t(1) << 2; // seed in direction 2
    f_in[2] = (bvec_t(1) << 4) | (bvec_t(1) << 63); // seed in direction 4 and 63

    // Reset sensitivities
    f_out[0] = 0;
    
    // Propagate dependencies
    f.spInit(fwd);
    f.spEvaluate(fwd);

    // Print the result
    printBinary(f_out[0]);
    
    // Propagate from output to input (adjoint/reverse/backward mode)
    cout << "backward mode" << endl;
    fwd = false;

    // Make sure that the class is able to support the dependency propagation
    casadi_assert(f.spCanEvaluate(fwd));

    // Pass seeds
    f_out[0] = (bvec_t(1) << 5) | (bvec_t(1) << 6); // seed in direction 5 and 6
    
    // Reset sensitivities
    f_in[0] = 0;
    f_in[1] = 0;
    f_in[2] = 0;
    
    // Propagate dependencies
    f.spInit(fwd);
    f.spEvaluate(fwd);

    // Print the result
    printBinary(f_in[0]);
    printBinary(f_in[1]);
    printBinary(f_in[2]);
  }
  
  return 0;
}
Beispiel #2
0
void EvaluationMX::create(const FX& fcn, const std::vector<MX> &arg,
    std::vector<MX> &res, const std::vector<std::vector<MX> > &fseed,
    std::vector<std::vector<MX> > &fsens,
    const std::vector<std::vector<MX> > &aseed,
    std::vector<std::vector<MX> > &asens, bool output_given) {

  // Number inputs and outputs
  int num_in = fcn.getNumInputs();
  int num_out = fcn.getNumOutputs();

  // Number of directional derivatives
  int nfdir = fseed.size();
  int nadir = aseed.size();

  // Create the evaluation node
  MX ev;
  if(nfdir>0 || nadir>0){
    // Create derivative function
    Derivative dfcn(fcn,nfdir,nadir);
    stringstream ss;
    ss << "der_" << fcn.getOption("name") << "_" << nfdir << "_" << nadir;
    dfcn.setOption("verbose",fcn.getOption("verbose"));
    dfcn.setOption("name",ss.str());
    dfcn.init();
    
    // All inputs
    vector<MX> darg;
    darg.reserve(num_in*(1+nfdir) + num_out*nadir);
    darg.insert(darg.end(),arg.begin(),arg.end());
    
    // Forward seeds
    for(int dir=0; dir<nfdir; ++dir){
      darg.insert(darg.end(),fseed[dir].begin(),fseed[dir].end());
    }
    
    // Adjoint seeds
    for(int dir=0; dir<nadir; ++dir){
      darg.insert(darg.end(),aseed[dir].begin(),aseed[dir].end());
    }
    
    ev.assignNode(new EvaluationMX(dfcn, darg));
  } else {
    ev.assignNode(new EvaluationMX(fcn, arg));
  }

  // Output index
  int ind = 0;

  // Create the output nodes corresponding to the nondifferented function
  res.resize(num_out);
  for (int i = 0; i < num_out; ++i, ++ind) {
    if(!output_given){
      if(!fcn.output(i).empty()){
        res[i].assignNode(new OutputNode(ev, ind));
      } else {
        res[i] = MX();
      }
    }
  }

  // Forward sensitivities
  fsens.resize(nfdir);
  for(int dir = 0; dir < nfdir; ++dir){
    fsens[dir].resize(num_out);
    for (int i = 0; i < num_out; ++i, ++ind) {
      if (!fcn.output(i).empty()){
        fsens[dir][i].assignNode(new OutputNode(ev, ind));
      } else {
        fsens[dir][i] = MX();
      }
    }
  }

  // Adjoint sensitivities
  asens.resize(nadir);
  for (int dir = 0; dir < nadir; ++dir) {
    asens[dir].resize(num_in);
    for (int i = 0; i < num_in; ++i, ++ind) {
      if (!fcn.input(i).empty()) {
        asens[dir][i].assignNode(new OutputNode(ev, ind));
      } else {
        asens[dir][i] = MX();
      }
    }
  }
}
Beispiel #3
0
// Create an IDAS instance (fully implicit integrator)
Integrator create_Sundials(){
  // Time 
  SX t("t");

  // Differential states
  SX s("s"), v("v"), m("m");
  vector<SX> x(3); 
  x[0] = s;
  x[1] = v;
  x[2] = m;
  
  // State derivatives
  SX sdot("sdot"), vdot("vdot"), mdot("mdot");
  vector<SX> xdot(3); 
  xdot[0] = sdot;
  xdot[1] = vdot;
  xdot[2] = mdot;

  // Control
  SX u("u");
  
  // Reference trajectory
  SX u_ref = 3-sin(t);
  
  // Square deviation from the state trajectory
  SX u_dev = u-u_ref;
  u_dev *= u_dev;
  
  // Differential equation (fully implicit form)
  vector<SX> res(3);
  res[0] = v - sdot;
  res[1] = (u-0.02*v*v)/m - vdot;
  res[2] = -0.01*u*u - mdot;

  // Input/output of the DAE residual function
  vector<SXMatrix> ffcn_in = daeIn<SXMatrix>("x",x, "p",u, "t",t, "xdot",xdot);
  vector<SXMatrix> ffcn_out = daeOut<SXMatrix>("ode",res, "quad",u_dev);

  // DAE residual function
  FX ffcn = SXFunction(ffcn_in,ffcn_out);

  // Overwrite ffcn with a plain c function (avoid this!)
  if(plain_c){
    // Use DAE residual defined in a c-function
    ffcn = CFunction(dae_res_c_wrapper);
    
    // Specify the number of inputs and outputs
    ffcn.setNumInputs(DAE_NUM_IN);
    ffcn.setNumOutputs(DAE_NUM_OUT);
    
    // Specify dimensions of inputs and outputs
    ffcn.input(DAE_T)    = DMatrix(1,1,0);
    ffcn.input(DAE_X)    = DMatrix(3,1,0);
    ffcn.input(DAE_XDOT) = DMatrix(3,1,0);
    ffcn.input(DAE_P)    = DMatrix(1,1,0);
    ffcn.output(DAE_ODE) = DMatrix(3,1,0);
    ffcn.output(DAE_QUAD) = DMatrix(1,1,0);
  }
  
  if(implicit_integrator){
    // Create an IDAS instance
    IdasIntegrator integrator(ffcn);
    
    // Set IDAS specific options
    integrator.setOption("calc_ic",calc_ic);

    // Return the integrator
    return integrator;
  } else {
    // Create an CVodes instance
    CVodesIntegrator integrator(ffcn);

    // Return the integrator
    return integrator;
  }
}