-
Notifications
You must be signed in to change notification settings - Fork 591
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add AGS global solver #194
Merged
Merged
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
2696355
Rely on ciso646 and __cplusplus macro when detecting cxx
sovrasov b5a5afc
Add CXX11 flag to cmake
sovrasov 9afec62
Add a stub for AGS algrithm
sovrasov de8fa3c
Finish basic integration of AGS
sovrasov e050013
Clenup ags header, change cmake for test
sovrasov 7657851
AGS: add stop by reaching required value
sovrasov ef16e49
AGS: add stop by timer
sovrasov 7f24c6f
AGS: add correct return code for max_time stop
sovrasov cf122f7
AGS: stop instead of throwing an exception
sovrasov 886d963
Get rid of unused code
sovrasov bd981b9
AGS: use NLOPT_CXX11 macro
sovrasov 1a3dc05
AGS: updated documentation
sovrasov d7f3030
AGS: fix wrong ifdef
sovrasov fb9a8b7
AGS: use spaces rather than tabs
sovrasov bdf8700
AGS: fix enum name
sovrasov b0b1834
AGS: fix wrong calculation of constraints
sovrasov c7b67be
AGS: add an example of problem with nonlinear constraints
sovrasov 7743d22
AGS: update docs
sovrasov 7b6aa88
Fix minor issues
sovrasov f66ac2d
AGS: allow up to 10 dimenstions instead of 5
sovrasov 0b60363
AGS: fix warnings
sovrasov 3cceeed
AGS: fix zero evaluations counter, set default maxeval
sovrasov 5e1e09f
AGS: fix generation of test suite
sovrasov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// A C-callable front-end to the AGS global-optimization library. | ||
// -- Vladislav Sovrasov | ||
|
||
#include "ags.h" | ||
#include "solver.hpp" | ||
#include <iostream> | ||
#include <cstring> | ||
#include <exception> | ||
|
||
double ags_eps = 0; | ||
double ags_r = 3; | ||
double eps_res = 0.001; | ||
unsigned evolvent_density = 12; | ||
int ags_refine_loc = 0; | ||
int ags_verbose = 0; | ||
|
||
int ags_minimize(unsigned n, nlopt_func func, void *data, unsigned m, nlopt_constraint *fc, | ||
double *x, double *minf, const double *l, const double *u, nlopt_stopping *stop) | ||
{ | ||
int ret_code = NLOPT_SUCCESS; | ||
|
||
if (n > ags::solverMaxDim) | ||
return NLOPT_INVALID_ARGS; | ||
if(m != nlopt_count_constraints(m, fc) || m > ags::solverMaxConstraints) | ||
return NLOPT_INVALID_ARGS; | ||
|
||
if (ags_verbose && n > 5) | ||
std::cout << "Warning: AGS is unstable when dimension > 5" << std::endl; | ||
|
||
std::vector<double> lb(l, l + n); | ||
std::vector<double> ub(u, u + n); | ||
std::vector<ags::NLPSolver::FuncPtr> functions; | ||
for (unsigned i = 0; i < m; i++) | ||
{ | ||
if (fc[i].m != 1) | ||
return NLOPT_INVALID_ARGS; | ||
functions.push_back([fc, data, n, i](const double* x) { | ||
double val = 0; | ||
nlopt_eval_constraint(&val, NULL, &fc[i], n, x); | ||
return val; | ||
}); | ||
} | ||
functions.push_back([func, data, n, stop](const double* x) { | ||
++ *(stop->nevals_p); | ||
return func(n, x, NULL, data);}); | ||
|
||
ags::SolverParameters params; | ||
params.r = ags_r; | ||
params.itersLimit = stop->maxeval != 0 ? stop->maxeval : 5000; | ||
params.eps = ags_eps; | ||
params.evolventDensity = evolvent_density; | ||
params.epsR = eps_res; | ||
params.stopVal = stop->minf_max; | ||
params.refineSolution = (bool)ags_refine_loc; | ||
|
||
ags::NLPSolver solver; | ||
solver.SetParameters(params); | ||
solver.SetProblem(functions, lb, ub); | ||
|
||
ags::Trial optPoint; | ||
try | ||
{ | ||
auto external_stop_func = [stop, &ret_code](){ | ||
if (nlopt_stop_time(stop)) { | ||
ret_code = NLOPT_MAXTIME_REACHED; | ||
return true; | ||
} | ||
else return false; | ||
}; | ||
optPoint = solver.Solve(external_stop_func); | ||
} | ||
catch (const std::exception& exp) | ||
{ | ||
std::cerr << "AGS internal error: " << std::string(exp.what()) << std::endl; | ||
return NLOPT_FAILURE; | ||
} | ||
|
||
if (ags_verbose) | ||
{ | ||
auto calcCounters = solver.GetCalculationsStatistics(); | ||
auto holderConstEstimations = solver.GetHolderConstantsEstimations(); | ||
|
||
std::cout << std::string(20, '-') << "AGS statistics: " << std::string(20, '-') << std::endl; | ||
for (size_t i = 0; i < calcCounters.size() - 1; i++) | ||
std::cout << "Number of calculations of constraint # " << i << ": " << calcCounters[i] << "\n"; | ||
std::cout << "Number of calculations of objective: " << calcCounters.back() << "\n";; | ||
|
||
for (size_t i = 0; i < holderConstEstimations.size() - 1; i++) | ||
std::cout << "Estimation of Holder constant of function # " << i << ": " << holderConstEstimations[i] << "\n"; | ||
std::cout << "Estimation of Holder constant of objective: " << holderConstEstimations.back() << "\n"; | ||
if (optPoint.idx != (int)m) | ||
std::cout << "Feasible point not found" << "\n"; | ||
std::cout << std::string(40, '-') << std::endl; | ||
} | ||
|
||
if ((int)m == optPoint.idx) | ||
{ | ||
memcpy(x, optPoint.y, n*sizeof(x[0])); | ||
*minf = optPoint.g[optPoint.idx]; | ||
} | ||
else //feasible point not found. | ||
return NLOPT_FAILURE; | ||
|
||
if (solver.GetCalculationsStatistics()[0] >= params.itersLimit) | ||
return NLOPT_MAXEVAL_REACHED; | ||
|
||
return ret_code; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* A C-callable front-end to the AGS global-optimization library. | ||
-- Vladislav Sovrasov */ | ||
|
||
#ifndef AGS_H | ||
#define AGS_H | ||
|
||
#include "nlopt-util.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
//The algorithm supports 3 types of stop criterions: stop by execution time, stop by value and stop by exceeding limit of iterations. | ||
|
||
int ags_minimize(unsigned n, nlopt_func func, void *data, unsigned m, nlopt_constraint *fc, | ||
double *x, double *minf, const double *l, const double *u, nlopt_stopping *stop); | ||
|
||
extern double ags_eps; //method tolerance in Holder metric on 1d interval. Less value -- better search precision, less probability of early stop. | ||
extern double ags_r; //reliability parameter. Higher value of r -- slower convergence, higher chance to cache the global minima. | ||
extern double eps_res; // parameter which prevents method from paying too much attention to constraints. Greater values of this parameter speed up convergence, | ||
// but global minima can be lost. | ||
extern unsigned evolvent_density; // density of evolvent. By default density is 2^-12 on hybercube [0,1]^N, | ||
// which means that maximum search accuracyis 2^-12. If search hypercube is large the density can be increased accordingly to achieve better accuracy. | ||
extern int ags_refine_loc; //refine the final optimum using built-in local optimizer | ||
extern int ags_verbose; //print additional info | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
Copyright (C) 2018 Sovrasov V. - All Rights Reserved | ||
* You may use, distribute and modify this code under the | ||
* terms of the MIT license. | ||
* You should have received a copy of the MIT license with | ||
* this file. If not visit https://opensource.org/licenses/MIT | ||
*/ | ||
#pragma once | ||
|
||
#include <stdexcept> | ||
#include <string> | ||
|
||
#define NLP_SOLVER_ERROR(msg) throw std::runtime_error(std::string(msg)) | ||
#define NLP_SOLVER_ASSERT(expr, msg) if(!(expr)) NLP_SOLVER_ERROR(msg) | ||
|
||
namespace ags | ||
{ | ||
|
||
const unsigned solverMaxDim = 10; | ||
const unsigned solverMaxConstraints = 10; | ||
|
||
template <class fptype> | ||
class IGOProblem | ||
{ | ||
public: | ||
~IGOProblem() {} | ||
|
||
virtual fptype Calculate(const fptype* y, int fNumber) const = 0; | ||
virtual int GetConstraintsNumber() const = 0; | ||
virtual int GetDimension() const = 0; | ||
virtual void GetBounds(fptype* left, fptype* right) const = 0; | ||
virtual int GetOptimumPoint(fptype* y) const = 0; | ||
virtual fptype GetOptimumValue() const = 0 ; | ||
}; | ||
|
||
struct Trial | ||
{ | ||
double x; | ||
double y[solverMaxDim]; | ||
double g[solverMaxConstraints + 1]; | ||
int idx; | ||
Trial() {} | ||
Trial(double _x) : x(_x) {} | ||
}; | ||
|
||
struct Interval | ||
{ | ||
Trial pl; | ||
Trial pr; | ||
double R; | ||
double delta; | ||
Interval() {} | ||
Interval(const Trial& _pl, const Trial& _pr) : pl(_pl), pr(_pr) {} | ||
}; | ||
|
||
struct CompareIntervals | ||
{ | ||
bool operator() (const Interval* i1, const Interval* i2) const | ||
{ | ||
return i1->pl.x < i2->pl.x; | ||
} | ||
}; | ||
|
||
class CompareByR | ||
{ | ||
public: | ||
bool operator() (const Interval* i1, const Interval* i2) const | ||
{ | ||
return i1->R < i2->R; | ||
} | ||
}; | ||
|
||
|
||
|
||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is wrong —
maxeval == 0
denotes no maximum, not 5000 iterations. If you must set it to a specific value, useINT_MAX
.