Chapter 6 ready
This commit is contained in:
parent
c0b6c97340
commit
66f167a6eb
345
luku06.tex
345
luku06.tex
|
@ -264,22 +264,20 @@ possibilities to select for the next events,
|
|||
compared to the strategy that we select the
|
||||
event that ends as soon as possible.
|
||||
|
||||
\section{Tehtävät ja deadlinet}
|
||||
\section{Tasks and deadlines}
|
||||
|
||||
Annettuna on $n$ tehtävää,
|
||||
joista jokaisella on kesto ja deadline.
|
||||
Tehtäväsi on valita järjestys,
|
||||
jossa suoritat tehtävät.
|
||||
Saat kustakin tehtävästä $d-x$ pistettä,
|
||||
missä $d$ on tehtävän deadline ja $x$
|
||||
on tehtävän valmistumishetki.
|
||||
Mikä on suurin mahdollinen
|
||||
yhteispistemäärä, jonka voit saada tehtävistä?
|
||||
We are given $n$ tasks with duration and deadline.
|
||||
Our task is to choose an order to perform the tasks.
|
||||
For each task, we get $d-x$ points
|
||||
where $d$ is the deadline of the task
|
||||
and $x$ is the moment when we finished the task.
|
||||
What is the largest possible total score
|
||||
we can obtain?
|
||||
|
||||
Esimerkiksi jos tehtävät ovat
|
||||
For example, if the tasks are
|
||||
\begin{center}
|
||||
\begin{tabular}{lll}
|
||||
tehtävä & kesto & deadline \\
|
||||
task & duration & deadline \\
|
||||
\hline
|
||||
$A$ & 4 & 2 \\
|
||||
$B$ & 3 & 5 \\
|
||||
|
@ -287,8 +285,8 @@ $C$ & 2 & 7 \\
|
|||
$D$ & 4 & 5 \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
niin optimaalinen ratkaisu on suorittaa
|
||||
tehtävät seuraavasti:
|
||||
then the optimal solution is to perform
|
||||
the tasks as follows:
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=.4]
|
||||
\begin{scope}
|
||||
|
@ -314,22 +312,21 @@ tehtävät seuraavasti:
|
|||
\end{scope}
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
Tässä ratkaisussa $C$ tuottaa 5 pistettä,
|
||||
$B$ tuottaa 0 pistettä, $A$ tuottaa $-7$ pistettä
|
||||
ja $D$ tuottaa $-8$ pistettä,
|
||||
joten yhteispistemäärä on $-10$.
|
||||
In this solution, $C$ yields 5 points,
|
||||
$B$ yields 0 points, $A$ yields $-7$ points
|
||||
and $D$ yields $-8$ points,
|
||||
so the total score is $-10$.
|
||||
|
||||
Yllättävää kyllä, tehtävän optimaalinen ratkaisu
|
||||
ei riipu lainkaan deadlineista,
|
||||
vaan toimiva ahne strategia on
|
||||
yksinkertaisesti
|
||||
suorittaa tehtävät \emph{järjestyksessä keston mukaan}
|
||||
lyhimmästä pisimpään.
|
||||
Syynä tähän on, että jos missä tahansa vaiheessa
|
||||
suoritetaan peräkkäin kaksi tehtävää,
|
||||
joista ensimmäinen kestää toista kauemmin,
|
||||
tehtävien järjestyksen vaihtaminen parantaa ratkaisua.
|
||||
Esimerkiksi jos peräkkäin ovat tehtävät
|
||||
Surprisingly, the optimal solution for the problem
|
||||
doesn't depend on the dedalines at all,
|
||||
but a correct greedy strategy is to simply
|
||||
perform the tasks \emph{sorted by their durations}
|
||||
in increasing order.
|
||||
The reason for this is that if we ever perform
|
||||
two successive tasks such that the first task
|
||||
takes longer than the second task,
|
||||
we can obtain a better solution if we swap the tasks.
|
||||
For example, if the successive tasks are
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=.4]
|
||||
\begin{scope}
|
||||
|
@ -348,7 +345,7 @@ Esimerkiksi jos peräkkäin ovat tehtävät
|
|||
\end{scope}
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
ja $a>b$, niin järjestyksen muuttaminen muotoon
|
||||
and $a>b$, the swapped order of the tasks
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=.4]
|
||||
\begin{scope}
|
||||
|
@ -367,97 +364,102 @@ ja $a>b$, niin järjestyksen muuttaminen muotoon
|
|||
\end{scope}
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
antaa $X$:lle $b$ pistettä vähemmän ja $Y$:lle $a$ pistettä enemmän,
|
||||
joten kokonaismuutos pistemäärään on $a-b > 0$.
|
||||
Optimiratkaisussa
|
||||
kaikille peräkkäin suoritettaville tehtäville
|
||||
tulee päteä, että lyhyempi tulee ennen pidempää,
|
||||
mistä seuraa, että tehtävät tulee suorittaa
|
||||
järjestyksessä keston mukaan.
|
||||
gives $b$ points less to $X$ and $a$ points more to $Y$,
|
||||
so the total score increases by $a-b > 0$.
|
||||
In an optimal solution,
|
||||
for each two successive tasks,
|
||||
it must hold that the shorter task comes
|
||||
before the longer task.
|
||||
Thus, the tasks must be performed
|
||||
sorted by their durations.
|
||||
|
||||
\section{Keskiluvut}
|
||||
\section{Minimizing sums}
|
||||
|
||||
Tarkastelemme seuraavaksi ongelmaa, jossa
|
||||
annettuna on $n$ lukua $a_1,a_2,\ldots,a_n$
|
||||
ja tehtävänä on etsiä luku $x$ niin, että summa
|
||||
We will next consider a problem where
|
||||
we are given $n$ numbers $a_1,a_2,\ldots,a_n$
|
||||
and our task is to find a value $x$
|
||||
such that the sum
|
||||
\[|a_1-x|^c+|a_2-x|^c+\cdots+|a_n-x|^c\]
|
||||
on mahdollisimman pieni.
|
||||
Keskitymme tapauksiin, joissa $c=1$ tai $c=2$.
|
||||
becomes as small as possible.
|
||||
We will focus on the cases $c=1$ and $c=2$.
|
||||
|
||||
\subsubsection{Tapaus $c=1$}
|
||||
\subsubsection{Case $c=1$}
|
||||
|
||||
Tässä tapauksessa minimoitavana on summa
|
||||
In this case, we should minimize the sum
|
||||
\[|a_1-x|+|a_2-x|+\cdots+|a_n-x|.\]
|
||||
Esimerkiksi jos luvut ovat $[1,2,9,2,6]$,
|
||||
niin paras ratkaisu on valita $x=2$,
|
||||
jolloin summaksi tulee
|
||||
For example, if the numbers are $[1,2,9,2,6]$,
|
||||
the best solution is to select $x=2$
|
||||
which produces the sum
|
||||
\[
|
||||
|1-2|+|2-2|+|9-2|+|2-2|+|6-2|=12.
|
||||
\]
|
||||
Yleisessä tapauksessa paras valinta $x$:n arvoksi
|
||||
on lukujen \textit{mediaani}
|
||||
eli keskimmäinen luku järjestyksessä.
|
||||
Esimerkiksi luvut $[1,2,9,2,6]$
|
||||
ovat järjestyksessä $[1,2,2,6,9]$,
|
||||
joten mediaani on 2.
|
||||
In the general case, the best choice for $x$
|
||||
is the \textit{median} of the numbers,
|
||||
i.e., the middle number after sorting.
|
||||
For example, the list $[1,2,9,2,6]$
|
||||
becomes $[1,2,2,6,9]$ after sorting,
|
||||
so the median is 2.
|
||||
|
||||
Mediaanin valinta on paras ratkaisu,
|
||||
koska jos $x$ on mediaania pienempi,
|
||||
$x$:n suurentaminen pienentää summaa,
|
||||
ja vastaavasti jos $x$ on mediaania suurempi,
|
||||
$x$:n pienentäminen pienentää summaa.
|
||||
Niinpä $x$ kannattaa siirtää mahdollisimman
|
||||
lähelle mediaania eli optimiratkaisu on
|
||||
valita $x$ mediaaniksi.
|
||||
Jos $n$ on parillinen ja mediaaneja on kaksi,
|
||||
kumpikin mediaani sekä kaikki niiden välillä
|
||||
olevat luvut tuottavat optimaalisen ratkaisun.
|
||||
The median is the optimal choice,
|
||||
because if $x$ is smaller than the median,
|
||||
the sum becomes smaller by increasing $x$,
|
||||
and if $x$ is larger then the median,
|
||||
the sum becomes smaller by decreasing $x$
|
||||
Thus, we should move $x$ as near the median
|
||||
as possible, so the optimal solution that $x$
|
||||
is the median.
|
||||
If $n$ is even and there are two medians,
|
||||
both medians and all values between them
|
||||
are optimal solutions.
|
||||
|
||||
\subsubsection{Tapaus $c=2$}
|
||||
\subsubsection{Case $c=2$}
|
||||
|
||||
Tässä tapauksessa minimoitavana on summa
|
||||
In this case, we should minimize the sum
|
||||
\[(a_1-x)^2+(a_2-x)^2+\cdots+(a_n-x)^2.\]
|
||||
Esimerkiksi jos luvut ovat $[1,2,9,2,6]$,
|
||||
niin paras ratkaisu on $x=4$,
|
||||
jolloin summaksi tulee
|
||||
For example, if the numbers are $[1,2,9,2,6]$,
|
||||
the best solution is to select $x=4$
|
||||
which produces the sum
|
||||
\[
|
||||
(1-4)^2+(2-4)^2+(9-4)^2+(2-4)^2+(6-4)^2=46.
|
||||
\]
|
||||
Yleisessä tapauksessa paras valinta $x$:n arvoksi on lukujen
|
||||
\textit{keskiarvo}.
|
||||
Esimerkissä lukujen keskiarvo on $(1+2+9+2+6)/5=4$.
|
||||
Tämän tuloksen voi johtaa järjestämällä summan
|
||||
uudestaan muotoon
|
||||
In the general case, the best choice for $x$
|
||||
is the \emph{average} of the numbers.
|
||||
In the example the average is $(1+2+9+2+6)/5=4$.
|
||||
This result can be derived by presenting
|
||||
the sum as follows:
|
||||
\[
|
||||
nx^2 - 2x(a_1+a_2+\cdots+a_n) + (a_1^2+a_2^2+\cdots+a_n^2).
|
||||
\]
|
||||
Viimeinen osa ei riipu $x$:stä, joten sen voi jättää huomiotta.
|
||||
Jäljelle jäävistä osista muodostuu funktio
|
||||
$nx^2-2xs$, kun $s=a_1+a_2+\cdots+a_n$.
|
||||
Tämä on ylöspäin aukeava paraabeli,
|
||||
jonka nollakohdat ovat $x=0$ ja $x=2s/n$
|
||||
ja pienin arvo on näiden keskikohta
|
||||
$x=s/n$ eli taulukon lukujen keskiarvo.
|
||||
The last part doesn't depend on $x$,
|
||||
so we can ignore it.
|
||||
The remaining parts form a function
|
||||
$nx^2-2xs$ where $s=a_1+a_2+\cdots+a_n$.
|
||||
This is a parabola opening upwards
|
||||
with roots $x=0$ and $x=2s/n$,
|
||||
and the minimum value is the average
|
||||
of the roots $x=s/n$, i.e.,
|
||||
the average of the numbers $a_1,a_2,\ldots,a_n$.
|
||||
|
||||
\section{Tiedonpakkaus}
|
||||
\section{Data compression}
|
||||
|
||||
\index{tiedonpakkaus}
|
||||
\index{binxxrikoodi@binäärikoodi}
|
||||
\index{koodisana@koodisana}
|
||||
\index{data compression}
|
||||
\index{binary code}
|
||||
\index{codeword}
|
||||
|
||||
Annettuna on merkkijono ja tehtävänä on
|
||||
\emph{pakata} se niin,
|
||||
että tilaa kuluu vähemmän.
|
||||
Käytämme tähän \key{binäärikoodia},
|
||||
joka määrittää kullekin merkille
|
||||
biteistä muodostuvan \key{koodisanan}.
|
||||
Tällöin merkkijonon voi pakata
|
||||
korvaamalla jokaisen merkin vastaavalla koodisanalla.
|
||||
Esimerkiksi seuraava binäärikoodi määrittää
|
||||
koodisanat merkeille \texttt{A}–\texttt{D}:
|
||||
We are given a string, and our task is to
|
||||
\emph{compress} it so that it requires less space.
|
||||
We will do this using a \key{binary code}
|
||||
that determines for each character
|
||||
a \key{codeword} that consists of bits.
|
||||
After this, we can compress the string
|
||||
by replacing each character by the
|
||||
corresponding codeword.
|
||||
For example, the following binary code
|
||||
determines codewords for characters
|
||||
\texttt{A}–\texttt{D}:
|
||||
\begin{center}
|
||||
\begin{tabular}{rr}
|
||||
merkki & koodisana \\
|
||||
character & codeword \\
|
||||
\hline
|
||||
\texttt{A} & 00 \\
|
||||
\texttt{B} & 01 \\
|
||||
|
@ -465,23 +467,25 @@ merkki & koodisana \\
|
|||
\texttt{D} & 11 \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
Tämä koodi on \key{vakiopituinen}
|
||||
eli jokainen koodisana on yhtä pitkä.
|
||||
Esimerkiksi merkkijono
|
||||
\texttt{AABACDACA} on pakattuna
|
||||
This is a \key{constant-length} code
|
||||
which means that the length of each
|
||||
codeword is the same.
|
||||
For example, the compressed form of the string
|
||||
\texttt{AABACDACA} is
|
||||
\[000001001011001000,\]
|
||||
eli se vie tilaa 18 bittiä.
|
||||
Pakkausta on kuitenkin mahdollista parantaa
|
||||
ottamalla käyttöön \key{muuttuvan pituinen} koodi,
|
||||
jossa koodisanojen pituus voi vaihdella.
|
||||
Tällöin voimme antaa usein esiintyville merkeille
|
||||
lyhyen koodisanan ja harvoin esiintyville
|
||||
merkeille pitkän koodisanan.
|
||||
Osoittautuu, että yllä olevalle merkkijonolle
|
||||
\key{optimaalinen} koodi on seuraava:
|
||||
so 18 bits are needed.
|
||||
However, we can compress the string better
|
||||
by using a \key{variable-length} code
|
||||
where codewords may have different lengths.
|
||||
Then we can give short codewords for
|
||||
characters that appear often,
|
||||
and long codewords for characters
|
||||
that appear rarely.
|
||||
It turns out that the \key{optimal} code
|
||||
for the aforementioned string is as follows:
|
||||
\begin{center}
|
||||
\begin{tabular}{rr}
|
||||
merkki & koodisana \\
|
||||
character & codeword \\
|
||||
\hline
|
||||
\texttt{A} & 0 \\
|
||||
\texttt{B} & 110 \\
|
||||
|
@ -489,27 +493,26 @@ merkki & koodisana \\
|
|||
\texttt{D} & 111 \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
Optimaalinen koodi tuottaa
|
||||
mahdollisimman lyhyen pakatun merkkijonon.
|
||||
Tässä tapauksessa optimaalinen koodi
|
||||
pakkaa merkkijonon muotoon
|
||||
The optimal code produces a compressed string
|
||||
that is as short as possible.
|
||||
In this case, the compressed form using
|
||||
the optimal code is
|
||||
\[001100101110100,\]
|
||||
ja tilaa kuluu vain 15 bittiä.
|
||||
Paremman koodin ansiosta onnistuimme siis säästämään
|
||||
3 bittiä tilaa pakkauksessa.
|
||||
so only 15 bits are needed.
|
||||
Thus, thanks to a better code it was possible to
|
||||
save 3 bits in the compressed string.
|
||||
|
||||
Huomaa, että koodin tulee olla aina sellainen,
|
||||
että mikään koodisana ei ole toisen koodisanan
|
||||
alkuosa.
|
||||
Esimerkiksi ei ole sallittua, että koodissa
|
||||
olisi molemmat koodisanat 10 ja 1011.
|
||||
Tämä rajoitus johtuu siitä,
|
||||
että haluamme myös pystyä palauttamaan
|
||||
alkuperäisen merkkijonon pakkauksen jälkeen.
|
||||
Jos koodisana voisi olla toisen alkuosa,
|
||||
tämä ei välttämättä olisi mahdollista.
|
||||
Esimerkiksi seuraava koodi
|
||||
\emph{ei} ole kelvollinen:
|
||||
Note that it is required that no codeword
|
||||
is a prefix of another codeword.
|
||||
For example, it is not allowed that a code
|
||||
would contain both codewords 10
|
||||
and 1011.
|
||||
The reason for this is that we also want
|
||||
to be able to generate the original string
|
||||
from the compressed string.
|
||||
If a codeword could be a prefix of another codeword,
|
||||
this would not always be possible.
|
||||
For example, the following code is \emph{not} valid:
|
||||
\begin{center}
|
||||
\begin{tabular}{rr}
|
||||
merkki & koodisana \\
|
||||
|
@ -520,40 +523,41 @@ merkki & koodisana \\
|
|||
\texttt{D} & 111 \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
Tätä koodia käyttäen ei olisi mahdollista tietää,
|
||||
tarkoittaako pakattu merkkijono 1011
|
||||
merkkijonoa \texttt{AB} vai merkkijonoa \texttt{C}.
|
||||
Using this code, it would not be possible to know
|
||||
if the compressed string 1011 means
|
||||
the string \texttt{AB} or the string \texttt{C}.
|
||||
|
||||
\index{Huffmanin koodaus}
|
||||
\index{Huffman coding}
|
||||
|
||||
\subsubsection{Huffmanin koodaus}
|
||||
\subsubsection{Huffman coding}
|
||||
|
||||
\key{Huffmanin koodaus} on ahne algoritmi,
|
||||
joka muodostaa optimaalisen koodin
|
||||
merkkijonon pakkaamista varten.
|
||||
Se muodostaa merkkien esiintymiskertojen
|
||||
perustella binääripuun, josta voi lukea
|
||||
kunkin merkin koodisanan
|
||||
liikkumalla huipulta merkkiä vastaavaan solmuun.
|
||||
Liikkuminen vasemmalle vastaa
|
||||
bittiä 0 ja liikkuminen oikealle
|
||||
vastaa bittiä 1.
|
||||
\key{Huffman coding} is a greedy algorithm
|
||||
that constructs an optimal code for
|
||||
compressing a string.
|
||||
The algorithm builds a binary tree
|
||||
based on the frequencies of the characters
|
||||
in the string,
|
||||
and a codeword for each characters can be read
|
||||
by following a path from the root to
|
||||
the corresponding node.
|
||||
A move to the left correspons to bit 0,
|
||||
and a move to the right corresponds to bit 1.
|
||||
|
||||
Aluksi jokaista merkkijonon merkkiä vastaa solmu,
|
||||
jonka painona on merkin esiintymiskertojen määrä merkkijonossa.
|
||||
Sitten joka vaiheessa puusta valitaan
|
||||
kaksi painoltaan pienintä solmua
|
||||
ja ne yhdistetään luomalla niiden
|
||||
yläpuolelle uusi solmu,
|
||||
jonka paino on solmujen yhteispaino.
|
||||
Näin jatketaan, kunnes kaikki solmut
|
||||
on yhdistetty ja koodi on valmis.
|
||||
Initially, each character of the string is
|
||||
represented by a node whose weight is the
|
||||
number of times the character appears in the string.
|
||||
Then at each step two nodes with minimum weights
|
||||
are selected and they are combined by creating
|
||||
a new node whose weight is the sum of the weights
|
||||
of the original nodes.
|
||||
The process continues until all nodes have been
|
||||
combined and the code is ready.
|
||||
|
||||
Tarkastellaan nyt, miten Huffmanin koodaus
|
||||
muodostaa optimaalisen koodin merkkijonolle
|
||||
Next we will see how Huffman coding creates
|
||||
the optimal code for the string
|
||||
\texttt{AABACDACA}.
|
||||
Alkutilanteessa on neljä solmua,
|
||||
jotka vastaavat merkkijonossa olevia merkkejä:
|
||||
Initially, there are four nodes that correspond
|
||||
to the characters in the string:
|
||||
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=0.9]
|
||||
|
@ -570,13 +574,16 @@ jotka vastaavat merkkijonossa olevia merkkejä:
|
|||
%\path[draw,thick,-] (4) -- (5);
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
Merkkiä \texttt{A} vastaavan solmun paino on
|
||||
5, koska merkki \texttt{A} esiintyy 5 kertaa merkkijonossa.
|
||||
Muiden solmujen painot on laskettu vastaavalla tavalla.
|
||||
The node that represents character \texttt{A}
|
||||
has weight 5 because character \texttt{A}
|
||||
appears 5 times in the string.
|
||||
The other weights have been calculated
|
||||
in the same way.
|
||||
|
||||
Ensimmäinen askel on yhdistää merkkejä \texttt{B} ja \texttt{D}
|
||||
vastaavat solmut, joiden kummankin paino on 1.
|
||||
Tuloksena on:
|
||||
The first step is to combine the nodes that
|
||||
correspond to characters \texttt{B} and \texttt{D},
|
||||
both with weight 1.
|
||||
The result is:
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=0.9]
|
||||
\node[draw, circle] (1) at (0,0) {$5$};
|
||||
|
@ -597,7 +604,7 @@ Tuloksena on:
|
|||
\path[draw,thick,-] (4) -- (5);
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
Tämän jälkeen yhdistetään solmut, joiden paino on 2:
|
||||
After this, the nodes with weight 2 are combined:
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=0.9]
|
||||
\node[draw, circle] (1) at (1,0) {$5$};
|
||||
|
@ -623,7 +630,7 @@ Tämän jälkeen yhdistetään solmut, joiden paino on 2:
|
|||
\path[draw,thick,-] (5) -- (6);
|
||||
\end{tikzpicture}
|
||||
\end{center}
|
||||
Lopuksi yhdistetään kaksi viimeistä solmua:
|
||||
Finally, the two remaining nodes are combined:
|
||||
\begin{center}
|
||||
\begin{tikzpicture}[scale=0.9]
|
||||
\node[draw, circle] (1) at (2,2) {$5$};
|
||||
|
@ -655,11 +662,11 @@ Lopuksi yhdistetään kaksi viimeistä solmua:
|
|||
\end{tikzpicture}
|
||||
\end{center}
|
||||
|
||||
Nyt kaikki solmut ovat puussa, joten koodi on valmis.
|
||||
Puusta voidaan lukea seuraavat koodisanat:
|
||||
Now all nodes are in the tree, so the code is ready.
|
||||
The following codewords can be read from the tree:
|
||||
\begin{center}
|
||||
\begin{tabular}{rr}
|
||||
merkki & koodisana \\
|
||||
character & codeword \\
|
||||
\hline
|
||||
\texttt{A} & 0 \\
|
||||
\texttt{B} & 110 \\
|
||||
|
|
Loading…
Reference in New Issue