Grundlagen Operations Research
Haase u. a. (2016)
Bisher fand der Simplex stets genau eine optimale Lösung. Das ist nicht selbstverständlich:
Idee
Der Simplex meldet jeden Sonderfall selbst. Man muss nur wissen, wo man hinschaut: -Zeile, -Spalte oder Pivotspalte.
Frage: Was fällt Ihnen an Zielfunktion und erster Restriktion auf?
Die Zielfunktion verläuft parallel zur ersten Nebenbedingung, das führt zu einer Besonderheit.
Im Optimaltableau sind die reduzierten Kosten der Nichtbasisvariablen null, ein Basistausch kostet nichts:
| BV | |||||
|---|---|---|---|---|---|
| 0 | 1 | 1 | −1 | 2 | |
| 1 | 0 | 0 | 1 | 2 | |
| 0 | 0 | 1 | 0 | 4 |
| BV | |||||
|---|---|---|---|---|---|
| 1 | 1 | 1 | 0 | 4 | |
| 1 | 0 | 0 | 1 | 2 | |
| 0 | 0 | 1 | 0 | 4 |
Optimal: , , . Der Multiplikator von ist null duale Degeneration.
Nach dem Basistausch ( für ): , , eine zweite optimale Basislösung, gleicher Zielwert.
Die Zielgerade liegt auf der ersten Nebenbedingung.
Mehrere Optima
, und alle Punkte dazwischen sind optimal.
Am Optimum treffen sich drei Restriktionen in einem Punkt, eine Basisvariable wird null.
| BV | ||||||
|---|---|---|---|---|---|---|
| 1 | 0 | 1 | 0 | −1 | 2 | |
| 0 | 0 | −1 | 1 | 1 | 0 | |
| 0 | 1 | 0 | 0 | 1 | 2 | |
| 0 | 0 | 1 | 0 | 1 | 6 |
Basisvariable : eine entartete (degenerierte) Basislösung.
Die gepunktete Restriktion ist redundant; sie läuft durch die optimale Ecke .
Gefahr des Kreisens
Der Simplex kann zwischen Basislösungen desselben Eckpunkts kreisen.
Frage: Sehen Sie den Widerspruch?
und erzwingen . Aber wie merkt das der Simplex?
Die -Zeile erhält eine künstliche Variable: , also -Zeile .
| BV | |||||||
|---|---|---|---|---|---|---|---|
| 1 | 1 | 1 | 0 | 0 | 0 | 4 | |
| 1 | 0 | 0 | −1 | 0 | 1 | 3 | |
| 1 | −1 | 0 | 0 | 1 | 0 | 0 | |
| −1 | −2 | 0 | 0 | 0 | 0 | 0 | |
| −1 | 0 | 0 | 1 | 0 | 0 | −3 |
| BV | |||||||
|---|---|---|---|---|---|---|---|
| 0 | 2 | 1 | 0 | −1 | 0 | 4 | |
| 0 | 1 | 0 | −1 | −1 | 1 | 3 | |
| 1 | −1 | 0 | 0 | 1 | 0 | 0 | |
| 0 | −3 | 0 | 0 | 1 | 0 | 0 | |
| 0 | −1 | 0 | 1 | 1 | 0 | −3 |
| BV | |||||||
|---|---|---|---|---|---|---|---|
| 0 | 1 | 1/2 | 0 | −1/2 | 0 | 2 | |
| 0 | 0 | −1/2 | −1 | −1/2 | 1 | 1 | |
| 1 | 0 | 1/2 | 0 | 1/2 | 0 | 2 | |
| 0 | 0 | 3/2 | 0 | −1/2 | 0 | 6 | |
| 0 | 0 | 1/2 | 1 | 1/2 | 0 | −1 |
-Zeile: unter ; kleinster Quotient Pivot [1].
-Zeile: unter ; Quotienten Pivot [2].
Die -Zeile hat keine negativen Einträge mehr, aber bleibt in der Basis: keine zulässige Lösung.
Alternative: mit multipliziert (). Die Startlösung ist unzulässig, der duale Simplex übernimmt.
| BV | ||||||
|---|---|---|---|---|---|---|
| 1 | 1 | 1 | 0 | 0 | 4 | |
| −1 | 0 | 0 | 1 | 0 | −3 | |
| 1 | −1 | 0 | 0 | 1 | 0 | |
| −1 | −2 | 0 | 0 | 0 | 0 |
| BV | ||||||
|---|---|---|---|---|---|---|
| 0 | 1 | 1 | 1 | 0 | 1 | |
| 1 | 0 | 0 | −1 | 0 | 3 | |
| 0 | −1 | 0 | 1 | 1 | −3 | |
| 0 | −2 | 0 | −1 | 0 | 3 |
| BV | ||||||
|---|---|---|---|---|---|---|
| 0 | 0 | 1 | 2 | 1 | −2 | |
| 1 | 0 | 0 | −1 | 0 | 3 | |
| 0 | 1 | 0 | −1 | −1 | 3 | |
| 0 | 0 | 0 | −3 | −2 | 9 |
ist unzulässig; einziger negativer Koeffizient Pivot [−1].
Jetzt ist unzulässig; wieder nur ein Kandidat Pivot [−1].
ist unzulässig, aber die Zeile hat keinen negativen Koeffizienten, kein zulässiger Basistausch: keine zulässige Lösung.
Beides signalisiert dasselbe: der Lösungsraum ist leer.
Die drei Halbräume haben keine gemeinsame Fläche.
Leere Lösungsmenge
Es gibt keine zulässige Lösung.
Der zulässige Bereich ist nach oben offen, die Zielfunktion kennt keine Schranke.
| BV | |||||
|---|---|---|---|---|---|
| 2 | 0 | 1 | −1 | 8 | |
| 1 | 1 | 0 | −1 | 4 | |
| 1 | 0 | 0 | −2 | 8 |
soll in die Basis, aber alle Koeffizienten der Pivotspalte sind . Es gibt keine Schranke: ist beliebig steigerbar.
Die Zielgerade lässt sich beliebig nach rechts oben schieben.
Keine endliche Lösung
: das Problem ist unbeschränkt.
Die reduzierten Kosten verraten die Mehrdeutigkeit: HiGHS findet die Ecke ; die Nichtbasisvariable hat reduzierte Kosten null, ein Basistausch wäre gratis:
using JuMP, HiGHS
modell = Model(HiGHS.Optimizer); set_silent(modell)
@variable(modell, X1 >= 0); @variable(modell, X2 >= 0)
@objective(modell, Max, X1 + X2)
@constraint(modell, X1 + X2 <= 4)
@constraint(modell, X1 <= 2)
optimize!(modell)
println("X = (", value(X1), ", ", value(X2), "), F* = ",
objective_value(modell))
println("Reduzierte Kosten von X1: ", round(Int, reduced_cost(X1)))X = (0.0, 4.0), F* = 4.0
Reduzierte Kosten von X1: 0
JuMP meldet jeden Sonderfall über den termination_status:
# Unzulässiges Problem
modell = Model(HiGHS.Optimizer); set_silent(modell)
@variable(modell, X1 >= 0); @variable(modell, X2 >= 0)
@objective(modell, Max, X1 + 2X2)
@constraint(modell, X1 + X2 <= 4)
@constraint(modell, X1 >= 3)
@constraint(modell, X1 <= X2)
optimize!(modell)
println("Status: ", termination_status(modell))Status: INFEASIBLE
Status: DUAL_INFEASIBLE
Warum DUAL_INFEASIBLE?
HiGHS meldet Unbeschränktheit über das Dualproblem: Ist das primale Problem unbeschränkt, dann ist sein Dual unzulässig (Vorlesung 4). DUAL_INFEASIBLE bedeutet hier also: unbeschränkt.
Vorlesung 05: Sonderfälle | Zur Webseite