Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(appunti): Advanced and Distributed Algorithms LaTex #53

Merged
merged 32 commits into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c153679
aggiunta latex
TommasoRomani Aug 8, 2023
c3beb26
fix: .devcontainer e template
ncvescera Aug 10, 2023
89776e4
fix: WISP
ncvescera Aug 10, 2023
29b9686
fix: SLS
ncvescera Aug 10, 2023
f9c43a3
fix: Knapsack
ncvescera Aug 10, 2023
d375d84
fix: RNA
ncvescera Aug 10, 2023
7bac983
fix: Pole Cutting
ncvescera Aug 10, 2023
dff0b18
fix: MCP
ncvescera Aug 10, 2023
c747661
fix: OBST
ncvescera Aug 11, 2023
8356f71
fix: SA
ncvescera Aug 11, 2023
b8c590d
fix: Ford Fulkerson
ncvescera Aug 11, 2023
91dedba
fix: FF Patological Example
ncvescera Aug 11, 2023
332fb4f
fix: Fat Flow
ncvescera Aug 11, 2023
8b44a89
fix: Delta Scaling
ncvescera Aug 11, 2023
2645780
fix: Preflow
ncvescera Aug 11, 2023
d66c409
fix: Matching Grafi Bipartiti
ncvescera Aug 11, 2023
4da722a
Aggiornato PDF
ncvescera Aug 11, 2023
d765598
fix: Typo
ncvescera Aug 11, 2023
bfd1f1e
fix: frontmatter
ncvescera Aug 11, 2023
3814c69
Aggiornato PDF
ncvescera Aug 11, 2023
e22a97e
fix: Impaginazione
ncvescera Aug 12, 2023
a09ba5e
fix: Impaginazione e Definizioni
ncvescera Aug 12, 2023
2f3b32e
fix: Impaginazione
ncvescera Aug 12, 2023
1a03c2f
Aggiornato PDF
ncvescera Aug 12, 2023
f2ebe90
Update main.tex
CristianCosci Aug 14, 2023
dc912f0
fix: quote
ncvescera Aug 16, 2023
bdbce4e
Aggiornato PDF
ncvescera Aug 16, 2023
18ca88a
fix: TODO
ncvescera Aug 17, 2023
3b29cd9
fix: TODO
ncvescera Aug 17, 2023
37cbee7
fix: TODO
ncvescera Aug 17, 2023
87fe59c
fix: TODO & Impaginazione
ncvescera Aug 17, 2023
04b2427
Aggiornato PDF
ncvescera Aug 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
\chapter{Designing a Faster Flow Algorithm}

\paragraph{Choosing Good Augmenting Paths}
Nella sezione precedente, abbiamo visto che qualsiasi modo di scegliere
un augmenting path aumenta il valore del flusso, e questo ha portato a
un limite per C sul numero di augmentations, dove
$C = \sum_{e \text{ out of }s} c_e$. Quando $C$ non è molto grande,
questo può essere un limite ragionevole; tuttavia, è molto debole quando
$C$ è grande.\\

L'obiettivo di questo capitolo è mostrare che con una migliore scelta dei
path, possiamo migliorare significativamente questo limite. Una grande
mole di lavoro è stata dedicata alla ricerca di metodi per scegliere
augmenting path nel problema del flusso massimo in modo da minimizzare
il numero di iterazioni. \textbf{Ricordiamo che l'augmentation aumenta
il valore del flusso del percorso selezionato di un valore che è dato
dal bottleneck; quindi, è un buon approccio quello di scegliere percorsi
con una grande capacità di bottleneck.}

\begin{myblockquote}
\textbf{L'approccio migliore è quello di selezionare il percorso che ha
il bottleneck di maggiore capacità.}
\end{myblockquote}

