Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Математические модели

Из книги "Теоретический минимум по Computer Science Distilled", автор Владстон Феррейра Фило.

Математическое моделирование рассматиривается в этом разделе для полноты картины, хотя формально оно является самостоятельной междисциплинарной областью.

Математическое моделирование — это умение перевести бизнес-задачу на язык цифр.

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

Математические модели имеют большое преимущество: их можно приспособить для компьютеров при помощи четко сформулированных математических методов.

Если ваша модель основана на графах, используйте теорию графов. Если она задействует уравнения, используйте алгебру.


Модель: Выбор лучшего кандидата

Для построения модели отлично подходит «Задача о разборчивой невесте».

Сценарий: Невеста ищет лучшего жениха из кандидатов.

  1. Невеста смотрит кандидатов по одному в случайном порядке.
  2. После каждого свидания она должна немедленно решить: станет ли он ей парой или отказать.
  3. Если невеста отказала — вернуться к кандидату уже нельзя.
  4. Если невеста выбрала кого-то — процесс останавливается, остальных она уже не смотрит.

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

Цель: Построить стратегию, которая максимизирует вероятность выбрать самого лучшего кандидата.

Математическое решение

Оптимальная стратегия заключается в разделении процесса на два этапа:

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

Вопрос моделирования: чему должно быть равно ?

Через вычисление предела вероятностей (используя натуральные логарифмы) математики вывели магическое число:

Вывод модели

Чтобы иметь наивысший шанс выбрать лучшее, нужно отклонить первые 37% вариантов, а затем выбрать первого, кто превзойдет всех увиденных.

  • Если у вас 10 кандидатов — посмотрите троих и берите следующего лучшего.
  • Если у вас 100 кандидатов — пропустите 37.

Интересный факт: При такой стратегии вероятность успеха (найма именно самого лучшего из всей сотни) также составляет примерно 37%. Для случайного выбора из 100 человек это очень высокий показатель.

Как Вы считаете, применима ли такая жесткая логика в реальных жизненных ситуациях? В реальности нам выгодней будет не заниматься поиском лучшего с максимальной вероятностью, а выбрать первого подходящего полностью под наши критерии, еще на этапе обучения.

Так мы максимизируем закрытие наших целей, и не будем заниматься поиском идеала, которого могли отфильтровать на этапе обучения.


Модель: Поиск экстремума функции

Загон для скота На ферме содержат два вида домашних животных. У вас есть 100 мотков проволоки для сооружения прямоугольного загона и перегородки внутри него, отделяющей одних животных от других. Как поставить забор, чтобы площадь пастбища была максимальной?

Где:

  • - ширина пастбища
  • - длина пастбища

Сделать площадь максимальной означает использовать всю проволоку, потому мы устанавливаем связь между и , с одной стороны, и 100 мотками, с другой:

Модель Поиск экстремума функции

Подберем и , при которых площадь будет максимальной.

Из уравнения связи (периметра с перегородкой) выразим :

Подставим полученное выражение в формулу площади :

Нахождение максимума. Графиком данной функции является парабола, ветви которой направлены вниз. Максимум находится в её вершине. Чтобы найти его, возьмем производную по и приравняем её к нулю:

Нахождение второй стороны. Теперь найдем оптимальное значение , подставив в уравнение связи:

Ответ:

Для достижения максимальной площади размеры загона должны быть:

  • Ширина (): единиц.
  • Длина (): (или примерно ) единиц.

Максимальная площадь при этом составит:


Модель: «Формула Уилсона» (Оптимальный размер заказа)

Представьте, что вы владелец небольшого завода по производству велосипедов, и вам постоянно нужны комплектующие, например педали. У вас есть два типа издержек, которые противоречат друг другу:

  • Издержки на заказ необходимых педалей. Вам выгоднее заказывать редко, но огромными партиями.
  • Издержки на хранение: Педали нужно где-то хранить. Склад стоит денег. Вам выгоднее заказывать часто, но крошечными партиями, чтобы склад был почти пустым.

Задача: Найти такой размер одной партии заказа комплектующих (), при котором суммарные издержки (доставка + хранение) будут минимальными.

Математическое решение

Если мы запишем это на языке формул, то увидим удивительную вещь: суммарные издержки описываются квадратичной зависимостью от размера заказа (в более сложной интерпретации, или суммой гиперболы и прямой, но принцип поиска минимума такой же, как у вершины параболы).

Пусть:

  • — годовой спрос (сколько всего педалей нам нужно в год);
  • — стоимость одного заказа педалей (фикс за доставку и оформление);
  • — стоимость хранения одной единицы товара в год;
  • — объем одной партии (искомая переменная).

Суммарные издержки состоят из двух частей:

  1. Издержки на заказ: (чем больше партия , тем меньше трат).
  2. Издержки на хранение: (чем больше партия , тем выше средний запас на складе и траты).

Итоговая функция издержек:

Чтобы найти минимум, мы берем производную и приравниваем её к нулю (как при поиске вершины параболы в Вашем примере с загоном):

Модель Формула Уилсона

