Parte III:
Algoritmo di Branch-and-Bound
Divide et Impera
Sia
z* = max {cTx : x ∈ S} (1)
un problema di ottimizzazione combinatoria difficile da risolvere.
Domanda: E’ possibile decomporre il problema (1) in una collezione di sottoproblemi tali che
1. ogni nuovo sottoproblema sia facile da risolvere, e
2. le informazioni ottenute risolvendo la collezione di sottoproblemi ci guidino nella ricerca della soluzione ottima di (1)?
Proposizione: Sia S = S1 ∪ S2 ∪… ∪ SK una decomposizione della regione ammissibile S in K sottoinsiemi, e sia zh = max {cTx : x ∈ Sh}, per h = 1,…,K. Allora z* = maxh zh.
Osservazione: Non abbiamo richiesto che la decomposizione sia una partizione (ovvero, che Si ∩ Sj = ∅), ma non abbiamo nemmeno escluso che possa esserlo!
Una tipica rappresentazione dell’approccio divide et impera è tramite un albero di enumerazione.
Divide et Impera
Un esempio
Se S ⊆ {0,1}3, possiamo costruire il seguente albero di enumerazione S
S0
x1=0
S1 x1=1
S00 x2=0
S01 x2=1
S10 x2=0
S11 x2=1
S000 x3=0
S001 x3=1
S010 x3=0
S011 x3=1
S100 x3=0
S101 x3=1
S110 x3=0
S111 x3=1
Le foglie dell’albero corrispondono esattamente ai punti che andremmo a esaminare se potessimo fare un’enumerazione completa.
Osservazione: Costruendo in questo modo l’albero di enumerazione stiamo semplicemente enumerando TUTTI gli insiemi ammissibili!!!!
Per la maggior parte dei problemi è impossibile effettuare una enumerazione completa.
Poiché per un problema di ottimizzazione combinatoria conosciamo i bound “primali” e i bound “duali”, l’idea è quella di utilizzare tali bound per enumerare gli insiemi ammissibili in modo più efficace.
Divide et Impera
Proposizione: Sia S = S1 ∪ S2 ∪.. ∪ SK una decomposizione della regione ammissibile S in K sottoinsiemi, e siano
• zh = max {cTx : x ∈ Sh},
• zhLB un lower bound per zh, e
• zhUB un upper bound per zh
per h = 1, …, K. Allora
• zUB = maxh zhUB è un upper bound per z*, e
• zLB = maxh zhLB è un lower bound per z*.
Divide et Impera
Potatura per ottimalità
S0
z0UB= 27 z0LB=13
Le informazioni su upper e lower bound per il valore ottimo z* permettono di decidere quali nodi dell’albero ha senso continuare ad esaminare per trovare la soluzione ottima.
Poiché z1LB = z1UB = 20, sicuramente z1 = 20. Pertanto, non c’è bisogno di esplorare ulteriormente il nodo S1 che può essere potato per ottimalità.
S2 x1=1
z2UB= 25 z2LB= 15 S1
x1= 0
z1UB= 20 z1LB=20
Potatura per ottimalità
S0
z0UB= 27 z0LB=13
zLB= 20
Ad ogni passo teniamo traccia di un lower bound globale zLB. Per il nodo S0, zLB = z0LB (alternativamente, zLB = -∞).
Per ciascun nodo di ogni livello dell’albero, aggiorniamo il valore di zLB se in corrispondenza di quel nodo abbiamo calcolato un lower bound MIGLIORE (ossia maggiore) di quello corrente.
S2 x1=1
z2UB= 25 z2LB= 15 S1
x1= 0
z1UB= 20 z1LB=20
= zLB
Potatura per bound
S0
z0UB= 27 z0LB=13
S2 x1=1
z2UB= 26 z2LB= 21 S1
x1= 0
z1UB= 20 z1LB= 18
Poiché zLB = 21, la soluzione ottima del problema iniziale ha valore almeno pari a 21. Dal momento che z1UB = 20, sicuramente non è possibile ottenere l’ottimo esplorando il nodo S1. Pertanto, S1 può essere potato per bound.
zLB= 21
= zLB
Potatura per inammissibilità
S0
z0UB= 27 z0LB=13
S2 x1=1
S2 = ∅ S1
x1= 0
z0UB= 20 z0LB= 18
Poiché il sottoproblema associato al nodo S2 è inammissibile, non è possibile ottenere l’ottimo esplorando il nodo S2. Pertanto S2 può essere potato per inammissibilità.
= zLB
zLB= 21
Nessuna potatura
In questo caso non possiamo fare nessuna osservazione che permetta di potare uno dei due nodi in esame e quindi è necessario esplorare sia S1 che S2.
S0
z0UB= 40 z0LB=0
S2 x1=1
z2UB = 37 z2LB = 0 S1
x1= 0
z1UB= 20 z1LB= 18
= zLB
zLB= 18
Procedura di Branch-and-Bound
Tramite l’albero di enumerazione, enumeriamo un insieme di soluzioni “implicitamente” perché alcuni rami dell’albero vengono potati per:
1. ottimalità, oppure 2. bound, oppure 3. inammissibilità.
Siano
• L = lista dei sottoproblemi che devono essere risolti
• Pi = formulazione del sottoproblema associato al nodo Si. L’algoritmo di Branch-and-Bound ha il seguente diagramma di flusso:
Inizializzazione L=S, zLB= - ∞ count = 0;
Test: L = ∅?
Scegli un problema Si dalla lista
Risolvi il Rilassamento Lineare RLi su Pi
Caso 2: Bound
Se Pi ≠ ∅, sia ziUB il valore della soluzione ottima xiUBdi RLi.
Se ziUB< zLB elimina Si per bound, vai a Test
Caso 3: Ottimalità
Se Pi ≠ ∅ e la soluzione ottima xiUB di RLi è intera, allora elimina Si.
Se ziLB> zLB allora zLB =ziLB, vai a Test
Individua una componente frazionaria k di xiUBe ramifica Si aggiungendo ad L Scount+1 = Si ∩ {xk= 0}
Scount+2 = Si ∩ {xk= 1}
count = count + 2
Caso 1: Inammissibilità Se Pi = ∅ elimina Si per inammissibilità, vai a Test
Branch-and-Bound
Esempio
Consideriamo il problema di knapsack
max 30 x1 + 36 x2 + 15 x3 + 11 x4 + 5 x5 + 3 x6
9 x1 + 12 x2 + 6 x3 + 5 x4 + 3 x5 + 2 x6 < 17 (1) x ∈ {0,1}6
La soluzione ottima del Knapsack continuo è
x0UB = (1, 2/3, 0, 0, 0, 0) di valore 54 (z0UB)
Inizializziamo il valore del lower bound uguale al valore di una soluzione ammissibile del problema
x0LB = (1, 0, 0, 0, 0, 0) di valore 30 (z0LB) zLB = 30
Osservazione: Poiché la funzione obiettivo ha coefficienti interi, possiamo scrivere la condizione di potatura per bound (caso 2) come ziUB < zLB.
S0
S1 S2
z1UB= 49.4 z1LB= 45
x2= 0 x2= 1
zLB= 45
z0UB = 54
z0LB = 30 = zLB
z2UB = 52.6 z2LB = 36
S3 S4
x4 = 0 x4= 1
z3UB = 48.33 z3LB = 45
z4UB = 48.5
z4LB = 41 S5 S6
x1 = 0 x1= 1
z5UB = 48.5
z5LB = 36 inammissibilità
×
S7 S8
x5= 0 x5 = 1
S7
z7UB = 48 z7LB = 48
×
zLB = 48 OPT .
z8UB = 47.5 z8LB= 35
bound.
×
S9 S10x3 = 0 x3= 1
z9UB = 46 z9LB = 46
bound .
×
z10UB = 36 z10LB = 36
bound.
×
S11 S12x3=0 x3=1
z11UB = 47 z11LB = 47
OPT .
× ×
inammissibilitàEsercizio 1
Algoritmo di programmazione
dinamica
Programmazione Dinamica
Schema di principio: Dato un problema di OC, P, la Programmazione Dinamica (PD):
1. Risolve un sottoproblema di P all’ottimo.
2. Iterativamente “estende” la soluzione a P.
Proprietà fondamentale (optimal substructure)
Sia KP (N, b) un problema di knapsack con soluzione ottima x*.
Consideriamo il problema di knapsack KP(N \ r, b – ar) che si ottiene da KP eliminando un qualsiasi oggetto r e diminuendo la capacità dello zaino della quantità ar..
La soluzione ottima di KP(r, b–ar) si ottiene da x* semplicemente eliminando la variabile xr .
Esempio
Consideriamo il seguente problema di knapsack:
max 6 x1 + 10 x2 + 12 x3
x1 + 2x2 + 3 x3 < 5 (1) x ∈ {0,1}3
La soluzione ottima è x*(1) = (0, 1, 1), di valore 22.
Consideriamo il problema che si ottiene eliminando l’oggetto 2 e diminuendo la capacità b del corrispondente ingombro a2:
max 6 x1 + 12 x3
x1 + 3 x3 < 5 – 2 = 3 (2) x ∈ {0,1}2
La soluzione ottima è x*(2)=(0, 1), di valore 12.
Osservazione: La soluzione x*(2)= (0, 1) è una “sottosoluzione” di x*(1) = (0, 1, 1), ovvero si ottiene da x*(1) semplicemente eliminando la variabile x2.
Notazione
Siano r e d due interi tali che 1 ≤ r ≤ n, 0 ≤ d ≤ b.
Sia KP (r, d) il problema di knapsack:
max
Σ
cjxjΣ
ajxj < d x∈ {0, 1}rKP (r, d) è un sottoproblema di KP, avente soluzione ottima di valore zr(d).
r
j = 1 r
j = 1
Programmazione dinamica
Con questo formalismo, il valore della soluzione ottima di KP vale zn(b).
Calcolo di zn(b):
1. Calcolo zr(d) per r = {1, …, n}.
2. Per ogni r, calcolo zr(d) per d = {0, …, b}.
Osservazione:
zr(d) si calcola in modo ricorsivo se conosco i valori zr-1(d) per d = {0, …, b}.
Formula ricorsiva
( )
≥
= <
1 1
1 1
0
a d
per c
a d
d per z
Condizione iniziale di ricorsione:
Questa condizione implica:
• Se z
1(d) = 0 ⇒ x
1= 0
• Se z
1(d) = c
1⇒ x
1= 1
Formula ricorsiva
Formula di ricorsione:
La formula implica
•
Se zr(d) = zr-1(d) ⇒ xr = 0 [l’oggetto r NON è stato scelto]•
Se zr(d) = zr-1(d–ar)+cr ⇒ xr = 1 [l’oggetto r E’ stato scelto]zr(d) =
zr–1 (d) se d < ar
max{zr–1 (d), zr–1(d–ar)+cr } se d > ar
Algoritmo e complessità
(b) z
max;
(d) z
; c ) a b ( z max
(d);
z max
) c ) a (d
z (d) (z
b a
d
(d) z
(d) z
1 a
0 d
n 2
m
; c (d)
z b a
d
0;
(d) z
1 a
0 d
n m
m m
1 m
1 m
m m
1 m 1
m
m 1 m m
m
1 1
1
1 1
return else then if
to for
to for
to for
to for
to for
c) a,
b, KP(n,
- DP
=
+
−
=
=
+
−
>
=
=
−
=
=
=
=
=
−
=
−
−
−
−
−
ˆ
Osservazione: La complessità dell’algoritmo è O(nb), ovvero dipende dall’intero b (dimensione dello zaino). In questo caso si dice che l’algoritmo ha complessità pseudo polinomiale.