| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <algorithm> | ||
| 4 | #include <cmath> | ||
| 5 | #include <cstdint> | ||
| 6 | #include <string> | ||
| 7 | #include <tuple> | ||
| 8 | |||
| 9 | #include "task/include/task.hpp" | ||
| 10 | |||
| 11 | namespace khruev_a_global_opt { | ||
| 12 | |||
| 13 | struct SearchData { | ||
| 14 | int func_id; | ||
| 15 | double ax, bx; | ||
| 16 | double ay, by; | ||
| 17 | double epsilon; | ||
| 18 | int max_iter; | ||
| 19 | double r; | ||
| 20 | }; | ||
| 21 | |||
| 22 | struct SearchResult { | ||
| 23 | double x; | ||
| 24 | double y; | ||
| 25 | double value; | ||
| 26 | int iter_count; | ||
| 27 | }; | ||
| 28 | |||
| 29 | using InType = SearchData; | ||
| 30 | using OutType = SearchResult; | ||
| 31 | using BaseTask = ppc::task::Task<InType, OutType>; | ||
| 32 | using TestType = std::tuple<std::string, int, double, double, double, double, double>; | ||
| 33 | |||
| 34 | // 1. Кривая Гильберта: переводит t [0,1] -> (x, y) [0,1]x[0,1] | ||
| 35 | // Вспомогательная функция для поворота/отражения квадранта | ||
| 36 | // n: размер текущего квадрата (степень двойки) | ||
| 37 | // x, y: координаты | ||
| 38 | // rx, ry: биты, определяющие квадрант | ||
| 39 | inline void Rotate(uint64_t n, uint64_t &x, uint64_t &y, uint64_t rx, uint64_t ry) { | ||
| 40 | 117888 | if (ry == 0) { | |
| 41 |
2/2✓ Branch 0 taken 23859 times.
✓ Branch 1 taken 45101 times.
|
68960 | if (rx == 1) { |
| 42 | 23859 | x = n - 1 - x; | |
| 43 | 23859 | y = n - 1 - y; | |
| 44 | } | ||
| 45 | // Swap x и y | ||
| 46 | uint64_t t = x; | ||
| 47 | x = y; | ||
| 48 | y = t; | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | // 1. Кривая Гильберта: переводит t [0,1] -> (x, y) [0,1]x[0,1] | ||
| 53 | // Используем 32-битный порядок кривой (сетка 2^32 x 2^32), что покрывает точность double | ||
| 54 |
2/2✓ Branch 0 taken 3644 times.
✓ Branch 1 taken 40 times.
|
3684 | inline void D2xy(double t, double &x, double &y) { |
| 55 | // Ограничиваем t диапазоном [0, 1] | ||
| 56 | t = std::max(t, 0.0); | ||
| 57 | t = std::min(t, 1.0); | ||
| 58 | |||
| 59 | // Порядок кривой N = 32. Всего точек 2^64 (влезает в uint64_t). | ||
| 60 | // Масштабируем t [0, 1] в целое число s [0, 2^64 - 1] | ||
| 61 | // Используем (2^64 - 1) как множитель. | ||
| 62 | const auto max_dist = static_cast<uint64_t>(-1); | ||
| 63 | const double two_to_64 = ldexp(1.0, 64); | ||
| 64 | 3684 | double val = t * two_to_64; | |
| 65 | uint64_t s = 0; | ||
| 66 |
2/2✓ Branch 0 taken 3644 times.
✓ Branch 1 taken 40 times.
|
3684 | if (val >= two_to_64) { |
| 67 | s = max_dist; | ||
| 68 | } else { | ||
| 69 | 3644 | s = static_cast<uint64_t>(val); | |
| 70 | } | ||
| 71 | |||
| 72 | uint64_t ix = 0; | ||
| 73 | uint64_t iy = 0; | ||
| 74 | |||
| 75 | // Итеративный алгоритм от младших битов к старшим (bottom-up) | ||
| 76 | // n - это размер под-квадрата на текущем уровне | ||
| 77 |
2/2✓ Branch 0 taken 117888 times.
✓ Branch 1 taken 3684 times.
|
121572 | for (uint64_t nn = 1; nn < (1ULL << 32); nn <<= 1) { |
| 78 | 117888 | uint64_t rx = 1 & (s / 2); | |
| 79 |
2/2✓ Branch 0 taken 68960 times.
✓ Branch 1 taken 48928 times.
|
117888 | uint64_t ry = 1 & (s ^ rx); |
| 80 | |||
| 81 | Rotate(nn, ix, iy, rx, ry); | ||
| 82 | |||
| 83 | 117888 | ix += nn * rx; | |
| 84 | 117888 | iy += nn * ry; | |
| 85 | |||
| 86 | 117888 | s /= 4; | |
| 87 | } | ||
| 88 | |||
| 89 | // Нормализуем обратно в [0, 1] | ||
| 90 | // Делим на 2^32 (размер сетки) | ||
| 91 | const double scale = 1.0 / 4294967296.0; // 1.0 / 2^32 | ||
| 92 | 3684 | x = static_cast<double>(ix) * scale; | |
| 93 | 3684 | y = static_cast<double>(iy) * scale; | |
| 94 | 3684 | } | |
| 95 | |||
| 96 |
4/6✓ Branch 0 taken 911 times.
✓ Branch 1 taken 911 times.
✓ Branch 2 taken 911 times.
✓ Branch 3 taken 911 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
3644 | inline double TargetFunction(int id, double x, double y) { |
| 97 | if (id == 1) { | ||
| 98 | // квадратичная | ||
| 99 | 911 | return ((x - 0.5) * (x - 0.5)) + ((y - 0.5) * (y - 0.5)); | |
| 100 | } | ||
| 101 | if (id == 2) { | ||
| 102 | // Rastrigin-like | ||
| 103 | constexpr double kA = 10.0; | ||
| 104 | constexpr double kTwoPi = 6.2831853071795864769; | ||
| 105 | 911 | return (2.0 * kA) + ((x * x) - (kA * std::cos(kTwoPi * x))) + ((y * y) - (kA * std::cos(kTwoPi * y))); | |
| 106 | } | ||
| 107 | if (id == 3) { | ||
| 108 | // BoothFunc | ||
| 109 | 911 | const double t1 = x + (2.0 * y) - 7.0; | |
| 110 | 911 | const double t2 = (2.0 * x) + y - 5.0; | |
| 111 | 911 | return (t1 * t1) + (t2 * t2); | |
| 112 | } | ||
| 113 | if (id == 4) { | ||
| 114 | // MatyasFunc | ||
| 115 | 911 | return (0.26 * ((x * x) + (y * y))) - (0.48 * x * y); | |
| 116 | } | ||
| 117 | if (id == 5) { // Himme | ||
| 118 | ✗ | const double t1 = ((x * x) + y - 11.0); | |
| 119 | ✗ | const double t2 = (x + (y * y) - 7.0); | |
| 120 | ✗ | return (t1 * t1) + (t2 * t2); | |
| 121 | } | ||
| 122 | |||
| 123 | return 0.0; | ||
| 124 | } | ||
| 125 | |||
| 126 | // Структура для хранения испытаний | ||
| 127 | struct Trial { | ||
| 128 | double x; // координата на отрезке [0, 1] | ||
| 129 | double z; // значение функции | ||
| 130 | int id; // исходный индекс | ||
| 131 | |||
| 132 | bool operator<(const Trial &other) const { | ||
| 133 | return x < other.x; | ||
| 134 | } | ||
| 135 | }; | ||
| 136 | |||
| 137 | } // namespace khruev_a_global_opt | ||
| 138 |