chart generate
import matplotlib.pyplot as plt
import numpy as np

# Параметры модели
D = 1000  # Годовой спрос
S = 50    # Стоимость заказа
H = 2     # Стоимость хранения

# Диапазон объемов заказа
Q = np.linspace(10, 500, 400)

# Функции издержек
ordering_cost = (D * S) / Q
holding_cost = (H * Q) / 2
total_cost = ordering_cost + holding_cost

# Оптимальная точка (EOQ)
q_opt = np.sqrt((2 * D * S) / H)
tc_min = (D * S / q_opt) + (H * q_opt / 2)

# Построение графика
plt.figure(figsize=(10, 6))
plt.plot(Q, ordering_cost, '--', label='Издержки на заказ (S/Q)', color='blue')
plt.plot(Q, holding_cost, '--', label='Издержки на хранение (H*Q/2)', color='green')
plt.plot(Q, total_cost, label='Суммарные издержки (TC)', color='red', linewidth=2)

# Отметка минимума (аналог вершины)
plt.scatter([q_opt], [tc_min], color='black', zorder=5)
plt.annotate(f'Оптимальный заказ Q* ≈ {int(q_opt)}', xy=(q_opt, tc_min), xytext=(q_opt+20, tc_min+100),
             arrowprops=dict(facecolor='black', shrink=0.05))

plt.title('Моделирование оптимального размера заказа (EOQ)')
plt.xlabel('Размер партии (Q)')
plt.ylabel('Суммарные затраты ($)')
plt.grid(True, linestyle=':', alpha=0.6)
plt.legend()
plt.show()

Это именно тот случай, когда квадратное уравнение (или его аналог при поиске экстремума) экономит компании миллионы, а программист, пишущий логику для ERP-системы, должен понимать, откуда этот взялся в техническом задании.


Модель: Сравнение сортировки вставками и сортировки слиянием

В теории алгоритмов (-нотация) мы часто отбрасываем константы, но в реальности они имеют решающее значение.

Допустим, у нас есть два алгоритма:

  1. Сортировка вставками (Insertion Sort): Имеет сложность , но она очень «легкая» и быстро выполняется на малых данных.
  2. Сортировка слиянием (Merge Sort): Имеет сложность , но она «тяжелая» из-за рекурсии и выделения памяти.

1. Формализация задачи

Представим, что мы замерили время работы на конкретном процессоре и получили следующие функции времени (в микросекундах) от количества элементов :

  • (Квадратичный алгоритм)
  • (Логарифмический алгоритм)

Нам нужно найти точку пересечения — критическое значение , после которого «быстрый» алгоритм действительно станет быстрее.

2. Математическая модель

Чтобы найти эту точку, нам нужно решить уравнение:

Разделим обе части на (при ):

Это трансцендентное уравнение, которое часто сводится к анализу функций, похожих на квадратичные зависимости в определенном диапазоне. Если мы упростим задачу для наглядности (например, сравнивая и ), мы получим классическое квадратное уравнение.

Модель Сравнение сортировки

chart generate
import matplotlib.pyplot as plt
import numpy as np

# Количество элементов
n = np.linspace(1, 350, 400)

# Время выполнения (условные единицы)
t_insertion = 2 * n**2              # Квадратичная сложность
t_merge = 50 * n * np.log2(n + 1)    # Сортировка слиянием

# Поиск точки пересечения (приблизительно)
idx = np.argwhere(np.diff(np.sign(t_insertion - t_merge))).flatten()

plt.figure(figsize=(10, 6))
plt.plot(n, t_insertion, label='Сортировка вставками (2n²)', color='red', linewidth=2)
plt.plot(n, t_merge, label='Сортировка слиянием (50n log n)', color='blue', linewidth=2)

if len(idx) > 0:
    plt.scatter(n[idx], t_insertion[idx], color='black', zorder=5)
    plt.annotate(f'Точка эффективности n ≈ {int(n[idx][0])}', 
                 xy=(n[idx], t_insertion[idx]), 
                 xytext=(n[idx]-40, t_insertion[idx]+2000),
                 arrowprops=dict(facecolor='black', shrink=0.05))

plt.title('Сравнение эффективности алгоритмов')
plt.xlabel('Количество элементов (n)')
plt.ylabel('Время выполнения (мкс)')
plt.grid(True, linestyle=':', alpha=0.6)
plt.legend()
plt.ylim(0, 120000)
plt.show()

На графике Вы увидите:

  1. Зона до : Квадратичный алгоритм (красная линия) находится ниже. Это значит, что для небольших массивов «плохая» сортировка вставками работает быстрее, чем «умная» сортировка слиянием.
  2. Точка пересечения: Здесь их эффективность равна.
  3. Зона после: Квадратичная функция начинает «взлетать» вверх. Здесь и проявляется важность -нотации.

Практический вывод: Именно поэтому в стандартных библиотеках (например, в Java или Python для Timsort) используется гибрид: массив сначала разбивается на мелкие куски, которые сортируются вставками (), а затем они объединяются слиянием (). Программисты рассчитали эту модель и поняли, что на малых парабола выгоднее логарифма.