Technische Universität München Zentrum Mathematik Optimierung

Werbung
Technische Universität München
Zentrum Mathematik
Prof. Dr. P. Gritzmann, Dipl.-Inf. Dipl.-Math. S. Borgwardt, Dr. M. Ritter
Optimierung 2, WS 2008/09
Übungsblatt 10
Aufgabe 10.1
Betrachten Sie das Problem
Subset Sum aus Aufgabe 8.2:
Problem (Subset Sum)
Gegeben: Eine Menge
S = {s1 , ..., sn }
mit
Auftrag: Entscheide, ob eine Teilmenge
si ∈ Z ∀i ∈ {1, ..., n}, β ∈ Z.
S0 ⊂ S
X
existiert, so dass
x = β.
x∈S 0
a) Zeigen Sie, dass
Subset Sum in N P
b) Geben Sie einen Algorithmus an, der
liegt.
Subset Sum
mit dynamischer Optimierung löst
und dazu eine Rückwärtsrekursion verwendet. Beachten Sie den Sonderfall
c) Beweisen Sie, dass
β = 0!
Subset Sum (durch dynamische Optimierung) in pseudo-polynomieller
Zeit gelöst werden kann.
Lösung zu Aufgabe 10.1
a) Als Zertikat benutzen wir eine gegebene Teilmenge
Zeit testen, ob die gegebene Teilmenge sich auf
für
Subset Sum ist.
β
S 0 ⊂ S . Wir können in polynomieller
aufsummiert und damit eine Lösung
b) Bei einer Rückwärtsrekursion bauen wir unseren Entscheidungsschichtgraphen von hinten auf. Wir konstruieren ihn ähnlich wie in der Vorlesung: Jedes Element
si ∈ S
Vi−1 von Knoten. Die Kanten des Graphen verlaufen jeweils zwi0
schen Schichten Vi−1 , Vi und entsprechen den Entscheidungen, ob si für S benutzt wird
oder nicht. Die Knoten in Schicht Vi bezeichnen wir mit vi,j , dabei entspricht j der in
den weiteren Schritten notwendigen Restsumme, d. h. für einen Knoten vi,j ist
X
j=β−
sk
induziert eine Schicht
k≥i+1
sk ∈S 0
Der Index
j
gibt also an, welche Summe die im Folgenden auszuwählenden Elemente
noch haben müssen. Zu einem Element vi,j ∈ Vi unterscheiden wir nun zwei Fälle:
0
Entweder si wird nicht in die Menge S aufgenommen, dann ändert sich beim Übergang
1
Vi nach Vi−1 die Summe j nicht, es gibt also eine Kante zwischen vi−1,j und
vi,j . Alternativ wird si in S 0 aufgenommen, dann verringert sich beim Übergang nach
Vi−1 die Summe um si , das kennzeichnen wir durch eine Kante zwischen vi−1,j−si und
vi,j . Wir beginnen die Rekursion mit einem Knoten t = vn,β und versuchen einen Weg
von t nach s = v0,0 durch den Schichtgraphen zu konstruieren, dieser entspricht dann
0
einem geeigneten S .
von Schicht
Um den Sonderfall
β =0
mitbehandeln zu können, müssen wir identizieren ob bzw.
ψ so, dass
1 auf den aktuellen Knoten addiert wird.
wie viele Elemente wir jeweils für unsere Teilmenge wählen. Dazu setzen wir
für jedes benutzte Element aus
S
ein Wert von
α für jeden neu erreichten Knoten des Graphen.
β
nichtleere Teilmenge geben, so ergibt sich α(s) > 0.
Wir wählen dann jeweils ein maximales
Wir nden auf diesem Weg die Teilmenge mit den meisten Elementen, die sich auf
aufsummiert. Sollte es eine solche
In Pseudocode erhalten wir folgenden Algorithmus für
•
Input:
•
Output:
Subset Sum:
S = {s1 , ..., sn }, β
α(s)
α(s) ≤ 0 ⇒ No-Instance
α(s) > 0 ⇒ Yes-Instance
•
Dene:
V = V0 ∪ ... ∪ Vn ,
where
V0 = {s = v0,0 }, Vn = {t = vn,β }
and
Vi = ∅
otherwise
•
Initialize:
•
For
α(t) = 0, α(s) = −∞.
i ∈ n, ..., 1
For all
do
vi,j ∈ Vi
do
∗
If
vi−1,j ∈
/ Vi−1 , create vi−1,j , Vi−1 ← Vi−1 ∪{vi−1,j } and set α(vi−1,j ) = −∞.
∗
/ Vi−1 , create vi−1,j−si , Vi−1 ← Vi−1 ∪{vi−1,j−si } and set α(vi−1,j−si ) =
vi−1,j−si ∈
−∞.
If
∗ α(vi−1,j ) = max{α(vi−1,j ), α(vi,j )}
∗ α(vi−1,j−si ) = max{α(vi−1,j−si ), α(vi,j ) + 1}
si ,P
SN ⊂ S
≤
x. Wir
die Teilmenge aller positiven
uns Indices
≥
P
x∈SN
x
und
n
P
|si | Knoten: Sei SP ⊂ S
i=1
die Teilmenge aller negativen si , dann reichen
c) In jeder Schicht unseres Graphen gibt es höchstens
Sum :=
führen die innere Schleife pro Schicht also
x∈SP
Sum mal aus und erhalten damit eine
Sum). Sei M ax := | max x|. Da Sum ≤ nM ax, ist
höchstens
x∈S
also pseudo-polynomiell. (Man beachte jedoch, dass
Anzahl von Operationen in O(n ·
2
unsere Laufzeit also in O(n M ax),
Sum
bzw.
M ax
nicht polynomiell,
sondern exponentiell, in der Länge des in Bitdarstellung kodierten Inputs ist.)
2
Aufgabe 10.2
Ein umweltbewuÿter Student möchte zwar weiterhin mit seinem Auto von seinem Wohnheim
in München an die TU nach Garching fahren, dabei aber nicht zuviel Benzin verbrauchen.
G = (V, E) und zwei Knoten s
t (TUM) gegeben. Die Fahrzeiten und den Spritverbrauch je Kante
geben zwei Abbildungen l : E → R≥0 und d : E → N0 (Spritverbrauch fällt nur in ganzzahligen
Einheiten an). Der Student möchte für seine Fahrten einen Gesamtverbrauch von D ∈ N
Die möglichen Verbindungen seien durch einen Digraphen
(Studentenwohnung) und
(einfache Fahrt) nicht überschreiten.
s-t-Weg ohne Beachtung
a) Bestimmen Sie in dem untenstehenden Graphen den kürzesten
des Verbrauchs. Welchen Spritverbrauch erfordert dieser Weg?
b) Sei
ξj (δ)
die Länge eines kürzesten
s-j -Weges,
auf dem höchstens
verbraucht werden. Formulieren Sie eine Rekursion für die
δ
Einheiten Sprit
ξj (δ).
c) Verwenden Sie die Rekursion aus b), um unter Verwendung von dynamischer Optimie-
D die Länge eines kürzesten
D Liter Sprit verbraucht wer-
rung einen Algorithmus zu entwerfen, der für gegebenes
s-t-Weges
bestimmt, auf dem insgesamt nicht mehr als
den. Skizzieren Sie zunächst einen geeigneten Schichtgraphen, denieren Sie Knoten und
Kanten dieses Schichtgraphen und eine passende Stufenkostenfunktion.
d) Lösen Sie mit Ihrem Algorithmus das Problem auf untenstehendem Graphen für
D = 8.
e) Wie hoch ist die Laufzeit Ihres Algorithmus? Bestimmen Sie eine möglichst gute obere
Schranke in Abhängigkeit von den Gröÿen im Input.
5/3
2/
1
3/
2/
2
2
4/2
7
6
2
6
6/
5/
3
2/4
1/3
1
4
2
5/
4
2/
3/
2
2
5
Beschriftung der Kanten: lij /dij
Lösung zu Aufgabe 10.2
a) Wir benutzen einen Dijkstra-Algorithmus zur Lösung des Problems, vgl. folgende graphische Darstellung. Als Beschriftung der Knoten verwenden wir hier das jeweilige Knotenlabel
ξ(vi ),
blaue Knoten sind bereits endgültig gelabelt.
3
2/
1
2
1
6
3/
1
1
2/
6
8
11
6
2
2/
2/
2
2/
2
2/
6
3/
11
2
5/
3/
2
2/
2
2/
2
3/
2
1
2
2/
2
6
3/
1
2/
2
2
3/
2/
1
2
3/
2
3/
2/
2/
3/
4/2
2/4
6/
2
11,
2
2
2
4
2/
1/3
5/
4/2
Der kürzeste Weg hat also Länge
5/
5
7
5
4
7
6/
5/
2
2
0
6
3/
2/4
1/3
2/4
6/
5/
5/3
∞
8
5/3
4
3
beträgt
4/2
4
2
4
1/3
0
2
5
2/
5/
2/
3/
3
5/
2
2
7
8
7
2/4
5/
2
4
12
∞
5/3
8
5
4/2
4/2
∞
6/
6
2
4
0
3/
6/
1/3
2/4
∞
5/
2
2/4
3
6/
2
5/3
4
8
2
8
5
2/
4
5/
4
4
5/
4/2
3
0
∞
5
4
2/
2/
1/3
0
1/3
5/3
3
2
2
4/2
5
0
5/
2
6/
2
5/
2/
∞
2/4
∞
1/3
0
2
5/
2/
4
5/3
3
3/
∞
3/
5/3
3
8
der Spritverbrauch entlang des kürzesten Weges
2 + 3 + 2 + 6 = 13.
b) Bei einem Gesamtbudget von
D
überschritten wird, also setzen wir
eignet sich
ξs (0) = 0.
bricht die Rekursion immer ab, wenn das Budget
ξj (δ) = ∞
für alle
δ > D.
Als Beginn der Rekursion
Für die Rekursion verwenden wir
ξj (δ) := min ξj (δ − 1), min [ξk (δ − δkj ) + lkj ]
k∈N (j)
4
Der Schichtgraph kann dann wie folgt deniert werden: In Schicht
Knoten
v0,s,0
entspricht also Knoten
Vk−1
Wenn Schicht
Schicht
Vk
0
bendet sich der
v0,s,0
von 0).
(wir indizieren immer mit Schicht,Knoten,gesamter Spritverbrauch,
s
in Schicht
V0
bei einem bisherigen Gesamtverbrauch
vk−1,i,δ enthält, so nehmen wir in
0
auf mit j ∈ N (i), für die δ ≥ δ + dij gilt. Der Schichtgraph
bekannt ist und einen Knoten
alle Knoten
vk,j,δ0
entspricht also im Wesentlichen dem fürs Kürzeste-Wege-Problem, wir nehmen aber zusätzlich eine Kopie jedes Knotens für jeden möglichen Gesamtverbrauch in die Schichten
mit auf. Eine Kante kennzeichnet jeweils alle möglichen Übergänge von einer Schicht in
die nächste, d. h. eine Kante (vk−1,i,δ , vk,j,δ 0 ) existiert genau dann, wenn (i, j) ∈ E und
δ 0 ≥ δ + dij . Die Stufenkostenfunktion ψk denieren wir als ψ(vk−1,i,δ , (vk−1,i,δ , vk,j,δ0 )) :=
lij . In der letzten Schicht k ∗ benötigen wir dann Knoten für den Originalknoten t ∈ V
und für jeden zulässigen Gesamtverbrauch, also z.B. alle Knoten
vk∗ ,t,δ
mit
0 ≤ δ ≤ D.
c) Der Algorithmus, der sich aus dem oben skizzierten dynamischen Programm ergibt,
kann als Abwandlung des Dijkstra-Algorithmus verstanden werden. Im Unterschied zu
diesem benötigen wir jetzt nicht mehr ein Label (das beim Dijkstra-Algorithmus die
Länge eines kürzesten
s-j -Weges
für jeden Knoten
j∈V
angibt), sondern wir benutzen
ein Label für jeden möglichen Spritverbrauch (das entspricht dem dritten Index der
D+1
Knoten im Schichtgraphen). Wir benutzen also eine Abbildung x : V → R
, xv =
T
(ξv (0), ξv (1), . . . , ξv (D)) . Das Update der Label im Dijkstra-Algorithmus führen wir
unter Berücksichtigung des jeweiligen Kantenverbrauchs durch. Es ergibt sich damit
Algorithmus 1.
Algorithm 1: Dijkstra-Variante für Constrained Shortest Path
Input: Digraph G = (V, E) mit Kantenbewertungen l, d : E → R≥0 , eine natürliche Zahl
D ∈ N0
und
s∈V.
Output: Die Längen xv = (ξv (0), ξv (1), . . . , ξv (D))T
Verbrauch in
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0, 1, . . . , D
und jeden Knoten
S ← {(s, 0), . . . , (s, D)}, xs ← 0 · 1, xv ← ∞ · 1
for v ∈ N (G, s) do
for δ = dsv , . . . , D do
ξv (δ) ← lsv
end
end
while es gibt (v, δ) ∈ V × {0, . . . , D} \ S
∗
∗
mit
eines kürzesten
für jeden
v ∈V.
für alle
v ∈ V \ {s}
ξv (δ) 6= ∞ do
v ∈ V , δ ∈ {0, . . . , D}, so dass
= min {ξv (δ) : (v, δ) ∈ V × {0, . . . , D} \ S}
0
∗
das ξv ∗ (δ ) = ξv ∗ (δ ).
∗
for v ∈ N (G, v ) do
for δ ∈ {δ ∗ + dv∗ ,v , . . . , D} do
ξv (δ) ← min {ξv (δ), ξv∗ (δ ∗ ) + lv∗ ,v }
Wähle
ξv∗ (δ ∗ )
s-v -Weges
end
end
S ← S ∪ {(v ∗ , δ ∗ )}
end
5
und so, dass es kein
δ0 < δ∗
gibt, für
d) Wir stellen die Lösung wieder graphisch dar, endgültige Label sind blau gezeichnet.
Die Label stehen jeweils in den Knoten und sind in der Form
ξv (0), . . . , ξv (8)
zu lesen.
Auÿerdem fassen wir mehrere gleiche Schritte zu einem einzigen zusammen. Beachte: Es
gibt mehrere reine Labelling-Schritte, bei denen keine tatsächliche Verbesserung mehr
stattndet. Das kann im Dijkstra-Algorithmus natürlich auch passieren, hier fällt es aber
stärker auf.
∞, ∞, 3, 3, 3, 3, 3, 3, 3
3/
2/
2
5/
6/
2
5/3
5/3
∞, ∞, ∞, ∞, ∞, 8, 8, 8, 8
5/
1
6/
∞, ∞, 5, 5, 5, 4, 4, 4, 4
2
4/2
6
2/4
1/3
∞, ∞, ∞, ∞, 7, 7, 5, 5, 5
2
6
∞, ∞, ∞, ∞, ∞, ∞, ∞, 8, 8
2/
4
2/
2/4
1/3
4/2
2
∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞
3/
2
2/
2
5/
1
2/
6/
∞, ∞, 3, 3, 3, 3, 3, 3, 3
5/
∞, ∞, ∞, ∞, ∞, 8, 8, 8, 8
2
∞, ∞, 5, 5, 5, 4, 4, 4, 4
2
6
∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞
∞, ∞, ∞, ∞, ∞, ∞, 5, 5, 5
2/
2/4
1/3
4/2
∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞
3/
2
4
2
2
6/
2
5/
5/
2/
2/
0, 0, 0, 0, 0, 0, 0, 0, 0
∞, ∞, ∞, ∞, ∞, 8, 8, 8, 8
2/
∞, ∞, 3, 3, 3, 3, 3, 3, 3
0, 0, 0, 0, 0, 0, 0, 0, 0
∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞
∞, ∞, ∞, ∞, ∞, ∞, 5, 5, 5
2
3/
1
4
∞, ∞, 5, 5, 5, 4, 4, 4, 4
3/
5/3
2/
2
2
3/
4/2
∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞
6
2
∞, ∞, 3, 3, 3, 3, 3, 3, 3
5/
2
∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞
∞, ∞, 5, 5, 5, 5, 5, 5, 5
0, 0, 0, 0, 0, 0, 0, 0, 0
5/
1
2/
4
2/
2
3/
∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞
2/4
1/3
0, 0, 0, 0, 0, 0, 0, 0, 0
5/3
2
∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞
3/
6
∞, ∞, ∞, ∞, 9, 9, 9, 8, 8
∞, ∞, 3, 3, 3, 3, 3, 3, 3
2/
2
5/
2
∞, ∞, ∞, ∞, 7, 7, 5, 5, 5
6/
2
2/
∞, ∞, 3, 3, 3, 3, 3, 3, 3
4/2
5/3
5/
1
4/2
5/3
6
∞, ∞, ∞, ∞, 9, 9, 9, 8, 8
∞, ∞, ∞, ∞, ∞, 8, 8, 7, 7
5/
1
6/
2
4/2
7
2/4
1/3
∞, ∞, ∞, ∞, 7, 7, 5, 5, 5
∞, ∞, 5, 5, 5, 4, 4, 4, 4
∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞
2/
2
2
3/
2
4
2/
2/4
1/3
6/
2
2/
2
∞, ∞, ∞, ∞, ∞, 8, 8, 7, 7
2/
2
5/
∞, ∞, ∞, ∞, 9, 9, 9, 8, 8
∞, ∞, ∞, ∞, 7, 7, 5, 5, 5
∞, ∞, 3, 3, 3, 3, 3, 3, 3
6
2/
4
∞, ∞, 5, 5, 5, 4, 4, 4, 4
∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞
3/
2
2/
2
0, 0, 0, 0, 0, 0, 0, 0, 0
2
6/
∞, ∞, 3, 3, 3, 3, 3, 3, 3
2
5/
1
2
2/
5/
∞, ∞, ∞, ∞, ∞, 8, 8, 7, 7
∞, ∞, ∞, ∞, 7, 7, 5, 5, 5
∞, ∞, 5, 5, 5, 4, 4, 4, 4
0, 0, 0, 0, 0, 0, 0, 0, 0
∞, ∞, ∞, ∞, 9, 9, 9, 8, 8
2/4
1/3
2
6
2/
4
5/
3/
5/3
2/
2
3/
4/2
2
∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞, ∞
3/
2
∞, ∞, 5, 5, 5, 4, 4, 4, 4
0, 0, 0, 0, 0, 0, 0, 0, 0
5/
2/
2/4
1/3
0, 0, 0, 0, 0, 0, 0, 0, 0
∞, ∞, ∞, ∞, ∞, 8, 8, 7, 7
1
4
3/
3/
5/3
2
∞, ∞, ∞, ∞, ∞, ∞, ∞, 13, 13
6
3/
∞, ∞, ∞, ∞, 9, 9, 9, 8, 8
5/3
∞, ∞, 3, 3, 3, 3, 3, 3, 3
2/
2
2/
5/
2
2/
∞, ∞, ∞, ∞, ∞, 8, 8, 7, 7
2/
2/
2
4/2
hat also Länge
e) Die Laufzeit des Algorithmus liegt in
2
∞, ∞, ∞, ∞, ∞, ∞, ∞, 13, 13
6/
2
∞, ∞, 5, 5, 5, 4, 4, 4, 4
D=8
2/4
1/3
∞, ∞, ∞, ∞, 7, 7, 5, 5, 5
2
Der kürzeste Weg bei
5/
1
2/
4
5/
3/
∞, ∞, ∞, ∞, 9, 9, 9, 8, 8
5/3
∞, ∞, 3, 3, 3, 3, 3, 3, 3
0, 0, 0, 0, 0, 0, 0, 0, 0
6
2
4/2
2
∞, ∞, ∞, ∞, ∞, ∞, ∞, 13, 13
6/
2
∞, ∞, 5, 5, 5, 4, 4, 4, 4
2
2/4
∞, ∞, ∞, ∞, 7, 7, 5, 5, 5
1/3
0, 0, 0, 0, 0, 0, 0, 0, 0
5/
1
4
3/
3/
∞, ∞, ∞, ∞, ∞, 8, 8, 7, 7
6
3/
∞, ∞, ∞, ∞, 9, 9, 9, 8, 8
13.
O(n2 D).
Die Updates funktionieren im Grunde
genauso wie im Dijkstra-Algorithmus, müssen aber für jedes der bis zu
D
Label durch-
geführt werden, damit ist der Algorithmus nur noch pseudopolynomiell (da sich
Codierungslänge
O(log2 D)
D
mit
codieren lässt). Wenn man den Dijkstra-Teil geschickt im-
plementiert (z. B. die Labels in einem entsprechend angepassten Heap verwaltet), lässt
2
sich diese Schranke noch ein wenig verbessern (genauer gesagt, der n -Anteil), pseudopolynomiell bleibt sie aber trotzdem.
Aufgabe 10.3
Hausaufgabe
Gegeben sei der Graph
G = (V, E, c)
e1
e4
e7
e10
und
= (v1 , v2 ),
= (v2 , v4 ),
= (v4 , v7 ),
= (v5 , v6 ),
mit
V = {v1 , . . . , v8 }, E = {e1 , . . . , e12 },
e2 = (v1 , v3 ),
e5 = (v3 , v6 ),
e8 = (v4 , v8 ),
e11 = (v6 , v7 ),
wobei
e3 = (v1 , v5 ),
e6 = (v3 , v8 ),
e9 = (v5 , v2 ),
e12 = (v7 , v8 ),
(c(e1 ), . . . , c(e12 )) = (28, 2, 1, 9, 24, 27, 8, 7, 8, 26, 8, 7).
Berechnen Sie mit Hilfe des Dijkstra-Algorithmus den kürzesten Weg zwischen den Ecken
und
v8 .
Skizzieren Sie jeden Zwischenschritt grasch!
8
v1
8
27
2
24
3
6
8
26
1
28
8
2
9
4
Lösung zu Aufgabe 10.3
9
7
7
1
5
7
8
10
11
Herunterladen