Після розрахунку ідеальної партії (EOQ) з першої задачі, з’ясувалося, що орендований склад компанії має фізичне обмеження. Максимальний обсяг однієї партії, який можна розмістити на стелажах, становить 250 одиниць. Будь-яке замовлення понад цю норму вимагає оренди додаткового терміналу, що різко підвищує витрати.
Умови задачі: Використовуючи ті самі фінансові показники, що й у попередньому прикладі, знайти найкращу стратегію замовлення, враховуючи, що ми не можемо перевищити ліміт у 250 одиниць.
Вихідні дані: Річна потреба D: 10 000 од.; вартість замовлення K: 40 грн.; вартість утримання h: 5 грн/од; обмеження 1>Q>250.
Завдання: Визначити, наскільки зростуть загальні витрати компанії через неможливість замовити оптимальні 400 одиниць, та візуалізувати «втрачену вигоду».
У цій задачі ми використаємо метод bounded у minimize_scalar, який ідеально підходить для задач із чіткими межами.
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize_scalar
# 1. Параметри задачі
D = 10000
K = 40
h = 5
storage_limit = 250 # Жорстке обмеження складу
def variable_costs(Q, D, K, h):
if Q <= 0: return np.inf
return (D * K) / Q + (h * Q) / 2
# 2. Оптимізація: Без обмежень (Ідеальний варіант)
res_ideal = minimize_scalar(variable_costs, args=(D, K, h), bounds=(1, D), method='bounded')
# 3. Оптимізація: З обмеженням складу (Реальний варіант)
res_constrained = minimize_scalar(variable_costs, args=(D, K, h), bounds=(1, storage_limit), method='bounded')
# Вивід результатів
print(f"--- ПОРІВНЯННЯ СТРАТЕГІЙ ---")
print(f"Ідеальне замовлення (без обмежень): {res_ideal.x:.0f} од. (Витрати: {res_ideal.fun:.2f})")
print(f"Оптимальне замовлення (склад 250 од.): {res_constrained.x:.0f} од. (Витрати: {res_constrained.fun:.2f})")
print(f"Додаткові витрати через обмеження: {res_constrained.fun - res_ideal.fun:.2f} грн/рік")
# 4. Візуалізація обмеження
Q_range = np.linspace(50, 800, 400)
costs = [variable_costs(q, D, K, h) for q in Q_range]
plt.figure(figsize=(12, 7))
plt.plot(Q_range, costs, color='black', lw=2, label='Крива витрат')
# Зафарбовуємо допустиму зону (0 - 250)
plt.axvspan(1, storage_limit, color='green', alpha=0.1, label='Допустима зона (Склад)')
plt.axvline(storage_limit, color='red', linestyle='--', label='Ліміт складу (250 од.)')
# Точки рішень
plt.scatter(res_ideal.x, res_ideal.fun, color='blue', s=100, label='Теоретичний мінімум (400)')
plt.scatter(res_constrained.x, res_constrained.fun, color='red', s=120, marker='X', label='Найкраще доступне рішення (250)')
plt.title('Оптимізація з обмеженням потужності складу', fontsize=14)
plt.xlabel('Обсяг замовлення (Q)')
plt.ylabel('Змінні витрати, грн')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
На рис. 1.6 показано результат виконання проєкту, а на рис. 1.7 графічна візуалізація.

Рисунок 1.6 – Результат виконання проєкту
Як видно із рис. 1.7 в коді ми знайшли додаткові витрати через обмеження.
Оскільки функція витрат T(Q) має форму чаші, будь-яке відхилення від ідеальної точки (дна чаші) призводить до зростання витрат.
Ідеальний сценарій (без обмежень):
Ми знайшли, що при Q* = 400 наші змінні витрати мінімальні:

Реальний сценарій (обмеження складу 1£Q£250):
Оскільки функція T(Q) спадає на всьому проміжку від 1 до 400, то найкраща точка в межах складу – це сама «стіна», тобто Q=250. Рахуємо витрати для цієї точки:

Додаткові витрати:
Це різниця між оптимальним значенням та обмеженнями, тобто


Рисунок 1.7 – Графічний розв’язок задачі про визначення оптимального обсягу замовлення
Вельми доцільно є розглянути задачі оптимізації з розривами, інакше кажучи «дискретною оптимізацією».
Якщо у Вас виникли труднощі, то раджу переглянути наступне відео
Сподіваюсь, що цей допис був для Вас корисним