Punishment update

This commit is contained in:
Efim Beshmenev
2026-07-11 11:11:28 +03:00
parent 5ba553a1d4
commit a8a8f50fbd
10299 changed files with 11355 additions and 4516 deletions
+51 -13
View File
@@ -39,6 +39,7 @@ constexpr int ID_MINUTES = 1003;
constexpr int ID_TOPOLOGY_FROM = 1004;
constexpr int ID_TOPOLOGY_TO = 1005;
constexpr int ID_CHECKPOINT_SECONDS = 1006;
constexpr int ID_SEARCH_MODE = 1007;
constexpr int ID_START = 2001;
constexpr int ID_STOP = 2002;
@@ -59,6 +60,7 @@ HWND g_minutes = nullptr;
HWND g_topology_from = nullptr;
HWND g_topology_to = nullptr;
HWND g_checkpoint_seconds = nullptr;
HWND g_search_mode = nullptr;
std::vector<HWND> g_setting_controls;
HFONT g_ui_font = nullptr;
@@ -569,6 +571,28 @@ HWND make_button(
return control;
}
HWND make_search_mode_combo(HWND parent, int x, int y, int width, int height) {
HWND control = CreateWindowExW(
0,
L"COMBOBOX",
L"",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST,
x,
y,
width,
height,
parent,
reinterpret_cast<HMENU>(static_cast<INT_PTR>(ID_SEARCH_MODE)),
nullptr,
nullptr);
SendMessageW(control, WM_SETFONT, reinterpret_cast<WPARAM>(g_ui_font), TRUE);
SendMessageW(control, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Обычный"));
SendMessageW(control, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Проработка худших"));
SendMessageW(control, CB_SETCURSEL, 0, 0);
g_setting_controls.push_back(control);
return control;
}
void create_controls(HWND window) {
g_title_font = CreateFontW(
24, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
@@ -606,6 +630,9 @@ void create_controls(HWND window) {
g_checkpoint_seconds =
make_number_edit(window, ID_CHECKPOINT_SECONDS, L"30", 592, 110, 125, 27);
make_label(window, L"Режим поиска", 735, 86, 245, 22);
g_search_mode = make_search_mode_combo(window, 735, 110, 245, 180);
make_label(
window,
L"CUDA-устройство выбирается автоматически. Поиск: FP32; финальная проверка кандидатов: DD.",
@@ -688,26 +715,37 @@ void start_search() {
const int seed = make_automatic_seed();
append_log_direct(L"Seed запуска: " + std::to_wstring(seed));
const bool prioritize_worst =
SendMessageW(g_search_mode, CB_GETCURSEL, 0, 0) == 1;
append_log_direct(
prioritize_worst
? L"Режим поиска: проработка худших вариантов."
: L"Режим поиска: обычный.");
const fs::path stop_path = make_stop_path();
const std::wstring title =
L"CUDA-поиск, топологии " + std::to_wstring(topology_from) +
L"" + std::to_wstring(topology_to);
std::vector<std::wstring> args{
L"--global-search",
L"--cuda",
L"--seed", std::to_wstring(seed),
L"--cuda-chains", std::to_wstring(cuda_chains),
L"--cuda-iters", std::to_wstring(cuda_iters),
L"--minutes", std::to_wstring(minutes),
L"--topology-from", std::to_wstring(topology_from),
L"--topology-to", std::to_wstring(topology_to),
L"--checkpoint-seconds", std::to_wstring(checkpoint_seconds),
L"--stop-file", stop_path.wstring(),
L"--global-dir", L"results\\search"
};
if (prioritize_worst) {
args.push_back(L"--prioritize-worst");
}
start_process(
title,
main_exe(),
{
L"--global-search",
L"--cuda",
L"--seed", std::to_wstring(seed),
L"--cuda-chains", std::to_wstring(cuda_chains),
L"--cuda-iters", std::to_wstring(cuda_iters),
L"--minutes", std::to_wstring(minutes),
L"--topology-from", std::to_wstring(topology_from),
L"--topology-to", std::to_wstring(topology_to),
L"--checkpoint-seconds", std::to_wstring(checkpoint_seconds),
L"--stop-file", stop_path.wstring(),
L"--global-dir", L"results\\search"
},
args,
stop_path);
}
+120 -21
View File
@@ -42,7 +42,8 @@
#define NUM_TOPOLOGIES 59
#define DUAL_PROBLEM 0
constexpr int GLOBAL_PLANE_VALUE_COUNT = 36;
constexpr std::uint32_t GLOBAL_OBJECTIVE_VERSION = 3;
constexpr std::uint32_t GLOBAL_OBJECTIVE_VERSION = 4;
constexpr std::uint32_t MIN_COMPATIBLE_ARCHIVE_OBJECTIVE_VERSION = 3;
constexpr int CUDA_SESSION_CACHE_LIMIT = NUM_TOPOLOGIES;
struct StudyOptions {
@@ -86,7 +87,8 @@ struct LocalRepairOptions {
int cuda_chains = 0;
int cuda_iterations = 64;
int checkpoint_seconds = 30;
double degeneracy_weight = 0.02;
double degeneracy_weight = 0.01;
bool prioritize_worst = false;
bool use_cuda = false;
};
@@ -152,7 +154,8 @@ void print_usage(const char* exe_name) {
<< " --cuda-chains <n> Parallel GPU chains. 0 = automatic (default).\n"
<< " --cuda-iters <n> Iterations per short GPU batch. Default: 64\n"
<< " --checkpoint-seconds <n> Durable checkpoint period. Default: 30\n"
<< " --degeneracy-weight <x> Degenerate-geometry penalty. Default: 0.02\n"
<< " --degeneracy-weight <x> Worst-barrier degeneracy penalty. Default: 0.01\n"
<< " --prioritize-worst Give depth priority to the worst current topologies.\n"
<< " --start-planes <p> Continue batch-hunt from a saved .planes sidecar.\n"
<< " --restarts <n> hunt-local restarts. Default: 256\n"
<< " --stagnation <n> Iterations before hunt-local reheat. Default: 2000\n"
@@ -2213,7 +2216,7 @@ struct GlobalMetrics {
bool precise = false;
};
double g_global_degeneracy_weight = 0.02;
double g_global_degeneracy_weight = 0.01;
std::string g_search_device_id = "CPU";
std::uint64_t topology_fingerprint() {
@@ -2446,18 +2449,54 @@ bool add_global_archive_elite(
return retained;
}
double topology_scheduler_severity(const GlobalMetrics& metrics) {
return static_cast<double>(global_defects(metrics)) +
0.10 * static_cast<double>(std::max(metrics.crossings, metrics.intersections)) +
0.01 * static_cast<double>(metrics.crossings);
}
double topology_scheduler_worstness(
const GlobalTopologyState& state,
double best_severity,
double worst_severity
) {
if (!state.has_state) {
return 1.0;
}
const double span = worst_severity - best_severity;
if (span <= 1.0e-9) {
return 0.0;
}
return std::clamp(
(topology_scheduler_severity(state.best) - best_severity) / span,
0.0,
1.0);
}
double topology_bandit_score(
const GlobalTopologyState& state,
std::uint64_t total_pulls,
std::uint64_t current_round,
int best_defects
double best_severity,
double worst_severity,
int best_defects,
bool prioritize_worst
) {
const double exploration = 0.60 * std::sqrt(
std::log(static_cast<double>(total_pulls) + 2.0) /
(static_cast<double>(state.scheduler_pulls) + 1.0));
const double quality_prior = state.has_state
? 0.30 / (1.0 + std::max(0, global_defects(state.best) - best_defects))
: 0.35;
double quality_prior = prioritize_worst ? 0.70 : 0.35;
if (state.has_state) {
if (prioritize_worst) {
quality_prior = 0.65 * topology_scheduler_worstness(
state,
best_severity,
worst_severity);
} else {
quality_prior = 0.30 /
(1.0 + std::max(0, global_defects(state.best) - best_defects));
}
}
const double rounds_since_pull = state.scheduler_last_pull == 0
? static_cast<double>(current_round + 1)
: static_cast<double>(current_round - state.scheduler_last_pull);
@@ -2695,12 +2734,20 @@ GlobalMetrics evaluate_global_state(
const double turn_barrier =
std::log1p(0.002 / std::max(1e-10, min_turn_sine));
const double extent_barrier = 0.10 * std::log1p(max_vertex_norm / 100.0);
const double worst_degeneracy_barrier = std::max({
determinant_barrier,
edge_barrier,
turn_barrier,
extent_barrier});
const double secondary_degeneracy_barriers =
determinant_barrier + edge_barrier + turn_barrier + extent_barrier -
worst_degeneracy_barrier;
metrics.min_plane_determinant = min_plane_determinant;
metrics.relative_min_edge = relative_min_edge;
metrics.min_turn_sine = min_turn_sine;
metrics.max_vertex_norm = max_vertex_norm;
metrics.degeneracy_penalty = g_global_degeneracy_weight *
(determinant_barrier + edge_barrier + turn_barrier + extent_barrier);
(worst_degeneracy_barrier + 0.05 * secondary_degeneracy_barriers);
metrics.geometry_penalty =
0.0010 * std::min(20.0, std::log1p(condition)) +
0.0002 * std::min(20.0, std::log1p(max_vertex_norm)) +
@@ -3306,7 +3353,9 @@ void load_mergeable_checkpoints(
if (record.delta.topology != topology) {
continue;
}
if (record.delta.objective_version != GLOBAL_OBJECTIVE_VERSION ||
if (record.delta.objective_version <
MIN_COMPATIBLE_ARCHIVE_OBJECTIVE_VERSION ||
record.delta.objective_version > GLOBAL_OBJECTIVE_VERSION ||
record.delta.topology_fingerprint != expected_fingerprint) {
incompatible_archive_deltas += 1;
continue;
@@ -3641,13 +3690,14 @@ bool write_run_manifest(
std::cerr << "Cannot write run manifest: " << manifest_path << std::endl;
return false;
}
out << "format\tszilassi-global-search-v3\n"
out << "format\tszilassi-global-search-v4\n"
<< "run_id\t" << identity.run_id << "\n"
<< "node_id\t" << identity.node_id << "\n"
<< "seed\t" << options.seed << "\n"
<< "topology_from\t" << options.topology_from << "\n"
<< "topology_to\t" << options.topology_to << "\n"
<< "backend\t" << (options.use_cuda ? "cuda-fp32" : "cpu-double") << "\n"
<< "objective_version\t" << GLOBAL_OBJECTIVE_VERSION << "\n"
<< "cuda_math\tstandard-fp32\n"
<< "cuda_chains_requested\t" << options.cuda_chains << "\n"
<< "cuda_chains_effective\t" << effective_cuda_chains << "\n"
@@ -3666,8 +3716,12 @@ bool write_run_manifest(
<< "map_elites_max_cells_per_topology\t4096\n"
<< "cem\tdiagonal-weighted,covariance-adaptation:0.18,new-injected-only\n"
<< "spsa\tadam:6,cpu-double,fp32-roundtrip,final-canonical-dd-gate\n"
<< "topology_scheduler\tucb-plus-quality,full-refresh-every-5\n"
<< "topology_scheduler\tucb-plus-reward-plus-staleness,full-refresh-every-5\n"
<< "topology_scheduler_mode\t"
<< (options.prioritize_worst ? "worst-first" : "quality-first") << "\n"
<< "worst_priority_coefficient\t0.65\n"
<< "cpu_iterations_per_trial\t" << options.iterations << "\n"
<< "degeneracy_formula\tworst-plus-0.05-rest\n"
<< "degeneracy_weight\t" << std::setprecision(17)
<< options.degeneracy_weight << "\n";
out.flush();
@@ -4208,6 +4262,8 @@ int global_search_all(const LocalRepairOptions& options) {
<< ", run " << run_identity.run_id
<< ", node " << run_identity.node_id
<< ", threads " << worker_count
<< ", scheduler "
<< (options.prioritize_worst ? "worst-first" : "quality-first")
<< ", minutes " << (options.time_limit_seconds / 60.0)
<< " ===\n";
std::ofstream metrics_log(
@@ -4222,7 +4278,7 @@ int global_search_all(const LocalRepairOptions& options) {
return 2;
}
metrics_log
<< "round\tunix_ns\tphase\ttopology\tdepth\tbandit_score"
<< "round\tunix_ns\tphase\ttopology\tdepth\tbandit_score\tworstness"
<< "\tbefore_C\tbefore_I\tafter_C\tafter_I\timproved\tbackend_error"
<< "\tarchive_cells\tarchive_improvements\tverified\taccounted_fp32_steps"
<< "\tnew_trials\tkernel_ms\ttransfer_ms\twall_ms"
@@ -4243,6 +4299,13 @@ int global_search_all(const LocalRepairOptions& options) {
<< std::endl;
std::cout << "Topologies: " << options.topology_from << ".."
<< options.topology_to << " (" << active_topologies.size() << ")" << std::endl;
std::cout << "Scheduler : "
<< (options.prioritize_worst
? "priority to the worst current topologies"
: "priority to the most promising topologies")
<< std::endl;
std::cout << "Degenerate: worst barrier + 5% of the rest, weight "
<< options.degeneracy_weight << std::endl;
std::cout << "Start : saved MAP-Elites/CEM seeds plus independent random starts"
<< std::endl;
std::cout << "Coordinates: "
@@ -4387,22 +4450,36 @@ int global_search_all(const LocalRepairOptions& options) {
[&](std::uint64_t sum, int item) {
return sum + states[item].scheduler_pulls;
});
double current_best_severity = std::numeric_limits<double>::infinity();
double current_worst_severity = -std::numeric_limits<double>::infinity();
int current_best_defects = std::numeric_limits<int>::max() / 4;
for (int item : active_topologies) {
if (states[item].has_state) {
const double severity = topology_scheduler_severity(states[item].best);
current_best_severity = std::min(current_best_severity, severity);
current_worst_severity = std::max(current_worst_severity, severity);
current_best_defects = std::min(
current_best_defects,
global_defects(states[item].best));
}
}
if (current_best_defects >= std::numeric_limits<int>::max() / 8) {
if (!std::isfinite(current_best_severity)) {
current_best_severity = 0.0;
current_worst_severity = 0.0;
current_best_defects = 0;
}
const double selection_score = topology_bandit_score(
state,
total_scheduler_pulls,
static_cast<std::uint64_t>(completed_rounds + 1),
current_best_defects);
current_best_severity,
current_worst_severity,
current_best_defects,
options.prioritize_worst);
const double selection_worstness = topology_scheduler_worstness(
state,
current_best_severity,
current_worst_severity);
const int round_seed = static_cast<int>(
1 + (static_cast<std::uint64_t>(static_cast<std::uint32_t>(options.seed)) +
static_cast<std::uint64_t>(state.visits + 1) * 15485863ULL +
@@ -4476,6 +4553,7 @@ int global_search_all(const LocalRepairOptions& options) {
<< szilassi::checkpoint::unix_time_ns_now() << "\t"
<< phase << "\t" << topology << "\t" << (depth ? 1 : 0) << "\t"
<< std::setprecision(17) << selection_score << "\t"
<< selection_worstness << "\t"
<< (had_before ? before.crossings : -1) << "\t"
<< (had_before ? before.intersections : -1) << "\t"
<< (state.has_state ? state.best.crossings : -1) << "\t"
@@ -4551,13 +4629,22 @@ int global_search_all(const LocalRepairOptions& options) {
[&](std::uint64_t sum, int topology) {
return sum + states[topology].scheduler_pulls;
});
double best_severity = std::numeric_limits<double>::infinity();
double worst_severity = -std::numeric_limits<double>::infinity();
int best_defects = std::numeric_limits<int>::max() / 4;
for (int topology : active_topologies) {
if (states[topology].has_state) {
best_defects = std::min(best_defects, global_defects(states[topology].best));
const double severity = topology_scheduler_severity(states[topology].best);
best_severity = std::min(best_severity, severity);
worst_severity = std::max(worst_severity, severity);
best_defects = std::min(
best_defects,
global_defects(states[topology].best));
}
}
if (best_defects >= std::numeric_limits<int>::max() / 8) {
if (!std::isfinite(best_severity)) {
best_severity = 0.0;
worst_severity = 0.0;
best_defects = 0;
}
std::unordered_map<int, double> bandit_scores;
@@ -4566,7 +4653,10 @@ int global_search_all(const LocalRepairOptions& options) {
states[topology],
total_scheduler_pulls,
static_cast<std::uint64_t>(completed_rounds + 1),
best_defects);
best_severity,
worst_severity,
best_defects,
options.prioritize_worst);
}
std::sort(ranked.begin(), ranked.end(), [&](int a, int b) {
if (bandit_scores[a] != bandit_scores[b]) {
@@ -4575,9 +4665,16 @@ int global_search_all(const LocalRepairOptions& options) {
if (states[a].has_state != states[b].has_state) {
return states[a].has_state;
}
return states[a].has_state
? better_global_metrics(states[a].best, states[b].best)
: a < b;
if (!states[a].has_state) {
return a < b;
}
if (better_global_metrics(states[a].best, states[b].best)) {
return true;
}
if (better_global_metrics(states[b].best, states[a].best)) {
return false;
}
return a < b;
});
const bool exploration_cycle = cycle % 5 == 4;
@@ -4885,6 +4982,8 @@ int main(int argc, char* argv[]) {
} else if (arg == "--degeneracy-weight" && i + 1 < argc) {
repair_options.degeneracy_weight = std::clamp(
std::atof(argv[++i]), 0.0, 1.0);
} else if (arg == "--prioritize-worst") {
repair_options.prioritize_worst = true;
} else if (arg == "--restarts" && i + 1 < argc) {
repair_options.restarts = std::atoi(argv[++i]);
} else if (arg == "--stagnation" && i + 1 < argc) {