Vorlesung 10: Mehrfache Zielsetzung
Grundlagen Operations Research
Mehrere Ziele
Zwei Ziele, ein Plan
Erinnerung: das LKW-Beispiel
| 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.
Ziel 1: Umsatz
Deckungsbeiträge
Zieht man die 5 EUR/Tonne ab, ergibt sich je Palette:
Das Controlling empfiehlt, nach Deckungsbeitrag statt Umsatz zu planen.
Ziel 2: Deckungsbeitrag
Die Umsatzerlöse sinken dabei auf EUR und die ungenutzte Ladekapazität steigt auf 4 Tonnen: ein Zielkonflikt.
Der Zielkonflikt
- Umsatz-Optimum: (rot).
- Deckungsbeitrag-Optimum: (orange).
Die orangefarbene Kante ist komplett DB-optimal: mehrdeutig (V05!).
Frage: Wie lösen wir den Konflikt auf?
Arten von Zielkonflikten
- Konkurrierende (konträre) Ziele: sie behindern sich.
- Komplementäre Ziele: sie unterstützen sich.
- Neutrale (orthogonale) Ziele: sie beeinflussen sich nicht.
Vier Ansätze zur Auflösung: lexikographische Ordnung, Haupt-/Nebenziele, Zielgewichtung, Goal Programming. Maßstab: der Zielerreichungsgrad.
Lexikographisch
Ziele nach Wichtigkeit
Eine strikte Rangfolge der Ziele
- Optimiere nur Ziel Lösungsmenge .
- Optimiere Ziel nur auf .
- Optimiere Ziel nur auf , und so weiter.
Anwendung auf das Beispiel
Ziel (Deckungsbeitrag): . Optimal ist die ganze Kante von bis , also gibt es noch Spielraum.
Ziel (Umsatz), aber Deckungsbeitrag beibehalten:
: beide Ziele erfüllt.
Haupt-/Nebenziel
Hauptziel plus Nebenziel
Ein Ziel wird optimiert, die übrigen als Mindestanforderung (satisfizierend) formuliert.
Mehrdeutig: Jeder Punkt der Kante von bis hat und mindestens 110 EUR Umsatz.
Zielgewichtung
Gewichtete Summe
Alle Ziele gleichrichten (Minimierung ) und mit Gewichten zusammenfassen:
Die Gewichte drücken die relative Bedeutung der Ziele aus.
Beispiel
Umsatz und Deckungsbeitrag gleich gewichtet, :
Goal Programming
Abstand zum Ideal
Erweiterung der Zielgewichtung: Minimiere den Abstand zwischen dem Ideal und dem erreichten Wert .
- Summe der gewichteten Abstände: .
- Maximaler gewichteter Abstand: .
- Summe der quadrierten Abstände: .
Ohne Betragsstriche
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 .
Der Min-Max-Ansatz
Je Ziel eine Restriktion, :
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.
Echter Konflikt
Variante: 8 EUR pro Tonne
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 gemeinsames Optimum
- Umsatz-Optimum : DB nur 48.
- DB-Optimum : Umsatz nur 100.
Kein Punkt erreicht beide Ideale (120 und 60): Die Ziele konkurrieren.
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?
Sie sind dran
Die Ansätze im Vergleich
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 |
Welcher Ansatz?
Dieselben Ansätze wie zuvor liefern jetzt unterschiedliche Empfehlungen. Bei einem echten Zielkonflikt müssen Sie den Ansatz selbst wählen.
Kontrolle mit Julia
Goal Programming mit JuMP
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)
endMin-Max-Ansatz mit JuMP
function 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
Standortplanung
Ein Gebietsplanungsproblem
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.
Variablen und Restriktionen
Frage: Welche Variablen und Restriktionen brauchen wir?
- : Standort errichten; : Gebiet Standort .
- Genau zwei Standorte: .
Zuordnung der Gebiete
- Zuordnung nur zu errichteten: ; ein Standort versorgt sein eigenes Gebiet: .
- Jedes Gebiet genau einmal: .
Im Original zusätzlich: Gebiete müssen zusammenhängend sein. Das lassen wir hier weg.
Zwei konkurrierende Ziele
- = kleinstes zugeordnetes Umsatzpotenzial maximieren (ausgewogene Gebiete).
- = gesamte Reisekosten minimieren.
Ein Zielkonflikt, aufzulösen mit Goal Programming (gleichgewichtete relative Abweichungen).
Daten und Entfernungen
using JuMP, HiGHS
u = [68,96,101,114, 42,73,78,34, 68,51,73,52, 51,105,123,77]
J = [2,8,9,15]; I = 1:16
pos(i) = (cld(i,4), mod1(i,4)) # Zeile, Spalte
d(i,j) = abs(pos(i)[1]-pos(j)[1]) + abs(pos(i)[2]-pos(j)[2])Das Grundmodell
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)
endDie Einzeloptima
Erst die beiden Ideale, jeweils mit demselben Grundmodell:
m1, _, _, F1v, _ = standortmodell()
@objective(m1, Max, F1v); optimize!(m1); F1stern = objective_value(m1)
m2, _, _, _, F2v = standortmodell()
@objective(m2, Min, F2v); optimize!(m2); F2stern = objective_value(m2)
println("F1* = ", round(Int, F1stern),
", F2* = ", round(Int, F2stern))F1* = 603, F2* = 24
Die Ideale auf der Karte
Fair achtet nicht auf Wege, kurz nicht auf Fairness (rechts: eine von mehreren).
Der Ausgleich
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.
Der Kompromiss auf der Karte
- Standorte 8 und 9.
- statt 603.
- Reisekosten 24, wie im Ideal.
Fast perfekt ausgewogen und kurz: Der Kompromiss kostet hier fast nichts.
Zusammenfassung
Das Wichtigste auf einen Blick
- Mehrere Ziele erzeugen oft Zielkonflikte.
- Lexikographische Ordnung: Ziele strikt nacheinander optimieren.
- Haupt-/Nebenziele: eines optimieren, andere als Mindestanforderung.
- Zielgewichtung und Goal Programming fassen die Ziele über Gewichte bzw. Abstände zusammen.
- Anwendung: Standortplanung wägt faire Umsätze gegen Reisekosten ab.