Tuttavia, trovare tali percorsi può rallentare di parecchio ogni singola
iterazione. Eviteremo questo rallentamento non preoccupandoci di
selezionare il percorso che ha esattamente la maggiore capacità di
bottleneck. Invece, manterremo un cosiddetto \textbf{scaling parameter}
$\Delta$ e cercheremo percorsi che abbiano un bottleneck di capacità
di almeno $\Delta$. Sia $G_f(\Delta)$ il sottoinsieme del grafo
residuo costituito solo da archi con capacità residua di almeno
$\Delta$. Lavoreremo con valori di $\Delta$ che sono potenze di 2.\\

L'algoritmo è il seguente.

\section{Scaling Max-Flow}


\begin{lstlisting}[language=Python, mathescape=true]
Initially f (e) = 0 for all e in G
Initially set $\Delta$ to be the largest power of 2 that is no larger than the maximum capacity out of s: $\Delta$ $\leq$ max(e out of s ce)

While $\Delta$ $\geq$ 1
While there is an s-t path in the graph Gf($\Delta$)
Let P be a simple s-t path in Gf($\Delta$)
f' = augment(f , P)
Update f to be f' and update Gf ($\Delta$)
Endwhile
$\Delta$ = $\Delta$/2
Endwhile

Return f
\end{lstlisting}

\subsection{Analyzing the Algorithm}

Innanzitutto dobbiamo osservare che l'algoritmo
\texttt{Scaling\ Max-Flow} \textbf{è in realtà solo una variante
dell'originale algoritmo di Ford-Fulkerson}. I nuovi cicli, il valore
$\Delta$ e il grafo residuo ristretto $G_f(\Delta)$ vengono
utilizzati solo per \textbf{guidare la selezione del percorso residuo,
con l'obiettivo di utilizzare archi con una grande capacità residua il
più a lungo possibile.} Inoltre, tutte le proprietà che abbiamo
dimostrato sull'algoritmo \texttt{Max-Flow} originale, sono vere anche
per questa nuova versione: il flusso rimane di valore intero per tutto
l'algoritmo, e quindi tutte le capacità residue sono di valore intero.

\paragraph{Def 7.14}

\begin{myblockquote}
(7.14) Se tutte le capacità nella rete di flusso sono intere, allora
esiste un flusso massimo $f$ per il quale ogni valore di flusso
$f(e)$ è un numero intero.
\end{myblockquote}

\paragraph{Def. 7.15}

\begin{myblockquote}
Se le capacità hanno valori interi, allora in tutto l'algoritmo
\texttt{Scaling\ Max-Flow} il flusso e le capacità residue rimangono
valori interi. Ciò implica che quando $\Delta$ = 1, $G_f(\Delta)$ è
uguale a $G_f$, e quindi quando l'algoritmo termina, $f$ è di valore
massimo.
\end{myblockquote}

\subsection{Costo}

Chiamiamo un'iterazione del ciclo esterno \texttt{While}, con un valore
fisso di $\Delta$, la fase di $\Delta$-scaling. È facile dare un
limite superiore al numero di diverse fasi di $\Delta$-scaling, in
termini di valore di $C = \sum_{e \text{ out of }s} c_e$ che abbiamo
usato anche nella sezione precedente. Il valore iniziale di $\Delta$ è
al massimo $C$, scende di un fattore 2 e non scende mai al di sotto di
1.\\

Quindi: \textgreater{} Il numero di iterazioni del ciclo \texttt{While}
esterno è al massimo $\left\lceil 1 + log_2 C \right\rceil$.\\

La parte più difficile è limitare il numero di \emph{aumenti} eseguiti
in ogni fase di ridimensionamento. L'idea qui è che stiamo usando
percorsi che aumentano molto il flusso, e quindi dovrebbero esserci
relativamente pochi aumenti. Durante la fase di $\Delta$-scaling
utilizziamo solo archi con capacità residua di almeno $\Delta$.\\
Quindi: \textgreater{} Durante la fase di $\Delta$-scaling, ogni
augmentation aumenta il valore del flusso di almeno $\Delta$.\\

L'intuizione chiave è che alla fine della fase di $\Delta$-scaling, il
flusso $f$ non può essere troppo lontano dal valore massimo possibile.\\

\paragraph{Teorema}

\begin{myblockquote}
Sia $f$ il flusso alla fine della fase di $\Delta$-scaling. Esiste
un taglio $s-t$ $(A, B)$ in $G$ per cui
$c(A, B) \le v(f) + m\Delta$ , dove $m$ è il numero di archi nel
grafo $G$. Di conseguenza, il flusso massimo nella rete ha valore al
massimo $v(f) + m\Delta$.
\end{myblockquote}

\paragraph{Dimostrazione}

Questa dimostrazione è analoga alla nostra dimostrazione della (7.9), la
quale stabilisce che il flusso restituito dall'originale
\texttt{Max-Flow\ Algorithm} è di valore massimo. Come in quella
dimostrazione, dobbiamo identificare un taglio $(A, B)$ con la
proprietà desiderata. Sia $A$ l'insieme di tutti i nodi $v$ in $G$
per i quali esiste un cammino $s-v$ in $G_f(\Delta)$. Sia $B$
l'insieme di tutti gli altri nodi: $B = V - A$. Possiamo vedere che
$(A, B)$ è effettivamente un taglio $s-t$ altrimenti la fase non
sarebbe terminata.\\

Consideriamo ora un arco $e = (u, v)$ in $G$ per il quale
$u \in A$ e $v \in B$. Affermiamo che $c_e < f(e) + \Delta$ .
Infatti, se così non fosse, allora $e$ sarebbe un arco in avanti nel
grafo $G_f(\Delta)$, e poiché $u \in A$, esiste un cammino $s-u$
in $G_f(\Delta)$; aggiungendo $e$ a questo cammino, otterremmo un
cammino $s-v$ in $G_f(\Delta)$, contraddicendo la nostra ipotesi che
$v \in B$. Allo stesso modo, affermiamo che per ogni arco
$e' = (u' , v')$ in $G$ per cui $u' \in B$ e $v' \in A$, abbiamo
$f(e') < \Delta$. Infatti, se $f(e') \ge \Delta$, allora $e'$
darebbe luogo ad un arco all'indietro $e'' = (v'' , u'')$ nel grafo
$G_f(\Delta)$, e poiché $v' \in A$, esiste un cammino $s-v'$ in
$G_f(\Delta)$; aggiungendo $e''$ a questo cammino, otterremmo un
cammino $s-u'$ $G_f(\Delta)$, contraddicendo la nostra ipotesi che
$u' \in B$.\\

Quindi tutti gli archi $e$ uscenti da $A$ sono quasi saturati
(soddisfano $c_e < f(e) + \Delta$) e tutti gli archi entranti in $A$
sono quasi vuoti (soddisfano $f(e) < \Delta$).\\

Possiamo ora usare (7.6) per raggiungere la conclusione desiderata:

$$
v(f) = \sum_{e \text{ out of } A}f(e) - \sum_{e \text{ into } A}f(e) \ge \sum_{e \text{ out of } A}(c_e - \Delta) - \sum_{e \text{ into } A}\Delta =
$$
$$
\sum_{e \text{ out of } A}c_e - \sum_{e \text{ out of } A}\Delta - \sum_{e \text{ into } A}\Delta \ge c(A, B) - m\Delta
$$

Qui la prima disuguaglianza segue dai nostri limiti sui valori di flusso
degli archi attraverso il taglio, e la seconda disuguaglianza segue dal
semplice fatto che il grafo contiene solo $m$ archi in totale. Il
valore del flusso massimo è limitato dalla capacità di qualsiasi taglio
di (7.8). Usiamo il taglio $(A, B)$ per ottenere il limite dichiarato
nella seconda affermazione.

\paragraph{Def. 7.19}

\begin{myblockquote}
Il numero di aumenti in una fase di ridimensionamento (\textbf{scaling})
è al massimo di $2m$.
\end{myblockquote}

\paragraph{Dimostrazione}

L'affermazione è chiaramente vera nella prima fase di scaling: possiamo
usare ciascuno degli archi di $s$ solo per al massimo un augmentation
in quella fase. Consideriamo ora una successiva fase di scaling
$\Delta$, e sia $f_p$ il flusso alla fine della precedente fase di
scalatura. In quella fase, abbiamo usato $\Delta' = 2\Delta$ come
nostro parametro. Per la (7.18), il flusso massimo $f^*$ è al massimo
$v(f^*) \le v(f_p) + m\Delta' = v(f_p) + 2m\Delta$ . Nella fase di
$\Delta$-scalatura, ogni augmentation aumenta il flusso di almeno
$\Delta$ , e quindi possono esserci al massimo $2m$ augmentations.\\

Una augmentation richiede un tempo $O(m)$, compreso il tempo
necessario per impostare il grafo e trovare il percorso appropriato.
Abbiamo al massimo $1 + \left\lceil log_2 C \right\rceil$ fasi di
ridimensionamento $C$ e al massimo $2m$ augmentations in ciascuna
fase di ridimensionamento. Abbiamo quindi il seguente risultato.

\paragraph{Teorema 7.20}

\begin{myblockquote}
L'algoritmo \texttt{Scaling\ Max-Flow} in un grafo con $m$ archi e
capacità intere trova un flusso massimo in al massimo
$2m(1 + \left\lceil log_2 C \right\rceil)$ augmentations. Può essere
implementato per eseguire al massimo in tempo $O(m^2 \cdot log_2 C)$.
\end{myblockquote}

Quando $C$ è grande, questo limite temporale è molto migliore del
limite $O(mC)$ applicato a un'implementazione arbitraria
dell'algoritmo di \texttt{Ford-Fulkerson}. Il generico algoritmo di
Ford-Fulkerson richiede un tempo proporzionale alla grandezza delle
capacità, mentre l'algoritmo di scaling richiede solo un tempo
proporzionale al numero di bit necessari per specificare le capacità
nell'input del problema . Di conseguenza, l'algoritmo di
ridimensionamento funziona in tempo polinomiale nella dimensione
dell'input (ovvero, il numero di archi e la rappresentazione numerica
delle capacità), e quindi soddisfa il nostro obiettivo tradizionale di
ottenere un algoritmo polinomiale.
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
\chapter{Algoritmo di Edmonds-Karp o Dinits(?)}
\section{Introduzione}
L'algoritmo di Ford-Fulkerson più che un algoritmo è un procedimento concettuale, dato che molte caratteristiche non sono specificate.\\

