| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "eremin_v_strongin_algorithm/mpi/include/ops_mpi.hpp" | ||
| 2 | |||
| 3 | #include <mpi.h> | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cmath> | ||
| 7 | #include <cstddef> | ||
| 8 | #include <functional> | ||
| 9 | #include <tuple> | ||
| 10 | #include <vector> | ||
| 11 | |||
| 12 | #include "eremin_v_strongin_algorithm/common/include/common.hpp" | ||
| 13 | |||
| 14 | namespace eremin_v_strongin_algorithm { | ||
| 15 | |||
| 16 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | EreminVStronginAlgorithmMPI::EreminVStronginAlgorithmMPI(const InType &in) { |
| 17 | SetTypeOfTask(GetStaticTypeOfTask()); | ||
| 18 | GetInput() = in; | ||
| 19 | 10 | GetOutput() = 0; | |
| 20 | 10 | } | |
| 21 | |||
| 22 | 10 | bool EreminVStronginAlgorithmMPI::ValidationImpl() { | |
| 23 | auto &input = GetInput(); | ||
| 24 | |||
| 25 | 10 | double lower_bound = std::get<0>(input); | |
| 26 | 10 | double upper_bound = std::get<1>(input); | |
| 27 | 10 | double epsilon = std::get<2>(input); | |
| 28 | 10 | int max_iters = std::get<3>(input); | |
| 29 | |||
| 30 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
10 | return (lower_bound < upper_bound) && (epsilon > 0.0 && epsilon <= (upper_bound - lower_bound)) && |
| 31 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
|
10 | (max_iters > 0 && max_iters <= 100000000) && (lower_bound >= -1e9 && lower_bound <= 1e9) && |
| 32 |
3/6✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
|
20 | (upper_bound >= -1e9 && upper_bound <= 1e9) && (GetOutput() == 0); |
| 33 | } | ||
| 34 | |||
| 35 | 10 | bool EreminVStronginAlgorithmMPI::PreProcessingImpl() { | |
| 36 | 10 | return true; | |
| 37 | } | ||
| 38 | |||
| 39 | 8000 | double EreminVStronginAlgorithmMPI::CalculateLipschitzEstimate(int rank, int size, | |
| 40 | const std::vector<double> &search_points, | ||
| 41 | const std::vector<double> &function_values) { | ||
| 42 | 8000 | double lipschitz_estimate = 0.0; | |
| 43 |
2/2✓ Branch 0 taken 1752000 times.
✓ Branch 1 taken 8000 times.
|
1760000 | for (std::size_t i = 1 + static_cast<std::size_t>(rank); i < search_points.size(); |
| 44 | 1752000 | i += static_cast<std::size_t>(size)) { | |
| 45 | 1752000 | double interval_width = search_points[i] - search_points[i - 1]; | |
| 46 | 1752000 | double value_difference = std::abs(function_values[i] - function_values[i - 1]); | |
| 47 | 1752000 | double current_slope = value_difference / interval_width; | |
| 48 | 1752000 | lipschitz_estimate = std::max(current_slope, lipschitz_estimate); | |
| 49 | } | ||
| 50 | |||
| 51 | 8000 | double global_lipschitz_estimate = 0.0; | |
| 52 | 8000 | MPI_Allreduce(&lipschitz_estimate, &global_lipschitz_estimate, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); | |
| 53 | |||
| 54 | 8000 | return global_lipschitz_estimate; | |
| 55 | } | ||
| 56 | |||
| 57 | 8000 | EreminVStronginAlgorithmMPI::IntervalCharacteristic EreminVStronginAlgorithmMPI::FindBestInterval( | |
| 58 | int rank, int size, const std::vector<double> &search_points, const std::vector<double> &function_values, | ||
| 59 | double m_parameter) { | ||
| 60 | 8000 | IntervalCharacteristic local{.value = -1e18, .index = 1}; | |
| 61 | |||
| 62 |
2/2✓ Branch 0 taken 1752000 times.
✓ Branch 1 taken 8000 times.
|
1760000 | for (std::size_t i = 1 + static_cast<std::size_t>(rank); i < search_points.size(); |
| 63 | 1752000 | i += static_cast<std::size_t>(size)) { | |
| 64 | 1752000 | double interval_width = search_points[i] - search_points[i - 1]; | |
| 65 | 1752000 | double value_difference = function_values[i] - function_values[i - 1]; | |
| 66 | |||
| 67 | 1752000 | double characteristic = (m_parameter * interval_width) + | |
| 68 | 1752000 | ((value_difference * value_difference) / (m_parameter * interval_width)) - | |
| 69 | 1752000 | (2.0 * (function_values[i] + function_values[i - 1])); | |
| 70 | |||
| 71 |
2/2✓ Branch 0 taken 194011 times.
✓ Branch 1 taken 1557989 times.
|
1752000 | if (characteristic > local.value) { |
| 72 | 194011 | local.value = characteristic; | |
| 73 | 194011 | local.index = static_cast<int>(i); | |
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | 8000 | IntervalCharacteristic global{}; | |
| 78 | 8000 | MPI_Allreduce(&local, &global, 1, MPI_DOUBLE_INT, MPI_MAXLOC, MPI_COMM_WORLD); | |
| 79 | 8000 | return global; | |
| 80 | } | ||
| 81 | |||
| 82 | 10 | bool EreminVStronginAlgorithmMPI::RunImpl() { | |
| 83 | 10 | int rank = 0; | |
| 84 | 10 | int size = 0; | |
| 85 | 10 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); | |
| 86 | 10 | MPI_Comm_size(MPI_COMM_WORLD, &size); | |
| 87 | |||
| 88 | 10 | double lower_bound = 0.0; | |
| 89 | 10 | double upper_bound = 0.0; | |
| 90 | 10 | double epsilon = 0.0; | |
| 91 | 10 | int max_iterations = 0; | |
| 92 | |||
| 93 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
|
10 | if (rank == 0) { |
| 94 | auto &input = GetInput(); | ||
| 95 | 5 | lower_bound = std::get<0>(input); | |
| 96 | 5 | upper_bound = std::get<1>(input); | |
| 97 | 5 | epsilon = std::get<2>(input); | |
| 98 | 5 | max_iterations = std::get<3>(input); | |
| 99 | } | ||
| 100 | |||
| 101 | 10 | MPI_Bcast(&lower_bound, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); | |
| 102 | 10 | MPI_Bcast(&upper_bound, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); | |
| 103 | 10 | MPI_Bcast(&epsilon, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); | |
| 104 | 10 | MPI_Bcast(&max_iterations, 1, MPI_INT, 0, MPI_COMM_WORLD); | |
| 105 | |||
| 106 | 10 | std::function<double(double)> objective_function = std::get<4>(GetInput()); | |
| 107 | ; | ||
| 108 | |||
| 109 |
1/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
10 | std::vector<double> search_points = {lower_bound, upper_bound}; |
| 110 |
3/8✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
30 | std::vector<double> function_values = {objective_function(lower_bound), objective_function(upper_bound)}; |
| 111 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | search_points.reserve(max_iterations + 2); |
| 112 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | function_values.reserve(max_iterations + 2); |
| 113 | |||
| 114 | int current_iteration = 0; | ||
| 115 | double r_coefficient = 2.0; | ||
| 116 | 10 | double max_interval_width = upper_bound - lower_bound; | |
| 117 | |||
| 118 |
3/4✓ Branch 0 taken 8010 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8000 times.
✓ Branch 3 taken 10 times.
|
8010 | while (max_interval_width > epsilon && current_iteration < max_iterations) { |
| 119 | 8000 | ++current_iteration; | |
| 120 | |||
| 121 |
1/2✓ Branch 1 taken 8000 times.
✗ Branch 2 not taken.
|
8000 | double lipschitz_estimate = CalculateLipschitzEstimate(rank, size, search_points, function_values); |
| 122 | |||
| 123 |
2/2✓ Branch 0 taken 7998 times.
✓ Branch 1 taken 2 times.
|
8000 | double m_parameter = (lipschitz_estimate > 0.0) ? r_coefficient * lipschitz_estimate : 1.0; |
| 124 | |||
| 125 |
1/2✓ Branch 1 taken 8000 times.
✗ Branch 2 not taken.
|
8000 | auto best_interval = FindBestInterval(rank, size, search_points, function_values, m_parameter); |
| 126 | 8000 | int best_interval_index = best_interval.index; | |
| 127 | |||
| 128 |
2/2✓ Branch 0 taken 4000 times.
✓ Branch 1 taken 4000 times.
|
8000 | double left_point = search_points[best_interval_index - 1]; |
| 129 | 8000 | double right_point = search_points[best_interval_index]; | |
| 130 | 8000 | double left_value = function_values[best_interval_index - 1]; | |
| 131 | 8000 | double right_value = function_values[best_interval_index]; | |
| 132 | |||
| 133 | 8000 | double new_point = 0.0; | |
| 134 | 8000 | double new_value = 0.0; | |
| 135 | |||
| 136 |
2/2✓ Branch 0 taken 4000 times.
✓ Branch 1 taken 4000 times.
|
8000 | if (rank == 0) { |
| 137 | 4000 | new_point = (0.5 * (left_point + right_point)) - ((right_value - left_value) / (2.0 * m_parameter)); | |
| 138 | |||
| 139 |
2/4✓ Branch 0 taken 4000 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4000 times.
|
4000 | if (new_point <= left_point || new_point >= right_point) { |
| 140 | ✗ | new_point = 0.5 * (left_point + right_point); | |
| 141 | } | ||
| 142 | |||
| 143 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4000 times.
|
8000 | new_value = objective_function(new_point); |
| 144 | } | ||
| 145 |
1/2✓ Branch 1 taken 8000 times.
✗ Branch 2 not taken.
|
8000 | MPI_Bcast(&new_point, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); |
| 146 |
1/2✓ Branch 1 taken 8000 times.
✗ Branch 2 not taken.
|
8000 | MPI_Bcast(&new_value, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); |
| 147 | |||
| 148 |
2/4✓ Branch 1 taken 8000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8000 times.
✗ Branch 5 not taken.
|
8000 | search_points.insert(search_points.begin() + static_cast<std::ptrdiff_t>(best_interval_index), new_point); |
| 149 |
1/4✓ Branch 1 taken 8000 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
8000 | function_values.insert(function_values.begin() + static_cast<std::ptrdiff_t>(best_interval_index), new_value); |
| 150 | |||
| 151 | 8000 | max_interval_width = 0.0; | |
| 152 |
2/2✓ Branch 0 taken 1756000 times.
✓ Branch 1 taken 8000 times.
|
1764000 | for (std::size_t i = 1 + static_cast<std::size_t>(rank); i < search_points.size(); |
| 153 | 1756000 | i += static_cast<std::size_t>(size)) { | |
| 154 | 1756000 | double current_width = search_points[i] - search_points[i - 1]; | |
| 155 | 1756000 | max_interval_width = std::max(current_width, max_interval_width); | |
| 156 | } | ||
| 157 | 8000 | double local_max_interval_width = max_interval_width; | |
| 158 |
1/2✓ Branch 1 taken 8000 times.
✗ Branch 2 not taken.
|
8000 | MPI_Allreduce(&local_max_interval_width, &max_interval_width, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); |
| 159 | } | ||
| 160 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | GetOutput() = *std::ranges::min_element(function_values); |
| 161 | 10 | return true; | |
| 162 | } | ||
| 163 | |||
| 164 | 10 | bool EreminVStronginAlgorithmMPI::PostProcessingImpl() { | |
| 165 | 10 | return true; | |
| 166 | } | ||
| 167 | |||
| 168 | } // namespace eremin_v_strongin_algorithm | ||
| 169 |