Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/libslic3r/Optimize/BruteforceOptimizer.hpp')
-rw-r--r--src/libslic3r/Optimize/BruteforceOptimizer.hpp140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/libslic3r/Optimize/BruteforceOptimizer.hpp b/src/libslic3r/Optimize/BruteforceOptimizer.hpp
new file mode 100644
index 000000000..2daef538e
--- /dev/null
+++ b/src/libslic3r/Optimize/BruteforceOptimizer.hpp
@@ -0,0 +1,140 @@
+#ifndef BRUTEFORCEOPTIMIZER_HPP
+#define BRUTEFORCEOPTIMIZER_HPP
+
+#include <libslic3r/Optimize/Optimizer.hpp>
+
+namespace Slic3r { namespace opt {
+
+namespace detail {
+// Implementing a bruteforce optimizer
+
+// Return the number of iterations needed to reach a specific grid position (idx)
+template<size_t N>
+long num_iter(const std::array<size_t, N> &idx, size_t gridsz)
+{
+ long ret = 0;
+ for (size_t i = 0; i < N; ++i) ret += idx[i] * std::pow(gridsz, i);
+ return ret;
+}
+
+// Implementation of a grid search where the search interval is sampled in
+// equidistant points for each dimension. Grid size determines the number of
+// samples for one dimension so the number of function calls is gridsize ^ dimension.
+struct AlgBurteForce {
+ bool to_min;
+ StopCriteria stc;
+ size_t gridsz;
+
+ AlgBurteForce(const StopCriteria &cr, size_t gs): stc{cr}, gridsz{gs} {}
+
+ // This function is called recursively for each dimension and generates
+ // the grid values for the particular dimension. If D is less than zero,
+ // the object function input values are generated for each dimension and it
+ // can be evaluated. The current best score is compared with the newly
+ // returned score and changed appropriately.
+ template<int D, size_t N, class Fn, class Cmp>
+ bool run(std::array<size_t, N> &idx,
+ Result<N> &result,
+ const Bounds<N> &bounds,
+ Fn &&fn,
+ Cmp &&cmp)
+ {
+ if (stc.stop_condition()) return false;
+
+ if constexpr (D < 0) { // Let's evaluate fn
+ Input<N> inp;
+
+ auto max_iter = stc.max_iterations();
+ if (max_iter && num_iter(idx, gridsz) >= max_iter)
+ return false;
+
+ for (size_t d = 0; d < N; ++d) {
+ const Bound &b = bounds[d];
+ double step = (b.max() - b.min()) / (gridsz - 1);
+ inp[d] = b.min() + idx[d] * step;
+ }
+
+ auto score = fn(inp);
+ if (cmp(score, result.score)) { // Change current score to the new
+ double absdiff = std::abs(score - result.score);
+
+ result.score = score;
+ result.optimum = inp;
+
+ // Check if the required precision is reached.
+ if (absdiff < stc.abs_score_diff() ||
+ absdiff < stc.rel_score_diff() * std::abs(score))
+ return false;
+ }
+
+ } else {
+ for (size_t i = 0; i < gridsz; ++i) {
+ idx[D] = i; // Mark the current grid position and dig down
+ if (!run<D - 1>(idx, result, bounds, std::forward<Fn>(fn),
+ std::forward<Cmp>(cmp)))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ template<class Fn, size_t N>
+ Result<N> optimize(Fn&& fn,
+ const Input<N> &/*initvals*/,
+ const Bounds<N>& bounds)
+ {
+ std::array<size_t, N> idx = {};
+ Result<N> result;
+
+ if (to_min) {
+ result.score = std::numeric_limits<double>::max();
+ run<int(N) - 1>(idx, result, bounds, std::forward<Fn>(fn),
+ std::less<double>{});
+ }
+ else {
+ result.score = std::numeric_limits<double>::lowest();
+ run<int(N) - 1>(idx, result, bounds, std::forward<Fn>(fn),
+ std::greater<double>{});
+ }
+
+ return result;
+ }
+};
+
+} // namespace detail
+
+using AlgBruteForce = detail::AlgBurteForce;
+
+template<>
+class Optimizer<AlgBruteForce> {
+ AlgBruteForce m_alg;
+
+public:
+
+ Optimizer(const StopCriteria &cr = {}, size_t gridsz = 100)
+ : m_alg{cr, gridsz}
+ {}
+
+ Optimizer& to_max() { m_alg.to_min = false; return *this; }
+ Optimizer& to_min() { m_alg.to_min = true; return *this; }
+
+ template<class Func, size_t N>
+ Result<N> optimize(Func&& func,
+ const Input<N> &initvals,
+ const Bounds<N>& bounds)
+ {
+ return m_alg.optimize(std::forward<Func>(func), initvals, bounds);
+ }
+
+ Optimizer &set_criteria(const StopCriteria &cr)
+ {
+ m_alg.stc = cr; return *this;
+ }
+
+ const StopCriteria &get_criteria() const { return m_alg.stc; }
+};
+
+}} // namespace Slic3r::opt
+
+#endif // BRUTEFORCEOPTIMIZER_HPP