void SnoptInterface::solve(void* mem) const { auto m = static_cast<SnoptMemory*>(mem); // Check the provided inputs checkInputs(mem); m->fstats.at("mainloop").tic(); // Memory object snProblem prob; // Evaluate gradF and jacG at initial value const double** arg = m->arg; *arg++ = m->x0; *arg++ = m->p; double** res = m->res; *res++ = 0; *res++ = m->jac_gk; calc_function(m, "nlp_jac_g"); res = m->res; *res++ = 0; *res++ = m->jac_fk; calc_function(m, "nlp_jac_f"); // perform the mapping: // populate A_data_ (the nonzeros of A) // with numbers pulled from jacG and gradF for (int k = 0; k < A_structure_.nnz(); ++k) { int i = A_structure_.nonzeros()[k]; if (i == 0) { m->A_data[k] = 0; } else if (i > 0) { m->A_data[k] = m->jac_gk[i-1]; } else { m->A_data[k] = m->jac_fk[-i-1]; } } int n = nx_; int nea = A_structure_.nnz(); double ObjAdd = 0; casadi_assert(m_ > 0); casadi_assert(n > 0); casadi_assert(nea > 0); casadi_assert(A_structure_.nnz() == nea); // Pointer magic, courtesy of Greg casadi_assert_message(!jac_f_fcn_.is_null(), "blaasssshc"); // Outputs //double Obj = 0; // TODO(Greg): get this from snopt // snInit must be called first. // 9, 6 are print and summary unit numbers (for Fortran). // 6 == standard out int iprint = 9; int isumm = 6; std::string outname = name_ + ".out"; snInit(&prob, const_cast<char*>(name_.c_str()), const_cast<char*>(outname.c_str()), iprint, isumm); // Set the problem size and other data. // This will allocate arrays inside snProblem struct. setProblemSize(&prob, m_, nx_, nea, nnCon_, nnJac_, nnObj_); setObjective(&prob, iObj_, ObjAdd); setUserfun(&prob, userfunPtr); // user data prob.leniu = 1; prob.iu = &m->memind; // Pass bounds casadi_copy(m->lbx, nx_, prob.bl); casadi_copy(m->ubx, nx_, prob.bu); casadi_copy(m->lbg, ng_, prob.bl + nx_); casadi_copy(m->ubg, ng_, prob.bu + nx_); // Initialize states and slack casadi_fill(prob.hs, ng_ + nx_, 0); casadi_copy(m->x0, nx_, prob.x); casadi_fill(prob.x + nx_, ng_, 0.); // Initialize multipliers casadi_copy(m->lam_g0, ng_, prob.pi); // Set up Jacobian matrix casadi_copy(A_structure_.colind(), A_structure_.size2()+1, prob.locJ); casadi_copy(A_structure_.row(), A_structure_.nnz(), prob.indJ); casadi_copy(get_ptr(m->A_data), A_structure_.nnz(), prob.valJ); for (auto&& op : opts_) { // Replace underscores with spaces std::string opname = op.first; std::replace(opname.begin(), opname.end(), '_', ' '); // Try integer if (op.second.can_cast_to(OT_INT)) { casadi_assert(opname.size() <= 55); int flag = setIntParameter(&prob, const_cast<char*>(opname.c_str()), op.second.to_int()); if (flag==0) continue; } // Try double if (op.second.can_cast_to(OT_DOUBLE)) { casadi_assert(opname.size() <= 55); int flag = setRealParameter(&prob, const_cast<char*>(opname.c_str()), op.second.to_double()); if (flag==0) continue; } // try string if (op.second.can_cast_to(OT_STRING)) { std::string buffer = opname + " " + op.second.to_string(); casadi_assert(buffer.size() <= 72); int flag = setParameter(&prob, const_cast<char*>(buffer.c_str())); if (flag==0) continue; } // Error if reached this point casadi_error("SNOPT error setting option \"" + opname + "\""); } m->fstats.at("mainloop").toc(); // Run SNOPT int info = solveC(&prob, Cold_, &m->fk); casadi_assert_message(99 != info, "snopt problem set up improperly"); // Negate rc to match CasADi's definition casadi_scal(nx_ + ng_, -1., prob.rc); // Get primal solution casadi_copy(prob.x, nx_, m->x); // Get dual solution casadi_copy(prob.rc, nx_, m->lam_x); casadi_copy(prob.rc+nx_, ng_, m->lam_g); // Copy optimal cost to output if (m->f) *m->f = m->fk; // Copy optimal constraint values to output casadi_copy(m->gk, ng_, m->g); // Free memory deleteSNOPT(&prob); }
int main( int argc , char* argv[] ) { snProblem toy; int i, info; int Cold = 0; int n = 2; int m = 3; int ne = 5; int nnCon = 2; int nnObj = 0; int nnJac = 2; int iObj = 2; double ObjAdd = 0; double objective; // snInit must be called first. // 9, 6 are print and summary unit numbers (for Fortran). // 6 == standard out snInit ( &toy, "ToyB", "ToyB.out", 9, 6 ); // Set the problem size and other data. // This will allocate arrays inside snProblem struct. setProblemSize ( &toy, m, n, ne, nnCon, nnJac, nnObj ); setObjective ( &toy, iObj, ObjAdd ); setFuncon ( &toy, (snConB) toycon ); setFunobj ( &toy, (snObjB) toyobj ); // User workspace allocated and set. // May be accesed in the user-defined function toyusrfun. toy.leniu = 2; toy.iu = (int*)malloc( sizeof(int) * toy.leniu ); toy.iu[0] = 0; toy.iu[1] = 1; // Set bounds toy.bl[0] = 0; toy.bu[0] = 1e20; toy.bl[1] = -1e20; toy.bu[1] = 1e20; toy.bl[2] = -1e20; toy.bu[2] = 4; toy.bl[3] = -1e20; toy.bu[3] = 5; toy.bl[4] = -1e20; toy.bu[4] = 1e20; // Initialize states, x and multipliers for ( i = 0; i < n+m; i++ ) { toy.hs[i] = 0; toy.x[i] = 0; toy.rc[i] = 0; } for ( i = 0; i < m; i++ ) { toy.pi[i] = 0; } toy.x[0] = 1.0; toy.x[1] = 1.0; // Set up the Jacobian matrix // Column 1 toy.locJ[0] = 0; toy.indJ[0] = 0; toy.valJ[0] = 0; toy.indJ[1] = 1; toy.valJ[1] = 0; // Column 2 toy.locJ[1] = 2; toy.indJ[2] = 0; toy.valJ[2] = 0; toy.indJ[3] = 1; toy.valJ[3] = 0; toy.indJ[4] = 2; toy.valJ[4] = 1; toy.locJ[2] = 5; // Read options, set options. info = setSpecsfile ( &toy, "sntoy.spc" ); setIntParameter( &toy, "Verify level", 3 ); setIntParameter( &toy, "Derivative option", 3 ); info = solveB( &toy, Cold, &objective ); // Deallocate space. free ( toy.iu ); deleteSNOPT ( &toy ); return 0; }