Chapter 16 first version
This commit is contained in:
parent
2d13a03056
commit
88fc8746e2
177
luku16.tex
177
luku16.tex
|
@ -475,28 +475,29 @@ corresponds to a solution with minimum number of coins,
|
||||||
and the total number of paths from node 0 to node $x$
|
and the total number of paths from node 0 to node $x$
|
||||||
equals the total number of solutions.
|
equals the total number of solutions.
|
||||||
|
|
||||||
\section{Tehokas eteneminen}
|
\section{Successor paths}
|
||||||
|
|
||||||
\index{seuraajaverkko@seuraajaverkko}
|
\index{successor graph}
|
||||||
\index{funktionaalinen verkko@funktionaalinen verkko}
|
\index{functional graph}
|
||||||
|
|
||||||
Seuraavaksi oletamme, että
|
For the rest of the chapter,
|
||||||
suunnaton verkko on \key{seuraajaverkko},
|
we concentrate on \key{successor graphs}
|
||||||
jolloin jokaisen solmun lähtöaste on 1
|
where the outdegree of each node is 1, i.e.,
|
||||||
eli siitä lähtee tasan yksi kaari ulospäin.
|
exactly one edge begins at the node.
|
||||||
Niinpä verkko muodostuu yhdestä tai useammasta
|
Thus, the graph consists of one or more
|
||||||
komponentista, joista jokaisessa on yksi sykli
|
components, and each component contains
|
||||||
ja joukko siihen johtavia polkuja.
|
one cycle and some paths that lead to it.
|
||||||
|
|
||||||
Seuraajaverkosta käytetään joskus nimeä
|
Successor graphs are sometimes called
|
||||||
\key{funktionaalinen verkko}.
|
\key{functional graphs}.
|
||||||
Tämä johtuu siitä, että jokaista seuraajaverkkoa
|
The reason for this is that any successor graph
|
||||||
vastaa funktio $f$, joka määrittelee verkon kaaret.
|
corresponds to a function $f$ that defines
|
||||||
Funktion parametrina on verkon solmu ja
|
the edges in the graph.
|
||||||
se palauttaa solmusta lähtevän kaaren kohdesolmun.
|
The parameter for the function is a node in the graph,
|
||||||
|
and the function returns the successor of the node.
|
||||||
|
|
||||||
\begin{samepage}
|
\begin{samepage}
|
||||||
Esimerkiksi funktio
|
For example, the function
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tabular}{r|rrrrrrrrr}
|
\begin{tabular}{r|rrrrrrrrr}
|
||||||
$x$ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 \\
|
$x$ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 \\
|
||||||
|
@ -505,7 +506,7 @@ $f(x)$ & 3 & 5 & 7 & 6 & 2 & 2 & 1 & 6 & 3 \\
|
||||||
\end{tabular}
|
\end{tabular}
|
||||||
\end{center}
|
\end{center}
|
||||||
\end{samepage}
|
\end{samepage}
|
||||||
määrittelee seuraavan verkon:
|
defines the following graph:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.9]
|
\begin{tikzpicture}[scale=0.9]
|
||||||
\node[draw, circle] (1) at (0,0) {$1$};
|
\node[draw, circle] (1) at (0,0) {$1$};
|
||||||
|
@ -530,12 +531,13 @@ määrittelee seuraavan verkon:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Koska seuraajaverkon jokaisella solmulla
|
Since each node in a successor graph has a
|
||||||
on yksikäsitteinen seuraaja, voimme määritellä funktion $f(x,k)$,
|
unique successor, we can define a function $f(x,k)$
|
||||||
joka kertoo solmun, johon päätyy solmusta $x$
|
that returns the node that we will reach if
|
||||||
kulkemalla $k$ askelta.
|
we begin at node $x$ and walk $k$ steps forward.
|
||||||
Esimerkiksi yllä olevassa verkossa $f(4,6)=2$,
|
For example, in the above graph $f(4,6)=2$
|
||||||
koska solmusta 4 päätyy solmuun 2 kulkemalla 6 askelta:
|
because by walking 6 steps from node 4,
|
||||||
|
we will reach node 2:
|
||||||
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.9]
|
\begin{tikzpicture}[scale=0.9]
|
||||||
|
@ -556,15 +558,16 @@ koska solmusta 4 päätyy solmuun 2 kulkemalla 6 askelta:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Suoraviivainen tapa laskea arvo $f(x,k)$
|
A straightforward way to calculate a value $f(x,k)$
|
||||||
on käydä läpi polku askel askeleelta, mihin kuluu aikaa $O(k)$.
|
is to walk through the path step by step which takes $O(k)$ time.
|
||||||
Sopivan esikäsittelyn avulla voimme laskea kuitenkin
|
However, using preprocessing, we can calculate any
|
||||||
minkä tahansa arvon $f(x,k)$ ajassa $O(\log k)$.
|
value $f(x,k)$ in only $O(\log k)$ time.
|
||||||
|
|
||||||
Ideana on laskea etukäteen kaikki arvot $f(x,k)$, kun $k$ on 2:n potenssi
|
The idea is to precalculate all values $f(x,k)$ where
|
||||||
ja enintään $u$, missä $u$ on suurin mahdollinen määrä
|
$k$ is a power of two and at most $u$ where $u$ is
|
||||||
askeleita, joista olemme kiinnostuneita.
|
the maximum number of steps we will ever walk.
|
||||||
Tämä onnistuu tehokkaasti, koska voimme käyttää rekursiota
|
This can be done efficiently because
|
||||||
|
we can use the following recursion:
|
||||||
|
|
||||||
\begin{equation*}
|
\begin{equation*}
|
||||||
f(x,k) = \begin{cases}
|
f(x,k) = \begin{cases}
|
||||||
|
@ -573,9 +576,9 @@ Tämä onnistuu tehokkaasti, koska voimme käyttää rekursiota
|
||||||
\end{cases}
|
\end{cases}
|
||||||
\end{equation*}
|
\end{equation*}
|
||||||
|
|
||||||
Arvojen $f(x,k)$ esilaskenta vie aikaa $O(n \log u)$,
|
Precalculating values $f(x,k)$ takes $O(n \log u)$ time
|
||||||
koska jokaisesta solmusta lasketaan $O(\log u)$ arvoa.
|
because we calculate $O(\log u)$ values for each node.
|
||||||
Esimerkin tapauksessa taulukko alkaa muodostua seuraavasti:
|
In the above graph, the first values are as follows:
|
||||||
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tabular}{r|rrrrrrrrr}
|
\begin{tabular}{r|rrrrrrrrr}
|
||||||
|
@ -589,29 +592,29 @@ $\cdots$ \\
|
||||||
\end{tabular}
|
\end{tabular}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Tämän jälkeen funktion $f(x,k)$ arvon saa laskettua
|
After this, any value $f(x,k)$ can be calculated
|
||||||
esittämällä luvun $k$ summana 2:n potensseja.
|
by presenting the value $k$ as a sum of powers of two.
|
||||||
Esimerkiksi jos haluamme laskea arvon $f(x,11)$,
|
For example, if we want to calculate the value $f(x,11)$,
|
||||||
muodostamme ensin esityksen $11=8+2+1$.
|
we first form the representation $11=8+2+1$.
|
||||||
Tämän ansiosta
|
Using this,
|
||||||
\[f(x,11)=f(f(f(x,8),2),1).\]
|
\[f(x,11)=f(f(f(x,8),2),1).\]
|
||||||
Esimerkiksi yllä olevassa verkossa
|
For example, in the above graph
|
||||||
\[f(4,11)=f(f(f(4,8),2),1)=5.\]
|
\[f(4,11)=f(f(f(4,8),2),1)=5.\]
|
||||||
|
|
||||||
Tällaisessa esityksessä on aina
|
Such a representation always consists of
|
||||||
$O(\log k)$ osaa, joten arvon $f(x,k)$ laskemiseen
|
$O(\log k)$ parts so calculating a value $f(x,k)$
|
||||||
kuluu aikaa $O(\log k)$.
|
takes $O(\log k)$ time.
|
||||||
|
|
||||||
\section{Syklin tunnistaminen}
|
\section{Cycle detection}
|
||||||
|
|
||||||
\index{sykli@sykli}
|
\index{cycle}
|
||||||
\index{syklin tunnistaminen@syklin tunnistaminen}
|
\index{cycle detection}
|
||||||
|
|
||||||
Kiinnostavia kysymyksiä seuraajaverkossa ovat,
|
Interesting questions in a successor graph are
|
||||||
minkä solmun kohdalla saavutaan sykliin
|
which node is the first node in the cycle
|
||||||
solmusta $x$ lähdettäessä
|
if we begin our walk at node $x$,
|
||||||
ja montako solmua kyseiseen sykliin kuuluu.
|
and what is the size of the cycle.
|
||||||
Esimerkiksi verkossa
|
For example, in the graph
|
||||||
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.9]
|
\begin{tikzpicture}[scale=0.9]
|
||||||
|
@ -630,35 +633,37 @@ Esimerkiksi verkossa
|
||||||
\path[draw,thick,->] (6) -- (4);
|
\path[draw,thick,->] (6) -- (4);
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
solmusta 1 lähdettäessä ensimmäinen sykliin kuuluva
|
if we begin at node 1, the first node that belongs
|
||||||
solmu on solmu 4 ja syklissä on kolme solmua
|
to the cycle is node 4, and the cycle consists
|
||||||
(solmut 4, 5 ja 6).
|
of three nodes (4, 5 and 6).
|
||||||
|
|
||||||
Helppo tapa tunnistaa sykli on alkaa kulkea verkossa
|
An easy way to detect a cycle is to walk in the
|
||||||
solmusta $x$ alkaen ja pitää kirjaa kaikista vastaan tulevista
|
graph beginning from node $x$ and keep track of
|
||||||
solmuista. Kun jokin solmu tulee vastaan toista kertaa,
|
all visited nodes. Once we will visit a node
|
||||||
sykli on löytynyt. Tämän menetelmän aikavaativuus on $O(n)$
|
for the second time, the first node in the cycle has been found.
|
||||||
ja muistia kuluu myös $O(n)$.
|
This method works in $O(n)$ time and also uses
|
||||||
|
$O(n)$ memory.
|
||||||
|
|
||||||
Osoittautuu kuitenkin, että syklin tunnistamiseen on
|
However, there are better algorithms for cycle detection.
|
||||||
olemassa parempia algoritmeja.
|
The time complexity of those algorithms is still $O(n)$,
|
||||||
Niissä aikavaativuus on edelleen $O(n)$,
|
but they only use $O(1)$ memory.
|
||||||
mutta muistia kuluu vain $O(1)$.
|
This is an important improvement if $n$ is large.
|
||||||
Tästä on merkittävää hyötyä, jos $n$ on suuri.
|
Next we will learn Floyd's algorithm that
|
||||||
Tutustumme seuraavaksi Floydin algoritmiin,
|
achieves these properties.
|
||||||
joka saavuttaa nämä ominaisuudet.
|
|
||||||
|
|
||||||
\subsubsection{Floydin algoritmi}
|
\subsubsection{Floyd's algorithm}
|
||||||
|
|
||||||
\index{Floydin algoritmi@Floydin algoritmi}
|
\index{Floyd's algorithm}
|
||||||
|
|
||||||
\key{Floydin algoritmi} kulkee verkossa eteenpäin rinnakkain
|
\key{Floyd's algorithm} walks forward
|
||||||
kahdesta kohdasta.
|
in the graph using two pointers $a$ and $b$.
|
||||||
Algoritmissa on kaksi osoitinta $a$ ja $b$,
|
Both pointers begin at the starting node
|
||||||
jotka molemmat ovat ensin alkusolmussa.
|
of the graph.
|
||||||
Osoitin $a$ liikkuu joka vuorolla askeleen eteenpäin,
|
Then, on each turn, pointer $a$ walks
|
||||||
kun taas osoitin $b$ liikkuu kaksi askelta eteenpäin.
|
one step forward, while pointer $b$
|
||||||
Haku jatkuu, kunnes osoittimet kohtaavat:
|
walks two steps forward.
|
||||||
|
The search continues like that until
|
||||||
|
the pointers will meet each other:
|
||||||
|
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
a = f(x);
|
a = f(x);
|
||||||
|
@ -669,12 +674,13 @@ while (a != b) {
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
Tässä vaiheessa osoitin $a$ on kulkenut $k$ askelta
|
At this point, pointer $a$ has walked $k$ steps,
|
||||||
ja osoitin $b$ on kulkenut $2k$ askelta,
|
and pointer $b$ has walked $2k$ steps
|
||||||
missä $k$ on jaollinen syklin pituudella.
|
where the length of the cycle divides $k$.
|
||||||
Niinpä ensimmäinen sykliin kuuluva solmu löytyy siirtämällä
|
Thus, the first node that belongs to the cycle
|
||||||
osoitin $a$ alkuun ja liikuttamalla osoittimia
|
can be found by moving pointer $a$ to the
|
||||||
rinnakkain eteenpäin, kunnes ne kohtaavat:
|
starting node and advancing the pointers
|
||||||
|
step by step until they will meet again:
|
||||||
|
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
a = x;
|
a = x;
|
||||||
|
@ -684,9 +690,10 @@ while (a != b) {
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
Nyt $a$ ja $b$ osoittavat ensimmäiseen syklin
|
Now $a$ and $b$ point to the first node in the cycle
|
||||||
solmuun, joka tulee vastaan solmusta $x$ lähdettäessä.
|
that can be reached from node $x$.
|
||||||
Lopuksi syklin pituus $c$ voidaan laskea näin:
|
Finally, the length $c$ of the cycle
|
||||||
|
can be calculated as follows:
|
||||||
|
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
b = f(a);
|
b = f(a);
|
||||||
|
|
Loading…
Reference in New Issue