\documentclass[10pt,a4paper]{article} % {{{

\usepackage{float,url,graphicx,booktabs}
\usepackage[dutch]{babel}

% }}}

\title{Modelleren, Simuleren \& Contin\"ue Wiskunde \\
       Assignment 2: Differentiation, roots and Integration}
\author{Tadde\"us Kroes (6054129) \and Sander van Veen (6167969)}

\begin{document}

\maketitle

\section*{Inleiding} % {{{
\label{sec:Inleiding}

Voor elk van de zeven opgaven in dit programma hebben we een aparte executable
gemaakt waarmee het programma voor de desbetreffende opgave wordt uitgevoerd.
Bijvoorbeeld is \texttt{q1} de naam van de executable die het programma van
opgave 1 uitvoert. De algoritmes die door meerdere opgaven worden gebruikt
hebben we ge\"implementeerd in aparte C-bestanden.

% }}}

\section{Differentiatie} % {{{
\label{sec:Differentiatie}

We kunnen op verschillende manieren de richtingsco\"effici\"ent van een functie
berekenen. Wij hebben twee manieren getest: het gebruik van een interval rechts
van een gegeven punt, en een interval om het gegeven punt heen (``right-hand''
en ``central'' differencing). Voor de berekening gebruiken we respectievelijk de
volgende functies:

\begin{equation}
    \label{eq:right}
    \frac{\sin(x + h) - \sin(x)}{h}
\end{equation}
\begin{equation}
    \label{eq:central}
    \frac{\sin(x + h) - \sin(x - h)}{2h}
\end{equation}

Als het interval rechts van een gegeven punt ligt nemen we geen informatie mee
over de grafiek links van het punt, terwijl we dit wel doen bij centrale
differentiatie. We verwachten daarom een klein verschil in de resultaten van
beide methodes. Om de accuratie van de resultaten te testen, berekenen we ook
handmatig het resultaat met behulp van $\sin(x)' = \cos(x)$. Hiermee berekenen
we dat $[\sin(\frac{\pi}{3})]' = \cos(\frac{\pi}{3}) = \frac{1}{2}$. De periode
van $\sin(x)$ id $2\pi$, dus zijn ook beide andere richtingsco\"effici\"enten
gelijk aan $\frac{1}{2}$ (immers zijn $100\pi$ en $10^{12}\pi$ veelvouden van
$2\pi$). De resultaten van ons programma staan in de volgende tabel:

\begin{table}[h]
\centering
\begin{tabular}{llll}
\toprule
$x$                          & right-hand       & central          & $h$ \\
\midrule
$\frac{\pi}{3}$              & $0.499995669867$ & $0.499999999992$ & $10^{-5}$ \\
$100\pi + \frac{\pi}{3}$     & $0.499956697770$ & $0.499999999041$ & $10^{-4}$ \\
$10^{12}\pi + \frac{\pi}{3}$ & $0.487956179030$ & $0.488369107296$ & $10^{-3}$ \\
\bottomrule
\end{tabular}
\end{table}

\noindent We hebben ook kleinere waardes voor $h$ gebruikt, maar dan werd het
resultaat voor $x = 10^{12}\pi + \frac{\pi}{3}$ gelijk aan $0$. Dit is te
verklaren door het feit dat de grootte $h$ significant genoeg moet zijn om $x$
te veranderen.  Bij een grote $|x|$ en een kleine $h$ kan het dus voorkomen dat
voor het begin en het eind van het interval dezelfde waarde wordt gebruikt
(namelijk $x$), dit levert een richtingsco\"effici\"ent van $0$ op. Een
oplossing voor dit probleem is om $h$ dynamisch te maken, door $h$ te berekenen
aan de hand van $x$, bijvoorbeeld door de minst significante mantissa van $x$ te
gebruiken. \\ De kleinere waarden voor $h$ geven wel betere resultaten voor de
kleinere waarden van $x$. We zien wel dat right-hand differencing een kleinere
richtingsco\"effici\"ent geeft dan central differencing. Dit kan worden
verklaard door het feit dat $\sin(x)$ op deze waarden van $x$ een afnemend
stijgende lijn is. Aan de rechterkant van $x$ stijgt de lijn dan minder hard dan
gemiddeld over de linker- en rechterkant.

% }}}

\section{Bisection} % {{{
\label{sec:Bisection}

We hebben een programma geschreven dat de bisection methode toepast om het
nulpunt van $f(x)$ te benaderen op het interval $[0, 2]$. De benadering is
gelijk aan $1.114157142 \dots$, interessanter is echter de relatie tussen de
nauwkeurigheid en het aantal stappen van de berekening:

\begin{figure}[H]
\includegraphics[width=12cm]{bisec}
\caption{Het verband tussen de nauwkeurigheid en het aantal stappen van de
berekening is exponentieel.}
\end{figure}

\noindent Uit de grafiek kunnen we aflezen dat het aantal benodigde stappen voor
de berekening lineair toeneemt met het aantal decimalen waarop de berekening
nauwkeurig is. Merk op dat de datapunten niet op een perfect rechte lijn
liggen, dit komt doordat het aantal stappen wordt afgerond op een geheel getal.

% }}}

\section{Benadering van $\sqrt{2}$} % {{{
\label{sec:benadering van sqrt 2}

$\sqrt{2}$ is gelijk aan het nulpunt van de functie $f(x) = x^2 - 2$. Dit nulpunt
hebben we met verschillende methoden benaderd, waarbij we verschillende
foutmarges hebben meegegeven. Door het aantal stappen van de berekening te
tellen kunnen we mogelijk een verband bepalen tussen de foutmarge en het aantal
benodigde stappen voor de berekening. We hebben de resultaten van ons programma
uitgezet in onderstaande grafiek:

\begin{figure}[H]
\includegraphics[width=12cm]{sqrt}
\caption{Het verband tussen de nauwkeurigheid en het aantal stappen van de
berekening voor drie verschillende ``root-finding'' methodes (blauw: Bisection,
rood: Regula Falsi, groen: Newton-Raphson).}
\end{figure}

We zien, net als bij opgave 2, dat bij elke methode het aantal benodigde stappen
lineair toeneemt met het aantal decimalen waarop het resultaat is afgerond. Merk
op dat ook hier geen perfect rechte lijnen door de datapunten gaan, omdat het
aantal stappen is afgerond op een geheel getal.

% }}}

\pagebreak

\section{Newton-Raphson} % {{{
\label{sec:Newton-Raphson}

We hebben een programma geschreven dat de nulpunten van de volgende drie
functies bepaald:

\begin{itemize}
    \item $f_1(x) = x^2 - x + 2$
    \item $f_2(x) = x^3 - 3x - 2$
    \item $f_3(x) = (x^2 - 1)(x - 4)$
\end{itemize}

Als parameter voor het programma dient een geheel positief getal op te worden
gegeven. Dat getal wordt gebruikt voor de bisection en regula falsi methode om
het totaal aantal stappen om de nulpunten te vinden te reduceren. Hieronder is
een voorbeeld weergave van het programma met een maximum van \texttt{5} stappen
voor de bisection en regula falsi methode:

\begin{verbatim}
$ ./q4 5
f1: could not find a root after 100000 steps
f2: -1.00000000011 (39 steps from start point -10.00000000000)
f2: 2.00000000000 (10 steps from start point 10.00000000000)
f3: 4.00000000000 (2 steps from start point 0.00000000000)

Now using Bisection to determine the first 5 steps.

Did first 1 steps using bisec
f2: -1.00000000010 (38 steps from start point -5.00000000000)
Did first 5 steps using bisec
f2: 2.00000000000 (10 steps from start point 2.18750000000)
Did first 5 steps using bisec
f3: 4.00000000000 (9 steps from start point 4.06250000000)

Now using Regula Falsi to determine the first 5 steps.

Did first 5 steps using regula_falsi
f2: -0.99999999985 (37 steps from start point 0.39763149048)
Did first 5 steps using regula_falsi
f2: -0.99999999992 (38 steps from start point 0.37773413585)
Did first 5 steps using regula_falsi
f3: 4.00000000000 (30 steps from start point 1.02650759729)
\end{verbatim}

De functie $f_1$ heeft geen nulpunten en na 100000 stappen zal onze
implementatie van de Newton-Raphson methode daarom ook aangeven dat er geen
nulpunten zijn gevonden.

Het aantal benodigde stappen voor het benaderen van de nulpunten van $f_2$ is
bij de Newton-Raphson methode gelijk aan $39 + 10 = 49$. Als we de bisection
methode toepassen, kost het benaderen van de nulpunten van $f_2$ een totaal $10
+ 38$ stappen, waarvan twee keer $5$ stappen voor de bisection methode). Regula
falsi in combinatie met de Newton-Raphson methode heeft voor de functies $f_2$
en $f_3$ veel meer stappen nodig (resp. $37 + 38 = 75$ en $30$ stappen; waarvan
twee keer $5$ stappen voor de regula falsi methode).

Op het moment dat we het maximum stappen van de regula falsi methode verhogen
naar \texttt{10}, dan ziet het resultaat er heel anders uit:

\begin{verbatim}
$ ./q4 10
f1: could not find a root after 100000 steps

 .. snip ..

Now using Regula Falsi to determine the first 10 steps.

Did first 7 steps using regula_falsi
f2: 2.00000000000 (13 steps from start point 2.62300283682)
Did first 10 steps using regula_falsi
f2: 2.00000000000 (14 steps from start point 1.99601959065)
Did first 10 steps using regula_falsi
f3: 4.00000000000 (14 steps from start point 4.00986504483)
\end{verbatim}

In dit geval is het aantal benodigde stappen voor regula falsi in combinatie met
de Newton-Raphson methode gereduceerd tot slechts 14 stappen (dus 4 stappen
totdat de Newton-Raphson methode klaar is) voor $f_3$. Merk op dat de regula
falsi methode voor $f_2$ het tweede nulpunt ($x = -1$) niet kan vinden.

\begin{figure}[H]
\centering
\includegraphics[width=12cm]{integration}
\caption{Plot van $f(x) = x^3 - 3x - 2$ voor $x$ in $[-3, 3]$.}
\end{figure}

De bisection en regula falsi methodes werken alleen goed wanneer de
functiewaarden op de linker- en rechtergrens aan tegenovergestelde zijden van de
x-as liggen (dus $f(l) \cdot f(r) \leq 0$). Dit is niet het geval bij het
nulpunt op $x = -1$ in bovenstaande grafiek, dit verklaart het feit dat dit
nulpunt niet wordt gevonden door de regula falsi methode in het interval
$[-10,0]$.

% }}}

\section{Vier numerieke integraal routines} % {{{
\label{sec:vier numerieke integraal routines}

We hebben de volgende vier methodes ge\"implementeerd om een numerieke integraal
uit te rekenen:

\begin{description}
    \item[Rectangle rule]
    $$rectangle(f, a, b) = (b - a) \cdot f(\frac{a + b}{2})$$
    \item[Trapezoidal rule]
    $$trapezoidal(f, a, b) = \frac{(b - a) \cdot (f(a) + f(b))}{2}$$
    \item[Simpson's rule]
    Simpson's rule kan worden berekend door middel van de bovenstaande methodes
    ``rectangle'' en ``trapezoidal'':
    $$simpson(f, a, b) = \frac{2 \cdot rectangle(f, a, b) + trapezoidal(f, a, b)}{3}$$
    \item[Two-point Gauss integratie]
    $$gauss(f, a, b) = (b - a) \frac{f(a + \frac{b - a}{2} \cdot (1 -
    \frac{1}{\sqrt{3}})) + f(a + \frac{b - a}{2} \cdot (1 +
    \frac{1}{\sqrt{3}}))}{2}$$
\end{description}

Naast de bovengenoemde methodes hebben we ook een integraal functie gemaakt die
de methodes aanroept:

\begin{verbatim}
double integral(f, method, a, b, dx):
    steps = (int) ((b - a) / dx)
    surface = 0
    for(i = 0; i < steps; i++):
        surface += method(f, a + i * dx, a + (i + 1) * dx)
    return surface
\end{verbatim}

\noindent Daarnaast hebben we drie functies gemaakt (waarbij \texttt{sin(x)}
onderdeel is van glibc) die de drie verschillende integranten voorstellen:

\begin{verbatim}
double f1(x):
    return pow(M_E, -x)
double f2(x):
    return x * f1(x)
double sin(x);
\end{verbatim}

\noindent We hebben de exacte resultaten van de integralen berekend en die van
vergeleken met de benaderingen. Dit heeft het volgende resultaat gegeven toen we
het programma met 1.000.000 ``slices'' (het aantal stukjes waarin het interval
$[a, b]$ wordt verdeeld) hebben uitgevoerd:

\begin{table}[H]
\begin{tabular}{llllrr} \toprule
f   & a & b      & methode     & \multicolumn{1}{l}{benadering}   & \multicolumn{1}{l}{afwijking}   \\
\midrule
f1  & 0 & 1      & rectangle   & $ 6.321205588285 \cdot 10^{-01}$ & $3.952393967666 \cdot 10^{-14}$ \\
f1  & 0 & 1      & trapezoidal & $ 6.321205588286 \cdot 10^{-01}$ & $4.141131881852 \cdot 10^{-14}$ \\
f1  & 0 & 1      & simpson     & $ 6.321205588285 \cdot 10^{-01}$ & $1.276756478319 \cdot 10^{-14}$ \\
f1  & 0 & 1      & gauss       & $ 6.321205588285 \cdot 10^{-01}$ & $1.276756478319 \cdot 10^{-14}$ \\
\midrule
f2  & 0 & 2      & rectangle   & $ 5.939941502904 \cdot 10^{-01}$ & $2.019495681793 \cdot 10^{-13}$ \\
f2  & 0 & 2      & trapezoidal & $ 5.939941502898 \cdot 10^{-01}$ & $3.644862189844 \cdot 10^{-13}$ \\
f2  & 0 & 2      & simpson     & $ 5.939941502902 \cdot 10^{-01}$ & $1.454392162259 \cdot 10^{-14}$ \\
f2  & 0 & 2      & gauss       & $ 5.939941502902 \cdot 10^{-01}$ & $1.454392162259 \cdot 10^{-14}$ \\
\midrule
f2  & 0 & 20     & rectangle   & $ 9.999999567325 \cdot 10^{-01}$ & $1.671296434580 \cdot 10^{-11}$ \\
f2  & 0 & 20     & trapezoidal & $ 9.999999566825 \cdot 10^{-01}$ & $3.332367715103 \cdot 10^{-11}$ \\
f2  & 0 & 20     & simpson     & $ 9.999999567158 \cdot 10^{-01}$ & $2.831068712794 \cdot 10^{-14}$ \\
f2  & 0 & 20     & gauss       & $ 9.999999567158 \cdot 10^{-01}$ & $2.808864252302 \cdot 10^{-14}$ \\
\midrule
f2  & 0 & 200    & rectangle   & $ 1.000000001666 \cdot 10^{+00}$ & $1.666276006063 \cdot 10^{-09}$ \\
f2  & 0 & 200    & trapezoidal & $ 9.999999966665 \cdot 10^{-01}$ & $3.333514797532 \cdot 10^{-09}$ \\
f2  & 0 & 200    & simpson     & $ 9.999999999998 \cdot 10^{-01}$ & $1.918465386552 \cdot 10^{-13}$ \\
f2  & 0 & 200    & gauss       & $ 9.999999999998 \cdot 10^{-01}$ & $1.918465386552 \cdot 10^{-13}$ \\
\midrule
sin & 0 & $8\pi$ & rectangle   & $ 1.649022273643 \cdot 10^{-14}$ & $1.649022273643 \cdot 10^{-14}$ \\
sin & 0 & $8\pi$ & trapezoidal & $-2.597858752022 \cdot 10^{-14}$ & $2.597858752022 \cdot 10^{-14}$ \\
sin & 0 & $8\pi$ & simpson     & $-1.797341770030 \cdot 10^{-14}$ & $1.797341770030 \cdot 10^{-14}$ \\
sin & 0 & $8\pi$ & gauss       & $-1.797258919631 \cdot 10^{-14}$ & $1.797258919631 \cdot 10^{-14}$ \\
\bottomrule
\end{tabular}
\end{table}

De benaderingsfuncties in de tabel hebben elk hetzelfde aantal slices gebruikt.
Toch zien we verschillen in de afwijking van de exacte resultaten. De simpson's
rule en two-point gauss integration hebben een kleinere afwijking dan de
rectangle rule en trapezoidal rule methoden. We zien slechts nihile verschillen
tussen simpson's rule en two-point gauss integration. Echter zijn er (mits goed
ge\"implementeerd) minder cycles nodig voor de gauss integration. Daarom heeft
deze methode de voorkeur. \\
\\
We kunnen de integraal $\int_0^2{x^{-0.5}dx}$ als volgt exact berekenen:
$$ \int_0^2{x^{-0.5}dx} = \left[2\sqrt{x}\right]_0^2 = 2\sqrt{2} $$

% }}}

\section{Instelbare accuratie} % {{{
\label{sec:Instelbare accuratie}

Het in natuurlijk interessant om te weten hoeveel het ``kost'' om een bepaalde
minimale nauwkeurigheid te bereiken bij een benadering van een integraal.
Hiervoor hebben we de functie \texttt{accurate\_integral} geschreven, waaraan we
een bepaalde nauwkeurigheid meegeven. Deze nauwkeurigheid is te specifi\"eren
door het gewenste aantal ``correcte'' decimalen mee te geven aan het programma.

In het onderstaande voorbeeld is de integraal $\int_0^2 x \cdot
e^{-x}$ berekend tot 14 decimalen nauwkeurig. Dit doen we door het aantal
stappen van de berekening steeds te verdubbelen totdat het verschil tussen de
twee laatste resultaten kleiner dan $10^{-14}$ is. In de uitvoer van het
voorbeeld is dit aangegeven door middel van het symbool \texttt{|}.

\begin{verbatim}
$ ./q6 14
0.593994150290161226912744041329
                | could deviate from here
0.593994150290164335537212991767
\end{verbatim}

\noindent We zien dat de eerste 14 decimalen gelijk zijn, daarna is er verschil
te zien. Dit is ook het geval als we een ander getal dan 14 opgeven, waaruit
blijkt dat de methode werkt.

% }}}

\section{Fibonacci} % {{{
\label{sec:Fibonacci}

Het programma wat we hebben gemaakt vraagt twee argumenten: het aantal te
simuleren generaties en optioneel de maximum leeftijd van een konijn (standaard
is deze oneindig). De volgende aanroep simuleert bijvoorbeeld de groei van een
konijnenpopulatie over 25 generaties, waarbij elk konijn maximaal 3 jaar oud
wordt:

\begin{verbatim}
./q7 25 3
\end{verbatim}

Naast de grootte van de populatie bevat de uitvoer van het programma ook de
groei van de populatie. We hebben het programma met verschillende waarden
uitgevoerd, de resultaten hiervan hebben we uitgezet in de volgende grafieken:

\begin{figure}[H]
\centering
\includegraphics[width=12cm]{rabbit}
\caption{Konijnenpopulatie per generatie voor verschillende maximum leeftijden
(2 t/m 10 jaar).}
\end{figure}

\begin{figure}[H]
\centering
\includegraphics[width=12cm]{rabbit_grow}
\caption{Groei van konijnenpopulatie over generaties voor verschillende maximum
leeftijden (2 t/m 10 jaar).}
\end{figure}

We zien dat de groei na een bepaald punt exponentieel is, wanneer de maximum
leeftijd groter is dan twee. Wanneer de maximum leeftijd gelijk is aan twee, is
er altijd maar \'e\'en paar konijnen. Wanneer er geen maximum leeftijd is, kan
de konijnenpopulatie $P(n)$ in generatie $n$ worden uitgedrukt als $P(n - 2) +
P(n - 1)$, dit staat ook wel bekend als de Rij van Fibonacci.

% }}}

\end{document}
% vim: foldmethod=marker:
