From 6b52ba4660f1184cc78287ab58319d0c42da8204 Mon Sep 17 00:00:00 2001 From: jze9 Date: Mon, 13 Jul 2026 17:03:14 +0500 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=BE=D0=BF=20=D1=81=D0=BA=D0=BE=D1=80?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B5=D0=B9=20=D1=81=D0=BD=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D1=8F=D0=B5=D1=82=D1=81?= =?UTF-8?q?=D1=8F:=20=D1=80=D0=B5=D0=BA=D0=BE=D1=80=D0=B4=20=D1=81=D0=BA?= =?UTF-8?q?=D0=BE=D1=80=D0=BE=D1=81=D1=82=D0=B8=20=D0=BE=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=20=D1=82=D0=BE=D0=B6=D0=B5=20=D0=BF=D0=B8?= =?UTF-8?q?=D1=88=D0=B5=D1=82=D1=81=D1=8F=20=D0=B2=20=D0=B1=D0=B0=D0=B7?= =?UTF-8?q?=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Регрессия выборочной записи (7732577): полная строка писалась только при улучшении КПД лучшего генома острова, а рекордсмены СКОРОСТИ — почти всегда прожорливые геномы с низким КПД (57.8 м/с при 0.5%), которые КПД-рекорд не улучшают. Топ «по скорости» на дашборде застыл на сутки, хотя эволюция продолжала находить всё более быстрые конфигурации (пользователь поймал: «даже случайно никто не стал быстрее лететь»). Теперь на каждом острове отслеживаются ДВА записываемых рекорда — КПД и скорость; это по-прежнему максимум пара строк на остров за поколение. --- src/gausse/optim/evolutionary.py | 18 ++++++++++++++++++ tests/test_evolutionary.py | 12 +++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/gausse/optim/evolutionary.py b/src/gausse/optim/evolutionary.py index 2a6b08a..737ea40 100644 --- a/src/gausse/optim/evolutionary.py +++ b/src/gausse/optim/evolutionary.py @@ -175,6 +175,13 @@ def run_evolution( # строки в базу идут только когда остров улучшился — иначе элитизм # дублировал бы один и тот же геном в топ дашборда каждое поколение written_best_fitness = [float("-inf")] * islands + # СКОРОСТЬ отслеживается отдельно: у дашборда два топа (КПД и + # скорость), а рекордсмены скорости — почти всегда «прожорливые» + # геномы с низким КПД, которые КПД-рекорд не улучшают. Без этого + # трекера топ скоростей замирал навсегда (реальный кейс: после + # перехода на выборочную запись он не обновлялся сутки, пока + # эволюция находила всё новые быстрые геномы) + written_best_velocity = [float("-inf")] * islands for generation in range(n_generations): # все острова — ОДНИМ плоским батчем (жирный батч кормит GPU) @@ -209,6 +216,17 @@ def run_evolution( written_best_fitness[i] = pairs[0][1].fitness queue.put(_best_record(pairs[0][0], pairs[0][1], db, bounds, mode)) recorded.add(id(pairs[0][1])) + # рекорд СКОРОСТИ острова — тоже полной строкой + fastest = max( + (p for p in pairs if p[1].feasible and p[1].exit_velocity_mps is not None), + key=lambda p: p[1].exit_velocity_mps, + default=None, + ) + if fastest is not None and fastest[1].exit_velocity_mps > written_best_velocity[i]: + written_best_velocity[i] = fastest[1].exit_velocity_mps + if id(fastest[1]) not in recorded: + queue.put(_best_record(fastest[0], fastest[1], db, bounds, mode)) + recorded.add(id(fastest[1])) next_population = [copy.deepcopy(pair[0]) for pair in pairs[:elitism]] while len(next_population) < population_size: parent_a = _tournament_select(pairs, rng) diff --git a/tests/test_evolutionary.py b/tests/test_evolutionary.py index f73cc8d..93eb12c 100644 --- a/tests/test_evolutionary.py +++ b/tests/test_evolutionary.py @@ -35,8 +35,9 @@ def test_run_evolution_counts_all_evaluations_but_stores_only_best_rows(tmp_path conn = open_connection(db_path) assert _stats_total(conn) == 12 # счётчики дашборда видят все оценки n_rows = count_runs(conn) - # строк меньше, чем оценок: максимум 1 улучшение на остров на поколение - assert 1 <= n_rows <= 2 + # строк меньше, чем оценок: максимум 2 улучшения (КПД+скорость) на + # остров на поколение + assert 1 <= n_rows <= 4 rows = fetch_runs(conn) assert all(r.search_mode == "evolve" for r in rows) # лучший найденный обязан лежать в базе полной строкой @@ -91,7 +92,8 @@ def test_run_evolution_gpu_batch_mode(tmp_path): assert summary["n_evaluated"] == 120 conn = open_connection(db_path) assert _stats_total(conn) == 120 - assert 1 <= count_runs(conn) <= 3 # 1 остров x 3 поколения, только улучшения + # 1 остров x 3 поколения, максимум 2 улучшения (КПД+скорость) за поколение + assert 1 <= count_runs(conn) <= 6 rows = fetch_runs(conn, limit=5) assert all(r.search_mode.startswith("evolve-gpu") for r in rows) # у сохранённых лучших должна быть посчитана стоимость (GPU-путь @@ -111,5 +113,5 @@ def test_run_evolution_islands(tmp_path): assert summary["n_evaluated"] == 4 * 15 * 3 conn = open_connection(db_path) assert _stats_total(conn) == 4 * 15 * 3 - # максимум одно улучшение на остров на поколение - assert 3 <= count_runs(conn) <= 4 * 3 + # максимум 2 улучшения (КПД+скорость) на остров на поколение + assert 3 <= count_runs(conn) <= 4 * 3 * 2