Практика численного кода и выбор метода

Заключительный урок: инженерная гигиена численного кода и карта-памятка для выбора метода под задачу.

Тестирование на известном решении — главный приём проверки численного кода: прогнать метод на задаче с заранее известным точным ответом и убедиться, что ошибка падает с ожидаемым порядком.

Гигиена численного кода

Численный код коварен: он почти никогда не падает с ошибкой — он молча возвращает неверное число. Поэтому к нему нужна особая дисциплина. Несколько правил, выстраданных практикой:

  • Тестируй на известных решениях. Прогони интегратор на ∫x² = 1/3, солвер ОДУ на y'=y → eˣ, поиск корня на √2. Если на эталоне неверно — код сломан, и хорошо, что вы это поймали до реальной задачи.
  • Проверяй порядок сходимости. Измельчи сетку вдвое и убедись, что ошибка упала, как обещает порядок (вчетверо для 2-го, в 16 раз для 4-го). Неверный порядок — сигнал бага.
  • Масштабируй данные. Если величины различаются на порядки (метры и нанометры в одной системе), приведи их к сопоставимому масштабу — это улучшает обусловленность и точность.
  • Контролируй погрешность, а не доверяй на глаз. Считай невязку, сравнивай два приближения, оценивай порядок — не верь «красивому» числу без проверки.
import math

# Универсальный тест: проверяем ПОРЯДОК сходимости метода на эталоне
def трапеции(f, a, b, n):
    h = (b - a) / n
    return (f(a)/2 + f(b)/2 + sum(f(a + i*h) for i in range(1, n))) * h

эталон = lambda x: x*x          # ∫x² от 0 до 1 = 1/3 (известный ответ!)
точно = 1/3
prev = None
print("проверка порядка сходимости (ждём ~4x за удвоение):")
for n in [8, 16, 32, 64]:
    ош = abs(трапеции(эталон, 0, 1, n) - точно)
    отношение = (prev / ош) if prev else float('nan')
    print(f"  n={n:3}: ошибка={ош:.3e}  отношение к пред.={отношение:.2f}")
    prev = ош

Вывод:

проверка порядка сходимости (ждём ~4x за удвоение):
  n=  8: ошибка=2.604e-03  отношение к пред.=nan
  n= 16: ошибка=6.510e-04  отношение к пред.=4.00
  n= 32: ошибка=1.628e-04  отношение к пред.=4.00
  n= 64: ошибка=4.069e-05  отношение к пред.=4.00

Отношение ошибок ровно 4.00 — это подтверждает второй порядок трапеций. Если бы оно оказалось 2 вместо 4, это кричало бы о баге (например, неверном весе краевых узлов). Такой тест порядка — лучшая страховка численного кода.

Карта выбора метода

Подведём итог всего курса единой таблицей: какой класс задач каким методом решать.

ЗадачаНадёжный выборКогда быстрее/лучше
Корень уравнения, есть отрезокбисекция (гарантия)Брент / Ньютон (если есть f')
Корень, есть производнаяНьютон (квадратичный)секущие (без f')
Малая плотная СЛАУГаусс с выбором / LUХолецкий (для SPD)
Трёхдиагональная СЛАУпрогонка O(n)
Большая разреженная СЛАУЗейдель / сопряжённые градиенты
Кривая через точкикубический сплайнЛагранж (мало узлов)
Тренд по зашумлённым даннымМНК (регрессия)
Интеграл, гладкая 1D-функцияСимпсон / адаптивныйГаусс (макс. точность)
Интеграл высокой размерностиМонте-Карлоквази-Монте-Карло
ОДУ, обычноеRK4 / адаптивный RK
ОДУ, жёсткоенеявные (BDF, Radau)
Главное собственное значениестепенной методQR (все λ)
Минимум 1D-функциизолотое сечение / Брентпарабол (гладкая)

Как работает под капотом: главные оси выбора

За всем многообразием стоят несколько универсальных вопросов. Есть ли производная? — если да, Ньютон/градиентные методы быстрее; если нет — бисекция, секущие, золотое сечение. Велика ли и разрежена ли система? — малую решают прямо (Гаусс/LU), большую разреженную — итерационно. Гладкая ли функция? — гладкость позволяет методы высокого порядка (Симпсон, RK4, Гаусс); особенности требуют адаптивности или робастности. Какая размерность? — низкая благоволит сеткам, высокая — Монте-Карло. Хорошо ли обусловлена задача? — плохая обусловленность ограничивает достижимую точность независимо от метода. Держа эти оси в голове, вы выберете инструмент осознанно, а не наугад.

Частые ошибки

  • Не тестировать на эталоне. Численный код молча врёт; без проверки на известном решении баги остаются незамеченными до катастрофы.
  • Игнорировать порядок сходимости. Если измельчение сетки не даёт ожидаемого падения ошибки — где-то ошибка в реализации.
  • Брать «крутой» метод вместо подходящего. Ньютон без производной, RK4 на жёсткой задаче, Монте-Карло в 1D — мощный метод не на своём месте проигрывает простому.

Итоги

  • Численный код молча возвращает неверное — тестируйте на задачах с известным точным ответом.
  • Проверяйте порядок сходимости: измельчение сетки должно давать предсказанное падение ошибки.
  • Масштабируйте данные и контролируйте погрешность явно — не доверяйте числу «на глаз».
  • Выбор метода определяют оси: производная, размер/разреженность, гладкость, размерность, обусловленность.
Проверьте себя
1. Почему численный код особенно важно тестировать на известных решениях?
Aон медленно работает
Bон почти никогда не падает с ошибкой, а молча возвращает неверное число
Cон требует много памяти
Dтак быстрее писать код
2. Метод имеет второй порядок. Как должна вести себя ошибка при удвоении числа узлов?
Aупасть вдвое
Bупасть примерно вчетверо
Cвырасти
Dне измениться
3. Какой метод предпочтителен для жёсткого ОДУ?
Aявный RK4
Bнеявные методы (BDF, Radau)
Cметод Эйлера явный
DМонте-Карло