Skip to content

Commit

Permalink
graph-theory/dfs: fix white-path-thm and slight refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
sharmaeklavya2 committed Jan 8, 2024
1 parent 1b431f2 commit fb96391
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 37 deletions.
42 changes: 24 additions & 18 deletions nodes/graph-theory/dfs/dfs.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,24 +64,30 @@ <h2> Dependencies:
</ol>

<div class="horizontal-rule"></div>
<p>Depth-first search (DFS) is an algorithm which systematically explores a graph $G = (V, E)$.</p>
<p><span class="invisible">
$\newcommand{\color}{\operatorname{color}}$
$\newcommand{\depth}{\operatorname{depth}}$
$\newcommand{\visit}{\operatorname{visit}}$
$\newcommand{\adj}{\operatorname{adj}}$
</span>
Depth-first search (DFS) is an algorithm which systematically explores a graph $G = (V, E)$.</p>
<p>It returns a DFS forest of $G$ and
discovery-start-time and discovery-finish-time for each vertex.</p>
<h2>The algorithm</h2>
<p>DFS maintains 5 attributes for every vertex:</p>
<ul>
<li>Start time: $\operatorname{s}: V \mapsto \mathbb{N}$</li>
<li>Finish time: $\operatorname{f}: V \mapsto \mathbb{N}$</li>
<li>$\operatorname{\pi}: V \mapsto V \cup \{\textrm{null}\}$</li>
<li>$\operatorname{color}: V \mapsto \{\textrm{black}, \textrm{gray}, \textrm{white}\}$</li>
<li>$\operatorname{depth}: V \mapsto \mathbb{N}$</li>
<li>Start time: $s: V \mapsto \mathbb{N}$</li>
<li>Finish time: $f: V \mapsto \mathbb{N}$</li>
<li>$\pi: V \mapsto V \cup \{\textrm{null}\}$</li>
<li>$\color: V \mapsto \{\textrm{black}, \textrm{gray}, \textrm{white}\}$</li>
<li>$\depth: V \mapsto \mathbb{N}$</li>
</ul>
<p>Initially,
$\operatorname{s}(v) = \operatorname{f}(v) = 0$,
$\operatorname{\pi}(v) = \textrm{null}$,
$\operatorname{color}(v) = \textrm{white}$
and $\operatorname{depth}(v) = 0$.</p>
<p>Let $\operatorname{adj}(u) = \{v \in V: (u, v) \in E\}$.</p>
<p>Initially, for every vertex $v$,
$s(v) = f(v) = 0$,
$\pi(v) = \textrm{null}$,
$\color(v) = \textrm{white}$,
and $\depth(v) = 0$.</p>
<p>Let $\adj(u) = \{v \in V: (u, v) \in E\}$.</p>
<p>DFS algorithm on $G$:</p>
<pre><code>for u in G.V:
color[u] = white
Expand All @@ -107,13 +113,13 @@ <h2>The algorithm</h2>
visit(u, 0)
</code></pre>
<p>As <code>visit(u)</code> iterates over <code>adj[u]</code>, we say that the edge $(u, v)$ is
<strong>explored</strong> for $v \in \operatorname{adj}(u)$.</p>
<strong>explored</strong> for $v \in \adj(u)$.</p>
<p>Vertices with depth 0 are called <strong>root vertices</strong>.
When DFS terminates, root vertices are the only vertices to have $\pi(u) = \textrm{null}$,
since $\pi(v)$ is set to a vertex before all non-root <code>visit(v)</code> calls.</p>
<p>When DFS terminates, $\pi$ can be interpreted as a graph $G_π = (V, E_π)$
where $(u, v) \in E_π \iff π(v) = u \neq \textrm{null}$.
Since $\pi(v)$ is set to $u$ only for $v \in \operatorname{adj}(u)$, $G_π \subseteq G$.
Since $\pi(v)$ is set to $u$ only for $v \in \adj(u)$, $G_π \subseteq G$.
Therefore, $G_π$ is called the <strong>predecessor subgraph</strong> of $G$.</p>
<h2>Properties of DFS</h2>
<ul>
Expand All @@ -123,7 +129,7 @@ <h2>Properties of DFS</h2>
and <code>visit(u)</code> makes $u$ gray before any recursive calls.</p>
</li>
<li>
<p>During the execution of DFS, whenever <code>time</code> is set, the following invariant holds on $\operatorname{color}(u)$:</p>
<p>During the execution of DFS, whenever <code>time</code> is set, the following invariant holds on $\color(u)$:</p>
<ul>
<li>If <code>visit(u)</code> hasn't yet been called, $u$ is white.</li>
<li>If <code>visit(u)</code> was called but <code>visit(u)</code> hasn't ended, $u$ is gray.</li>
Expand All @@ -132,16 +138,16 @@ <h2>Properties of DFS</h2>
</li>
<li>
<p>$G_π$ is acyclic because for every edge $(v, u)$ in $G_π$,
$\operatorname{depth}(v) = \operatorname{depth}(u) + 1$.
$\depth(v) = \depth(u) + 1$.
Since $G_π$ is an acyclic predecessor graph, it is a union of rooted trees.
Therefore, $G_π$ is also called the <strong>DFS forest</strong> of $G$.</p>
</li>
<li>
<p><code>visit(v)</code> was called during <code>visit(u)</code> iff $v$ is a descendant of $u$ in $G_π$. Proof: \begin{align}
&amp; \operatorname{visit}(v) \textrm{ was called during } \operatorname{visit}(u)
&amp; \visit(v) \textrm{ was called during } \visit(u)
\\ &amp;\iff \exists w_0, w_1, \ldots, w_k, \textrm{ such that } (
w_0 = u \wedge w_k = v \wedge (\forall 1 \le i &lt; k,
\operatorname{visit}(w_i) \textrm{ made a direct call to } \operatorname{visit}(w_{i+1})))
\visit(w_i) \textrm{ made a direct call to } \visit(w_{i+1})))
\\ &amp;\iff \exists w_0, w_1, \ldots, w_k, \textrm{ such that } (
w_0 = u \wedge w_k = v \wedge (\forall 1 \le i &lt; k, \pi(w_{i+1}) = w_i))
\\ &amp;\iff \textrm{ there is a path in } G_π \textrm{ from } u \textrm{ to } v
Expand Down
48 changes: 29 additions & 19 deletions nodes/graph-theory/dfs/white-path-theorem.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,38 +51,48 @@ <h2> Dependencies:
</ol>

