This documentation is automatically generated by online-judge-tools/verification-helper
#include "include/search/golden_section_search.hpp"
黄金分割探索によって凸関数の区間内の最小値(または最大値)とそれを達成する引数を求める関数が定義されています。
golden_section_search<true>(a, b, f, diff)
区間 $I = [a, b]$ で定義される凸関数 $f: I \to \mathbf{R}$ に対して $\mathrm{argmin}{x \in I} \, f(x)$ と $\mathrm{min}{x \in I} f(x)$ をこの順番で持つ std::pair
型の値を返します。
diff
は $\mathrm{argmin} \, f(x)$ に対する許容誤差です。
golden_section_search<false>(a, b, f, diff)
区間 $I = [a, b]$ で定義される凸関数 $f: I \to \mathbf{R}$ に対して $\mathrm{argmax}{x \in I} \, f(x)$ と $\mathrm{max}{x \in I} f(x)$ をこの順番で持つ std::pair
型の値を返します。
diff
は $\mathrm{argmax} \, f(x)$ に対する許容誤差です。
//! @file golden_section_search.hpp
#ifndef CP_LIBRARY_GOLDEN_SECTION_SEARCH_HPP
#define CP_LIBRARY_GOLDEN_SECTION_SEARCH_HPP
#include <cassert>
#include <cmath>
#include <type_traits>
#include <utility>
#ifndef CP_LIBRARY_ASSERT
//! @brief Assert macro
# define CP_LIBRARY_ASSERT(...) assert(__VA_ARGS__)
# define CP_LIBRARY_ASSERT_NOT_DEFINED
#endif
namespace lib {
//! @brief Function to find the maximum or minimum value of a convex function f(x) when x is in [a, b]
//! @tparam minimize Set to true if you want to minimize the f(x), otherwise set to false.
//! @tparam RealType type of x (deduced from parameters)
//! @tparam Func type of f (deduced from parameters)
//! @param low lower bound (a)
//! @param high upper bound (b)
//! @param f function to minimize or maximize
//! @param diff acceptable error
//! @return std::pair { argmin(f(x)), min(f(x)) } (or argmax & max)
//! @note time complexity: O(log((high - low) / diff * (time needed to calculate f(x))))
template <bool minimize, typename RealType, typename Func>
[[nodiscard]] auto golden_section_search(RealType low, RealType high, const Func& f, const RealType diff = 1e-9L) {
using F_ResType = decltype(f(std::declval<RealType>()));
CP_LIBRARY_ASSERT(low <= high);
using std::sqrt;
const RealType phi = (1 + sqrt(RealType(5.0L))) / 2;
const RealType phi_plus_1 = phi + 1;
RealType mid_low = (low * phi + high) / phi_plus_1;
RealType mid_high = (low + high * phi) / phi_plus_1;
F_ResType score_low = f(mid_low);
F_ResType score_high = f(mid_high);
while (high - low > diff) {
if (minimize ^ (score_low < score_high)) {
low = mid_low;
mid_low = mid_high;
score_low = score_high;
mid_high = (low + high * phi) / phi_plus_1;
score_high = f(mid_high);
} else {
high = mid_high;
mid_high = mid_low;
score_high = score_low;
mid_low = (low * phi + high) / phi_plus_1;
score_low = f(mid_low);
}
}
return std::pair {low, score_low};
}
} // namespace lib
#ifdef CP_LIBRARY_ASSERT_NOT_DEFINED
# undef CP_LIBRARY_ASSERT
# undef CP_LIBRARY_ASSERT_NOT_DEFINED
#endif
#endif // CP_LIBRARY_GOLDEN_SECTION_SEARCH_HPP
#line 1 "include/search/golden_section_search.hpp"
//! @file golden_section_search.hpp
#ifndef CP_LIBRARY_GOLDEN_SECTION_SEARCH_HPP
#define CP_LIBRARY_GOLDEN_SECTION_SEARCH_HPP
#include <cassert>
#include <cmath>
#include <type_traits>
#include <utility>
#ifndef CP_LIBRARY_ASSERT
//! @brief Assert macro
# define CP_LIBRARY_ASSERT(...) assert(__VA_ARGS__)
# define CP_LIBRARY_ASSERT_NOT_DEFINED
#endif
namespace lib {
//! @brief Function to find the maximum or minimum value of a convex function f(x) when x is in [a, b]
//! @tparam minimize Set to true if you want to minimize the f(x), otherwise set to false.
//! @tparam RealType type of x (deduced from parameters)
//! @tparam Func type of f (deduced from parameters)
//! @param low lower bound (a)
//! @param high upper bound (b)
//! @param f function to minimize or maximize
//! @param diff acceptable error
//! @return std::pair { argmin(f(x)), min(f(x)) } (or argmax & max)
//! @note time complexity: O(log((high - low) / diff * (time needed to calculate f(x))))
template <bool minimize, typename RealType, typename Func>
[[nodiscard]] auto golden_section_search(RealType low, RealType high, const Func& f, const RealType diff = 1e-9L) {
using F_ResType = decltype(f(std::declval<RealType>()));
CP_LIBRARY_ASSERT(low <= high);
using std::sqrt;
const RealType phi = (1 + sqrt(RealType(5.0L))) / 2;
const RealType phi_plus_1 = phi + 1;
RealType mid_low = (low * phi + high) / phi_plus_1;
RealType mid_high = (low + high * phi) / phi_plus_1;
F_ResType score_low = f(mid_low);
F_ResType score_high = f(mid_high);
while (high - low > diff) {
if (minimize ^ (score_low < score_high)) {
low = mid_low;
mid_low = mid_high;
score_low = score_high;
mid_high = (low + high * phi) / phi_plus_1;
score_high = f(mid_high);
} else {
high = mid_high;
mid_high = mid_low;
score_high = score_low;
mid_low = (low * phi + high) / phi_plus_1;
score_low = f(mid_low);
}
}
return std::pair {low, score_low};
}
} // namespace lib
#ifdef CP_LIBRARY_ASSERT_NOT_DEFINED
# undef CP_LIBRARY_ASSERT
# undef CP_LIBRARY_ASSERT_NOT_DEFINED
#endif
#endif // CP_LIBRARY_GOLDEN_SECTION_SEARCH_HPP