21 RandomNumberEngine &random_number_engine
24 return {x + std::uniform_int_distribution<std::int64_t>(l, u)(random_number_engine), 0.0};
28 const auto clamped_center = std::clamp(-b / (2.0 * a),
static_cast<double>(l),
static_cast<double>(u));
29 const auto dx =
static_cast<std::int64_t
>(std::round(clamped_center));
30 const double energy_diff = a * dx * dx + b * dx;
31 return {x + dx, energy_diff};
33 const double el = a * l * l + b * l;
34 const double eu = a * u * u + b * u;
52 RandomNumberEngine &random_number_engine
56 const double val_l = a * l * l * l + b * l * l + c * l;
57 const double val_u = a * u * u * u + b * u * u + c * u;
70 const double delta = b * b - 3 * a * c;
72 const double sqrt_delta = std::sqrt(delta);
73 const double r1 = (-b + sqrt_delta) / (3 * a);
74 const double r2 = (-b - sqrt_delta) / (3 * a);
76 const double local_min_root = (a > 0) ? std::max(r1, r2) : std::min(r1, r2);
78 if (l < local_min_root && local_min_root < u) {
79 const auto cand1 =
static_cast<std::int64_t
>(std::floor(local_min_root));
80 const double val1 = a * cand1 * cand1 * cand1 + b * cand1 * cand1 + c * cand1;
86 const auto cand2 =
static_cast<std::int64_t
>(std::ceil(local_min_root));
88 const double val2 = a * cand2 * cand2 * cand2 + b * cand2 * cand2 + c * cand2;
96 return {x + best_dx, min_val};
109 const std::int64_t l,
110 const std::int64_t u,
111 const std::int64_t x,
112 RandomNumberEngine &random_number_engine
116 const auto f = [&](
double dx) {
117 return a * dx * dx * dx * dx + b * dx * dx * dx + c * dx * dx + d * dx;
120 const double val_l = f(
static_cast<double>(l));
121 const double val_u = f(
static_cast<double>(u));
122 const double m_pi = 3.14159265358979323846;
124 std::int64_t best_dx;
127 if (val_l <= val_u) {
135 const double A = 4.0 * a;
136 const double B = 3.0 * b;
137 const double C = 2.0 * c;
139 const double p = (3.0 * A * C - B * B) / (3.0 * A * A);
140 const double q = (2.0 * B * B * B - 9.0 * A * B * C + 27.0 * A * A * D) / (27.0 * A * A * A);
142 const double delta = std::pow(q / 2.0, 2) + std::pow(p / 3.0, 3);
144 const auto check_and_update =
145 [&](
double r, std::int64_t current_best_dx,
double current_min_val)
146 -> std::pair<std::int64_t, double> {
147 const double f_double_prime = 12.0 * a * r * r + 6.0 * b * r + 2.0 * c;
148 if (f_double_prime > 0 && l < r && r < u) {
149 const double floor_r = std::floor(r);
150 const double v1 = f(floor_r);
151 if (v1 < current_min_val) {
152 current_min_val = v1;
153 current_best_dx =
static_cast<std::int64_t
>(floor_r);
156 const double ceil_r = std::ceil(r);
157 if (
static_cast<std::int64_t
>(ceil_r) <= u) {
158 const double v2 = f(ceil_r);
159 if (v2 < current_min_val) {
160 current_min_val = v2;
161 current_best_dx =
static_cast<std::int64_t
>(ceil_r);
165 return {current_best_dx, current_min_val};
169 const double sqrt_delta = std::sqrt(delta);
170 const double u_cbrt = std::cbrt(-q / 2.0 + sqrt_delta);
171 const double v_cbrt = std::cbrt(-q / 2.0 - sqrt_delta);
172 const double r1 = u_cbrt + v_cbrt - B / (3.0 * A);
173 const auto result = check_and_update(r1, best_dx, min_val);
174 best_dx = result.first;
175 min_val = result.second;
177 const double r_term = std::sqrt(-std::pow(p, 3) / 27.0);
178 const double theta = std::acos(-q / (2.0 * r_term));
180 const double common_term = 2.0 * std::cbrt(r_term);
181 const double shift = B / (3.0 * A);
183 const double r1 = common_term * std::cos(theta / 3.0) - shift;
184 auto result1 = check_and_update(r1, best_dx, min_val);
185 best_dx = result1.first;
186 min_val = result1.second;
188 const double r2 = common_term * std::cos((theta + 2.0 * m_pi) / 3.0) - shift;
189 auto result2 = check_and_update(r2, best_dx, min_val);
190 best_dx = result2.first;
191 min_val = result2.second;
193 const double r3 = common_term * std::cos((theta + 4.0 * m_pi) / 3.0) - shift;
194 auto result3 = check_and_update(r3, best_dx, min_val);
195 best_dx = result3.first;
196 min_val = result3.second;
198 return {x + best_dx, min_val};
std::pair< std::int64_t, double > FindMinimumIntegerQuartic(const double a, const double b, const double c, const double d, const std::int64_t l, const std::int64_t u, const std::int64_t x, RandomNumberEngine &random_number_engine)
Definition min_polynomial.hpp:104
std::pair< std::int64_t, double > FindMinimumIntegerQuadratic(const double a, const double b, const std::int64_t l, const std::int64_t u, const std::int64_t x, RandomNumberEngine &random_number_engine)
Definition min_polynomial.hpp:15
std::pair< std::int64_t, double > FindMinimumIntegerCubic(const double a, const double b, const double c, const std::int64_t l, const std::int64_t u, const std::int64_t x, RandomNumberEngine &random_number_engine)
Definition min_polynomial.hpp:45