GCC Code Coverage Report


Directory: ./
File: tasks/eremin_v_strongin_algorithm/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 94 95 98.9%
Functions: 7 7 100.0%
Branches: 47 82 57.3%

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