void makeSmooth(SXMatrix &ex, SXMatrix &bvar, SXMatrix &bexpr){ // Initialize SXFunction fcn(SXMatrix(),ex); casadi_assert(bexpr.empty()); // Nodes to be replaced std::map<int,SX> replace; // Go through all nodes and check if any node is non-smooth for(int i=0; i<fcn->algorithm.size(); ++i){ // Check if we have a step node if(fcn->algorithm[i].op == STEP){ // Get the index of the child int ch0 = fcn->algorithm[i].ch[0]; // Binary variable corresponding to the the switch SXMatrix sw; #if 0 // Find out if the switch has already been added for(int j=0; j<bexpr.size(); ++j) if(bexpr[j].isEqual(algorithm[i]->child0)){ sw = bvar[j]; break; } #endif if(sw.empty()){ // the switch has not yet been added // Get an approriate name of the switch std::stringstream name; name << "sw_" << bvar.size1(); sw = SX(name.str()); // Add to list of switches bvar << sw; // bexpr << algorithm[i]->child0; } // Add to the substition map replace[i] = sw[0]; } } SXMatrix res; fcn->eval(SXMatrix(),res,replace,bexpr); for(int i=0; i<bexpr.size(); ++i) bexpr[i] = bexpr[i]->dep(0); ex = res; #if 0 // Make sure that the binding expression is smooth bexpr.init(SXMatrix()); SXMatrix b; bexpr.eval_symbolic(SXMatrix(),b,replace,bexpr); bexpr = b; #endif }
void substituteInPlace(const SXMatrix &v, SXMatrix &vdef, std::vector<SXMatrix>& ex, bool reverse){ casadi_assert_message(isSymbolic(v),"the variable is not symbolic"); casadi_assert_message(v.sparsity() == vdef.sparsity(),"the sparsity patterns of the expression and its defining expression do not match"); if(v.empty()) return; // quick return if nothing to replace // Function inputs std::vector<SXMatrix> f_in; if(!reverse) f_in.push_back(v); // Function outputs std::vector<SXMatrix> f_out; f_out.push_back(vdef); f_out.insert(f_out.end(),ex.begin(),ex.end()); // Write the mapping function SXFunction f(f_in,f_out); f.init(); // Get references to the internal data structures const vector<SXAlgEl>& algorithm = f.algorithm(); vector<SX> work(f.getWorkSize()); // Iterator to the binary operations vector<SX>::const_iterator b_it=f->operations_.begin(); // Iterator to stack of constants vector<SX>::const_iterator c_it = f->constants_.begin(); // Iterator to free variables vector<SX>::const_iterator p_it = f->free_vars_.begin(); // Evaluate the algorithm for(vector<SXAlgEl>::const_iterator it=algorithm.begin(); it<algorithm.end(); ++it){ switch(it->op){ case OP_INPUT: // reverse is false, substitute out work[it->res] = vdef.at(it->arg.i[1]); break; case OP_OUTPUT: if(it->res==0){ vdef.at(it->arg.i[1]) = work[it->arg.i[0]]; if(reverse){ // Use the new variable henceforth, substitute in work[it->arg.i[0]] = v.at(it->arg.i[1]); } } else { // Auxillary output ex[it->res-1].at(it->arg.i[1]) = work[it->arg.i[0]]; } break; case OP_CONST: work[it->res] = *c_it++; break; case OP_PARAMETER: work[it->res] = *p_it++; break; default: { switch(it->op){ CASADI_MATH_FUN_BUILTIN(work[it->arg.i[0]],work[it->arg.i[1]],work[it->res]) } // Avoid creating duplicates const int depth = 2; // NOTE: a higher depth could possibly give more savings work[it->res].assignIfDuplicate(*b_it++,depth); } } } }