Exemple #1
0
/**
 * 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, &params, &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, &params, &control);
		}

		if (GetUserAction(&control, iterOutput)) 
		{
			IterationOutput(&opt, &workspace, &params, &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, &params, &control);
		}
	}

	for (int i = 0; i < opt.n; ++i) {
		x[i] = opt.X[i];
	}
	pop.set_x(best_idx, x);

	StatusMsg(&opt, &workspace, &params, &control);
	WorhpFree(&opt, &workspace, &params, &control);
}
Exemple #2
0
  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++;
      }
    }
  }