BruteforceOptimizer.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #ifndef BRUTEFORCEOPTIMIZER_HPP
  2. #define BRUTEFORCEOPTIMIZER_HPP
  3. #include <libslic3r/Optimize/Optimizer.hpp>
  4. namespace Slic3r { namespace opt {
  5. namespace detail {
  6. // Implementing a bruteforce optimizer
  7. template<size_t N>
  8. constexpr long num_iter(const std::array<size_t, N> &idx, size_t gridsz)
  9. {
  10. long ret = 0;
  11. for (size_t i = 0; i < N; ++i) ret += idx[i] * std::pow(gridsz, i);
  12. return ret;
  13. }
  14. struct AlgBurteForce {
  15. bool to_min;
  16. StopCriteria stc;
  17. size_t gridsz;
  18. AlgBurteForce(const StopCriteria &cr, size_t gs): stc{cr}, gridsz{gs} {}
  19. template<int D, size_t N, class Fn, class Cmp>
  20. bool run(std::array<size_t, N> &idx,
  21. Result<N> &result,
  22. const Bounds<N> &bounds,
  23. Fn &&fn,
  24. Cmp &&cmp)
  25. {
  26. if (stc.stop_condition()) return false;
  27. if constexpr (D < 0) {
  28. Input<N> inp;
  29. auto max_iter = stc.max_iterations();
  30. if (max_iter && num_iter(idx, gridsz) >= max_iter) return false;
  31. for (size_t d = 0; d < N; ++d) {
  32. const Bound &b = bounds[d];
  33. double step = (b.max() - b.min()) / (gridsz - 1);
  34. inp[d] = b.min() + idx[d] * step;
  35. }
  36. auto score = fn(inp);
  37. if (cmp(score, result.score)) {
  38. double absdiff = std::abs(score - result.score);
  39. result.score = score;
  40. result.optimum = inp;
  41. if (absdiff < stc.abs_score_diff() ||
  42. absdiff < stc.rel_score_diff() * std::abs(score))
  43. return false;
  44. }
  45. } else {
  46. for (size_t i = 0; i < gridsz; ++i) {
  47. idx[D] = i;
  48. if (!run<D - 1>(idx, result, bounds, std::forward<Fn>(fn),
  49. std::forward<Cmp>(cmp))) return false;
  50. }
  51. }
  52. return true;
  53. }
  54. template<class Fn, size_t N>
  55. Result<N> optimize(Fn&& fn,
  56. const Input<N> &/*initvals*/,
  57. const Bounds<N>& bounds)
  58. {
  59. std::array<size_t, N> idx = {};
  60. Result<N> result;
  61. if (to_min) {
  62. result.score = std::numeric_limits<double>::max();
  63. run<int(N) - 1>(idx, result, bounds, std::forward<Fn>(fn),
  64. std::less<double>{});
  65. }
  66. else {
  67. result.score = std::numeric_limits<double>::lowest();
  68. run<int(N) - 1>(idx, result, bounds, std::forward<Fn>(fn),
  69. std::greater<double>{});
  70. }
  71. return result;
  72. }
  73. };
  74. } // namespace bruteforce_detail
  75. using AlgBruteForce = detail::AlgBurteForce;
  76. template<>
  77. class Optimizer<AlgBruteForce> {
  78. AlgBruteForce m_alg;
  79. public:
  80. Optimizer(const StopCriteria &cr = {}, size_t gridsz = 100)
  81. : m_alg{cr, gridsz}
  82. {}
  83. Optimizer& to_max() { m_alg.to_min = false; return *this; }
  84. Optimizer& to_min() { m_alg.to_min = true; return *this; }
  85. template<class Func, size_t N>
  86. Result<N> optimize(Func&& func,
  87. const Input<N> &initvals,
  88. const Bounds<N>& bounds)
  89. {
  90. return m_alg.optimize(std::forward<Func>(func), initvals, bounds);
  91. }
  92. Optimizer &set_criteria(const StopCriteria &cr)
  93. {
  94. m_alg.stc = cr; return *this;
  95. }
  96. const StopCriteria &get_criteria() const { return m_alg.stc; }
  97. };
  98. }} // namespace Slic3r::opt
  99. #endif // BRUTEFORCEOPTIMIZER_HPP