ags.cc 3.5 KB
Newer Older
1 2 3 4 5
// A C-callable front-end to the AGS global-optimization library.
//  -- Vladislav Sovrasov

#include "ags.h"
#include "solver.hpp"
6

7 8 9
#include <iostream>
#include <cstring>
#include <exception>
10
#include <limits>
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

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;
S
Steven G. Johnson 已提交
39
    functions.push_back([fc, n, i](const double* x) {
40 41 42 43 44 45 46 47 48 49 50
      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;
51
  params.itersLimit = stop->maxeval != 0 ? stop->maxeval : std::numeric_limits<int>::max();
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
  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;
        }
70 71 72 73
        else if (nlopt_stop_forced(stop)) {
          ret_code = NLOPT_FORCED_STOP;
          return true;
        }
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
        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;
}