/** * Run the WORHP algorithm. * * @param[in,out] pop input/output pagmo::population to be evolved. */ void worhp::evolve(pagmo::population& pop) const { if (pop.size() == 0) { return; } const auto& prob = pop.problem(); if (prob.get_i_dimension() != 0) { pagmo_throw(value_error, "The problem has an integer part and WORHP is not suitable to solve it."); } if (prob.get_f_dimension() != 1) { pagmo_throw(value_error, "The problem is not single objective and WORHP is not suitable to solve it"); } // We check the screen output again as the user may have changed it if (m_screen_output) { SetWorhpPrint(default_output); } else { SetWorhpPrint(no_screen_output); } OptVar opt; Control control; Params params; Workspace workspace; opt.initialised = false; control.initialised = false; params.initialised = false; workspace.initialised = false; opt.n = prob.get_dimension(); // number of variables opt.m = prob.get_c_dimension(); // number of constraints auto n_eq = prob.get_c_dimension() - prob.get_ic_dimension(); // number of equality constraints // specify nonzeros of derivative matrixes workspace.DF.nnz = opt.n; // dense workspace.DG.nnz = opt.n * opt.m; // dense workspace.HM.nnz = opt.n; WorhpInit(&opt, &workspace, ¶ms, &control); assert(control.status == FirstCall); params = m_params; // Specify a derivative free case params.UserDF = false; params.UserDG = false; params.UserHM = false; params.initialised = true; // Initialization of variables const auto best_idx = pop.get_best_idx(); pagmo::decision_vector x = pop.get_individual(best_idx).cur_x; for (int i = 0; i < opt.n; ++i) { opt.X[i] = x[i]; opt.Lambda[i] = 0; opt.XL[i] = prob.get_lb()[i]; opt.XU[i] = prob.get_ub()[i]; } // Equality constraints for (auto i = 0u; i < n_eq; ++i) { opt.Mu[i] = 0; opt.GL[i] = 0; opt.GU[i] = 0; } // Inequality constraints for (auto i = n_eq; i < unsigned(opt.m); ++i) { opt.Mu[i] = 0; opt.GL[i] = -params.Infty; opt.GU[i] = 0; } // Define HM as a diagonal LT-CS-matrix, but only if needed by WORHP // Not sure if this is needed at all if (workspace.HM.NeedStructure) { for(int i = 0; i < workspace.HM.nnz; ++i) { workspace.HM.row[i] = i + 1; workspace.HM.col[i] = i + 1; } } while (control.status < TerminateSuccess && control.status > TerminateError) { if (GetUserAction(&control, callWorhp)) { Worhp(&opt, &workspace, ¶ms, &control); } if (GetUserAction(&control, iterOutput)) { IterationOutput(&opt, &workspace, ¶ms, &control); DoneUserAction(&control, iterOutput); } if (GetUserAction(&control, evalF)) { for (int i = 0; i < opt.n; ++i) { x[i] = opt.X[i]; } auto f = prob.objfun(x); opt.F = workspace.ScaleObj * f[0]; DoneUserAction(&control, evalF); } if (GetUserAction(&control, evalG)) { for (int i = 0; i < opt.n; ++i) { x[i] = opt.X[i]; } auto g = prob.compute_constraints(x); for (int i = 0; i < opt.m; ++i) { opt.G[i] = g[i]; } DoneUserAction(&control, evalG); } if (GetUserAction(&control, fidif)) { WorhpFidif(&opt, &workspace, ¶ms, &control); } } for (int i = 0; i < opt.n; ++i) { x[i] = opt.X[i]; } pop.set_x(best_idx, x); StatusMsg(&opt, &workspace, ¶ms, &control); WorhpFree(&opt, &workspace, ¶ms, &control); }
void WorhpInterface::set_work(void* mem, const double**& arg, double**& res, casadi_int*& iw, double*& w) const { auto m = static_cast<WorhpMemory*>(mem); // Set work in base classes Nlpsol::set_work(mem, arg, res, iw, w); // Free existing Worhp memory (except parameters) m->worhp_p.initialised = false; // Avoid freeing the memory for parameters if (m->worhp_o.initialised || m->worhp_w.initialised || m->worhp_c.initialised) { WorhpFree(&m->worhp_o, &m->worhp_w, &m->worhp_p, &m->worhp_c); } m->worhp_p.initialised = true; // Number of (free) variables m->worhp_o.n = nx_; // Number of constraints m->worhp_o.m = ng_; /// Control data structure needs to be reset every time m->worhp_c.initialised = false; m->worhp_w.initialised = false; m->worhp_o.initialised = false; // Worhp uses the CS format internally, hence it is the preferred sparse matrix format. m->worhp_w.DF.nnz = nx_; if (m->worhp_o.m>0) { m->worhp_w.DG.nnz = jacg_sp_.nnz(); // Jacobian of G } else { m->worhp_w.DG.nnz = 0; } if (true /*m->worhp_w.HM.NeedStructure*/) { // not initialized m->worhp_w.HM.nnz = nx_ + hesslag_sp_.nnz_lower(true); } else { m->worhp_w.HM.nnz = 0; } /* Data structure initialisation. */ WorhpInit(&m->worhp_o, &m->worhp_w, &m->worhp_p, &m->worhp_c); m->init_ = true; if (m->worhp_c.status != FirstCall) { string msg = return_codes(m->worhp_c.status); casadi_error("Main: Initialisation failed. Status: " + msg); } if (m->worhp_w.DF.NeedStructure) { for (casadi_int i=0; i<nx_; ++i) { m->worhp_w.DF.row[i] = i + 1; // Index-1 based } } if (m->worhp_o.m>0 && m->worhp_w.DG.NeedStructure) { casadi_int nz=0; const casadi_int* colind = jacg_sp_.colind(); const casadi_int* row = jacg_sp_.row(); for (casadi_int c=0; c<nx_; ++c) { for (casadi_int el=colind[c]; el<colind[c+1]; ++el) { casadi_int r = row[el]; m->worhp_w.DG.col[nz] = c + 1; // Index-1 based m->worhp_w.DG.row[nz] = r + 1; nz++; } } } if (m->worhp_w.HM.NeedStructure) { // Get the sparsity pattern of the Hessian const casadi_int* colind = hesslag_sp_.colind(); const casadi_int* row = hesslag_sp_.row(); casadi_int nz=0; // Strictly lower triangular part of the Hessian (note CCS -> CRS format change) for (casadi_int c=0; c<nx_; ++c) { for (casadi_int el=colind[c]; el<colind[c+1]; ++el) { if (row[el]>c) { m->worhp_w.HM.row[nz] = row[el] + 1; m->worhp_w.HM.col[nz] = c + 1; nz++; } } } // Diagonal always included for (casadi_int r=0; r<nx_; ++r) { m->worhp_w.HM.row[nz] = r + 1; m->worhp_w.HM.col[nz] = r + 1; nz++; } } }
void WorhpInternal::reset(){ // Number of (free) variables worhp_o_.n = nx_; // Number of constraints worhp_o_.m = ng_; // Free existing Worhp memory (except parameters) bool p_init_backup = worhp_p_.initialised; worhp_p_.initialised = false; // Avoid freeing the memory for parameters if (worhp_o_.initialised || worhp_w_.initialised || worhp_c_.initialised){ WorhpFree(&worhp_o_, &worhp_w_, &worhp_p_, &worhp_c_); } worhp_p_.initialised = p_init_backup; /// Control data structure needs to be reset every time worhp_c_.initialised = false; worhp_w_.initialised = false; worhp_o_.initialised = false; // Worhp uses the CS format internally, hence it is the preferred sparse matrix format. worhp_w_.DF.nnz = nx_; if (worhp_o_.m>0) { worhp_w_.DG.nnz = jacG_.output().size(); // Jacobian of G } else { worhp_w_.DG.nnz = 0; } if (exact_hessian_ /*worhp_w_.HM.NeedStructure*/) { // not initialized // Get the sparsity pattern of the Hessian const Sparsity& spHessLag = this->spHessLag(); const vector<int>& colind = spHessLag.colind(); const vector<int>& row = spHessLag.row(); // Get number of nonzeros in the lower triangular part of the Hessian including full diagonal worhp_w_.HM.nnz = nx_; // diagonal entries for(int c=0; c<nx_; ++c){ for(int el=colind[c]; el<colind[c+1] && row[el]<c; ++el){ worhp_w_.HM.nnz++; // strictly lower triangular part } } } else { worhp_w_.HM.nnz = 0; } /* Data structure initialisation. */ WorhpInit(&worhp_o_, &worhp_w_, &worhp_p_, &worhp_c_); if (worhp_c_.status != FirstCall) { casadi_error("Main: Initialisation failed. Status: " << formatStatus(worhp_c_.status)); } if (worhp_w_.DF.NeedStructure){ for(int i=0; i<nx_; ++i){ worhp_w_.DF.row[i] = i + 1; // Index-1 based } } if (worhp_o_.m>0 && worhp_w_.DG.NeedStructure) { // Get sparsity pattern. Note WORHP is column major const DMatrix & J = jacG_.output(JACG_JAC); int nz=0; const vector<int>& colind = J.colind(); const vector<int>& row = J.row(); for(int c=0; c<nx_; ++c){ for(int el=colind[c]; el<colind[c+1]; ++el){ int r = row[el]; worhp_w_.DG.col[nz] = c + 1; // Index-1 based worhp_w_.DG.row[nz] = r + 1; nz++; } } } if (worhp_w_.HM.NeedStructure) { // Get the sparsity pattern of the Hessian const Sparsity& spHessLag = this->spHessLag(); const vector<int>& colind = spHessLag.colind(); const vector<int>& row = spHessLag.row(); int nz=0; // Upper triangular part of the Hessian (note CCS -> CRS format change) for(int c=0; c<nx_; ++c){ for(int el=colind[c]; el<colind[c+1]; ++el){ if(row[el]>c){ worhp_w_.HM.row[nz] = row[el] + 1; worhp_w_.HM.col[nz] = c + 1; nz++; } } } // Diagonal always included for(int r=0; r<nx_; ++r){ worhp_w_.HM.row[nz] = r + 1; worhp_w_.HM.col[nz] = r + 1; nz++; } } }