"static __declspec(noalias) void agp_run_branch_mp...

Criado em: 18 de dezembro de 2025

Respondido usando GPT-5.2 Thinking por Chat01

Pergunta

"static __declspec(noalias) void agp_run_branch_mpi(
const MortonND& map,
const ManipCost& cost,
int maxIter,
float r,
bool adaptive,
float eps,
unsigned seed,
std::vector<IntervalND*, boost::alignment::aligned_allocator<IntervalND*, 16u>>& H,
std::vector<float, boost::alignment::aligned_allocator<float, 16u>>& bestQ,
float& bestF,
float& bestX,
float& bestY,
size_t& out_iterations,
float& out_achieved_epsilon,
float M_prior) noexcept
{
const int n = cost.n;
const int dim = n + (cost.variableLen ? n : 0);
const float dim_f = static_cast<float>(dim);
unsigned exchange_counter = 0;
unsigned exchange_counter_T = 0;
alignas(16) float M_by_span[12];
int msi = 0;
while (msi < 12) M_by_span[msi++] = M_prior;
float Mmax = M_prior;
alignas(16) float q_local[32];
alignas(16) float phi[32];
alignas(16) float s_arr[32];
alignas(16) float c_arr[32];
alignas(16) float sum_s[32];
alignas(16) float sum_c[32];
alignas(16) float q_try[32];
bestQ.reserve(static_cast<size_t>(dim));
float x = 0.0f;
float y = 0.0f;
int no_improve = 0;
auto t_to_idx = [&](float t) -> unsigned long long {
unsigned long long idx = static_cast<unsigned long long>(fmaf(t, static_cast<float>(map.scale), 0.0f));
return idx;
};
auto update_pockets_and_Mmax = [&](IntervalND* I) {
const int k = I->span_level;
if (I->M > M_by_span[k]) M_by_span[k] = I->M;
if (M_by_span[k] > Mmax) Mmax = M_by_span[k];
};
const float a = 0.0f;
const float b = 1.0f;
float p = 0.0f;
float dmax = fmaf(b, 1.0f, -a);
const float initial_len = dmax;
float exp_arg_threshold = fmaf(1.0f / fmaf(dim_f, fmaf(dim_f, fmaf(dim_f, fmaf(dim_f, fmaf(dim_f, -0.2f, 0.25f), -0.33333333f), 0.5f), -1.0f), dim_f), 0.415888308336f, 0.0f);
const float log_arg_threshold = fmaf(dim_f, 0.1f, -0.105f);
const float adaptive_coeff_addition_threshold = fmaf(fmaf(exp_arg_threshold, fmaf(exp_arg_threshold, fmaf(exp_arg_threshold, fmaf(exp_arg_threshold, 0.00833333377f, 0.0416666679f), 0.16666667f), 0.5f), 1.0f), 1.0f / fmaf(log_arg_threshold, fmaf(log_arg_threshold, fmaf(log_arg_threshold, fmaf(log_arg_threshold, fmaf(log_arg_threshold, 0.164056f, -0.098462f), 0.240884f), -0.351834f), 0.999996f), log_arg_threshold), 0.17814618538f);
float adaptive_coeff_threshold = adaptive_coeff_addition_threshold + 1.0f;
const float log_arg = dim_f + 5.0f;
const float A_dim = fmaf(1.0f / fmaf(log_arg, fmaf(log_arg, fmaf(log_arg, fmaf(log_arg, fmaf(log_arg, 0.164056f, -0.098462f), 0.240884f), -0.351834f), 0.999996f), log_arg), 3.0f, 0.0f);
const float B_dim = fmaf(A_dim, 0.65f, 0.0f);
const float log_argument = A_dim - 2.03f;
const float C_dim = fmaf(log_argument, fmaf(log_argument, fmaf(log_argument, fmaf(log_argument, fmaf(log_argument, 0.164056f, -0.098462f), 0.240884f), -0.351834f), 0.999996f), log_argument) - B_dim;
const float adaptive_coeff_addition = fmaf(C_dim, fmaf(C_dim, fmaf(C_dim, fmaf(C_dim, 0.00833333377f, 0.0416666679f), 0.16666667f), 0.55f), 1.0f);
float adaptive_coeff = A_dim - adaptive_coeff_addition;
const float A_dim_clone = fmaf(A_dim - fmaf(-fmaf(B_dim, fmaf(B_dim, fmaf(B_dim, fmaf(B_dim, 0.00833333377f, 0.0416666679f), 0.16666667f), 0.5f), 1.0f), adaptive_coeff_addition, A_dim), 0.5f, 0.0f);
int it = 0;
auto evalAt = [&](float t) -> float {
map.map01ToPoint(t, q_local);
float f = cost(q_local, x, y);
const float step_arg = fmaf(-dim_f, 0.825f, 3.3f);
float eta = fmaf(fmaf(step_arg, fmaf(step_arg, fmaf(step_arg, fmaf(step_arg, 0.00833333377f, 0.0416666679f), 0.16666667f), 0.5f), 1.0f), 0.0685f, 0.0f);
if ((((f < fmaf(bestF, 2.03f - adaptive_coeff, 0.0f) && p > 0.55f) || (f < fmaf(bestF, adaptive_coeff, 0.0f) && ((p > 0.7f && !(it % 3)) || p > 0.9f))) && dim > 2) || (f < fmaf(bestF, adaptive_coeff, 0.0f) && dim < 3)) {
float acc = 0.0f;
int ii = 0;
while (ii < n) {
acc = fmaf(q_local[ii], 1.0f, acc);
phi[ii] = acc;
++ii;
}
FABE13_SINCOS(phi, s_arr, c_arr, n);
float as = 0.0f;
float ac = 0.0f;
int k = n - 1;
while (k >= 0) {
const float Lk = cost.variableLen ? q_local[n + k] : 1.0f;
as = fmaf(Lk, s_arr[k], as);
ac = fmaf(Lk, c_arr[k], ac);
sum_s[k] = as;
sum_c[k] = ac;
--k;
}
const float dx = fmaf(x, 1.0f, -cost.targetX);
const float dy = fmaf(y, 1.0f, -cost.targetY);
const float dist = sqrtf(fmaf(dx, dx, dy * dy)) + 1.0e-8f;
int stepI = 0;
const float adaptive_window = fmaf(1.0f / fmaf(bestF, adaptive_coeff_threshold, 0.0f), fmaf(bestF, adaptive_coeff_threshold, -f), 0.0f);
const float curse_dim_arg = fmaf(dim_f, 0.825f, 0.0f);
const int threshold_iters_grad = static_cast<int>(fmaf(fmaf(adaptive_window, adaptive_window, 1.0f), fmaf(fmaf(curse_dim_arg, fmaf(curse_dim_arg, fmaf(curse_dim_arg, fmaf(curse_dim_arg, 0.00833333377f, 0.0416666679f), 0.16666667f), 0.5f), 1.0f), 0.0685f, 0.0f), 0.0f));
int no_improve_steps = 0;
float f_at_check_start = f;
int steps_since_check = 0;
const int check_interval = static_cast<int>(fmaf(1.0f / log2f(fmaf(dim_f, 0.5f, 1.0f)), static_cast<float>(threshold_iters_grad >> 2), 0.0f));
while (stepI < threshold_iters_grad) {
int i = 0;
#pragma loop ivdep
while (i < n) {
float gpen = 0.0f;
{
const float ai = fabsf(q_local[i]);
const float v = fmaf(ai, 1.0f, -cost.minTheta);
if (v > 0.0f) {
const float scale_arg = fmaf(2.0f / (cost.minTheta + 1.0e-6f), fmaf(v, 0.69314718055994530941723212145818f, 0.0f), 0.0f);
const float exp_val = fmaf(scale_arg, fmaf(scale_arg, fmaf(scale_arg, fmaf(scale_arg, 0.00833333377f, 0.0416666679f), 0.16666667f), 0.5f), 1.0f);
const float dpen_dtheta = fmaf(cost.sharpW, fmaf(exp_val, 0.69314718055994530941723212145818f * (2.0f / (cost.minTheta + 1.0e-6f)), 0.0f), copysignf(1.0f, q_local[i]));
gpen = fmaf(dpen_dtheta, 1.0f, gpen);
}
}
{
const float tsg = fmaf(-q_local[i], cost.archBiasK, 0.0f);
const float exp_arg = -tsg;
const float exp_val = fmaf(exp_arg, fmaf(exp_arg, fmaf(exp_arg, fmaf(exp_arg, 0.00833333377f, 0.0416666679f), 0.16666667f), 0.5f), 1.0f);
const float sig = 1.0f / fmaf(exp_val, 1.0f, 1.0f);
gpen = fmaf(-fmaf(cost.archBiasW, cost.archBiasK, 0.0f), sig, gpen);
}
const float g = fmaf(fmaf(dx, -sum_s[i], fmaf(dy, sum_c[i], 0.0f)), 1.0f / dist, gpen);
q_try[i] = fmaf(-eta, g, q_local[i]);
const float lo = (i == 0) ? -1.0471975511965977461542144610932f : -2.6179938779914943653855361527329f;
const float hi = 2.6179938779914943653855361527329f;
if (q_try[i] < lo) q_try[i] = lo;
else if (q_try[i] > hi) q_try[i] = hi;
++i;
}
if (cost.variableLen) {
int j = 0;
#pragma loop ivdep
while (j < n) {
const float g = fmaf(fmaf(dx, c_arr[j], fmaf(dy, s_arr[j], 0.0f)), 1.0f / dist, 0.0f);
float v = fmaf(-eta, g, q_local[n + j]);
if (v < 0.5f) v = 0.5f;
else if (v > 2.0f) v = 2.0f;
q_try[n + j] = v;
++j;
}
}
float x2;
float y2;
const float f2 = cost(q_try, x2, y2);
const float rel_improvement = fmaf(-1.0f / f, f2, 1.0f);
if (f2 < f) {
memcpy(q_local, q_try, static_cast<size_t>(dim) * sizeof(float));
f = f2;
x = x2;
y = y2;
eta = fmaf(eta, fmaf(10.0f / sqrtf(dim_f), 1.0f / (1.0f + rel_improvement) * rel_improvement, 1.0f), 0.0f);
}
else {
const float caution_coeff = 5.0f / sqrtf(dim_f) * rel_improvement;
eta = fmaf(eta, fmaf(caution_coeff, fmaf(caution_coeff, fmaf(caution_coeff, fmaf(caution_coeff, 0.00833333377f, 0.0416666679f), 0.16666667f), 0.5f), 1.0f), 0.0f);
memcpy(q_try, q_local, static_cast<size_t>(dim) * sizeof(float));
++no_improve_steps;
}
++steps_since_check;
if (steps_since_check == check_interval) {
if (fmaf(-1.0f / f_at_check_start, f, 1.0f) < 1e-3f) break;
f_at_check_start = f;
steps_since_check = 0;
}
if (no_improve_steps > threshold_iters_grad >> 2) break;
++stepI;
}
}
if (f < bestF) {
if (0.95f < p || dim < 3) {
const int last = n - 1;
const float lo = (last == 0) ? -1.0471975511965977461542144610932f : -2.6179938779914943653855361527329f;
const float hi = 2.6179938779914943653855361527329f;
float bestLocF = f;
float saved = q_local[last];
float delta = eta;
while (delta > fmaf(delta, 0.15f, 0.0f)) {
int sgn = -1;
while (sgn < 2) {
float cand = fmaf(static_cast<float>(sgn), delta, saved);
if (cand < lo) cand = lo;
else if (cand > hi) cand = hi;
const float backup = q_local[last];
q_local[last] = cand;
float x2;
float y2;
const float f2 = cost(q_local, x2, y2);
if (f2 < bestLocF) {
bestLocF = f2;
x = x2;
y = y2;
saved = cand;
}
q_local[last] = backup;
sgn += 2;
}
delta = fmaf(delta, 0.5f, 0.0f);
}
if (bestLocF < f) {
q_local[last] = saved;
f = bestLocF;
}
}
bestF = f;
bestQ.assign(q_local, q_local + dim);
bestX = x;
bestY = y;
no_improve = 0;
}
else ++no_improve;
return f;
};
const float f_a = evalAt(a);
const float f_b = evalAt(b);
const float Kf = fminf(fmaxf(2.0f * dim_f, 8.0f), 128.0f);
const int K = static_cast<int>(Kf);
H.reserve(static_cast<size_t>(maxIter) + static_cast<size_t>(K) + 16u);
const int rank = g_world->rank();
const int world = g_world->size();
alignas(16) float seeds[256 * 32];
const int seedCnt = generate_heuristic_seeds(cost, map, dim, seeds, 32, static_cast<unsigned>(fmaf(static_cast<float>(rank), 7919.0f, static_cast<float>(seed))));
int i = 0;
while (i < seedCnt) {
const float* s = seeds + static_cast<size_t>(fmaf(static_cast<float>(i), 32.0f, 0.0f));
const float t_seed = map.pointToT(s);
const float interval_size = (i < 3) ? fmaf(0.0004f, static_cast<float>(dim), 0.0f) : fmaf(fmaf(0.00031f, static_cast<float>(dim), 0.0f), exp2f((1.0f / static_cast<float>(seedCnt - 4)) * log2f(fmaf(0.00025f, 1.0f / 0.00031f, 0.0f)) * static_cast<float>(i - 3)), 0.0f);
const float t1 = fmaxf(a, fmaf(-interval_size, 1.0f, t_seed));
const float t2 = fminf(b, fmaf(interval_size, 1.0f, t_seed));
if (t2 > t1) {
alignas(16) float q1[32];
alignas(16) float q2[32];
float x1;
float y1;
float x2;
float y2;
map.map01ToPoint(t1, q1);
const float f1 = cost(q1, x1, y1);
map.map01ToPoint(t2, q2);
const float f2 = cost(q2, x2, y2);
IntervalND* I = new IntervalND(t1, t2, f1, f2);
I->i1 = t_to_idx(t1);
I->i2 = t_to_idx(t2);
I->diam = map.block_diameter(I->i1, I->i2);
I->compute_span_level(map);
I->set_metric(I->diam);
update_pockets_and_Mmax(I);
I->ChangeCharacteristic(fmaf(r, Mmax, 0.0f));
if (i < 3) I->R = fmaf(I->R, fmaf(0.01f, static_cast<float>(dim), 0.85f), 0.0f);
else {
const float start_mult = fmaf(0.214f, static_cast<float>(dim), 0.0f);
const float end_mult = fmaf(0.174f, static_cast<float>(dim), 0.0f);
const float mult = fmaf(start_mult, exp2f((1.0f / static_cast<float>(seedCnt - 4)) * log2f(fmaf(end_mult, 1.0f / start_mult, 0.0f)) * static_cast<float>(i - 3)), 0.0f);
I->R = fmaf(I->R, mult, 0.0f);
}
H.emplace_back(I);
std::push_heap(H.begin(), H.end(), ComparePtrND);
if (f1 < bestF) {
bestF = f1;
bestQ.assign(q1, q1 + dim);
bestX = x1;
bestY = y1;
}
if (f2 < bestF) {
bestF = f2;
bestQ.assign(q2, q2 + dim);
bestX = x2;
bestY = y2;
}
}
++i;
}
float prev_t = a;
float prev_f = f_a;
int k = 1;
while (k <= K) {
const float t = fmaf(fmaf(b - a, static_cast<float>(k) / static_cast<float>(K + 1), a), 1.0f, static_cast<float>(rank) / static_cast<float>(world * (K + 1)));
const float f = evalAt(t);
IntervalND* I = new IntervalND(prev_t, t, prev_f, f);
I->i1 = t_to_idx(prev_t);
I->i2 = t_to_idx(t);
I->diam = map.block_diameter(I->i1, I->i2);
I->compute_span_level(map);
I->set_metric(I->diam);
update_pockets_and_Mmax(I);
I->ChangeCharacteristic(fmaf(r, Mmax, 0.0f));
H.emplace_back(I);
std::push_heap(H.begin(), H.end(), ComparePtrND);
prev_t = t;
prev_f = f;
++k;
}
IntervalND* tail = new IntervalND(prev_t, b, prev_f, f_b);
tail->i1 = t_to_idx(prev_t);
tail->i2 = t_to_idx(b);
tail->diam = map.block_diameter(tail->i1, tail->i2);
tail->compute_span_level(map);
tail->set_metric(tail->diam);
update_pockets_and_Mmax(tail);
tail->ChangeCharacteristic(fmaf(r, Mmax, 0.0f));
H.emplace_back(tail);
std::push_heap(H.begin(), H.end(), ComparePtrND);
const int kickEveryDim = static_cast<int>(fmaf(22.5f, exp2f(-0.295f * dim_f), 0.0f));
const int noImproveThrDim = static_cast<int>(fmaf(32.5f, exp2f(-0.1f * dim_f), 0.0f));
while (it < maxIter) {
p = fmaf(-1.0f / initial_len, dmax, 1.0f);
const float p_arg = fmaf(p, 2.3f, -2.9775f);
const float r_eff = fmaf(-fmaf(p_arg, fmaf(p_arg, fmaf(p_arg, fmaf(p_arg, 0.00833333377f, 0.0416666679f), 0.16666667f), 0.5f), 1.0f) + 1.05f, r, 0.0f);
const bool staganition = no_improve > noImproveThrDim;
if (!(it % kickEveryDim) || staganition) {
const float t_best = map.pointToT(bestQ.data());
const float log_arg = fmaf(dim_f, 1.0f, -1.0f);
const float adaptive_diameter = fmaf(fmaf(log_arg, fmaf(log_arg, fmaf(log_arg, fmaf(log_arg, fmaf(log_arg, 0.164056f, -0.098462f), 0.240884f), -0.351834f), 0.999996f), log_arg), dim > 2 ? fmaf(adaptive_coeff, 0.00475f, 0.0f) : 0.00545f, 0.0f);
int ii = 0;
while (ii < 2) {
const float off = (ii == 0) ? fmaf(adaptive_diameter, 2.0f, 0.0f) : fmaf(-adaptive_diameter, 2.0f, 0.0f);
const float t_seed = fminf(b, fmaxf(a, fmaf(off, 1.0f, t_best)));
const float f_seed = evalAt(t_seed);
IntervalND* J = new IntervalND(fmaf(-adaptive_diameter, 1.0f, t_seed), fmaf(adaptive_diameter, 1.0f, t_seed), f_seed, f_seed);
J->i1 = t_to_idx(fmaf(-adaptive_diameter, 1.0f, t_seed));
J->i2 = t_to_idx(fmaf(adaptive_diameter, 1.0f, t_seed));
J->diam = map.block_diameter(J->i1, J->i2);
J->compute_span_level(map);
J->set_metric(J->diam);
update_pockets_and_Mmax(J);
J->ChangeCharacteristic(fmaf(r_eff, Mmax, 0.0f));
J->R = fmaf(J->R, 2.03f - adaptive_coeff, 0.0f);
H.emplace_back(J);
std::push_heap(H.begin(), H.end(), ComparePtrND);
++ii;
}
no_improve = 0;
}
exp_arg_threshold = fmaf(-exp_arg_threshold * p, 10.0f, 0.0f);
adaptive_coeff_threshold = fmaf(fmaf(exp_arg_threshold, fmaf(exp_arg_threshold, fmaf(exp_arg_threshold, fmaf(exp_arg_threshold, 0.00833333377f, 0.0416666679f), 0.16666667f), 0.5f), 1.0f), adaptive_coeff_addition_threshold, 1.0f); ..." - в приведённом блоке кода рассмотри такой параметр как "adaptive_coeff_threshold" мне важно понять по какому закону он изменяется в зависимости от прогресса "p" при фиксированной размерности - рассмотри например в каких пределах он меняется при фиксированной размерности dim=3, в коде используются следующие аппроксимации: "Для натурального логарифма (ln) можно использовать подобную аппроксимацию, но обычно для логарифма используется ряд Тейлора для ln(1+x) в окрестности 0:

ln(1+x) ≈ x - x²/2 + x³/3 - x⁴/4 + x⁵/5 - ...

Вот функция для ln(1+x) через FMA:

c
float fast_log1p(float x) {
// ln(1+x) для малых x через ряд Тейлора (x в [-0.5, 0.5])
return fmaf(x,
fmaf(x,
fmaf(x,
fmaf(x,
fmaf(x, -0.2f, 0.25f), // -1/5 и +1/4
-0.33333333f), // -1/3
0.5f), // +1/2
-1.0f), // -1
x); // +x
}
А для вычисления ln(x) общего вида:

c
float fast_log(float x) {
// Приведение к диапазону [1,2] и использование ln(x) = ln(1+(x-1))
// Более точный вариант с полиномом Чебышева для ln(x) на [1,2]
const float x_minus_1 = x - 1.0f;

text
return fmaf(x_minus_1, fmaf(x_minus_1, fmaf(x_minus_1, fmaf(x_minus_1, fmaf(x_minus_1, 0.164056f, -0.098462f), 0.240884f), -0.351834f), 0.999996f), x_minus_1);

}
Для более точного вычисления на всем диапазоне положительных чисел обычно используют:

Представление x = 2ⁿ × m, где m ∈ [1, 2)

Вычисление ln(x) = n × ln(2) + ln(m)

Аппроксимацию ln(m) полиномом

Вот более полная версия:

c
float fast_log_full(float x) {
// Представление x = 2^exp * mantissa, где mantissa в [0.5, 1.0)
int exp;
float mantissa = frexpf(x, &exp);

text
// Сдвигаем мантиссу в [1, 2) mantissa *= 2.0f; exp -= 1; // t = mantissa - 1, где t в [0, 1) float t = mantissa - 1.0f; // Аппроксимация ln(1+t) полиномом 5-й степени float ln_mantissa = fmaf(t, fmaf(t, fmaf(t, fmaf(t, fmaf(t, -0.2f, 0.25f), -0.33333333f), 0.5f), -1.0f), t); // Добавляем экспоненту × ln(2) return ln_mantissa + exp * 0.69314718056f; // ln(2)

}
Для log₂(x) (логарифма по основанию 2) можно использовать:

c
float fast_log2(float x) {
// log2(x) ≈ (x-1) - (x-1)²/2 + (x-1)³/3 - (x-1)⁴/4 + ...
const float x_minus_1 = x - 1.0f;

text
return fmaf(x_minus_1, fmaf(x_minus_1, fmaf(x_minus_1, fmaf(x_minus_1, fmaf(x_minus_1, 0.1442695f, -0.0866434f), // коэффициенты для log2 0.2062995f), -0.3465736f), 0.9999934f), x_minus_1);

}" - для логарифмов, и: "float fast_exp(float x) {
return fmaf(x, fmaf(x, fmaf(x, fmaf(x, 0.00833333377f, 0.0416666679f), 0.16666667f), 0.5f), 1.0f);
}" - для экспоненты, также fmaf часто используются для обычного умножения, мне нужно чтобы ты вывел мне математическую запись формулы этого адаптивного коэффициента в зависимости от прогресса, не код, а именно математический вид зависимости и именно для этого коэффициента "adaptive_coeff_threshold" - мне нужен закон изменения

Python

python
import numpy as np, math def fast_log1p_series(x): # x*(x*(x*(x*(x*(-0.2)+0.25)-1/3)+0.5)-1)+x return x*(x*(x*(x*(x*(-0.2)+0.25)-0.33333333)+0.5)-1.0)+x def fast_log_poly(x): # x*(x*(x*(x*(0.164056*x-0.098462)+0.240884)-0.351834)+0.999996)+x return x*(x*(x*(x*(0.164056*x-0.098462)+0.240884)-0.351834)+0.999996)+x def fast_exp5(x): # 1 + x + x^2/2 + x^3/6 + x^4/24 + x^5/120 using Horner return 1.0 + x*(1.0 + x*(0.5 + x*(0.16666667 + x*(0.0416666679 + x*0.00833333377)))) def compute_constants(dim): dim_f=float(dim) e0 = 0.415888308336 / fast_log1p_series(dim_f) # per code log_arg_thr = 0. (-0.012660222510667276, 2.788221607690742, 3.788221607690742)

Python

python
fast_log1p_series(3.0) -32.84999991

Python

python
def T_single(p, dim=3): e0,C,T0=compute_constants(dim) e = -10.0*p*e0 # one-step interpretation return 1.0 + C*fast_exp5(e) ps=np.linspace(0,1,11) vals=[T_single(p) for p in ps] vals[:3], vals[-1] ([3.788221607690742, 3.8237455094200303, 3.859722010608466], 4.164535223444544)

Python

python
dim=3 dimf=float(dim) S=0.5*dimf**2 - (1/3)*dimf**3 + 0.25*dimf**4 - 0.2*dimf**5 S -32.85

Python

python
x=0.1*3-0.105 L = fast_log_poly(x) x,L (0.19500000000000006, 0.3783107463233837)

Python

python
e0,C,T0=compute_constants(3) alpha=-10*e0 alpha,C,T0 (0.12660222510667277, 2.788221607690742, 3.788221607690742)

Python

python
a=alpha C=C coeff = [1 + C*1] # constant term # but for polynomial of p, constant should be 1 + C*1, yes (p^0) terms = [1, a, a**2/2, a**3/6, a**4/24, a**5/120] # multiply by C for p^k for k>=0 and add 1 to constant separately poly = [1 + C*terms[0]] + [C*t for t in terms[1:]] poly [3.788221607690742, 0.35299505962415234, 0.022344980000040152, 0.0009429747293230615, 2.9845674737915517e-05, 7.557057663260233e-07]

Pensamento

Deriving general expression for adaptive coefficient threshold

The polynomial T(p) is approximately 3.7882 + 0.3529951p + 0.0223450p² + 0.000942975p³ + 2.98457e-05p⁴ + 7.55706e-07p⁵. It ranges from 3.7882 to 4.1645 at p=1. We need to extend this for general dimensions. I'll define parameter functions like S(d) and E(z) along with C(d), resulting in adaptive_coeff_threshold(p, d) = 1 + C(d)·E(e(p)).

Explaining the law of adaptive coefficient threshold

The formula for the adaptive coefficient involves a multiplicative update: e_{k+1} = -10 p_k e_k. This leads to the threshold being expressed as 1 + C(d)·E(e_{k+1}). As e_k alternates signs with each iteration, this creates a piecewise function. The parameter p ranges from 0 to 1, and for a fixed dimension, the threshold is a 5th-degree polynomial in p. Let's provide a numeric analysis for dim = 3.

Final expression and constants for the threshold formula

The final expression for the threshold is a 5th-degree polynomial in p: E(α p) * C + 1. For dim=3\text{dim} = 3, using constants like C=2.78822C = 2.78822, e0=0.0126602e_0 = -0.0126602, and values for functions like S(3)S(3), we compute bounds for the threshold. I’ll also mention possible adjustments using full exponentiation and derivatives, depending on the closeness of differences.

Explaining the recursive update and smooth law

In the code:

  • p=1dmaxinitial_lenp = 1 - \frac{d_{\text{max}}}{\text{initial\_len}}.
  • ee is updated recursively: e10pee \leftarrow -10 p e.
  • The threshold is given by 1+adaptive_coeff_addition_thresholdexpapprox(e)1 + \text{adaptive\_coeff\_addition\_threshold} \cdot \exp_{\text{approx}}(e), with a polynomial approximation for the exponential function.

For smoothness, assume constant e0e_0 is used through each iteration to avoid explosive growth as pp increases. Also, coefficients depend on the dimension through recursive and smooth methods. Let me explain both approaches for you.

Thought for 3m 43s

Resposta

В твоём фрагменте adaptive_coeff_threshold вычисляется не напрямую из p, а через промежуточный аргумент экспоненты exp_arg_threshold (обозначу его ee).

1) Что именно делает код в цикле

В начале каждой итерации цикла задаётся прогресс

p  =  1dmaxdinitial(в типичном сценарии p[0,1]).p \;=\; 1-\frac{d_{\max}}{d_{\text{initial}}}\qquad(\text{в типичном сценарии }p\in[0,1]).

Дальше состояние ee обновляется строкой

e10pee \leftarrow -10\,p\,e

(это ровно exp_arg_threshold = (-exp_arg_threshold * p)*10).

И затем считается

adaptive_coeff_threshold  =  1+CExp5(e),\texttt{adaptive\_coeff\_threshold} \;=\; 1 + C\cdot \mathrm{Exp}_5(e),

где C=adaptive_coeff_addition_thresholdC=\texttt{adaptive\_coeff\_addition\_threshold}константа для фиксированной размерности (она вычисляется один раз до цикла), а Exp5\mathrm{Exp}_5 — полиномиальная аппроксимация экспоненты из твоего кода:

Exp5(x)=1+x+x22+x36+x424+x5120.\mathrm{Exp}_5(x)=1+x+\frac{x^2}{2}+\frac{x^3}{6}+\frac{x^4}{24}+\frac{x^5}{120}.

То есть закон изменения в коде буквально такой (как рекурсия):

    ek+1=10pkek,adaptive_coeff_thresholdk+1=1+CExp5(ek+1).    \boxed{\;\;e_{k+1}=-10\,p_k\,e_k,\qquad \texttt{adaptive\_coeff\_threshold}_{k+1}=1+C\cdot \mathrm{Exp}_5(e_{k+1}).\;\;}

Здесь видно важное: значение зависит не только от текущего pkp_k, но и от предыдущего eke_k (т.е. от истории).


2) Если выразить именно как функцию от прогресса pp (самая “чистая” зависимость)

Часто под “зависимостью от прогресса” подразумевают подстановку начального e0e_0 (который зависит только от dim) в формулу, без накопления по итерациям. Тогда:

    adaptive_coeff_threshold(p)=1+CExp5(10e0p).    \boxed{\;\;\texttt{adaptive\_coeff\_threshold}(p)=1+C\cdot \mathrm{Exp}_5(-10\,e_0\,p).\;\;}

Это уже явная функция от pp: по сути “экспоненциальная”, но в реализации — полином 5-й степени по pp (потому что Exp5\mathrm{Exp}_5 — полином, а аргумент линейный по pp).


3) Численно для dim = 3 (в пределах p[0,1]p\in[0,1]) — по тем же полиномам, что в коде

Если взять именно те аппроксимации, которые реально зашиты в строках (и посчитать константы при dim=3), получается:

  • начальный аргумент e00.01266022e_0 \approx -0.01266022
  • C=adaptive_coeff_addition_threshold2.78822161C=\texttt{adaptive\_coeff\_addition\_threshold}\approx 2.78822161
  • α=10e00.12660223\alpha=-10e_0\approx 0.12660223

Тогда

adaptive_coeff_threshold(p)=1+2.78822161Exp5(αp)\texttt{adaptive\_coeff\_threshold}(p) =1+2.78822161\cdot \mathrm{Exp}_5(\alpha p)

и в развёрнутом виде (полином по pp):

adaptive_coeff_threshold(p)3.78822161+0.35299506p+0.02234498p2+0.000942975p3+2.98457105p4+7.55706107p5\boxed{ \texttt{adaptive\_coeff\_threshold}(p)\approx 3.78822161 +0.35299506\,p +0.02234498\,p^2 +0.000942975\,p^3 +2.98457\cdot 10^{-5}\,p^4 +7.55706\cdot 10^{-7}\,p^5 }

Отсюда диапазон при p[0,1]p\in[0,1]:

adaptive_coeff_threshold(0)3.7882,adaptive_coeff_threshold(1)4.1645.\boxed{\texttt{adaptive\_coeff\_threshold}(0)\approx 3.7882,\qquad \texttt{adaptive\_coeff\_threshold}(1)\approx 4.1645.}

То есть при dim=3 он растёт с прогрессом примерно на 0.376\approx 0.376 в этом интервале (если трактовать зависимость “за один шаг” от pp).


Важное замечание про “буквально как в коде”

Если следовать строго рекурсии e10pee\leftarrow -10pe, то при pp не очень маленьких будет смена знака и быстрый рост e|e| по итерациям (зависимость становится “исторической”: от произведения всех прошлых pkp_k). Поэтому, если тебе нужен именно гладкий “закон от прогресса”, наиболее естественная форма — это пункт (2):

1+CExp5(10e0p).1+C\cdot \mathrm{Exp}_5(-10e_0p).

Если покажешь, как именно у тебя меняется dmaxd_{\max} (и значит pkp_k) дальше по коду, я могу записать eke_k и adaptive_coeff_thresholdk\texttt{adaptive\_coeff\_threshold}_k уже как явную функцию от последовательности p0,p1,p_0,p_1,\dots (без предположений).

Compartilhar esta Q&A