Рейтинг: поле 2×3 для дуэли и шкала 1500 в эталонной реализации
Решения владельца по #22: у дуэли поле 2×3 (6 тайлов, 6.6 мира на игрока), шкала — классический Elo (R0 = 1500, D = 400, K 64 → 16; чистый Elo — 96 → 16). Примеры и assert переведены в новую шкалу, сетки K в --grid умножены на 10, |ΔR| League Points в сравнении приводится к шкале 1500. Добавлена проверка, что шкала не влияет на точность, Brier и ρ. #22 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LqSoRj99iwVEH5U5fnZgsd
This commit is contained in:
+74
-52
@@ -6,6 +6,7 @@
|
|||||||
1. Формулы документа в коде (раздел «Эталонная реализация»). #23 может сверять
|
1. Формулы документа в коде (раздел «Эталонная реализация»). #23 может сверять
|
||||||
с ними свою реализацию.
|
с ними свою реализацию.
|
||||||
2. Пошаговые примеры документа с assert на числа: документ и код не разъедутся.
|
2. Пошаговые примеры документа с assert на числа: документ и код не разъедутся.
|
||||||
|
Плюс проверка, что шкала (1500 или прежние 50) не влияет на качество прогноза.
|
||||||
3. Синтетическая лига: игроки со скрытой «истинной» силой, партии на 2–6 человек.
|
3. Синтетическая лига: игроки со скрытой «истинной» силой, партии на 2–6 человек.
|
||||||
Детали партии (раунд, цели, миры, тип победы) выводятся из отрыва
|
Детали партии (раунд, цели, миры, тип победы) выводятся из отрыва
|
||||||
по производительности. На одних и тех же партиях сравниваются текущий League
|
по производительности. На одних и тех же партиях сравниваются текущий League
|
||||||
@@ -29,8 +30,8 @@ from itertools import combinations
|
|||||||
|
|
||||||
# ═══ Правила игры ═══════════════════════════════════════════════════════════════
|
# ═══ Правила игры ═══════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
# Размер поля в тайлах по числу игроков (6 игроков — 4×5, ответ владельца в #22).
|
# Размер поля в тайлах по числу игроков (дуэль — 2×3, 6 игроков — 4×5; уточнения владельца в #22).
|
||||||
BOARD_TILES = {2: 4, 3: 9, 4: 12, 5: 16, 6: 20}
|
BOARD_TILES = {2: 6, 3: 9, 4: 12, 5: 16, 6: 20}
|
||||||
WORLDS_PER_TILE = 2.2
|
WORLDS_PER_TILE = 2.2
|
||||||
BASE_ROUNDS = 8
|
BASE_ROUNDS = 8
|
||||||
# Хоумрул группы: при 5–6 игроках играется 9 раундов.
|
# Хоумрул группы: при 5–6 игроках играется 9 раундов.
|
||||||
@@ -73,11 +74,11 @@ class Match:
|
|||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class Params:
|
class Params:
|
||||||
# Шкала «Elo / 10»: старт 50, разница 40 = шансы 10:1. Классический Elo — R·10 + 1000.
|
# Классическая шкала Elo (решение владельца в PR #65): старт 1500, разница 400 = шансы 10:1.
|
||||||
r0: float = 50.0 # стартовый рейтинг
|
r0: float = 1500.0 # стартовый рейтинг
|
||||||
d: float = 40.0 # масштаб логистики
|
d: float = 400.0 # масштаб логистики
|
||||||
k_max: float = 6.4 # K новичка (0 партий)
|
k_max: float = 64.0 # K новичка (0 партий)
|
||||||
k_min: float = 1.6 # K опытного игрока
|
k_min: float = 16.0 # K опытного игрока
|
||||||
k_games: int = 20 # за сколько партий K линейно спускается от k_max к k_min
|
k_games: int = 20 # за сколько партий K линейно спускается от k_max к k_min
|
||||||
w_table: float = 0.0 # вес размера стола (треб. 2)
|
w_table: float = 0.0 # вес размера стола (треб. 2)
|
||||||
w_tempo: float = 0.0 # вес темпа победы (треб. 1)
|
w_tempo: float = 0.0 # вес темпа победы (треб. 1)
|
||||||
@@ -155,8 +156,8 @@ def pair_multiplier(
|
|||||||
add += p.w_worlds * (wor - p.mu_worlds)
|
add += p.w_worlds * (wor - p.mu_worlds)
|
||||||
|
|
||||||
if p.autocorr and add > 1.0 and not tie:
|
if p.autocorr and add > 1.0 and not tie:
|
||||||
# Поправка FiveThirtyEight (2.2 / (0.001·ΔElo + 2.2)) в шкале Elo/10.
|
# Поправка FiveThirtyEight: 2.2 / (0.001·ΔElo + 2.2).
|
||||||
kappa = 2.2 / (0.01 * (r_a - r_b) + 2.2)
|
kappa = 2.2 / (0.001 * (r_a - r_b) + 2.2)
|
||||||
parts["kappa"] = kappa
|
parts["kappa"] = kappa
|
||||||
add = 1.0 + (add - 1.0) * kappa
|
add = 1.0 + (add - 1.0) * kappa
|
||||||
parts["additive"] = add
|
parts["additive"] = add
|
||||||
@@ -202,6 +203,8 @@ class LeaguePoints:
|
|||||||
"""Текущая система (backend/app/services/scoring.py): сглаженное среднее очков за место."""
|
"""Текущая система (backend/app/services/scoring.py): сглаженное среднее очков за место."""
|
||||||
|
|
||||||
probabilistic = False
|
probabilistic = False
|
||||||
|
# Рейтинг в шкале 0–100; |ΔR| сравнивается с Elo в пересчёте R_Elo = 10·score + 1000.
|
||||||
|
move_scale = 10.0
|
||||||
PRIOR_GAMES = 10
|
PRIOR_GAMES = 10
|
||||||
PRIOR_MEAN = 0.5
|
PRIOR_MEAN = 0.5
|
||||||
|
|
||||||
@@ -232,6 +235,7 @@ class Elo:
|
|||||||
"""Парный многопользовательский Elo; с нулевыми весами — «чистый» Elo."""
|
"""Парный многопользовательский Elo; с нулевыми весами — «чистый» Elo."""
|
||||||
|
|
||||||
probabilistic = True
|
probabilistic = True
|
||||||
|
move_scale = 1.0
|
||||||
|
|
||||||
def __init__(self, p: Params) -> None:
|
def __init__(self, p: Params) -> None:
|
||||||
self.p = p
|
self.p = p
|
||||||
@@ -253,8 +257,8 @@ class Elo:
|
|||||||
|
|
||||||
SIGMA_SKILL = 150.0 # разброс «истинной» силы игроков
|
SIGMA_SKILL = 150.0 # разброс «истинной» силы игроков
|
||||||
SIGMA_PERF = 225.0 # шум производительности в отдельной партии (кубы, карты, ошибки)
|
SIGMA_PERF = 225.0 # шум производительности в отдельной партии (кубы, карты, ошибки)
|
||||||
# Истинная сила в шкале рейтинга: Φ(Δθ/(σ√2)) ≈ логистика с масштабом d=40 при ΔR ≈ 0.093·Δθ.
|
# Истинная сила в шкале рейтинга: Φ(Δθ/(σ√2)) ≈ логистика с масштабом d=400 при ΔR ≈ 0.93·Δθ.
|
||||||
SKILL_TO_RATING = 1.702 * 40 / (math.log(10) * SIGMA_PERF * math.sqrt(2))
|
SKILL_TO_RATING = 1.702 * 400 / (math.log(10) * SIGMA_PERF * math.sqrt(2))
|
||||||
TABLE_SIZES = ((2, 0.45), (3, 0.25), (4, 0.20), (5, 0.07), (6, 0.03))
|
TABLE_SIZES = ((2, 0.45), (3, 0.25), (4, 0.20), (5, 0.07), (6, 0.03))
|
||||||
ELIM_Z = 2.3 # отставание (в σ), при котором игрок может выбыть
|
ELIM_Z = 2.3 # отставание (в σ), при котором игрок может выбыть
|
||||||
ELIM_P = 0.35 # вероятность выбывания при таком отставании
|
ELIM_P = 0.35 # вероятность выбывания при таком отставании
|
||||||
@@ -472,7 +476,7 @@ def evaluate(system, skill: dict[str, float], matches: list[Match], feed=None) -
|
|||||||
games[s.player] = games.get(s.player, 0) + 1
|
games[s.player] = games.get(s.player, 0) + 1
|
||||||
gp = games[s.player]
|
gp = games[s.player]
|
||||||
if gp > 20:
|
if gp > 20:
|
||||||
abs_moves.append(abs(delta[s.player]))
|
abs_moves.append(abs(delta[s.player]) * system.move_scale)
|
||||||
if gp in at_k:
|
if gp in at_k:
|
||||||
at_k[gp][s.player] = system.rating(s.player)
|
at_k[gp][s.player] = system.rating(s.player)
|
||||||
played = [pl for pl in skill if games.get(pl, 0) >= 10]
|
played = [pl for pl in skill if games.get(pl, 0) >= 10]
|
||||||
@@ -530,7 +534,7 @@ def summarize(rows: list[dict]) -> dict[str, tuple[float, float]]:
|
|||||||
|
|
||||||
# ═══ Коэффициенты ═════════════════════════════════════════════════════════════
|
# ═══ Коэффициенты ═════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
PLAIN = Params(k_max=9.6, k_min=1.6) # чистый Elo со своими лучшими K (перебор, этап 1)
|
PLAIN = Params(k_max=96.0, k_min=16.0) # чистый Elo со своими лучшими K (перебор, этап 1)
|
||||||
CLOSENESS = (
|
CLOSENESS = (
|
||||||
("objectives", 1.0),
|
("objectives", 1.0),
|
||||||
("worlds", 0.85),
|
("worlds", 0.85),
|
||||||
@@ -564,67 +568,67 @@ def examples() -> list[tuple[str, str, dict, dict, Match]]:
|
|||||||
five = [Seat("A", 1), Seat("B", 2), Seat("C", 3), Seat("D", 4), Seat("E", 5)]
|
five = [Seat("A", 1), Seat("B", 2), Seat("C", 3), Seat("D", 4), Seat("E", 5)]
|
||||||
six = [Seat(x, i + 1) for i, x in enumerate("ABCDEF")]
|
six = [Seat(x, i + 1) for i, x in enumerate("ABCDEF")]
|
||||||
return [
|
return [
|
||||||
("1a", "Дуэль 60 против 40: побеждает сильный",
|
("1a", "Дуэль 1600 против 1400: побеждает сильный",
|
||||||
{"A": 60, "B": 40}, _vets("A", "B"), duel("A", "B", win_reason="objectives")),
|
{"A": 1600, "B": 1400}, _vets("A", "B"), duel("A", "B", win_reason="objectives")),
|
||||||
("1b", "Дуэль 60 против 40: побеждает слабый",
|
("1b", "Дуэль 1600 против 1400: побеждает слабый",
|
||||||
{"A": 60, "B": 40}, _vets("A", "B"), duel("B", "A", win_reason="objectives")),
|
{"A": 1600, "B": 1400}, _vets("A", "B"), duel("B", "A", win_reason="objectives")),
|
||||||
("2a", "Быстрая победа: 3-й раунд",
|
("2a", "Быстрая победа: 3-й раунд",
|
||||||
{"A": 50, "B": 50}, _vets("A", "B"),
|
{"A": 1500, "B": 1500}, _vets("A", "B"),
|
||||||
Match([Seat("A", 1, 2, 5), Seat("B", 2, 1, 4)], "objectives", round=3)),
|
Match([Seat("A", 1, 2, 5), Seat("B", 2, 1, 4)], "objectives", round=3)),
|
||||||
("2b", "Медленная победа: 8-й раунд",
|
("2b", "Медленная победа: 8-й раунд",
|
||||||
{"A": 50, "B": 50}, _vets("A", "B"),
|
{"A": 1500, "B": 1500}, _vets("A", "B"),
|
||||||
Match([Seat("A", 1, 2, 5), Seat("B", 2, 1, 4)], "objectives", round=8)),
|
Match([Seat("A", 1, 2, 5), Seat("B", 2, 1, 4)], "objectives", round=8)),
|
||||||
("3a", "Первое место в дуэли",
|
("3a", "Первое место в дуэли",
|
||||||
{"A": 50, "B": 50}, _vets("A", "B"), duel("A", "B", win_reason="objectives")),
|
{"A": 1500, "B": 1500}, _vets("A", "B"), duel("A", "B", win_reason="objectives")),
|
||||||
("3b", "Стол на 5: все места",
|
("3b", "Стол на 5: все места",
|
||||||
dict.fromkeys("ABCDE", 50), _vets(*"ABCDE"), Match(five, "objectives")),
|
dict.fromkeys("ABCDE", 1500), _vets(*"ABCDE"), Match(five, "objectives")),
|
||||||
("4a", "Тип победы без деталей: по мирам",
|
("4a", "Тип победы без деталей: по мирам",
|
||||||
{"A": 50, "B": 50}, _vets("A", "B"), duel("A", "B", win_reason="worlds")),
|
{"A": 1500, "B": 1500}, _vets("A", "B"), duel("A", "B", win_reason="worlds")),
|
||||||
("4b", "Тип победы без деталей: по пластику",
|
("4b", "Тип победы без деталей: по пластику",
|
||||||
{"A": 50, "B": 50}, _vets("A", "B"), duel("A", "B", win_reason="plastic")),
|
{"A": 1500, "B": 1500}, _vets("A", "B"), duel("A", "B", win_reason="plastic")),
|
||||||
("4c", "Тип победы без деталей: по ресурсам",
|
("4c", "Тип победы без деталей: по ресурсам",
|
||||||
{"A": 50, "B": 50}, _vets("A", "B"), duel("A", "B", win_reason="resources")),
|
{"A": 1500, "B": 1500}, _vets("A", "B"), duel("A", "B", win_reason="resources")),
|
||||||
("4d", "Самая близкая полная партия: по мирам на 8-м раунде, 2:2 цели, 6:5 миров",
|
("4d", "Самая близкая полная партия: по мирам на 8-м раунде, 2:2 цели, 6:5 миров",
|
||||||
{"A": 50, "B": 50}, _vets("A", "B"),
|
{"A": 1500, "B": 1500}, _vets("A", "B"),
|
||||||
Match([Seat("A", 1, 2, 6), Seat("B", 2, 2, 5)], "worlds", round=8)),
|
Match([Seat("A", 1, 2, 6), Seat("B", 2, 2, 5)], "worlds", round=8)),
|
||||||
("4e", "Разгром: 3-й раунд, 2:0 цели, 8:2 миров",
|
("4e", "Разгром: 3-й раунд, 2:0 цели, 8:2 миров",
|
||||||
{"A": 50, "B": 50}, _vets("A", "B"),
|
{"A": 1500, "B": 1500}, _vets("A", "B"),
|
||||||
Match([Seat("A", 1, 2, 8), Seat("B", 2, 0, 2)], "objectives", round=3)),
|
Match([Seat("A", 1, 2, 8), Seat("B", 2, 0, 2)], "objectives", round=3)),
|
||||||
("5", "Стол на 4: ничья выбывших, раунд 7",
|
("5", "Стол на 4: ничья выбывших, раунд 7",
|
||||||
{"A": 55, "B": 50, "C": 48, "D": 45}, _vets(*"ABCD"),
|
{"A": 1550, "B": 1500, "C": 1480, "D": 1450}, _vets(*"ABCD"),
|
||||||
Match(
|
Match(
|
||||||
[Seat("A", 1, 4, 8), Seat("B", 2, 3, 7),
|
[Seat("A", 1, 4, 8), Seat("B", 2, 3, 7),
|
||||||
Seat("C", 3, 1, 0, eliminated=True), Seat("D", 3, 0, 0, eliminated=True)],
|
Seat("C", 3, 1, 0, eliminated=True), Seat("D", 3, 0, 0, eliminated=True)],
|
||||||
"objectives", round=7,
|
"objectives", round=7,
|
||||||
)),
|
)),
|
||||||
("6a", "Стол на 6, конец на 8-м раунде, хоумрул 9 раундов включён",
|
("6a", "Стол на 6, конец на 8-м раунде, хоумрул 9 раундов включён",
|
||||||
dict.fromkeys("ABCDEF", 50), _vets(*"ABCDEF"),
|
dict.fromkeys("ABCDEF", 1500), _vets(*"ABCDEF"),
|
||||||
Match(six, "objectives", round=8, nine_rounds=True)),
|
Match(six, "objectives", round=8, nine_rounds=True)),
|
||||||
("6b", "Стол на 6, конец на 8-м раунде, хоумрул выключен",
|
("6b", "Стол на 6, конец на 8-м раунде, хоумрул выключен",
|
||||||
dict.fromkeys("ABCDEF", 50), _vets(*"ABCDEF"),
|
dict.fromkeys("ABCDEF", 1500), _vets(*"ABCDEF"),
|
||||||
Match(six, "objectives", round=8, nine_rounds=False)),
|
Match(six, "objectives", round=8, nine_rounds=False)),
|
||||||
("7", "Новичок (0 партий) побеждает ветерана, оба 50",
|
("7", "Новичок (0 партий) побеждает ветерана, оба 1500",
|
||||||
{"A": 50, "B": 50}, {"A": 0, "B": VETERAN}, duel("A", "B", win_reason="objectives")),
|
{"A": 1500, "B": 1500}, {"A": 0, "B": VETERAN}, duel("A", "B", win_reason="objectives")),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# Изменения рейтинга в примерах (округление до 0.001) — те же числа стоят в документе.
|
# Изменения рейтинга в примерах (округление до 0.01) — те же числа стоят в документе.
|
||||||
EXPECTED: dict[str, dict[str, float]] = {
|
EXPECTED: dict[str, dict[str, float]] = {
|
||||||
"1a": {"A": 0.384, "B": -0.384},
|
"1a": {"A": 3.84, "B": -3.84},
|
||||||
"1b": {"B": 1.216, "A": -1.216},
|
"1b": {"B": 12.16, "A": -12.16},
|
||||||
"2a": {"A": 1.148, "B": -1.148},
|
"2a": {"A": 11.18, "B": -11.18},
|
||||||
"2b": {"A": 0.577, "B": -0.577},
|
"2b": {"A": 5.46, "B": -5.46},
|
||||||
"3a": {"A": 0.8, "B": -0.8},
|
"3a": {"A": 8.0, "B": -8.0},
|
||||||
"3b": {"A": 1.1, "B": 0.55, "C": 0.0, "D": -0.55, "E": -1.1},
|
"3b": {"A": 11.0, "B": 5.5, "C": 0.0, "D": -5.5, "E": -11.0},
|
||||||
"4a": {"A": 0.68, "B": -0.68},
|
"4a": {"A": 6.8, "B": -6.8},
|
||||||
"4b": {"A": 0.56, "B": -0.56},
|
"4b": {"A": 5.6, "B": -5.6},
|
||||||
"4c": {"A": 0.48, "B": -0.48},
|
"4c": {"A": 4.8, "B": -4.8},
|
||||||
"4d": {"A": 0.34, "B": -0.34},
|
"4d": {"A": 3.4, "B": -3.4},
|
||||||
"4e": {"A": 1.6, "B": -1.6},
|
"4e": {"A": 16.0, "B": -16.0},
|
||||||
"5": {"A": 0.927, "B": 0.585, "C": -0.778, "D": -0.735},
|
"5": {"A": 9.27, "B": 5.85, "C": -7.78, "D": -7.35},
|
||||||
"6a": {"A": 1.2, "B": 0.72, "C": 0.24, "D": -0.24, "E": -0.72, "F": -1.2},
|
"6a": {"A": 12.0, "B": 7.2, "C": 2.4, "D": -2.4, "E": -7.2, "F": -12.0},
|
||||||
"6b": {"A": 1.029, "B": 0.754, "C": 0.274, "D": -0.206, "E": -0.686, "F": -1.166},
|
"6b": {"A": 10.29, "B": 7.54, "C": 2.74, "D": -2.06, "E": -6.86, "F": -11.66},
|
||||||
"7": {"A": 3.2, "B": -0.8},
|
"7": {"A": 32.0, "B": -8.0},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -632,7 +636,7 @@ def run_examples(p: Params = PROPOSED, verbose: bool = True) -> None:
|
|||||||
for key, title, ratings, games, m in examples():
|
for key, title, ratings, games, m in examples():
|
||||||
trace: list = []
|
trace: list = []
|
||||||
delta = rate_match(ratings, games, m, p, trace)
|
delta = rate_match(ratings, games, m, p, trace)
|
||||||
got = {pl: round(v, 3) for pl, v in delta.items()}
|
got = {pl: round(v, 2) for pl, v in delta.items()}
|
||||||
if verbose:
|
if verbose:
|
||||||
n = len(m.seats)
|
n = len(m.seats)
|
||||||
print(f"\n### Пример {key}. {title}\n")
|
print(f"\n### Пример {key}. {title}\n")
|
||||||
@@ -651,6 +655,23 @@ def run_examples(p: Params = PROPOSED, verbose: bool = True) -> None:
|
|||||||
print("\nВсе примеры совпадают с документом.")
|
print("\nВсе примеры совпадают с документом.")
|
||||||
|
|
||||||
|
|
||||||
|
def check_scale_invariance(seasons: int = 1) -> None:
|
||||||
|
"""Шкала «50 / 40» (R = 10·score + 1000, D и K ÷10) и шкала 1500 дают одинаковые
|
||||||
|
точность, Brier и ρ; изменения рейтинга различаются ровно в 10 раз (документ, 4.1)."""
|
||||||
|
for cfg in SCENARIOS.values():
|
||||||
|
for s in range(seasons):
|
||||||
|
skill, matches = generate_season(
|
||||||
|
cfg["seed"] + s, SEASON_MATCHES, cfg["informative"], cfg["clubs"], cfg["learning"]
|
||||||
|
)
|
||||||
|
for p in (PROPOSED, PLAIN):
|
||||||
|
small = replace(p, r0=(p.r0 - 1000) / 10, d=p.d / 10, k_max=p.k_max / 10, k_min=p.k_min / 10)
|
||||||
|
big, tiny = evaluate(Elo(p), skill, matches), evaluate(Elo(small), skill, matches)
|
||||||
|
for key in ("acc", "brier", "rho", *(f"rho@{k}" for k in CHECKPOINTS)):
|
||||||
|
assert math.isclose(big[key], tiny[key], abs_tol=1e-9), f"шкала: {key}"
|
||||||
|
assert math.isclose(big["move"], 10 * tiny["move"], rel_tol=1e-9), "шкала: |ΔR|"
|
||||||
|
print("Шкала 1500 и шкала 50 дают одинаковые точность, Brier и ρ.")
|
||||||
|
|
||||||
|
|
||||||
# ═══ Сценарии запуска ═════════════════════════════════════════════════════════
|
# ═══ Сценарии запуска ═════════════════════════════════════════════════════════
|
||||||
|
|
||||||
SEASON_MATCHES = 300
|
SEASON_MATCHES = 300
|
||||||
@@ -750,8 +771,8 @@ def grid(seasons: int) -> None:
|
|||||||
print("|---|---|---|---|")
|
print("|---|---|---|---|")
|
||||||
k_res = []
|
k_res = []
|
||||||
for k_games in (10, 20):
|
for k_games in (10, 20):
|
||||||
for k_max in (4.8, 6.4, 9.6, 12.8, 16.0):
|
for k_max in (48.0, 64.0, 96.0, 128.0, 160.0):
|
||||||
for k_min in (1.6, 2.4, 3.2):
|
for k_min in (16.0, 24.0, 32.0):
|
||||||
p = replace(PLAIN, k_max=k_max, k_min=k_min, k_games=k_games)
|
p = replace(PLAIN, k_max=k_max, k_min=k_min, k_games=k_games)
|
||||||
b = brier(p, SCENARIOS)
|
b = brier(p, SCENARIOS)
|
||||||
k_res.append((b, k_max, k_min, k_games))
|
k_res.append((b, k_max, k_min, k_games))
|
||||||
@@ -790,8 +811,8 @@ def grid(seasons: int) -> None:
|
|||||||
print("| k_max | k_min | k_games | autocorr | Brier (сигнальные) | Brier «шум» |")
|
print("| k_max | k_min | k_games | autocorr | Brier (сигнальные) | Brier «шум» |")
|
||||||
print("|---|---|---|---|---|---|")
|
print("|---|---|---|---|---|---|")
|
||||||
for k_games2 in (10, 20):
|
for k_games2 in (10, 20):
|
||||||
for k_max2 in (4.8, 6.4, 8.0):
|
for k_max2 in (48.0, 64.0, 80.0):
|
||||||
for k_min2 in (1.2, 1.6, 2.4):
|
for k_min2 in (12.0, 16.0, 24.0):
|
||||||
for ac in (False, True):
|
for ac in (False, True):
|
||||||
p = replace(PROPOSED, k_max=k_max2, k_min=k_min2, k_games=k_games2, autocorr=ac)
|
p = replace(PROPOSED, k_max=k_max2, k_min=k_min2, k_games=k_games2, autocorr=ac)
|
||||||
print(
|
print(
|
||||||
@@ -829,6 +850,7 @@ def main() -> None:
|
|||||||
args = ap.parse_args()
|
args = ap.parse_args()
|
||||||
print("# Примеры расчётов")
|
print("# Примеры расчётов")
|
||||||
run_examples()
|
run_examples()
|
||||||
|
check_scale_invariance()
|
||||||
if args.grid:
|
if args.grid:
|
||||||
grid(args.grid_seasons)
|
grid(args.grid_seasons)
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user