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