Grundlagen Operations Research
| Auftrag | Stückerlös | Paletten | Tonnen |
|---|---|---|---|
| 1 | 20 | 1 | 1 |
| 2 | 30 | 1 | 3 |
| Kapazität | 5 | 9 |
Für das Be- und Entladen fallen 5 EUR pro Tonne an.
Zieht man die 5 EUR/Tonne ab, ergibt sich je Palette:
Das Controlling empfiehlt, nach Deckungsbeitrag statt Umsatz zu planen.
Die Umsatzerlöse sinken dabei auf EUR und die ungenutzte Ladekapazität steigt auf 4 Tonnen: ein Zielkonflikt.
Die orangefarbene Kante ist komplett DB-optimal: mehrdeutig (V05!).
Frage: Wie lösen wir den Konflikt auf?
Vier Ansätze zur Auflösung: lexikographische Ordnung, Haupt-/Nebenziele, Zielgewichtung, Goal Programming. Maßstab: der Zielerreichungsgrad.
Eine strikte Rangfolge der Ziele
Ziel (Deckungsbeitrag): . Optimal ist die ganze Kante von bis , also gibt es noch Spielraum.
Ziel (Umsatz), aber Deckungsbeitrag beibehalten:
: beide Ziele erfüllt.
Ein Ziel wird optimiert, die übrigen als Mindestanforderung (satisfizierend) formuliert.
Mehrdeutig: Jeder Punkt der Kante von bis hat und mindestens 110 EUR Umsatz.
Alle Ziele gleichrichten (Minimierung ) und mit Gewichten zusammenfassen:
Die Gewichte drücken die relative Bedeutung der Ziele aus.
Umsatz und Deckungsbeitrag gleich gewichtet, :
Erweiterung der Zielgewichtung: Minimiere den Abstand zwischen dem Ideal und dem erreichten Wert .
Frage: Warum dürfen die Beträge einfach wegfallen?
Im zulässigen Bereich gilt für Maximierungsziele stets : der Abstand ist nie negativ.
Für (mit ) heißt das konkret:
Wieder ein gewöhnliches LP: Optimum mit .
Je Ziel eine Restriktion, :
Kein echter Zielkonflikt
Der Punkt erreicht beide Ideale (Umsatz 120, DB 75). Die Ziele konkurrieren in diesem Beispiel also nicht wirklich, deshalb ist bei allen Ansätzen optimal.
Das Be- und Entladen kostet jetzt 8 EUR pro Tonne statt 5:
Ziel 2 bei unveränderten Restriktionen:
Dieses Optimum ist eindeutig, der Umsatz beträgt dort nur 100 EUR.
Kein Punkt erreicht beide Ideale (120 und 60): Die Ziele konkurrieren.
Gleich ausprobieren
Auf der nächsten Folie suchen Sie selbst den Min-Max-Kompromiss: den Plan, bei dem der größere der beiden Abstände zum Ideal am kleinsten ist. Liegt er an einer Ecke?
Im Spiel: Min-Max-Kompromiss auf der Kante, beide Abstände 7,5.
| Ansatz | Lösung | Umsatz | DB |
|---|---|---|---|
| Lexikographisch | 100 | 60 | |
| Haupt-/Nebenziele | 110 | 54 | |
| Zielgewichtung | 120 | 48 | |
| Goal Programming | 120 | 48 | |
| Goal Programming | 112,5 | 52,5 |
Ergebnis
Dieselben Ansätze wie zuvor liefern jetzt unterschiedliche Empfehlungen. Bei einem echten Zielkonflikt müssen Sie den Ansatz selbst wählen.
Zuerst die beiden Einzeloptima , dann der Ausgleich:
using JuMP, HiGHS
# Einzeloptima bestimmen
ideal(c1, c2) = begin
modell = Model(HiGHS.Optimizer); set_silent(modell)
@variable(modell, X[1:2] >= 0)
@objective(modell, Max, c1*X[1] + c2*X[2])
@constraint(modell, X[1] + X[2] <= 5)
@constraint(modell, X[1] + 3X[2] <= 9)
optimize!(modell); objective_value(modell)
endfunction ausgleich(db1, db2) # minimiere max. Abweichung
F1, F2 = ideal(20, 30), ideal(db1, db2) # Umsatz-, DB-Maximum
modell = Model(HiGHS.Optimizer); set_silent(modell)
@variable(modell, X[1:2] >= 0); @variable(modell, Z >= 0)
@constraint(modell, Z + 20X[1] + 30X[2] >= F1)
@constraint(modell, Z + db1*X[1] + db2*X[2] >= F2)
@constraint(modell, X[1] + X[2] <= 5)
@constraint(modell, X[1] + 3X[2] <= 9)
@objective(modell, Min, Z)
optimize!(modell)
wert(v) = round(value(v), digits = 2)
println("X = ", wert.(X), ", Umsatz = ", wert(20X[1] + 30X[2]),
", DB = ", wert(db1*X[1] + db2*X[2]), ", Z* = ", wert(Z))
end
ausgleich(15, 15) # 5 EUR pro Tonne
ausgleich(12, 6) # 8 EUR pro TonneX = [3.0, 2.0], Umsatz = 120.0, DB = 75.0, Z* = 0.0
X = [3.75, 1.25], Umsatz = 112.5, DB = 52.5, Z* = 7.5
16 Gebiete (4×4-Raster) mit Umsatzpotenzialen; 4 mögliche Standorte (Gebiete 2, 8, 9, 15, grau). Wähle genau zwei und ordne jedes Gebiet einem Standort zu.
Frage: Welche Variablen und Restriktionen brauchen wir?
Im Original zusätzlich: Gebiete müssen zusammenhängend sein. Das lassen wir hier weg.
Fairness gegen Kosten
Ein Zielkonflikt, aufzulösen mit Goal Programming (gleichgewichtete relative Abweichungen).
function standortmodell()
modell = Model(HiGHS.Optimizer); set_silent(modell)
@variable(modell, Y[J], Bin); @variable(modell, X[I,J], Bin)
@variable(modell, F1 >= 0)
@constraint(modell, sum(Y[j] for j in J) == 2)
@constraint(modell, [i in I, j in J], X[i,j] <= Y[j])
@constraint(modell, [j in J], X[j,j] == Y[j])
@constraint(modell, [i in I], sum(X[i,j] for j in J) == 1)
@constraint(modell, [j in J],
F1 <= sum(u[i]*X[i,j] for i in I) + sum(u)*(1 - Y[j]))
modell, X, Y, F1, sum(d(i,j)*X[i,j] for i in I, j in J)
endErst die beiden Ideale, jeweils mit demselben Grundmodell:
F1* = 603, F2* = 24
Fair achtet nicht auf Wege, kurz nicht auf Fairness (rechts: eine von mehreren).
Jetzt das angekündigte Goal Programming, minimiere die Summe der relativen Abweichungen von beiden Idealen:
modell, X, Y, F1v, F2v = standortmodell()
@objective(modell, Min,
(F1stern - F1v)/F1stern + (F2v - F2stern)/F2stern)
optimize!(modell)
println("Standorte: ", [j for j in J if value(Y[j]) > 0.5])
println("F1 = ", round(Int, value(F1v)),
" (Ideal ", round(Int, F1stern), "), ",
"F2 = ", round(Int, value(F2v)),
" (Ideal ", round(Int, F2stern), ")")Standorte: [8, 9]
F1 = 602 (Ideal 603), F2 = 24 (Ideal 24)
Beide Ziele bleiben nahe an ihrem Ideal. Der Preis des Kompromisses ist direkt ablesbar.
Fast perfekt ausgewogen und kurz: Der Kompromiss kostet hier fast nichts.
Vorlesung 10: Mehrfache Zielsetzung | Prof. Dr. Knut Haase | Zur Webseite