Початок

Після розрахунку ідеальної партії (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 – Графічний розв’язок задачі про визначення оптимального обсягу замовлення

Вельми доцільно є розглянути задачі оптимізації з розривами, інакше кажучи «дискретною оптимізацією».

Якщо у Вас виникли труднощі, то раджу переглянути наступне відео

Сподіваюсь, що цей допис був для Вас корисним

Цей блог розвивається без агресивної реклами завдяки вашому інтересу та підтримці. Кожен ваш внесок допомагає мені інвестувати більше часу в створення якісного контенту, розбір складних тем та популяризацію науки. Підтримати проект можна тут:

Переглядів: