diff --git a/Gruntfile.js b/Gruntfile.js index 0e5ad77..9b72e8d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -10,7 +10,7 @@ module.exports = function(grunt) { options: { port: port, base: base, - livereload: true, + livereload: false, open: true } } @@ -18,7 +18,7 @@ module.exports = function(grunt) { watch: { options: { - livereload: true + livereload: false }, // js: { // files: [ 'Gruntfile.js', 'js/reveal.js' ], diff --git a/documentation/contents/chapter3-background.tex b/documentation/contents/chapter3-background.tex index d3cc76b..712ac33 100644 --- a/documentation/contents/chapter3-background.tex +++ b/documentation/contents/chapter3-background.tex @@ -69,6 +69,19 @@ \section{The \maxflow{}} \section{\pushRelabel{}} +The push-relabel algorithm operates locally and does not, in contrast to the less efficient globally operating maximum flow algorithms based on augmenting paths, maintain a feasible flow during the algorithm execution. Instead, it maintains a preflow. The capacity constraints of the edges are still maintainted, but the flow conservation at the nodes is not: + +\begin{definition}[preflow] + The preflow $\tilde f$ is a generalization of the flow $f$, the equality sign $=$ in the flow conservation is replaced with $\geq$. This means that more flow can enter an inner node than leaving it, e.g. we allow leaks in our pipe system. +\end{definition} + +Another important concept in in the push-relabel algorithm is the height function, which is an approximation of the distance of a node towards the sink. The local \textit{push} operations try to move \textit{excess} at inner nodes 'downwards' towards the sink. If the current node is at a local minimum and still has excess, we \textit{relabel} the node by increasing its \textit{height} so that subsequent push operations can remove the excess. +\begin{definition}[valid edge with respect to the height function] + An edge $e'=(v,w)$ of the \textbf{residual graph} is valid with respect to the current height function, if $h(v)==h(w)+1$, meaning that the current node is one level above the one to where we wish to push excess to. +\end{definition} + +The important property of the push-relabel algorithm is that when the algorithm terminates, the computed preflow is actually a flow! + \input{pseudocode/pseudocode-maxflow} @@ -106,10 +119,9 @@ \section{The \spprc{}} \begin{example}[SPPTW] An illustrative example is the two-resource SPPRC, the shortest path problem with time windows (SPPTW). In addition to the \textit{cost} $c$, each edge additionally bears the resource \textit{time} $t$. Thus each edge is associated with the two-dimensional resource vector $(t,c) \forall e \in E$. The secondary resource \textit{time} is constrained, while the primary resource \textit{cost} is unconstrained, but seeks to be minimized. -The accumulated consumptions of the resource \textit{time} along a path are constrained at the intermediate vertices along that path by lower and upper limits, that is the earliest arrival time $t_a$ and the latest departure time $t_b$ and called the \textit{resource window}, denoted as a tuple $[t_a,t_b] \forall v \in V$. +The accumulated consumptions of the resource \textit{time} along a path are constrained at the intermediate vertices along that path by lower and upper limits, that is the earliest arrival time $t_a$ and the latest departure time $t_b$ and called the \textit{resource window}, denoted as tuples $[t_a,t_b] \, \forall v \in V$. \end{example} -$[t_{arrival},t_{departure}] \forall v \in V$ \section{\labelSetting{}} diff --git a/documentation/pseudocode/pseudocode-maxflow.tex b/documentation/pseudocode/pseudocode-maxflow.tex index 16bcbbb..96e6a26 100644 --- a/documentation/pseudocode/pseudocode-maxflow.tex +++ b/documentation/pseudocode/pseudocode-maxflow.tex @@ -6,42 +6,39 @@ \begin{algorithm}[h!] \caption{Goldberg-Tarjan Push-Relabel algorithm} -\DontPrintSemicolon % Some LaTeX compilers require you to use \dontprintsemicolon instead -\KwIn{directed Graph $G=(V,E)$ with -\begin{itemize} - \setlength\itemsep{0pt} - \setlength{\parskip}{0pt} - \item digraph $G=(V,E)$ with start $s$, sink $t$ - \item $\forall$ edges $e \in E$: (cap) capacity -\end{itemize} +\DontPrintSemicolon +\KwIn{digraph $G=(V,E)$ with nodes $s,t \in V$ and edge capacities $c(e) \, \forall e \in E$ +%\begin{itemize} +% \setlength\itemsep{0pt} +% \setlength{\parskip}{0pt} +% \item nodes start $s \in V$, sink $t \in V$ +% \item edge capacities $c(e) \, \forall e \in E$ +%\end{itemize} } \KwOut{A feasible maximum s-t flow f(e)}\vspace{0.2cm} (* Initialize the preflow *)\; \ForAll{$e=(u,w) \in E$}{ - \If{$u==s$}{ - $f(e) \gets c(e)$\; - \If{$w \neq t$}{$Q$.add(w)} - } - \Else{$f(e) \gets 0$} + $f(e) \gets (u==s) \; ? \; c(e) : 0$\; + \If{$u==s$ AND $w \neq t$}{$Q$.add(w)} } ((* Initialize the height function *))\; -$h(s) = |V|$\; -\ForAll{$v \in V$}{ - $h(v) \gets$ number of arcs on directed v-t path\; +$h(s) \gets |V|$\; +\ForAll{$v \in V \setminus \{s \}$}{ + $h(v) \gets$ number of arcs on shortest v-t path\; } ((* Main Loop *))\; \While{$\setfont{Q} \neq \emptyset$}{ $v \gets \setfont{Q}$.pop()\; - \While{$e(v)>0$ AND $\exists e'=(v,w) \in E' | h(v)==h(w)+1$}{ + \While{$e(v)>0$ AND $\exists \, e'=(v,w) \in E' \, | \, h(v)==h(w)+1$}{ (* Push *)\; push $\min(e(v),c'(e'))$ flow from v to w\; \If{$w \neq s,t$ AND $w \notin \setfont{Q}$}{ $\setfont{Q}$.add($w$)\; } } - \If{$e(v)>0$ AND $\not\exists e'=(v,w) \in E' | h(v)==h(w)+1$}{ + \If{$e(v)>0$}{ (* Relabel *)\; - $h(v) \gets 1 + \min(h(w) | e*=(v,w)\in E'$ \; + $h(v) \gets 1 + \min(\{h(w) | e^*=(v,w)\in E'\})$ \; $\setfont{Q}$.add($v$) \; } } diff --git a/documentation/pseudocode/pseudocode-spprc.tex b/documentation/pseudocode/pseudocode-spprc.tex index a977f9f..147d393 100644 --- a/documentation/pseudocode/pseudocode-spprc.tex +++ b/documentation/pseudocode/pseudocode-spprc.tex @@ -6,34 +6,30 @@ \begin{algorithm}[h!] \DontPrintSemicolon % Some LaTeX compilers require you to use \dontprintsemicolon instead -\KwIn{directed Graph $G=(V,E)$ with -\begin{itemize} - \setlength\itemsep{0pt} - \setlength{\parskip}{0pt} - \item $\forall$ nodes $v \in V$: [arrive, depart] time window resource constraint - \item $\forall$ edges $e \in E$: (time,cost) 2-dimensional resource consumptions - \item start Node $s$, end Node $t$ -\end{itemize}} -\KwOut{feasible, pareto-optimal $s \rightarrow t$ paths} \vspace{0.2cm} +\KwIn{digraph $G=(V,E)$ with start node $s \in V$, target node $t \in V$, resource windows for all nodes %$[t_a, t_d] \, \forall v \in V$ +and resource vectors for all edges} %$(t,c) \, \forall e \in E$} +\KwOut{feasible, pareto-optimal $s$-$t$ path $l^*$ with minimal cost} \vspace{0.2cm} (* Initialize *) \; -SET $\setfont{U} = \{(s)\}$ and $\setfont{P} = \emptyset$ \; -\While{$\setfont{U} \neq \emptyset$}{ +$U \gets \{(\epsilon,s)\}$ and $P \gets \emptyset$ \; +(* Main Loop *) \; +\While{$\exists l=(\sim,v) \in U$}{ + $U \gets U \setminus \{l\}$\; (* Path extension step *)\; - CHOOSE a path $\setfont{Q} \in \setfont{U}$ and REMOVE $\setfont{Q}$ from $\setfont{U}$\; - \ForAll{arcs $(v(\setfont{Q}), w) \in A$ of the forward star of $v(\setfont{Q})$}{ - \If{$(\setfont{Q},w) \in \setfont{F}(s,w) \cap \setfont{G}$}{ - ADD $(\setfont{Q},w)$ to $\setfont{U}$ + \ForAll{$e=(v,w) \in E$}{ + $l'=(l,w) \gets$ EXTEND$(l,e)$\; + \If{$l' \in \mathrm{FEASIBLE}(w)$}{ + $U \gets U \cup \{l'\}$\; } } - ADD $\setfont{Q}$ to $\setfont{P}$\; + $P \gets P \cup \{l\}$\; (* Dominance step *)\; - \If{(* any condition *)}{ - APPLY dominance algorithm to paths from $\setfont{U} \cup \setfont{P}$ ending at some node $v$\; + \ForAll{$v \in V\setminus\{s\}$}{ + $U,P \gets$ REMOVE-DOMINATED$(U,P)$\; } } -(* Filtering step *)\; -FILTER $\setfont{P}$, i.e., identify a solution $\setfont{S} \subseteq \setfont{P}$\; -\caption{Generic Dynamic Programming SPPRC Algorithm} +((* Filtering step *))\; +$l^* \in P \; | \; cost(l^*) ==\min( \{ cost(l=(\sim,t)\in P) \} )$\; +\caption{Generic Dynamic Programming SPPTW Label Setting Algorithm} \end{algorithm} diff --git a/implementation/library-d3-svg/js/AlgorithmTab.js b/implementation/library-d3-svg/js/AlgorithmTab.js index e7510f1..4826926 100644 --- a/implementation/library-d3-svg/js/AlgorithmTab.js +++ b/implementation/library-d3-svg/js/AlgorithmTab.js @@ -88,7 +88,7 @@ function AlgorithmTab(algo,p_tab) { return "pseudocode"; }); - d3.select("#tw_div_statusPseudocode").text(pseudocode.text()) + d3.select("#tw_div_statusPseudocode").html(pseudocode.html()) Tab.prototype.init.call(this); diff --git a/implementation/library-d3-svg/js/GraphDrawer.js b/implementation/library-d3-svg/js/GraphDrawer.js index 04cf899..d08ddbf 100644 --- a/implementation/library-d3-svg/js/GraphDrawer.js +++ b/implementation/library-d3-svg/js/GraphDrawer.js @@ -101,7 +101,7 @@ GraphDrawer = function(svgOrigin,extraMargin,transTime){ left: global_KnotenRadius+wS +(extraMargin.left || 0) } - var width = xRange - margin.left - margin.right, + var width = xRange - margin.left - margin.right; var height = yRange - margin.top - margin.bottom; this.height = height; diff --git a/implementation/maxflow-push-relabel/index_en.html b/implementation/maxflow-push-relabel/index_en.html index 8780043..ff639e3 100644 --- a/implementation/maxflow-push-relabel/index_en.html +++ b/implementation/maxflow-push-relabel/index_en.html @@ -416,27 +416,25 @@
s ← pick(v)
t ← pick(v)
BEGIN
(* Initializing the preflow *)
-FORALL e=(u,w) ∈ E
-IF u == s THEN f(e) ← c(e)
-ELSE f(e) ← 0
-IF u == s AND w ≠ t THEN Q.add(w)
(* Initializing the height function *)
-h(s) = |V|
-FORALL v ∈ V\{s}
-h(v) ← #arcs on directed v-t path
(* Initialize the preflow *)
+FORALL e=(u,w) ∈ E
+f(e) ← (u == s) ? c(e) : 0
+IF u == s AND w ≠ t THEN Q.add(w)
(* Initialize the height function *)
+h(s) ← |V|
+FORALL v ∈ V\{s}
+h(v) ← #arcs on shortest v-t path
(* Main Loop *)
-WHILE Q ≠ ∅
-v ← Q.pop()
WHILE e(v)>0
-AND ∃ e'=(v,w)∈E'|h(v)==h(w)+1
(* PUSH *)
-push min{e(v),c'(e')} flow from v to w
-IF w != s,t AND w ∉ Q THEN Q.add(w)
IF e(v)>0 AND ∄ e'=(v,w)∈E'|h(v)==h(w)+1
(* RELABEL *)
-h(v) ← 1+min{h(w)|e*=(v,w)∈E'}
-Q.add(v)
WHILE Q ≠ ∅
+v ← Q.pop()
+WHILE e(v)>0 AND ∃ e'=(v,w)∈E'|h(v)==h(w)+1
(* PUSH *)
+push min(e(v),c'(e')) flow from v to w
+IF w ≠ s,t AND w ∉ Q THEN Q.add(w)
IF e(v)>0
(* RELABEL *)
+h(v) ← 1+min({h(w)|e*=(v,w)∈E'})
+Q.add(v)
END
-
+
+s ← pick(v)
BEGIN
(* Initialize *)
-U ← {(ε,s)}, P ← ∅
(* Main Loop *)
-WHILE ∃ l=(~,v) ∈ U
(* Path extension step *)
-FORALL e=(v,w) ∈ E
-l'=(l,w) ← EXTEND(l,e)
IF l' ∈ FEASIBLE(w)
-U ← U ∪ {l'}
ELSE
-throw away l'
P ← P ∪ {l}
(* Dominance step *)
-FORALL v ∈ V\{s}
U,P ← REMOVE-DOMINATED(U,P)
END
-t ← pick(v)
-(* Filtering step *)
-solution ← l=(~,t) ∈ P :
-cost(l) = min(cost(l)) ∀ l=(~,t) ∈ P
s ← pick(v)
BEGIN
(* Initialize *)
+U ← {(ε,s)} and P ← ∅
(* Main Loop *)
+WHILE ∃ l=(~,v) ∈ U
+U ← U \ {l}
(* Path extension step *)
+FORALL e=(v,w) ∈ E
+l'=(l,w) ← EXTEND(l,e)
IF l' ∈ FEASIBLE(w)
+U ← U ∪ {l'}
ELSE
+throw away l'
P ← P ∪ {l}
(* Dominance step *)
+FORALL v ∈ V\{s}
U,P ← REMOVE-DOMINATED(U,P)
END
+(* Filtering step *)
+t ← pick(v)
+l* ∈ P | cost(l*) == min({cost(l=(~,t)∈P)})
-Input: Weighted, undirected graph G=(V,E) with weight function l.
-Output: A list {d(v[j]) : j = 1,..,n} containing the distances dist(v[1],v[j]) = d(v[j]),
- if there are no negative circles reachable from v[1].
- The message "Negative Circle" is shown, if a negative circle can be reached from v[1].
+Input: directed graph G=(V,E) with
+ start node s and end node t
+ resource windows for all nodes
+ resource vectors for all edges
+Output: feasible, pareto-optimal s-t path l* with minimal cost
-
+
+