| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "eremin_v_strongin_algorithm/seq/include/ops_seq.hpp" | ||
| 2 | |||
| 3 | #include <algorithm> | ||
| 4 | #include <cmath> | ||
| 5 | #include <cstddef> | ||
| 6 | #include <functional> | ||
| 7 | #include <tuple> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #include "eremin_v_strongin_algorithm/common/include/common.hpp" | ||
| 11 | |||
| 12 | namespace eremin_v_strongin_algorithm { | ||
| 13 | |||
| 14 |
1/2✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
|
40 | EreminVStronginAlgorithmSEQ::EreminVStronginAlgorithmSEQ(const InType &in) { |
| 15 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 16 | GetInput() = in; | ||
| 17 | 40 | GetOutput() = 0.0; | |
| 18 | 40 | } | |
| 19 | |||
| 20 | 40 | bool EreminVStronginAlgorithmSEQ::ValidationImpl() { | |
| 21 | auto &input = GetInput(); | ||
| 22 | |||
| 23 | 40 | double lower_bound = std::get<0>(input); | |
| 24 | 40 | double upper_bound = std::get<1>(input); | |
| 25 | 40 | double epsilon = std::get<2>(input); | |
| 26 | 40 | int max_iters = std::get<3>(input); | |
| 27 | |||
| 28 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
|
40 | return (lower_bound < upper_bound) && (epsilon > 0.0 && epsilon <= (upper_bound - lower_bound)) && |
| 29 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 40 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 40 times.
|
40 | (max_iters > 0 && max_iters <= 100000000) && (lower_bound >= -1e9 && lower_bound <= 1e9) && |
| 30 |
3/6✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 40 times.
|
80 | (upper_bound >= -1e9 && upper_bound <= 1e9) && (GetOutput() == 0); |
| 31 | } | ||
| 32 | |||
| 33 | 40 | bool EreminVStronginAlgorithmSEQ::PreProcessingImpl() { | |
| 34 | 40 | return true; | |
| 35 | } | ||
| 36 | |||
| 37 | 32000 | double EreminVStronginAlgorithmSEQ::CalculateLipschitzEstimate(const std::vector<double> &search_points, | |
| 38 | const std::vector<double> &function_values) { | ||
| 39 | 32000 | double lipschitz_estimate = 0.0; | |
| 40 |
2/2✓ Branch 0 taken 14016000 times.
✓ Branch 1 taken 32000 times.
|
14048000 | for (std::size_t i = 1; i < search_points.size(); ++i) { |
| 41 | 14016000 | double interval_width = search_points[i] - search_points[i - 1]; | |
| 42 | 14016000 | double value_difference = std::abs(function_values[i] - function_values[i - 1]); | |
| 43 | 14016000 | double current_slope = value_difference / interval_width; | |
| 44 | 14016000 | lipschitz_estimate = std::max(current_slope, lipschitz_estimate); | |
| 45 | } | ||
| 46 | 32000 | return lipschitz_estimate; | |
| 47 | } | ||
| 48 | |||
| 49 | 32000 | EreminVStronginAlgorithmSEQ::IntervalCharacteristic EreminVStronginAlgorithmSEQ::FindBestInterval( | |
| 50 | const std::vector<double> &search_points, const std::vector<double> &function_values, double m_parameter) { | ||
| 51 | IntervalCharacteristic best{.value = -1e18, .index = 1}; | ||
| 52 | |||
| 53 |
2/2✓ Branch 0 taken 14016000 times.
✓ Branch 1 taken 32000 times.
|
14048000 | for (std::size_t i = 1; i < search_points.size(); ++i) { |
| 54 | 14016000 | double interval_width = search_points[i] - search_points[i - 1]; | |
| 55 | 14016000 | double characteristic = (m_parameter * interval_width) + | |
| 56 | 14016000 | ((function_values[i] - function_values[i - 1]) * | |
| 57 | 14016000 | (function_values[i] - function_values[i - 1]) / (m_parameter * interval_width)) - | |
| 58 | 14016000 | (2.0 * (function_values[i] + function_values[i - 1])); | |
| 59 | |||
| 60 |
2/2✓ Branch 0 taken 1424040 times.
✓ Branch 1 taken 12591960 times.
|
14016000 | if (characteristic > best.value) { |
| 61 | best.value = characteristic; | ||
| 62 | 1424040 | best.index = static_cast<int>(i); | |
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | 32000 | return best; | |
| 67 | } | ||
| 68 | |||
| 69 | 40 | bool EreminVStronginAlgorithmSEQ::RunImpl() { | |
| 70 | auto &input = GetInput(); | ||
| 71 | 40 | double lower_bound = std::get<0>(input); | |
| 72 | 40 | double upper_bound = std::get<1>(input); | |
| 73 | 40 | double epsilon = std::get<2>(input); | |
| 74 | 40 | int max_iterations = std::get<3>(input); | |
| 75 | |||
| 76 | 40 | std::function<double(double)> objective_function = std::get<4>(GetInput()); | |
| 77 | ; | ||
| 78 | |||
| 79 |
2/6✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 40 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
40 | std::vector<double> search_points = {lower_bound, upper_bound}; |
| 80 |
2/6✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
✓ Branch 3 taken 40 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
80 | std::vector<double> function_values = {objective_function(lower_bound), objective_function(upper_bound)}; |
| 81 |
1/2✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
|
40 | search_points.reserve(max_iterations + 2); |
| 82 |
1/2✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
|
40 | function_values.reserve(max_iterations + 2); |
| 83 | |||
| 84 | int current_iteration = 0; | ||
| 85 | double r_coefficient = 2.0; | ||
| 86 | 40 | double max_interval_width = upper_bound - lower_bound; | |
| 87 | |||
| 88 |
3/4✓ Branch 0 taken 32040 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 32000 times.
✓ Branch 3 taken 40 times.
|
32040 | while (max_interval_width > epsilon && current_iteration < max_iterations) { |
| 89 | 32000 | ++current_iteration; | |
| 90 | |||
| 91 | 32000 | double lipschitz_estimate = CalculateLipschitzEstimate(search_points, function_values); | |
| 92 | |||
| 93 |
2/2✓ Branch 0 taken 31992 times.
✓ Branch 1 taken 8 times.
|
32000 | double m_parameter = (lipschitz_estimate > 0.0) ? r_coefficient * lipschitz_estimate : 1.0; |
| 94 | |||
| 95 | 32000 | auto best_interval = FindBestInterval(search_points, function_values, m_parameter); | |
| 96 | 32000 | std::size_t best_interval_index = best_interval.index; | |
| 97 | |||
| 98 |
1/2✓ Branch 0 taken 32000 times.
✗ Branch 1 not taken.
|
32000 | double left_point = search_points[best_interval_index - 1]; |
| 99 | 32000 | double right_point = search_points[best_interval_index]; | |
| 100 | 32000 | double left_value = function_values[best_interval_index - 1]; | |
| 101 | 32000 | double right_value = function_values[best_interval_index]; | |
| 102 | |||
| 103 | 32000 | double new_point = (0.5 * (left_point + right_point)) - ((right_value - left_value) / (2.0 * m_parameter)); | |
| 104 | |||
| 105 |
2/4✓ Branch 0 taken 32000 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32000 times.
|
32000 | if (new_point <= left_point || new_point >= right_point) { |
| 106 | ✗ | new_point = 0.5 * (left_point + right_point); | |
| 107 | } | ||
| 108 | |||
| 109 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 32000 times.
✓ Branch 3 taken 32000 times.
✗ Branch 4 not taken.
|
64000 | double new_value = objective_function(new_point); |
| 110 | |||
| 111 |
2/4✓ Branch 1 taken 32000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32000 times.
✗ Branch 5 not taken.
|
32000 | search_points.insert(search_points.begin() + static_cast<std::ptrdiff_t>(best_interval_index), new_point); |
| 112 |
1/4✓ Branch 1 taken 32000 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
32000 | function_values.insert(function_values.begin() + static_cast<std::ptrdiff_t>(best_interval_index), new_value); |
| 113 | |||
| 114 | 32000 | max_interval_width = 0.0; | |
| 115 |
2/2✓ Branch 0 taken 14048000 times.
✓ Branch 1 taken 32000 times.
|
14080000 | for (std::size_t i = 1; i < search_points.size(); ++i) { |
| 116 | 14048000 | double current_width = search_points[i] - search_points[i - 1]; | |
| 117 | 14048000 | max_interval_width = std::max(current_width, max_interval_width); | |
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 |
1/2✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
|
40 | GetOutput() = *std::ranges::min_element(function_values); |
| 122 | 40 | return true; | |
| 123 | } | ||
| 124 | |||
| 125 | 40 | bool EreminVStronginAlgorithmSEQ::PostProcessingImpl() { | |
| 126 | 40 | return true; | |
| 127 | } | ||
| 128 | |||
| 129 | } // namespace eremin_v_strongin_algorithm | ||
| 130 |