3  Упражнение с Excel. Графичен метод част 2. Сензитивност

3.1 Инструкции за добавяне на Solver в Excel

Solver е добавка (Add-in), която позволява намирането на оптимални решения, при наличието на определени ограничения.

Инструкции стъпка по стъпка:

1. Отворете Excel и отидете на таб File (Файл) в горния ляв ъгъл.

2. Изберете Options (Опции) в самото дъно на менюто.

3. В левия панел на прозореца кликнете върху Add-ins (Добавки).

4. В долната част на прозореца, при менюто Manage (Управление), се уверете, че е избрано Excel Add-ins и натиснете бутона Go... (Напред).

5. В появилия се диалогов прозорец поставете отметка пред Solver Add-in.

6. Потвърдете с OK.

3.2 Задача 1

Фирма произвежда 3 вида изделия – А, Б и В и разполага с 600 единици електроенергия, 480 единици един вид метал и 750 единици от друг вид метал. Разходите за електроенергия и метали са дадени в следната таблица:

Ресурси / Продукти А Б В
Ел. енергия 3 3 3
Метал 1 3 2 1
Метал 2 4 1 2

Цената на продукт А е 9 единици, на продукт Б – 8 единици, а на продукт В – 4 единици. Формулирайте математическия модел. С помощта на Excel намерете максималния приход, който може да реализира фирмата.

Целева функция: z(x) = 9x_1 + 8x_2 + 4x_3 \xrightarrow{x \in X} max

Ограничения: X: \begin{cases} 3x_1 + 3x_2 + 3x_3 \le 600 \\ 3x_1 + 2x_2 + x_3 \le 480 \\ 4x_1 + x_2 + 2x_3 \le 750 \\ x_j \ge 0, j = 1, 2, 3 \end{cases}

3.3 Постоптимален анализ на решението на двумерната задача

Изследваме всеки ресурс или точно определен(и) ресурс(и) за:


I. Дефицитност II. Допустими граници на изменение III. Ценност, скрита цена
Дали ресурсът се изразходва напълно при производството на оптималния план? В какви граници може да се променя наличното количество ресурс без да се промени характера на решението? Как ще се измени стойността на целевата функция при увеличение в количеството на ресурса (при равни други условия)?

3.4 Задача за чувствителност

Металообработващо предприятие произвежда два вида отливки: стоманени и чугунени. Едно от ограниченията в производствения процес е времето за работа на две от машините, които обработват отливките. Една стоманена отливка изисква 2 часа на първата машина и 1 час на втората машина, докато една чугунена отливка изисква 1 час на първата машина и три часа на втората машина. Всяка от машините може да работи най-много по 8 часа на ден. Печалбата от продажбата на една стоманена отливка е 130 EUR, а от една чугунена отливка - 100 EUR. Целта е да се максимизира общата печалба от производството на отливките.

Какъв производствен план ще препоръчате на предприятието, за да максимизира печалбата си?

Кои ограничения са активни в оптимума?

Управителят на предприятието иска от вас препоръка дали да наеме още една машина от вид 1 за 8 часа на ден срещу 50 евро на час.

Предприятието обмисля дали да въведе нов продукт, за чието производство (за една единица) са нужни по един час от всяка машина. Каква трябва да е печалбата на единица от новия продукт, за да си струва въвеждането му?

В какви интервали могат да варират коефициентите във функцията на печалба без това да промени оптималния производствен план? При анализа варирайте само един от коефициентите, а другите оставете на първоначалните им стойности.

Добавете следното ограничение: за всеки час работа на машина 1 са нужни 15 минути за поддръжка след края на работния ден. За машина 2 са нужни 20 мин. Техническият отдел може да отдели до 4 часа за тази дейност.

Изчислете оптималния производствен план, като съобразите и новото ограничение.

Кои са активните ограничения?

Струва ли си наемането на един допълнителен час за поддръжка на цена от 40 евро на ден?
Покажи
import gurobipy as gp
from gurobipy import GRB

# Create model
model = gp.Model("metal_castings")

# Decision variables: x1 = steel castings, x2 = cast iron castings
x1 = model.addVar(name="steel", lb=0)
x2 = model.addVar(name="cast_iron", lb=0)

# Objective: maximize profit
model.setObjective(130 * x1 + 100 * x2, GRB.MAXIMIZE)

# Constraints
# Machine 1: 2*x1 + 1*x2 <= 8 hours
model.addConstr(2 * x1 + x2 <= 8, "machine_1")

# Machine 2: 1*x1 + 3*x2 <= 8 hours
model.addConstr(x1 + 3 * x2 <= 8, "machine_2")

# model.addConstr((5/6) * x1 + (5/4) * x2 <= 4, "Maintenance")
# Solve
model.optimize()

