Coin problem and scheduling

This commit is contained in:
Antti H S Laaksonen 2017-01-01 23:43:44 +02:00
parent 30bb6699b5
commit c0b6c97340
1 changed files with 151 additions and 161 deletions

View File

@ -1,131 +1,127 @@
\chapter{Greedy algorithms} \chapter{Greedy algorithms}
\index{ahne algoritmi@ahne algoritmi} \index{greedy algorithm}
\key{Ahne algoritmi} A \key{greedy algorithm}
muodostaa tehtävän ratkaisun constructs a solution for a problem
tekemällä joka askeleella by always making a choice that looks
sillä hetkellä parhaalta näyttävän valinnan. the best at the moment.
Ahne algoritmi ei koskaan A greedy algorithm never takes back
peruuta tekemiään valintoja vaan its choices, but directly constructs
muodostaa ratkaisun suoraan valmiiksi. the final solution.
Tämän ansiosta ahneet algoritmit ovat For this reason, greedy algorithms
yleensä hyvin tehokkaita. are usually very efficient.
Vaikeutena ahneissa algoritmeissa on The difficulty in designing a greedy algorithm
keksiä toimiva ahne strategia, is to invent a greedy strategy
joka tuottaa aina optimaalisen ratkaisun tehtävään. that always produces an optimal solution
Ahneen algoritmin tulee olla sellainen, for the problem.
että kulloinkin parhaalta näyttävät valinnat The locally optimal choices in a greedy
tuottavat myös parhaan kokonaisuuden. algorithm should also be globally optimal.
Tämän perusteleminen on usein hankalaa. It's often difficult to argue why
a greedy algorithm works.
\section{Kolikkotehtävä} \section{Coin problem}
Aloitamme ahneisiin algoritmeihin tutustumisen As the first example, we consider a problem
tehtävästä, jossa muodostettavana on where we are given a set of coin values
rahamäärä $x$ kolikoista. and our task is to form a sum of money
Kolikoiden arvot ovat $\{c_1,c_2,\ldots,c_k\}$, using the coins.
ja jokaista kolikkoa on saatavilla rajattomasti. The values of the coins are
Tehtävänä on selvittää, mikä on pienin määrä $\{c_1,c_2,\ldots,c_k\}$,
kolikoita, joilla rahamäärän voi muodostaa. and each coin can be used as many times we want.
What is the minimum number of coins needed?
Esimerkiksi jos muodostettava For example, if the coins are euro coins (in cents)
rahamäärä on 520 \[\{1,2,5,10,20,50,100,200\}\]
ja kolikot ovat eurokolikot eli sentteinä and the sum of money is 520,
\[\{1,2,5,10,20,50,100,200\},\] we need at least four coins.
niin kolikoita tarvitaan vähintään 4. The optimal solution is to select coins
Tämä on mahdollista valitsemalla kolikot $200+200+100+20$ whose sum is 520.
$200+200+100+20$, joiden summa on 520.
\subsubsection{Ahne algoritmi} \subsubsection{Greedy algorithm}
Luonteva ahne algoritmi tehtävään A natural greedy algorithm for the problem
on poistaa rahamäärästä aina mahdollisimman is to always select the largest possible coin,
suuri kolikko, kunnes rahamäärä on 0. until we have constructed the required sum of money.
Tämä algoritmi toimii esimerkissä, This algorithm works in the example case,
koska rahamäärästä 520 because we first select two 200 cent coins,
poistetaan ensin kahdesti 200, sitten 100 then one 100 cent coin and finally one 20 cent coin.
ja lopuksi 20. But does this algorithm always work?
Mutta toimiiko ahne algoritmi aina oikein?
Osoittautuu, että eurokolikoiden tapauksessa It turns out that, for the set of euro coins,
ahne algoritmi \emph{toimii} aina oikein, the greedy algorithm \emph{always} works, i.e.,
eli se tuottaa aina ratkaisun, it always produces a solution with the fewest
jossa on pienin määrä kolikoita. possible number of coins.
Algoritmin toimivuuden voi perustella The correctness of the algorithm can be
seuraavasti: argued as follows:
Kutakin kolikkoa 1, 5, 10, 50 ja 100 Each coin 1, 5, 10, 50 and 100 appears
on optimiratkaisussa enintään yksi. at most once in the optimal solution.
Tämä johtuu siitä, että jos The reason for this is that if the
ratkaisussa olisi kaksi tällaista kolikkoa, solution would contain two such coins,
saman ratkaisun voisi muodostaa we could replace them by one coin and
käyttäen vähemmän kolikoita. obtain a better solution.
Esimerkiksi jos ratkaisussa on For example, if the solution would contain
kolikot $5+5$, ne voi korvata kolikolla 10. coins $5+5$, we could replace them by coin $10$.
Vastaavasti kumpaakin kolikkoa 2 ja 20 In the same way, both coins 2 and 20 can appear
on optimiratkaisussa enintään kaksi, at most twice in the optimal solution
koska kolikot $2+2+2$ voi korvata kolikoilla $5+1$ because, we could replace
ja kolikot $20+20+20$ voi korvata kolikoilla $50+10$. coins $2+2+2$ by coins $5+1$ and
Lisäksi ratkaisussa ei voi olla yhdistelmiä coins $20+20+20$ by coins $50+10$.
$2+2+1$ ja $20+20+10$, Moreover, the optimal solution can't contain
koska ne voi korvata kolikoilla 5 ja 50. coins $2+2+1$ or $20+20+10$
because we would replace them by coins $5$ and $50$.
Näiden havaintojen perusteella Using these observations,
jokaiselle kolikolle $x$ pätee, we can show for each coin $x$ that
että $x$:ää pienemmistä kolikoista it is not possible to optimally construct
ei ole mahdollista saada aikaan summaa sum $x$ or any larger sum by only using coins
$x$ tai suurempaa summaa optimaalisesti. that are smaller than $x$.
Esimerkiksi jos $x=100$, pienemmistä kolikoista For example, if $x=100$, the largest optimal
saa korkeintaan summan $50+20+20+5+2+2=99$. sum using the smaller coins is $5+20+20+5+2+2=99$.
Niinpä ahne algoritmi, Thus, the greedy algorithm that always selects
joka valitsee aina suurimman kolikon, the largest coin produces the optimal solution.
tuottaa optimiratkaisun.
Kuten tästä esimerkistä huomaa, This example shows that it can be difficult
ahneen algoritmin toimivuuden perusteleminen to argue why a greedy algorithm works,
voi olla työlästä, even if the algorithm itself is simple.
vaikka kyseessä olisi yksinkertainen algoritmi.
\subsubsection{Yleinen tapaus} \subsubsection{General case}
Yleisessä tapauksessa kolikot voivat olla mitä tahansa. In the general case, the coin set can contain any coins
Tällöin suurimman kolikon valitseva ahne algoritmi and the greedy algorithm \emph{not} necessarily produces
\emph{ei} välttämättä tuota optimiratkaisua. an optimal solution.
Jos ahne algoritmi ei toimi, tämän voi osoittaa We can prove that a greedy algorithm doesn't work
näyttämällä vastaesimerkin, jossa algoritmi by showing a counterexample
antaa väärän vastauksen. where the algorithm gives a wrong answer.
Tässä tehtävässä vastaesimerkki on helppoa keksiä: In this problem it's easy to find a counterexample:
jos kolikot ovat $\{1,3,4\}$ ja muodostettava if the coins are $\{1,3,4\}$ and the sum of money
rahamäärä on 6, ahne algoritmi tuottaa ratkaisun is 6, the greedy algorithm produces the solution
$4+1+1$, kun taas optimiratkaisu on $3+3$. $4+1+1$, while the optimal solution is $3+3$.
Yleisessä tapauksessa kolikkotehtävän ratkaisuun We don't know if the general coin problem
ei tunneta ahnetta algoritmia, can be solved using any greedy algorithm.
mutta palaamme tehtävään seuraavassa luvussa. However, we will revisit the problem in the next chapter
Tehtävään on nimittäin olemassa dynaamista because the general problem can be solved using a dynamic
ohjelmointia käyttävä algoritmi, programming algorithm that always gives the
joka tuottaa optimiratkaisun correct answer.
millä tahansa kolikoilla ja rahamäärällä.
\section{Aikataulutus} \section{Scheduling}
Monet aikataulutukseen liittyvät ongelmat Many scheduling problems can be solved
ratkeavat ahneesti. using a greedy strategy.
Klassinen ongelma on seuraava: A classic problem is as follows:
Annettuna on $n$ tapahtumaa, Given $n$ events with their starting and ending
jotka alkavat ja päättyvät tiettyinä hetkinä. times, our task is to plan a schedule
Tehtäväsi on suunnitella aikataulu, so that we can join as many events as possible.
jota seuraamalla pystyt osallistumaan It's not possible to join an event partially.
mahdollisimman moneen tapahtumaan. For example, consider the following events:
Et voi osallistua tapahtumaan vain osittain.
Esimerkiksi tilanteessa
\begin{center} \begin{center}
\begin{tabular}{lll} \begin{tabular}{lll}
tapahtuma & alkuaika & loppuaika \\ event & starting time & ending time \\
\hline \hline
$A$ & 1 & 3 \\ $A$ & 1 & 3 \\
$B$ & 2 & 5 \\ $B$ & 2 & 5 \\
@ -133,10 +129,9 @@ $C$ & 3 & 9 \\
$D$ & 6 & 8 \\ $D$ & 6 & 8 \\
\end{tabular} \end{tabular}
\end{center} \end{center}
on mahdollista osallistua korkeintaan In this case the maximum number of events is two.
kahteen tapahtumaan. For example, we can join events $B$ and $D$
Yksi mahdollisuus on osallistua tapahtumiin as follows:
$B$ ja $D$ seuraavasti:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=.4] \begin{tikzpicture}[scale=.4]
\begin{scope} \begin{scope}
@ -152,16 +147,15 @@ $B$ ja $D$ seuraavasti:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Tehtävän ratkaisuun on mahdollista It is possible to invent several greedy algorithms
keksiä useita ahneita algoritmeja, for the problem, but which of them works in every case?
mutta mikä niistä toimii kaikissa tapauksissa?
\subsubsection*{Algoritmi 1} \subsubsection*{Algorithm 1}
Ensimmäinen idea on valita ratkaisuun The first idea is to select as \emph{short}
mahdollisimman \emph{lyhyitä} tapahtumia. events as possible.
Esimerkin tapauksessa tällainen In the example case this algorithm
algoritmi valitsee seuraavat tapahtumat: selects the following events:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=.4] \begin{tikzpicture}[scale=.4]
\begin{scope} \begin{scope}
@ -177,9 +171,9 @@ algoritmi valitsee seuraavat tapahtumat:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Lyhimpien tapahtumien valinta ei ole kuitenkaan However, choosing short events is not always
aina toimiva strategia, a correct strategy but the algorithm fails,
vaan algoritmi epäonnistuu esimerkiksi seuraavassa tilanteessa: for example, in the following case:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=.4] \begin{tikzpicture}[scale=.4]
\begin{scope} \begin{scope}
@ -189,16 +183,14 @@ vaan algoritmi epäonnistuu esimerkiksi seuraavassa tilanteessa:
\end{scope} \end{scope}
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Kun lyhyt tapahtuma valitaan mukaan, If we select the short event, we can only select one event.
on mahdollista osallistua vain yhteen tapahtumaan. However, it would be possible to select both the long events.
Kuitenkin valitsemalla pitkät tapahtumat
olisi mahdollista osallistua kahteen tapahtumaan.
\subsubsection*{Algoritmi 2} \subsubsection*{Algorithm 2}
Toinen idea on valita aina seuraavaksi tapahtuma, Another idea is to always select the next possible
joka \emph{alkaa} mahdollisimman aikaisin. event that \emph{begins} as \emph{early} as possible.
Tämä algoritmi valitsee esimerkissä seuraavat tapahtumat: This algorithm selects the following events:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=.4] \begin{tikzpicture}[scale=.4]
\begin{scope} \begin{scope}
@ -214,9 +206,10 @@ Tämä algoritmi valitsee esimerkissä seuraavat tapahtumat:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Tämäkään algoritmi ei kuitenkaan toimi aina. However, we can find a counterexample for this
Esimerkiksi seuraavassa tilanteessa algorithm, too.
algoritmi valitsee vain yhden tapahtuman: For example, in the following case,
the algorithm selects only one event:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=.4] \begin{tikzpicture}[scale=.4]
\begin{scope} \begin{scope}
@ -226,18 +219,16 @@ algoritmi valitsee vain yhden tapahtuman:
\end{scope} \end{scope}
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Kun ensimmäisenä alkava tapahtuma If we select the first event, it is not possible
valitaan mukaan, mitään muuta tapahtumaa to select any other events.
ei ole mahdollista valita. However, it would be possible to join the
Kuitenkin olisi mahdollista osallistua other two events.
kahteen tapahtumaan valitsemalla
kaksi myöhempää tapahtumaa.
\subsubsection*{Algoritmi 3} \subsubsection*{Algorithm 3}
Kolmas idea on valita aina seuraavaksi tapahtuma, The third idea is to always select the next
joka \emph{päättyy} mahdollisimman aikaisin. possible event that \emph{ends} as \emph{early} as possible.
Tämä algoritmi valitsee esimerkissä seuraavat tapahtumat: This algorithm selects the following events:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=.4] \begin{tikzpicture}[scale=.4]
\begin{scope} \begin{scope}
@ -253,26 +244,25 @@ Tämä algoritmi valitsee esimerkissä seuraavat tapahtumat:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Osoittautuu, että tämä ahne algoritmi It turns out that this algorithm
tuottaa \textit{aina} optimiratkaisun. \emph{always} produces an optimal solution.
Algoritmi toimii, koska on aina kokonaisuuden The algorithm works because
kannalta optimaalista valita regarding the final solution, it is
ensimmäiseksi tapahtumaksi optimal to select an event that
mahdollisimman aikaisin päättyvä tapahtuma. ends as soon as possible.
Tämän jälkeen on taas optimaalista Then it is optimal to select
valita seuraava aikatauluun sopiva the next event using the same strategy, etc.
mahdollisimman aikaisin
päättyvä tapahtua, jne.
Yksi tapa perustella valintaa on miettiä, One way to justify the choice is to think
mitä tapahtuu, jos ensimmäiseksi tapahtumaksi what happens if we first select some event
valitaan jokin muu kuin mahdollisimman that ends later than the event that ends
aikaisin päättyvä tapahtuma. as soon as possible.
Tällainen valinta ei ole koskaan parempi, This can never be a better choice
koska myöhemmin päättyvän tapahtuman because after an event that ends later,
jälkeen on joko yhtä paljon tai vähemmän we will have at most an equal number of
mahdollisuuksia valita seuraavia tapahtumia possibilities to select for the next events,
kuin aiemmin päättyvän tapahtuman jälkeen. compared to the strategy that we select the
event that ends as soon as possible.
\section{Tehtävät ja deadlinet} \section{Tehtävät ja deadlinet}