Altri hanno studiato delle implementazioni di Ford-Fulkerson specificando l'oridne ci scelta dei nodi su cui effettuare l'augment, due di queste sono lo \textbf{shortest path max flow} e il \textbf{fat flow}.


\section{Shortest Path Max Flow}
Migliora la complessità di Ford-Fulkerson scegliendo il cammino aumentante in base al risultato di una ricerca in ampiezza, preferendo quindi il cammino più corto tra il nodo e il sink.\\

Il cammino corretto può essere trovato in tempo $O(E)$ eseguendo una \texttt{BFS} nel grafo residuale, e ci garantisce di terminare in tempo polinomiale, tagliando quindi la dipendenza dell'algoritmo di Ford-Fulkerson dalle capacità degli archi.

\subsection{Analisi dell'algoritmo}
Ora andremo a dimostrare la terminazione polinomiale dell'algoritmo con le seguenti 2 osservazioni, ma prima ci definiamo $\delta_f(u,v)$ come la distanza del cammino minimo da $u$ a $v$ nel grafo residuale $G_f$, considerando che ogni arco ha distanza unitaria.

\begin{myblockquote}
Se l'agloritmo di Edmonds-Karp viene eseguito su una rete di flusso $G = (V, E)$ con sorgente $s$ e pozzo $t$, allora per ogni vertice $v \in V - \{s,t\}$, la distanza de cammino minimo $\delta_f(s,v)$ nella rete residua $G_f$ aumenta monotonicamente per ogni aumento di flusso.
\end{myblockquote}

\textbf{Dimostrazione.} Supponiamo per assurdo che per qualche vertice $v \in V - \{s, t\}$ ci sia un aumento di flusso che provoca una diminuzione della distanza del cammino minimo da $s$ a $v$. Sia $f$ il flusso appena prima del primo aumento che riduce una distanza del cammino minimo;
sia $f^{'}$ il flusso subito dopo. Se $v$ è il vertice con il minimo $\delta_{f^{'}}(s,v)$ la cui distanza è stata ridotta dall'aumento, allora $\delta_{f^{'}}(s,v) < \delta_{f}(s,v)$.
Se $p = s \rightsquigarrow u \rightarrow v$ è un cammino minimo da $s$ a $v$ in $G_{f{'}}$, allora
$(u,v) \in E_{f^{'}}$ e:

$$
\delta_{f^{'}}(s,u) = \delta_{f^{'}}(s,v) -1
$$

Per il modo in cui abbiamo scelto $v$, sappiamo che la distanza del vertice $u$ dalla sorgente $s$ non è \textbf{aumentata(?)}, ovvero:
$$
\delta_{f^{'}}(s,u) \ge \delta_{f}(s,u)
$$
Noi asseriamo che $(u,v) \notin E_f$. \textbf{Perchè?}

Se avessimo $(u,v) \in E_f$ allora dovremmo avere anche:

$$
\delta_{f}(s,v) \le \delta_{f}(s,u) +1 \\
\le \delta_{f^{'}}(s,u) -1 \\
= \delta_{f^{'}}(s,v) -2
$$
Questo contraddice l'ipotesi che $\delta_{f^{'}}(s,v) < \delta_{f}(s,v)$.

Come è possibile avere $(u,v) \notin E_f$ e $(u,v) \in E_f^{'}$?
L'augment deve avere incrementato il flusso da $v$ a $u$. L'algoritmo di Edmondo-Karp aumenta sempre il flusso lungo tutto i cammini minimi, e quindi il cammino minimo da $s$ a $u$ in $G_f$ ha $(v,u)$ come suo ultimo arco, per tanto si ha:

$$
\delta_{f}(s,v) = \delta_{f}(s,u) -1 \\
\le \delta_{f^{'}}(s,u) -1 \\
= \delta_{f^{'}}(s,v) -2
$$

Questo contraddice l'ipotesi che $\delta_f^{'}(s,v) < \delta_f(s,v)$, quindi l'ipotesi dell'esistenza di un tale vertice $v$ non è corretta.\\
\\
\textbf{Il prossimo teorema limita il numero di iterazioni dell'algoritmo}

\begin{myblockquote}
Se l'algoritmo viene eseguito su una rete di flusso $G = (V, E)$ con sorgente $s$ e pozzo $t$, allora il numero totale di aumenti di glusso effettuati dall'algoritmo è $O(VE)$
\end{myblockquote}

\textbf{Dimostrazione.} Diciamo che un arco $(u,v)$ di una rete residua $G_f$ è \textbf{critico} in un cammino aumentante $p$ se la capacità residua di $p$ è la capacità residua di $(u,v)$.
Dopo aver aumentato il flusso lungo un cammino aumentante ogni arco critico scompare dalla rete residua. Inoltre in ogni cammino aumentante ci deve essere almeno un arco critico.

Dimostreremo che ogni arco può diventare critico al più $\frac{|V|}{2}$ volte.\\

Siano $u$ e $v$ due vertici collegati da un arco, poichè i cammini aumentanti sono i cammini minimi, quando $(u,v)$ diventa \textbf{critico} si ha:
$$
\delta_f(s,v) = \delta_{f^{'}}(s,u) +1
$$
Una volta che il flusso viene aumentato l'arco $(u,v)$ scompare dalla rete residua e non potrà riapparire successivamente in un altro cammino aumentante fino a che il flusso da $u$ a $v$ non diminuirà, e questo accade solo se $(u,v)$ apppare in un cammino aumentante.

Se consideriamo che $f^{'}$ è il flusso quando si verifica questo evento, allora si ha

$$
\delta_{f^{'}}(s,u) = \delta_{f^{'}}(s,v) +1
$$
Poichè $\delta_f(s,v) \le \delta_{f^{'}}(s,v)$ per la dimostrazione precedente, si ha:

$$
\delta_{f^{'}}(s,u) = \delta_{f^{'}}(s,v) + 1 \\
\ge \delta_f(s,v) + 1
= \delta_f(s,v) +2
$$


Di conseguenza, dall'istante in cui $(u,v)$ diventa critico, all'istante in cui diventa di nuovo critico, la distanza di $u$ dalla sorgente aumenta almeno di 2 unità.

La distanza di $u$ dalla sorgente inizialmente è almeno pari a 0.

I vertici intermedi in un cammino minimo da $s$ a $u$ non possono contenere $s, u$ o $t$.
Pertanto, fino al momento in cui u diventa irraggiungibile dalla sorgente, se mai si verifica la cosa, la sua distanza sarà al massimo $|V| -2$. Quindi dopo la prima volta che diventa critico esso può ridiventarlo al massimo altre $\frac{|V|}{2}$ volte.

Poichè ci sono $O(E)$ coppie di vertici che possono essere connessi da un arco in un grafo residuale, il numero di archi critici durante l'intera esecuzione dell'algoritmo è $O(VE)$.




\section{Fat Flow}
Migliora la complessità di Ford-Fulkerson scegliendo il cammino aumentante con il più grande bottleneck disponibile.\\

È relativamente facile far vedere come il cammino con il massimo bottleneck da $s$ a $t$ in un grafo direzionato può essere calcolato in tempo di $O(E\log{V})$ usando una variante dell'algoritmo di Dijkstra. Semplicemente si crea uno spanning tree direzionato $T$, con radice in $s$. Ripetutamente trovando l'arco con capacità maggiore uscente da $T$ e lo si aggiunge a $T$ stesso finchè $T$ non conterrà un cammino da $s$ a $t$.

\subsection{Analisi dell'algoritmo}

Possiamo ora analizzare l'algoritmo in termini di maximum flow $f^{*}$. Sia $f$ un qualsiasi flow in $G$, e $f'$ il maximum flow nel grafo residuale corrente $G_f$. (All'inizio dell'algoritmo $G_f = G$ e $f' = f^{*}$.)
Sia $e$ l'arco del bottleneck nel prossimo augmenting path. Sia $S$ il set di nodi raggiungibili da $s$ attraverso archi in $G$ con capacità maggiore di $c(e)$ e sia $T = V$ \textbackslash $S$. Per costruzione, $T$ non è vuoto, e ogni arco da $S$ a $T$ ha capacità al massimo $c(e)$. Perciò la capacità del taglio $(S,T)$ è al massimo $c(e) \cdot E$. D'altro canto, il teorema del Maxflow-Mincut implica che $||S,T|| \geq |f|$. Da ciò si evince che $c(e) \geq |f|/E$.\\

La dimostrazione precedente implica che aumentando $f$ attraverso il path con il maggior bottleneck in $G_f$ moltiplica il valore del flusso massimo in $G_f$ di un fattore di al massimo $1 - 1/E$. In altre parole il flusso residuale \textit{decade esponenzialmente} all'aumentare delle iterazioni. Dopo $E \cdot \ln{|f^{*}|}$ iterazioni il valore del flusso massimo in $G_f$ sarà al amssimo:
$$
|f^{*}|\cdot(1-1/E)^{E\cdot \ln{|f^{*}|}} < |f^{*}|e^{-\ln{|f^{*}|}} = 1
$$
(La $e$ in questione è la costante di Eulero, non l'arco) In particolare, \textit{se tutte le capacità sono interi}, allora dopo $E\cdot \ln{|f^{*}|}$ iterazioni la capacità massima del grafo residuale sarà \textit{zero} e $f$ sarà il flusso massimo.\\

Concludiamo che per grafi con capacità intere l'algoritmo \textbf{Fat Flow} richiede $O(E^2\log{E}\log{|f^{*}|})$.
Loading
Loading