# Print results
if model.status == GRB.OPTIMAL:
    print(f"Optimal solution found:")
    print(f"Steel castings (x1): {x1.X:.2f}")
    print(f"Cast iron castings (x2): {x2.X:.2f}")
    print(f"Maximum profit: {model.ObjVal:.2f} EUR")

    # Print shadow prices (dual values) for the constraints
    print("\nShadow prices (dual values):")
    for constr in model.getConstrs():
        print(f"{constr.ConstrName}: {constr.Pi:.2f}")

    # Print allowable increases and decreases for the right-hand side of the constraints
    print("\nAllowable increases and decreases for the right-hand side of the constraints:")
    for constr in model.getConstrs():
        print(f"{constr.ConstrName}: Lower = {constr.SARHSLow}, Upper = {constr.SARHSUp}")
Restricted license - for non-production use only - expires 2027-11-29
Gurobi Optimizer version 13.0.1 build v13.0.1rc0 (linux64 - "Ubuntu 24.04.4 LTS")

CPU model: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz, instruction set [SSE2|AVX|AVX2|AVX512]
Thread count: 2 physical cores, 4 logical processors, using up to 4 threads

Optimize a model with 2 rows, 2 columns and 4 nonzeros (Max)
Model fingerprint: 0xc7c8ddaf
Model has 2 linear objective coefficients
Coefficient statistics:
  Matrix range     [1e+00, 3e+00]
  Objective range  [1e+02, 1e+02]
  Bounds range     [0e+00, 0e+00]
  RHS range        [8e+00, 8e+00]

Presolve time: 0.01s
Presolved: 2 rows, 2 columns, 4 nonzeros

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    2.3000000e+32   2.500000e+30   2.300000e+02      0s
       2    5.7600000e+02   0.000000e+00   0.000000e+00      0s

Solved in 2 iterations and 0.01 seconds (0.00 work units)
Optimal objective  5.760000000e+02
Optimal solution found:
Steel castings (x1): 3.20
Cast iron castings (x2): 1.60
Maximum profit: 576.00 EUR

Shadow prices (dual values):
machine_1: 58.00
machine_2: 14.00

Allowable increases and decreases for the right-hand side of the constraints:
machine_1: Lower = 2.666666666666666, Upper = 16.0
machine_2: Lower = 4.0, Upper = 24.0
Покажи
model.addConstr((5/6) * x1 + (5/4) * x2 <= 4, "Maintenance")
model.optimize()

# Print results
if model.status == GRB.OPTIMAL:
    print(f"Optimal solution found:")
    print(f"Steel castings (x1): {x1.X:.2f}")
    print(f"Cast iron castings (x2): {x2.X:.2f}")
    print(f"Maximum profit: {model.ObjVal:.2f} EUR")

    # Print shadow prices (dual values) for the constraints
    print("\nShadow prices (dual values):")
    for constr in model.getConstrs():
        print(f"{constr.ConstrName}: {constr.Pi:.2f}")

    # Print allowable increases and decreases for the right-hand side of the constraints
    print("\nAllowable increases and decreases for the right-hand side of the constraints:")
    for constr in model.getConstrs():
        print(f"{constr.ConstrName}: Lower = {constr.SARHSLow}, Upper = {constr.SARHSUp}")
Gurobi Optimizer version 13.0.1 build v13.0.1rc0 (linux64 - "Ubuntu 24.04.4 LTS")

CPU model: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz, instruction set [SSE2|AVX|AVX2|AVX512]
Thread count: 2 physical cores, 4 logical processors, using up to 4 threads

Optimize a model with 3 rows, 2 columns and 6 nonzeros (Max)
Model has 2 linear objective coefficients
Coefficient statistics:
  Matrix range     [8e-01, 3e+00]
  Objective range  [1e+02, 1e+02]
  Bounds range     [0e+00, 0e+00]
  RHS range        [4e+00, 8e+00]

LP warm-start: use basis

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0    5.7600000e+02   6.666667e-01   0.000000e+00      0s
       1    5.4800000e+02   0.000000e+00   0.000000e+00      0s

Solved in 1 iterations and 0.01 seconds (0.00 work units)
Optimal objective  5.480000000e+02
Optimal solution found:
Steel castings (x1): 3.60
Cast iron castings (x2): 0.80
Maximum profit: 548.00 EUR

Shadow prices (dual values):
machine_1: 47.50
machine_2: 0.00
Maintenance: 42.00

Allowable increases and decreases for the right-hand side of the constraints:
machine_1: Lower = 5.333333333333336, Upper = 9.6
machine_2: Lower = 6.0, Upper = inf
Maintenance: Lower = 3.3333333333333335, Upper = 4.666666666666666