GCC Code Coverage Report


Directory: ./
File: tasks/alekseev_a_global_opt_chars/seq/src/ops_seq.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 98 100 98.0%
Functions: 10 10 100.0%
Branches: 47 96 49.0%

Line Branch Exec Source
1 #include "alekseev_a_global_opt_chars/seq/include/ops_seq.hpp"
2
3 #include <algorithm>
4 #include <cmath>
5 #include <cstddef>
6 #include <limits>
7 #include <utility>
8 #include <vector>
9
10 #include "alekseev_a_global_opt_chars/common/include/common.hpp"
11
12 namespace alekseev_a_global_opt_chars {
13
14
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 AlekseevAGlobalOptCharsSEQ::AlekseevAGlobalOptCharsSEQ(const InType &in) {
15 SetTypeOfTask(GetStaticTypeOfTask());
16 GetInput() = in;
17 48 GetOutput() = OutType();
18 48 }
19
20
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 bool AlekseevAGlobalOptCharsSEQ::ValidationImpl() {
21 const auto &input = GetInput();
22
23 bool valid = true;
24
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 valid = valid && (input.func != nullptr);
25
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 valid = valid && (input.max_iterations > 0);
26
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 valid = valid && (input.epsilon > 0.0);
27
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 valid = valid && (input.r_param > 1.0);
28
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 valid = valid && (input.x_min < input.x_max);
29
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 valid = valid && (input.y_min < input.y_max);
30
31 48 return valid;
32 }
33
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 bool AlekseevAGlobalOptCharsSEQ::PreProcessingImpl() {
35 const auto &input = GetInput();
36
37 trial_points_.clear();
38 t_points_.clear();
39 48 lipschitz_estimate_ = 1.0;
40
41 48 const double t_left = 0.0;
42 48 const double t_right = 1.0;
43
44
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 t_points_.push_back(t_left);
45 t_points_.push_back(t_right);
46
47 48 const double x0 = PeanoToX(t_left, input.x_min, input.x_max, peano_level_);
48
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
48 const double y0 = PeanoToY(t_left, input.y_min, input.y_max, peano_level_);
49 48 const double z0 = input.func(x0, y0);
50
51 48 const double x1 = PeanoToX(t_right, input.x_min, input.x_max, peano_level_);
52
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
48 const double y1 = PeanoToY(t_right, input.y_min, input.y_max, peano_level_);
53 48 const double z1 = input.func(x1, y1);
54
55 48 trial_points_.emplace_back(x0, y0, z0);
56 48 trial_points_.emplace_back(x1, y1, z1);
57
58 48 return true;
59 }
60
61
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 bool AlekseevAGlobalOptCharsSEQ::RunImpl() {
62 const auto &input = GetInput();
63 auto &output = GetOutput();
64
65
2/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
48 if (t_points_.size() < 2 || trial_points_.size() < 2) {
66 if (!PreProcessingImpl()) {
67 return false;
68 }
69 }
70
71 48 output.iterations = 0;
72 48 output.converged = false;
73
74
1/2
✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
560 for (int iter = 0; iter < input.max_iterations; ++iter) {
75 560 SortingTrials();
76
77 560 lipschitz_estimate_ = ComputeLipschitzEstimate();
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 560 times.
560 if (lipschitz_estimate_ < 1e-10) {
79 lipschitz_estimate_ = 1.0;
80 }
81
82 560 const int best_interval_idx = BestInterval();
83
84
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 512 times.
560 const double t_left = t_points_[best_interval_idx];
85 560 const double t_right = t_points_[best_interval_idx + 1];
86 560 const double z_left = trial_points_[best_interval_idx].z;
87 560 const double z_right = trial_points_[best_interval_idx + 1].z;
88
89 560 const double interval_len = t_right - t_left;
90
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 512 times.
560 if (interval_len < input.epsilon) {
91 48 output.converged = true;
92 48 output.iterations = iter + 1;
93 48 break;
94 }
95
96 512 const double m_val = input.r_param * lipschitz_estimate_;
97
98 512 double t_new = (0.5 * (t_left + t_right)) - ((z_right - z_left) / (2.0 * m_val));
99
100
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 512 times.
✓ Branch 2 taken 512 times.
✗ Branch 3 not taken.
512 t_new = std::max(t_left + 1e-12, std::min(t_new, t_right - 1e-12));
101
102 512 const double z_new = PerformTrial(t_new);
103
104 512 const double x_new = PeanoToX(t_new, input.x_min, input.x_max, peano_level_);
105 512 const double y_new = PeanoToY(t_new, input.y_min, input.y_max, peano_level_);
106
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 512 times.
512 t_points_.push_back(t_new);
108 512 trial_points_.emplace_back(x_new, y_new, z_new);
109
110 512 output.iterations = iter + 1;
111 }
112
113 return true;
114 }
115
116 48 bool AlekseevAGlobalOptCharsSEQ::PostProcessingImpl() {
117 auto &output = GetOutput();
118
119 double best_z = std::numeric_limits<double>::max();
120 std::size_t best_idx = 0;
121
122
2/2
✓ Branch 0 taken 608 times.
✓ Branch 1 taken 48 times.
656 for (std::size_t i = 0; i < trial_points_.size(); ++i) {
123
2/2
✓ Branch 0 taken 208 times.
✓ Branch 1 taken 400 times.
608 if (trial_points_[i].z < best_z) {
124 best_z = trial_points_[i].z;
125 best_idx = i;
126 }
127 }
128 48 output.x_opt = trial_points_[best_idx].x;
129 48 output.y_opt = trial_points_[best_idx].y;
130 48 output.func_min = best_z;
131
132 48 return true;
133 }
134
135 560 void AlekseevAGlobalOptCharsSEQ::SortingTrials() {
136 560 std::vector<std::size_t> idx(t_points_.size());
137
2/2
✓ Branch 0 taken 4272 times.
✓ Branch 1 taken 560 times.
4832 for (std::size_t i = 0; i < idx.size(); ++i) {
138 4272 idx[i] = i;
139 }
140
141
3/22
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 3712 times.
✓ Branch 20 taken 1880 times.
✓ Branch 21 taken 3712 times.
9304 std::ranges::sort(idx, [this](std::size_t a, std::size_t b) { return t_points_[a] < t_points_[b]; });
142
143
2/6
✓ Branch 1 taken 560 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 560 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
560 std::vector<double> sorted_t(t_points_.size());
144
1/4
✓ Branch 1 taken 560 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
560 std::vector<TrialPoint> sorted_trials(trial_points_.size());
145
146
2/2
✓ Branch 0 taken 4272 times.
✓ Branch 1 taken 560 times.
4832 for (std::size_t i = 0; i < idx.size(); ++i) {
147 4272 sorted_t[i] = t_points_[idx[i]];
148 4272 sorted_trials[i] = trial_points_[idx[i]];
149 }
150
151 560 t_points_ = std::move(sorted_t);
152 560 trial_points_ = std::move(sorted_trials);
153 560 }
154
155 560 double AlekseevAGlobalOptCharsSEQ::ComputeLipschitzEstimate() {
156 560 double max_slope = 0.0;
157
158
2/2
✓ Branch 0 taken 3712 times.
✓ Branch 1 taken 560 times.
4272 for (std::size_t i = 1; i < t_points_.size(); ++i) {
159 3712 const double dt = t_points_[i] - t_points_[i - 1];
160
1/2
✓ Branch 0 taken 3712 times.
✗ Branch 1 not taken.
3712 if (dt > 1e-15) {
161 3712 const double dz = std::abs(trial_points_[i].z - trial_points_[i - 1].z);
162 3712 max_slope = std::max(max_slope, dz / dt);
163 }
164 }
165
166
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 48 times.
560 return (max_slope > 0.0) ? max_slope : 1.0;
167 }
168
169 3712 double AlekseevAGlobalOptCharsSEQ::ComputeIntervalCharacteristic(int interval_idx, double m_val) const {
170 3712 const double t_i = t_points_[interval_idx];
171 3712 const double t_j = t_points_[interval_idx + 1];
172 3712 const double z_i = trial_points_[interval_idx].z;
173 3712 const double z_j = trial_points_[interval_idx + 1].z;
174
175 3712 const double dt = t_j - t_i;
176 3712 const double dz = z_j - z_i;
177
178 3712 return (m_val * dt) + ((dz * dz) / (m_val * dt)) - (2.0 * (z_j + z_i));
179 }
180
181 560 int AlekseevAGlobalOptCharsSEQ::BestInterval() {
182 const auto &input = GetInput();
183 560 const double m_val = input.r_param * lipschitz_estimate_;
184
185 double best_char = -std::numeric_limits<double>::max();
186 int best_idx = 0;
187
188
2/2
✓ Branch 0 taken 3712 times.
✓ Branch 1 taken 560 times.
4272 for (std::size_t i = 0; i + 1 < t_points_.size(); ++i) {
189 3712 const double c = ComputeIntervalCharacteristic(static_cast<int>(i), m_val);
190
2/2
✓ Branch 0 taken 1320 times.
✓ Branch 1 taken 2392 times.
3712 if (c > best_char) {
191 best_char = c;
192 best_idx = static_cast<int>(i);
193 }
194 }
195
196 560 return best_idx;
197 }
198
199 512 double AlekseevAGlobalOptCharsSEQ::PerformTrial(double t) {
200 const auto &input = GetInput();
201
202 512 const double x = PeanoToX(t, input.x_min, input.x_max, peano_level_);
203 512 const double y = PeanoToY(t, input.y_min, input.y_max, peano_level_);
204
205 512 return input.func(x, y);
206 }
207
208 } // namespace alekseev_a_global_opt_chars
209