Program Listing for File ellipsoid.hpp¶
↰ Return to documentation for file (ellip/ellipsoid.hpp)
#ifndef _ELLIPSOID_HPP
#define _ELLIPSOID_HPP
#include <cassert>
#include <valarray>
enum CUTSTATUS
{
CUT,
NOSOLUTION,
NOEFFECT
};
class ellipsoid
{
using Vec = std::valarray<double>;
using Matrix = std::valarray<Vec>;
public:
ellipsoid(Vec& x, double rho)
: _n(x.size())
, _Ae(Vec(0., _n), _n)
, _x(x)
{
assert(rho > 0);
for (auto i = 0; i != _n; ++i)
{
_Ae[i][i] = rho; // initial radius
}
}
ellipsoid(Vec& x, const Vec& r)
: _n(x.size())
, _Ae(Vec(0., _n), _n)
, _x(x)
{
for (auto i = 0; i != _n; ++i)
{
assert(r[i] > 0);
_Ae[i][i] = r[i]; // initial radius
}
}
~ellipsoid() { }
Vec& x()
{
return _x;
}
void update(const Vec& g);
CUTSTATUS update(const Vec& g, double beta);
private:
size_t _n;
Matrix _Ae;
Vec _x; //< centroid of ellipsoid
};
enum STATUS
{
FOUND,
EXCEEDMAXITER,
NOTFOUND
};
//#include <iostream>
template <class Vec>
struct Info4EM
{
bool _is_feasible;
Vec _g;
double _f;
Vec _x;
};
#include <limits>
template <class Vec>
inline double norm(const Vec& x)
{
return sqrt((x * x).sum());
}
template <class Enclosing, class Oracle, class Vec>
STATUS ellipsoid_dc_discrete(Enclosing& E, Oracle& P, Vec& best_x,
double& best_f, int max_it = 100, double tol = 1e-4)
{
STATUS flag = NOTFOUND;
CUTSTATUS status = CUT;
Vec lx = E.x();
best_f = 1.e100; // std::numeric_limits<double>::max()
for (int iter = 1; iter <= max_it; ++iter)
{
const Info4EM<Vec> info = P(lx);
const Vec& x = info._x;
const Vec& g = info._g;
double f = info._f;
double beta = (g * (lx - x)).sum();
if (info._is_feasible)
{
flag = FOUND;
if (f < best_f)
{
best_f = f;
best_x = x;
}
status = E.update(g, beta);
}
else
{
status = E.update(g, f + beta);
}
if (status != CUT)
return flag;
if (norm(lx - E.x()) < tol)
return flag;
lx = E.x();
}
return EXCEEDMAXITER;
}
template <class Enclosing, class Oracle, class Vec>
STATUS ellipsoid_dc(Enclosing& E, Oracle& P, Vec& best_x, double& best_f,
int max_it = 100, double tol = 1e-4)
{
STATUS flag = NOTFOUND;
CUTSTATUS status = CUT;
Vec lx = E.x();
best_f = 1.e100; // std::numeric_limits<double>::max()
for (int iter = 1; iter <= max_it; ++iter)
{
const Info4EM<Vec> info = P(lx);
// const Vec& x = info._x;
const Vec& g = info._g;
double f = info._f;
// double beta = (g * (lx - x)).sum();
if (info._is_feasible)
{
flag = FOUND;
if (f < best_f)
{
best_f = f;
best_x = x;
}
// status = E.update(g, beta);
status = E.update(g);
}
else
{
// status = E.update(g, f + beta);
status = E.update(g, f);
}
if (status != CUT)
return flag;
if (norm(lx - E.x()) < tol)
return flag;
lx = E.x();
}
return EXCEEDMAXITER;
}
template <class Enclosing, class Oracle, class Vec>
STATUS ellipsoid_algo(Enclosing& E, Oracle& P, Vec& best_x, double& best_f,
int max_it = 100, double tol = 1e-4)
{
STATUS flag = NOTFOUND;
Vec lx = E.x();
best_f = 1.e100; // std::numeric_limits<double>::max()
for (int iter = 1; iter <= max_it; ++iter)
{
const Info4EM<Vec> info = P(lx);
const Vec& g = info._g;
double f = info._f;
if (info._is_feasible)
{
flag = FOUND;
if (f < best_f)
{
best_f = f;
best_x = lx;
}
}
E.update(g);
if (norm(lx - E.x()) < tol)
return flag;
lx = E.x();
}
return EXCEEDMAXITER;
}
#endif