7 #ifndef JADE_SIMPLEX_HPP__
8 #define JADE_SIMPLEX_HPP__
10 #include "jade.assert.hpp"
19 template <
typename TValue>
49 static const char *
str(
54 #define CASE(E) case E: return #E
90 static const char *
str(
95 #define CASE(E) case E: return #E
131 const double second_,
132 const size_t iteration_,
146 std::ostringstream out;
147 out <<
"iteration: " <<
iteration << std::endl
148 <<
"second: " <<
second << std::endl;
163 std::numeric_limits<size_t>::max();
167 std::numeric_limits<double>::quiet_NaN();
171 std::numeric_limits<value_type>::quiet_NaN();
175 std::numeric_limits<value_type>::quiet_NaN();
179 std::numeric_limits<value_type>::quiet_NaN();
256 std::ostringstream out;
258 << _str(
logfunc !=
nullptr,
"assigned")
261 << _str(
user !=
nullptr,
"assigned")
283 template <
typename T>
284 static std::string _str(
285 const bool is_assigned,
288 std::ostringstream out;
289 if (is_assigned) out << value;
290 else out <<
"<not-assigned>";
345 ,
gamma (_init_gamma(n))
347 ,
sigma (_init_sigma(n))
366 assert(
vertex.size() > 0);
374 std::ostringstream out;
377 auto iter =
vertex.begin();
381 while (++iter !=
vertex.end())
384 out <<
"}" << std::endl;
387 <<
"chi: " <<
chi << std::endl
388 <<
"gamma: " <<
gamma << std::endl
389 <<
"rho: " <<
rho << std::endl
390 <<
"sigma: " <<
sigma << std::endl
391 <<
"unit: " <<
unit << std::endl;
405 return n >= 2 ? k1_00 + (k2_00 /
value_type(n)) : k2_00;
411 return n >= 2 ? k0_75 - (k1_00 /
418 return n >= 2 ? k1_00 - (k1_00 /
value_type(n)) : k0_50;
481 std::ostringstream out;
497 template <
typename TObjfunc>
499 const TObjfunc objfunc,
509 template <
typename TObjfunc>
511 const TObjfunc objfunc,
513 : _n (opts.vertex.size())
525 assert(opts.
rho > 0);
526 assert(opts.
chi >= 1 && opts.
chi >= opts.
rho);
529 assert(opts.
unit > 0);
530 assert(opts.
vertex.empty() || opts.
vertex.size() == _n);
536 for (
size_t i = 0; i <= _n; i++)
537 _x.emplace_back(
new vertex(opts, i));
542 for (
const auto & xi : _x)
543 xi->objval = _evaluate(objfunc, xi->params);
548 std::sort(_x.begin(), _x.end(), _is_less);
566 template <
typename TObjfunc>
568 const TObjfunc objfunc,
571 typedef std::chrono::high_resolution_clock clock_type;
572 typedef std::chrono::duration<double> duration_type;
574 const auto t0 = clock_type::now();
575 const auto get_seconds = [t0]() ->
double
577 return duration_type(clock_type::now() - t0).count();
580 auto iteration = size_t(0);
587 return exit_condition_type::iteration;
591 return exit_condition_type::timeout;
595 return exit_condition_type::delta;
599 return exit_condition_type::length;
614 if (std::fabs(flux0 - flux) <= exe_args.
min_epsilon)
626 return _x.back()->objval - _x.front()->objval;
637 static const auto inf = std::numeric_limits<value_type>::max();
642 for (
const auto & x : _x)
651 return count == 0 ?
value_type(0) : sum / count / count;
666 const auto & p0 = _x[0]->params;
668 for (
size_t i = 1; i <= _n; i++)
670 const auto & p = _x[i]->params;
672 _subtract(vec, p, p0);
673 _multiply(vec, vec, vec);
675 max = std::max(max, std::accumulate(
679 std::plus<value_type>()));
716 return _x[0]->objval;
727 return _x[index]->objval;
736 return _x[0]->params;
748 return _x[index]->params;
760 template <
typename TObjfunc>
762 const TObjfunc objfunc)
764 const auto & x0 = _x[0];
771 _copy(_xbar, x0->params);
772 for (
size_t i = 1; i < _n; i++)
773 _add(_xbar, _xbar, _x[i]->params);
776 _subtract(_xr, _xbar, _x[_n]->params);
777 _scale(_xr, _opts.
rho);
778 _add(_xr, _xr, _xbar);
780 const auto fr = _evaluate(objfunc, _xr);
781 if (x0->objval <= fr && fr < _x[_n - 1]->objval)
790 _subtract(_xe, _xr, _xbar);
791 _scale(_xe, _opts.
chi);
792 _add(_xe, _xe, _xbar);
794 const auto fe = _evaluate(objfunc, _xe);
805 if (fr >= _x[_n - 1]->objval)
807 if (fr < _x[_n]->objval)
809 _subtract(_xc, _xr, _xbar);
810 _scale(_xc, _opts.
gamma);
811 _add(_xc, _xc, _xbar);
813 const auto fc = _evaluate(objfunc, _xc);
820 _subtract(_xcc, _xbar, _x[_n]->params);
821 _scale(_xcc, _opts.
gamma);
822 _subtract(_xcc, _xbar, _xcc);
824 const auto fcc = _evaluate(objfunc, _xcc);
825 if (fcc < _x[_n]->objval)
834 for (
size_t i = 1; i <= _n; i++)
837 _subtract(xi->params, xi->params, x0->params);
838 _scale(xi->params, _opts.
sigma);
839 _add(xi->params, xi->params, x0->params);
840 xi->objval = _evaluate(objfunc, xi->params);
843 std::sort(_x.begin(), _x.end(), _is_less);
857 const options & opts,
859 : params (opts.vertex)
863 params[index - 1] += opts.unit;
867 typedef std::unique_ptr<vertex> vertex_ptr_type;
868 typedef std::vector<vertex_ptr_type> vertex_container_type;
882 const auto n = params.size();
884 _copy(v->params, params);
886 std::sort(_x.begin(), _x.end(), _is_less);
897 assert(dst.size() == lhs.size());
898 assert(lhs.size() == rhs.size());
899 std::transform(lhs.begin(), lhs.end(), rhs.begin(), dst.begin(),
900 std::plus<value_type>());
904 static bool _is_less(
905 const vertex_ptr_type & lhs,
906 const vertex_ptr_type & rhs)
908 return lhs->objval < rhs->objval;
916 assert(dst.size() == src.size());
917 std::copy(src.begin(), src.end(), dst.begin());
921 template <
typename TObjfunc>
923 const TObjfunc objfunc,
927 return objfunc(params);
931 static void _multiply(
936 assert(dst.size() == lhs.size());
937 assert(dst.size() == rhs.size());
938 std::transform(lhs.begin(), lhs.end(), rhs.begin(), dst.begin(),
939 std::multiplies<value_type>());
952 static void _subtract(
957 assert(dst.size() == lhs.size());
958 assert(dst.size() == rhs.size());
959 std::transform(lhs.begin(), lhs.end(), rhs.begin(), dst.begin(),
960 std::minus<value_type>());
966 vertex_container_type _x;
979 template <
typename TValue>
980 std::ostream & operator << (
986 <<
"delta: " << rhs.
get_delta() << std::endl
987 <<
"flux: " << rhs.
get_flux() << std::endl
988 <<
"length: " << rhs.
get_length() << std::endl;
991 #endif // JADE_SIMPLEX_HPP__