<div class="horizontal-rule"></div>
<p>Let $G_π$ be the DFS forest of $G$.
<p><span class="invisible">
$\newcommand{\visit}{\operatorname{visit}}$
</span>
Let $G_π$ be the DFS forest of $G$.
$v$ is a descendant of $u$ in $G_π$ when DFS terminates iff
at the time when <code>visit(u)</code> is called, there is a white path from $u$ to $v$ in $G$.
(i.e. a path consisting entirely of white vertices).</p>
<h2>Proof</h2>
<h3>Descendant implies white path</h3>
<p>\begin{align}
&amp; v \textrm{ is a descendant of } u \textrm{ in DFS forest}
\\ &amp;\Rightarrow \operatorname{visit}(v) \textrm{ was called during visit}(u)
\\ &amp;\Rightarrow \exists w_0, w_1, \ldots, w_k, \textrm{ such that }
\\ &amp;\implies \operatorname{visit}(v) \textrm{ was called during visit}(u)
\\ &amp;\implies \exists w_0, w_1, \ldots, w_k, \textrm{ such that }
(u = w_0 \wedge v = w_k \wedge (\forall 1 \le i &lt; k,
\operatorname{visit}(w_i) \textrm{ makes a direct call to visit}(w_{i+1})))
\\ &amp;\Rightarrow (u = w_0 \wedge v = w_k \wedge (\forall 1 \le i &lt; k,
\\ &amp;\implies (u = w_0 \wedge v = w_k \wedge (\forall 1 \le i &lt; k,
w_{i+1} \textrm{ is white when visit}(w_i) \textrm{ is called}))
\\ &amp;\Rightarrow (u = w_0 \wedge v = w_k \wedge (\forall 1 \le i &lt; k,
\\ &amp;\implies (u = w_0 \wedge v = w_k \wedge (\forall 1 \le i &lt; k,
w_{i+1} \textrm{ is white when visit}(u) \textrm{ is called}))
\\ &amp;\Rightarrow \textrm{ there is a white path from } u \textrm{ to } v
\\ &amp;\implies \textrm{ there is a white path from } u \textrm{ to } v
\end{align}</p>
<p>Let there be a white path from $u$ to $v$ in $G$ when <code>visit(u)</code> was called.
Consider the non-trivial case $u \neq v$, so the path has length ≥ 1.
Let $w$ be the predecessor of $v$ in this path.
Without loss of generality, assume all vertices in the path from $u$ to $w$
become descendants of $u$ when DFS terminates.</p>
<h3>White path implies descendant</h3>
<p>For any vertex $u$, the vertex $v$ is called a <em>counterexample</em> if $v$ is not a descendant
of $u$ in $G_π$ and there was a white path from $u$ to $v$ in $G$ when $\visit(u)$ was called.
Suppose a counterexample exists for some vertex $u$.
Let $v$ be a counterexample for $u$ with the shortest white path.
Then $u \neq v$, so the white path has length ≥ 1.</p>
<p>Let $w$ be the predecessor of $v$ in this white path.
Then all vertices in the white path from $u$ to $w$ are descendants of $u$ in $G_π$,
otherwise we can find a counterexample with a shorter white path.</p>
<ul>
<li>$v$ was white when <code>visit(u)</code> was called $\implies s(u) &lt; s(v)$.</li>
<li>$w$ is a descendant of $u$ in $G_π$, so $[s(w), f(w)]$ lies within $[s(u), f(u)]$
by the parenthesis theorem.</li>
<li>$v$ is not a descendant of $u \implies u$ was already non-white when <code>visit(w)</code> was called.
Therefore, $s(v) &lt; s(w)$.</li>
<li>$v$ was white when $\visit(u)$ was called. Hence, $s(u) &lt; s(v)$.</li>
<li>Since $v$ is not a descendant of $u$ in $G_π$, $\visit(v)$ was not called during $\visit(u)$.
Hence, $s(v) \not\in [s(u), f(u)]$.</li>
</ul>
<p>Combining the above facts, we get $s(u) &lt; s(v) &lt; s(w) &lt; f(u)$.
This means $[s(v), f(v)]$ is not disjoint with $[s(u), f(u)]$.
Therefore, $v$ is a descendant of $u$ by the parenthesis theorem.</p>
<p>Combining the above two facts tells us that $s(v) &gt; f(u)$.
Hence, $v$ remains white throughout $\visit(u)$.</p>
<p>$w$ is a descendant of $u$ in $G_π$, so $\visit(w)$ is called during $\visit(u)$.
By the parenthesis theorem, $[s(w), f(w)]$ lies in $[s(u), f(u)]$.
Since $(w, v) \in G$ and $v$ remains white during $\visit(u)$,
$\visit(v)$ will be called during $\visit(w)$.
This is a contradiction, since $\visit(v)$ cannot be called during $\visit(u)$.</p>

<div class="horizontal-rule"></div>
<h2> Dependency for: </h2>
Expand Down

0 comments on commit fb96391

Please sign in to comment.