Files
gausse/tests/test_objective.py
jze9 d4affa9574 Физреализм v2: скин/близость (Доуэлл), трение+воздух, паспортные импульсные токи ключей
- physics/ac_resistance.py: R_AC обмотки по Доуэллу на частоте импульса
  1/sqrt(LC) — для толстого провода во многих слоях потери в разы выше DC
- трение о трубку (0.35·m·g) + аэродинамика (0.5·rho·Cd·A·v^2) во всей
  динамике: CPU ОДУ разряда, подлёт к датчику (с событием остановки),
  GPU numpy-путь, fused cupy-ядро, аналитический coast GPU-sweep'а
- SwitchSpec.pulse_current_a: паспортные ITSM/IDM/ICM из даташитов вместо
  generic-множителей; отчёт теперь различает превышение продолжительного
  рейтинга (норма для импульса) и импульсного предела (отбраковка) — фикс
  вводившего в заблуждение флага switch_current_over_limit
- КПД теперь может быть слегка отрицательным (трение съело больше, чем
  добавила слабая катушка) — это честно
- MODEL_VERSION -> gausse-physics-v2

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 00:57:07 +05:00

63 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import random
from gausse.components.database import ComponentDatabase
from gausse.optim.objective import compute_cost_rub, decoded_summary, evaluate
from gausse.optim.search_space import SearchBounds, decode, sample_genome
DB = ComponentDatabase.load()
BOUNDS = SearchBounds()
def test_evaluate_feasible_genome_has_fitness_equal_efficiency():
rng = random.Random(2)
found_feasible = False
for _ in range(50):
genome = sample_genome(DB, BOUNDS, rng)
result = evaluate(genome, DB, BOUNDS)
if result.feasible:
found_feasible = True
assert result.fitness == result.efficiency
# КПД <= 1 всегда; может быть СЛЕГКА отрицательным: трение о трубку
# за время разряда может съесть больше, чем слабая катушка добавила
assert -0.01 <= result.efficiency <= 1.0
assert result.cost_rub > 0
break
assert found_feasible, "ни один из 50 случайных геномов не оказался реализуемым"
def test_evaluate_infeasible_genome_has_negative_fitness_and_reason():
rng = random.Random(9)
genome = sample_genome(DB, BOUNDS, rng)
# индукционный датчик требует скорости >= порог/чувствительность = 5 м/с,
# а старт по умолчанию 3 м/с -- первая ступень обязана провалиться
inductive_idx = next(i for i, s in enumerate(DB.sensors) if s.kind == "inductive")
genome.stages[0].sensor_idx = inductive_idx
result = evaluate(genome, DB, BOUNDS)
assert not result.feasible
assert result.fitness < 0
assert result.reason is not None
assert result.failed_stage_index == 0
def test_compute_cost_rub_is_positive_and_scales_with_stage_count():
rng = random.Random(4)
genome = sample_genome(DB, BOUNDS, rng)
config, _, _ = decode(genome, DB, BOUNDS)
cost = compute_cost_rub(config, DB)
assert cost > 0
genome.stages.append(genome.stages[0])
genome.inter_stage_gaps_m.append(0.05)
config2, _, _ = decode(genome, DB, BOUNDS)
cost2 = compute_cost_rub(config2, DB)
assert cost2 > cost
def test_decoded_summary_uses_real_part_numbers():
rng = random.Random(6)
genome = sample_genome(DB, BOUNDS, rng)
summary = decoded_summary(genome, DB)
assert len(summary["stages"]) == len(genome.stages)
real_wire_ids = {w.part_id for w in DB.wires}
assert all(s["wire"] in real_wire_ids for s in summary["stages"])