aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToby Vincent <tobyv13@gmail.com>2021-10-24 03:01:51 -0500
committerToby Vincent <tobyv13@gmail.com>2021-10-24 03:01:51 -0500
commit6bb48b46a74a1a3ed9b0fdfac97b808eacd88e6d (patch)
treee020f643cc6167db7f58bd55e557bb57fcb8ac65
parentcccc5d059f0d1c53b992adb6a7b776b6e18dcefe (diff)
wrote report
-rw-r--r--.gitignore303
-rw-r--r--.vscode/settings.json58
-rw-r--r--docs/Project3SubsetSum.pdfbin0 -> 157033 bytes
-rw-r--r--docs/report/__latexindent_temp.tex116
-rw-r--r--docs/report/report.pdfbin0 -> 153411 bytes
-rw-r--r--docs/report/report.tex109
-rw-r--r--docs/report/styles/header.sty35
-rw-r--r--docs/report/styles/packages.sty12
-rw-r--r--docs/report/styles/section.sty35
-rw-r--r--docs/report/styles/title.sty29
-rw-r--r--src/Program/runtimes.csv12
-rw-r--r--src/Program/scores.csv12
12 files changed, 718 insertions, 3 deletions
diff --git a/.gitignore b/.gitignore
index dfe9b34..8d9970c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
-# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,dotnetcore,csharp
-# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,dotnetcore,csharp
+# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,dotnetcore,csharp,latex
+# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,dotnetcore,csharp,latex
### Csharp ###
## Ignore Visual Studio temporary files, build results, and
@@ -410,4 +410,301 @@ obj/
.history
.ionide
-# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,dotnetcore,csharp
+### LaTeX ###
+## Core latex/pdflatex auxiliary files:
+*.aux
+*.lof
+*.log
+*.lot
+*.fls
+*.out
+*.toc
+*.fmt
+*.fot
+*.cb
+*.cb2
+.*.lb
+
+## Intermediate documents:
+*.dvi
+*.xdv
+*-converted-to.*
+# these rules might exclude image files for figures etc.
+# *.ps
+# *.eps
+# *.pdf
+
+## Generated if empty string is given at "Please type another file name for output:"
+.pdf
+
+## Bibliography auxiliary files (bibtex/biblatex/biber):
+*.bbl
+*.bcf
+*.blg
+*-blx.aux
+*-blx.bib
+*.run.xml
+
+## Build tool auxiliary files:
+*.fdb_latexmk
+*.synctex
+*.synctex(busy)
+*.synctex.gz
+*.synctex.gz(busy)
+*.pdfsync
+
+## Build tool directories for auxiliary files
+# latexrun
+latex.out/
+
+## Auxiliary and intermediate files from other packages:
+# algorithms
+*.alg
+*.loa
+
+# achemso
+acs-*.bib
+
+# amsthm
+*.thm
+
+# beamer
+*.nav
+*.pre
+*.snm
+*.vrb
+
+# changes
+*.soc
+
+# comment
+*.cut
+
+# cprotect
+*.cpt
+
+# elsarticle (documentclass of Elsevier journals)
+*.spl
+
+# endnotes
+*.ent
+
+# fixme
+*.lox
+
+# feynmf/feynmp
+*.mf
+*.mp
+*.t[1-9]
+*.t[1-9][0-9]
+*.tfm
+
+#(r)(e)ledmac/(r)(e)ledpar
+*.end
+*.?end
+*.[1-9]
+*.[1-9][0-9]
+*.[1-9][0-9][0-9]
+*.[1-9]R
+*.[1-9][0-9]R
+*.[1-9][0-9][0-9]R
+*.eledsec[1-9]
+*.eledsec[1-9]R
+*.eledsec[1-9][0-9]
+*.eledsec[1-9][0-9]R
+*.eledsec[1-9][0-9][0-9]
+*.eledsec[1-9][0-9][0-9]R
+
+# glossaries
+*.acn
+*.acr
+*.glg
+*.glo
+*.gls
+*.glsdefs
+*.lzo
+*.lzs
+
+# uncomment this for glossaries-extra (will ignore makeindex's style files!)
+# *.ist
+
+# gnuplottex
+*-gnuplottex-*
+
+# gregoriotex
+*.gaux
+*.glog
+*.gtex
+
+# htlatex
+*.4ct
+*.4tc
+*.idv
+*.lg
+*.trc
+*.xref
+
+# hyperref
+*.brf
+
+# knitr
+*-concordance.tex
+# TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files
+# *.tikz
+*-tikzDictionary
+
+# listings
+*.lol
+
+# luatexja-ruby
+*.ltjruby
+
+# makeidx
+*.idx
+*.ilg
+*.ind
+
+# minitoc
+*.maf
+*.mlf
+*.mlt
+*.mtc[0-9]*
+*.slf[0-9]*
+*.slt[0-9]*
+*.stc[0-9]*
+
+# minted
+_minted*
+*.pyg
+
+# morewrites
+*.mw
+
+# newpax
+*.newpax
+
+# nomencl
+*.nlg
+*.nlo
+*.nls
+
+# pax
+*.pax
+
+# pdfpcnotes
+*.pdfpc
+
+# sagetex
+*.sagetex.sage
+*.sagetex.py
+*.sagetex.scmd
+
+# scrwfile
+*.wrt
+
+# sympy
+*.sout
+*.sympy
+sympy-plots-for-*.tex/
+
+# pdfcomment
+*.upa
+*.upb
+
+# pythontex
+*.pytxcode
+pythontex-files-*/
+
+# tcolorbox
+*.listing
+
+# thmtools
+*.loe
+
+# TikZ & PGF
+*.dpth
+*.md5
+*.auxlock
+
+# todonotes
+*.tdo
+
+# vhistory
+*.hst
+*.ver
+
+# easy-todo
+*.lod
+
+# xcolor
+*.xcp
+
+# xmpincl
+*.xmpi
+
+# xindy
+*.xdy
+
+# xypic precompiled matrices and outlines
+*.xyc
+*.xyd
+
+# endfloat
+*.ttt
+*.fff
+
+# Latexian
+TSWLatexianTemp*
+
+## Editors:
+# WinEdt
+*.bak
+*.sav
+
+# Texpad
+.texpadtmp
+
+# LyX
+*.lyx~
+
+# Kile
+*.backup
+
+# gummi
+.*.swp
+
+# KBibTeX
+*~[0-9]*
+
+# TeXnicCenter
+*.tps
+
+# auto folder when using emacs and auctex
+./auto/*
+*.el
+
+# expex forward references with \gathertags
+*-tags.tex
+
+# standalone packages
+*.sta
+
+# Makeindex log files
+*.lpz
+
+# xwatermark package
+*.xwm
+
+# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib
+# option is specified. Footnotes are the stored in a file with suffix Notes.bib.
+# Uncomment the next line to have this generated file ignored.
+#*Notes.bib
+
+### LaTeX Patch ###
+# LIPIcs / OASIcs
+*.vtc
+
+# glossaries
+*.glstex
+
+# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,dotnetcore,csharp,latex \ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..0aa9a3f
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,58 @@
+{
+ "files.exclude": {
+ "**/*.aux": true,
+ "**/*.lof": true,
+ // "**/*.log": true,
+ "**/*.lot": true,
+ "**/*.fls": true,
+ "**/*.out": true,
+ "**/*.toc": true,
+ "**/*.fmt": true,
+ "**/*.fot": true,
+ "**/*.cb": true,
+ "**/*.cb2": true,
+ "**/.*.lb": true,
+ "**/*.fdb_latexmk": true,
+ "**/*.synctex": true,
+ "**/*.synctex(busy)": true,
+ "**/*.synctex.gz": true,
+ "**/*.synctex.gz(busy)": true,
+ "**/*.pdfsync": true,
+ "**/*.nav": true,
+ "**/*.pre": true,
+ "**/*.snm": true,
+ "**/*.vrb": true,
+ },
+ "[latex]": {
+ "editor.wordWrap": "wordWrapColumn",
+ "editor.wordWrapColumn": 100,
+ "editor.rulers": [
+ {
+ "column": 100,
+ "color": "#242424"
+ }
+ ],
+ },
+ "[csharp]": {
+ "editor.rulers": [
+ {
+ "column": 90,
+ "color": "#242424"
+ }
+ ],
+ },
+ "ltex.dictionary": {
+ "en-US": [
+ "csharp",
+ "Kollack",
+ "optimality",
+ "SolveSubsetSum",
+ "SubsetSum"
+ ]
+ },
+ "ltex.disabledRules": {
+ "en-US": [
+ "DOUBLE_PUNCTUATION"
+ ]
+ },
+} \ No newline at end of file
diff --git a/docs/Project3SubsetSum.pdf b/docs/Project3SubsetSum.pdf
new file mode 100644
index 0000000..e048de3
--- /dev/null
+++ b/docs/Project3SubsetSum.pdf
Binary files differ
diff --git a/docs/report/__latexindent_temp.tex b/docs/report/__latexindent_temp.tex
new file mode 100644
index 0000000..0036a6e
--- /dev/null
+++ b/docs/report/__latexindent_temp.tex
@@ -0,0 +1,116 @@
+\documentclass[11pt]{scrartcl}
+
+% Metadata
+\title{SubsetSum}
+\subtitle{CS 456: Project 2}
+\author{Neil Kollack and Toby Vincent}
+
+% Packages
+\usepackage{styles/packages}
+\usepackage{styles/header}
+\usepackage{styles/title}
+\usepackage{styles/section}
+\usepackage{csvsimple}
+\usepackage{minted}
+\usepackage{xcolor}
+
+\newcommand{\respectpercent}{\catcode`\%=12\relax}
+
+\begin{document}
+\maketitle
+
+\section{Introduction}
+The goal of this project was to explore and compare two approaches for finding a solution to the Subset Sum problem. The Subset Sum Problem is a general scheduling problem. The main use of Subset Sum is to maximize a specific resource and can be used in a variety of situations, for example: Maximizing the uptime of a single machine. Generally, we have some number of items, $n$, each with a corresponding weight, $w_i$, that does not exceed the maximum weight, $W$, of the resource we're attempting to maximize. The algorithm then uses these weights to find the set of items with the greatest possible valid weight.
+
+The first approach we explored was the greedy algorithm, which finds an approximation of the optimal solution by continually choosing the largest remaining value until adding the largest remaining would exceed the maximum weight. Our implementation of the greedy algorithm is $O(n \log n)$, with the time complexity being dominated by the sorting of the items.
+
+The second approach we explored was the dynamic programming algorithm. This algorithm begins by creating a matrix of size $n \times m$, where n is the number of items, and m is the maximum usable weight. Starting with an empty set of items, and working our way up to a set of all possible items, the matrix is filled with the maximum valid weight that has been found at each step. After each index in the matrix has been iterated over we can then return the final index of the matrix which will contain the maximum valid weight. This process has a runtime of $O(n \cdot m)$ because each index of the matrix must be iterated over.
+
+We implemented these solutions in C\# programming language, due to the languages general robustness and our familiarity with the language. We did not encounter any problems along the way as this was relatively a simple project to program.
+
+\section{Proof\label{proof:greedy}}
+
+\subsection{Assumptions}
+
+We begin by making a few assumptions about the problem:
+
+\begin{enumerate}
+ \item All items have a weight (w): $1 \leq w \leq $ \emph{total weight (T)}
+ \item There are enough items with weights to fill the
+ knapsack at least half full.
+\end{enumerate}
+
+\pagebreak
+
+\subsection{Definition}
+
+The Greedy Algorithm performs as such:
+
+\begin{enumerate}
+ \item Order all items by their weights in descending order. $item_{1} \geq item_{2} \geq ... $
+ \item The current $ Sum = 0 $ and index $ j = 1 $
+ \item If $ Sum + item_{j} \leq T, $ then $ Sum = Sum + item_{j}; $ otherwise end
+ \item If $ j < n $ (Number of Items) return to step 3; otherwise end
+\end{enumerate}
+
+\subsection{Explanation of Proof}
+
+\subsubsection{All Items}
+
+We begin by looking at the Definition of the algorithm. We can see that the algorithm either runs until there are no items left, or it finds an item that is too large to add to the Sum. From there, we make the assumption that if the algorithm runs until there are no remaining items, along with our assumption that there are enough items with weights to fill the knapsack to at least half full, then in this case we can say that the knapsack is at least half full.
+
+\subsubsection{Early Termination}
+
+The other possible scenario is when the algorithm terminates early due to coming across a number that is too large and would thus cause the Sum to exceed the Total Weight. Because of the assumption we made that there are enough items to fill the knapsack to at least half full we can split the Total Weight into two partitions (one that is full, and one that is not full).
+
+Due to the fact that all items are sorted in descending order by their weight, meaning that all items following an item added to our Sum are less than the weight of their predecessor. In this situation, items are added until they cannot be added anymore, which would imply if the algorithm were to terminate early that an item attempting to be added is greater than the size of the "remaining available space" partition. Our assumptions then allow us to say that the unfilled partition is equal to or smaller than the filled partition and that we have filled the knapsack at least half full.
+
+\pagebreak
+
+\section{Results}
+
+\subsection{Comparison of Scores}
+
+\begin{table}[ht]
+ \centering
+ \csvautotabular[before table=\respectpercent]{../../src/Program/scores.csv}
+ \caption{\label{tab:scores} Table showing the optimality of each iteration.}
+\end{table}
+
+As you can see in Table~\ref{tab:scores}, as expected, the dynamic algorithm was able to produce the optimal solution in every iteration. The greedy algorithm's solutions were, on average, only $\sim60\%$ as good as the optimal solution. That being said, as the proof in Section~\ref{proof:greedy} shows, the greedy algorithm always fills the knapsack at least half full.
+
+\pagebreak
+
+\subsection{Comparison of Runtimes}
+
+\begin{table}[ht]
+ \centering
+ \csvautotabular[before table=\respectpercent]{../../src/Program/runtimes.csv}
+ \caption{\label{tab:runtimes} Table showing the runtimes for each iteration.}
+\end{table}
+
+The increased optimality of the dynamic approach comes at a cost. The dynamic algorithm's runtimes were \emph{significantly} (on average $1582.52\%$ with dataset of 1000 items) longer than the greedy approach, as shown in Table~\ref{tab:runtimes}. The difference in runtimes are a result of the much lower $O(n\log n)$ time complexity of the greedy algorithm, compared to the $O(n\cdot m)$ time complexity of the dynamic algorithm. The greedy algorithm is able to have such a low runtime due it's early termination (after finding the first weight that can not be added). The difference demonstrates the trade-off of optimality and speed between the two algorithms.
+
+\pagebreak
+\begin{appendices}
+ \definecolor{bg}{HTML}{282828}
+\setminted{bgcolor=bg,
+ style=monokai,
+ fontsize=\small,
+ linenos,
+ autogobble,
+ baselinestretch=1,
+ }
+ \section{SubsetSum.cs}
+ \label{app:subsetsum}
+
+
+\inputminted{csharp}{../../src/SubsetSum/SolveSubsetSum.cs}
+
+
+\pagebreak
+
+\inputminted{csharp}{../../src/Program/Program.cs}
+
+\end{appendices}
+\end{document} \ No newline at end of file
diff --git a/docs/report/report.pdf b/docs/report/report.pdf
new file mode 100644
index 0000000..f54ac1d
--- /dev/null
+++ b/docs/report/report.pdf
Binary files differ
diff --git a/docs/report/report.tex b/docs/report/report.tex
new file mode 100644
index 0000000..00cd4d5
--- /dev/null
+++ b/docs/report/report.tex
@@ -0,0 +1,109 @@
+\documentclass[11pt]{scrartcl}
+
+% Metadata
+\title{SubsetSum}
+\subtitle{CS 456: Project 2}
+\author{Neil Kollack and Toby Vincent}
+
+% Packages
+\usepackage{styles/packages}
+\usepackage{styles/header}
+\usepackage{styles/title}
+\usepackage{styles/section}
+\usepackage{csvsimple}
+\usepackage{minted}
+\usepackage{xcolor}
+
+\newcommand{\respectpercent}{\catcode`\%=12\relax}
+
+\begin{document}
+\maketitle
+
+\section{Introduction}
+The goal of this project was to explore and compare two approaches for finding a solution to the Subset Sum problem. The Subset Sum Problem is a general scheduling problem. The main use of Subset Sum is to maximize a specific resource and can be used in a variety of situations, for example: Maximizing the uptime of a single machine. Generally, we have some number of items, $n$, each with a corresponding weight, $w_i$, that does not exceed the maximum weight, $W$, of the resource we're attempting to maximize. The algorithm then uses these weights to find the set of items with the greatest possible valid weight.
+
+The first approach we explored was the greedy algorithm, which finds an approximation of the optimal solution by continually choosing the largest remaining value until adding the largest remaining would exceed the maximum weight. Our implementation of the greedy algorithm is $O(n \log n)$, with the time complexity being dominated by the sorting of the items.
+
+The second approach we explored was the dynamic programming algorithm. This algorithm begins by creating a matrix of size $n \times m$, where n is the number of items, and m is the maximum usable weight. Starting with an empty set of items, and working our way up to a set of all possible items, the matrix is filled with the maximum valid weight that has been found at each step. After each index in the matrix has been iterated over we can then return the final index of the matrix which will contain the maximum valid weight. This process has a runtime of $O(n \cdot m)$ because each index of the matrix must be iterated over.
+
+We implemented these solutions in C\# programming language, due to the languages general robustness and our familiarity with the language. We did not encounter any problems along the way as this was relatively a simple project to program.
+
+\section{Proof\label{proof:greedy}}
+
+\subsection{Assumptions}
+
+We begin by making a few assumptions about the problem:
+
+\begin{enumerate}
+ \item All items have a weight (w): $1 \leq w \leq $ \emph{total weight (T)}
+ \item There are enough items with weights to fill the
+ knapsack at least half full.
+\end{enumerate}
+
+\pagebreak
+
+\subsection{Definition}
+
+The Greedy Algorithm performs as such:
+
+\begin{enumerate}
+ \item Order all items by their weights in descending order. $item_{1} \geq item_{2} \geq ... $
+ \item The current $ Sum = 0 $ and index $ j = 1 $
+ \item If $ Sum + item_{j} \leq T, $ then $ Sum = Sum + item_{j}; $ otherwise end
+ \item If $ j < n $ (Number of Items) return to step 3; otherwise end
+\end{enumerate}
+
+\subsection{Explanation of Proof}
+
+\subsubsection{All Items}
+
+We begin by looking at the Definition of the algorithm. We can see that the algorithm either runs until there are no items left, or it finds an item that is too large to add to the Sum. From there, we make the assumption that if the algorithm runs until there are no remaining items, along with our assumption that there are enough items with weights to fill the knapsack to at least half full, then in this case we can say that the knapsack is at least half full.
+
+\subsubsection{Early Termination}
+
+The other possible scenario is when the algorithm terminates early due to coming across a number that is too large and would thus cause the Sum to exceed the Total Weight. Because of the assumption we made that there are enough items to fill the knapsack to at least half full we can split the Total Weight into two partitions (one that is full, and one that is not full).
+
+Due to the fact that all items are sorted in descending order by their weight, meaning that all items following an item added to our Sum are less than the weight of their predecessor. In this situation, items are added until they cannot be added anymore, which would imply if the algorithm were to terminate early that an item attempting to be added is greater than the size of the "remaining available space" partition. Our assumptions then allow us to say that the unfilled partition is equal to or smaller than the filled partition and that we have filled the knapsack at least half full.
+
+\section{Results}
+
+\subsection{Comparison of Scores}
+
+\begin{table}[ht]
+ \centering
+ \csvautotabular[before table=\respectpercent]{../../src/Program/scores.csv}
+ \caption{\label{tab:scores} Table showing the optimality of each iteration.}
+\end{table}
+
+As you can see in Table~\ref{tab:scores}, as expected, the dynamic algorithm was able to produce the optimal solution in every iteration. The greedy algorithm's solutions were, on average, only $\sim60\%$ as good as the optimal solution. That being said, as the proof in Section~\ref{proof:greedy} shows, the greedy algorithm always fills the knapsack at least half full.
+
+
+\subsection{Comparison of Runtimes}
+
+\begin{table}[ht]
+ \centering
+ \csvautotabular[before table=\respectpercent]{../../src/Program/runtimes.csv}
+ \caption{\label{tab:runtimes} Table showing the runtimes for each iteration.}
+\end{table}
+
+The increased optimality of the dynamic approach comes at a cost. The dynamic algorithm's runtimes were \emph{significantly} (on average $1582.52\%$ with dataset of 1000 items) longer than the greedy approach, as shown in Table~\ref{tab:runtimes}. The difference in runtimes are a result of the much lower $O(n\log n)$ time complexity of the greedy algorithm, compared to the $O(n\cdot m)$ time complexity of the dynamic algorithm. The greedy algorithm is able to have such a low runtime due it's early termination (after finding the first weight that can not be added). The difference demonstrates the trade-off of optimality and speed between the two algorithms.
+
+\clearpage
+\appendix
+ \definecolor{bg}{HTML}{f2f2f2}
+ \setminted{bgcolor=bg,
+ fontsize=\small,
+ linenos,
+ autogobble,
+ baselinestretch=1,
+ }
+
+ \section{SubsetSum.cs}
+ \label{app:subsetsum}
+ \inputminted{csharp}{../../src/SubsetSum/SolveSubsetSum.cs}
+
+ \section{Program.cs}
+ \label{app:program}
+ \inputminted{csharp}{../../src/Program/Program.cs}
+
+\end{document} \ No newline at end of file
diff --git a/docs/report/styles/header.sty b/docs/report/styles/header.sty
new file mode 100644
index 0000000..b86e98e
--- /dev/null
+++ b/docs/report/styles/header.sty
@@ -0,0 +1,35 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{styles/header}[2021/09/29 Header style]
+
+% ┌───────────────────────────────────┐
+% │ Title: Subtitle │ ──┬─ [Header]
+% │ Author │ ──┘
+% │ Title │ ──┬─ Title
+% │ Subtitle │ ──┘
+% │ │
+% │ A Section │ ──┬─ Sections
+% │ ... │ │
+% │ 1.1 A Subsection │ ──┤
+% │ ... │ │
+% │ Another Section │ ──┤
+% │ ... │ │
+% │ 2.1 A Subsection │ ──┤
+% │ ... │ │
+% │ 2.2 Another Subsection │ ──┘
+% │ ... │
+% │ │
+% │ │
+% └───────────────────────────────────┘
+
+\pagestyle{myheadings}
+
+\newsavebox{\headingbox}
+\sbox{\headingbox}{%
+ \begin{minipage}[b]{0.5\textwidth}
+ \begin{flushright}
+ \@title \\
+ \@subtitle \\
+ \@author \\
+ \end{flushright}
+ \end{minipage}}
+\markright{\hfill\usebox{\headingbox}}
diff --git a/docs/report/styles/packages.sty b/docs/report/styles/packages.sty
new file mode 100644
index 0000000..262b9d1
--- /dev/null
+++ b/docs/report/styles/packages.sty
@@ -0,0 +1,12 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{styles/packages}[2021/09/29 Package imports]
+
+\RequirePackage[english]{babel}
+\RequirePackage[letterpaper,top=2.54cm,bottom=2.54cm,left=2.54cm,right=2.54cm,marginparwidth=1.75cm]{geometry}
+\RequirePackage{lipsum}
+\RequirePackage{array}
+\RequirePackage[colorlinks=true, allcolors=blue]{hyperref}
+\RequirePackage[autostyle, english = american]{csquotes}
+
+% Styles
+\MakeOuterQuote{"} \ No newline at end of file
diff --git a/docs/report/styles/section.sty b/docs/report/styles/section.sty
new file mode 100644
index 0000000..ed4d606
--- /dev/null
+++ b/docs/report/styles/section.sty
@@ -0,0 +1,35 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{styles/section}[2021/09/29 Section style]
+
+% ┌───────────────────────────────────┐
+% │ Title: Subtitle │ ──┬─ Header
+% │ Author │ ──┘
+% │ Title │ ──┬─ Title
+% │ Subtitle │ ──┘
+% │ │
+% │ A Section │ ──┬─ [Sections]
+% │ ... │ │
+% │ 1.1 A Subsection │ ──┤
+% │ ... │ │
+% │ Another Section │ ──┤
+% │ ... │ │
+% │ 2.1 A Subsection │ ──┤
+% │ ... │ │
+% │ 2.2 Another Subsection │ ──┘
+% │ ... │
+% │ │
+% │ │
+% └───────────────────────────────────┘
+
+\RequirePackage{indentfirst}
+% \RequirePackage{titlesec}
+% \titlespacing*{\section}{0pt}{1.1\baselineskip}{\baselineskip}
+
+% Paragraph spacing
+\setlength{\parskip}{1em}
+
+\RedeclareSectionCommand[
+ afterindent=false,
+ beforeskip=.5\baselineskip,
+ afterskip=.5\baselineskip
+]{section} \ No newline at end of file
diff --git a/docs/report/styles/title.sty b/docs/report/styles/title.sty
new file mode 100644
index 0000000..fdeabbe
--- /dev/null
+++ b/docs/report/styles/title.sty
@@ -0,0 +1,29 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{styles/title}[2021/09/29 Title style]
+
+% ┌───────────────────────────────────┐
+% │ Title: Subtitle │ ──┬─ Header
+% │ Author │ ──┘
+% │ Title │ ──┬─ [Title]
+% │ Subtitle │ ──┘
+% │ │
+% │ A Section │ ──┬─ Sections
+% │ ... │ │
+% │ 1.1 A Subsection │ ──┤
+% │ ... │ │
+% │ Another Section │ ──┤
+% │ ... │ │
+% │ 2.1 A Subsection │ ──┤
+% │ ... │ │
+% │ 2.2 Another Subsection │ ──┘
+% │ ... │
+% │ │
+% │ │
+% └───────────────────────────────────┘
+
+\renewcommand{\maketitle}{
+ \begin{flushleft}
+ {\Huge \bfseries \sffamily \@title }\\[2ex]
+ {\Large \sffamily \@subtitle }\\[4ex]
+ \end{flushleft}
+}
diff --git a/src/Program/runtimes.csv b/src/Program/runtimes.csv
new file mode 100644
index 0000000..c2945d0
--- /dev/null
+++ b/src/Program/runtimes.csv
@@ -0,0 +1,12 @@
+Iteration,Dynamic (ms),Greedy (ms),Runtime Factor
+1,3.0493,2.3276,131.01%
+2,2.0367,0.0984,2069.82%
+3,2,0.0078,25641.03%
+4,1.9843,0.0081,24497.53%
+5,2.0263,0.0097,20889.69%
+6,1.5457,0.0063,24534.92%
+7,1.6297,0.0086,18950.00%
+8,1.7441,0.0104,16770.19%
+9,3.9223,0.0084,46694.05%
+10,1.3263,0.0073,18168.49%
+Average,2.1265,0.2492,853.33%
diff --git a/src/Program/scores.csv b/src/Program/scores.csv
new file mode 100644
index 0000000..88b243d
--- /dev/null
+++ b/src/Program/scores.csv
@@ -0,0 +1,12 @@
+Iteration,Dynamic (Exact),Greedy (Approx.),Approximation Factor
+1,999,586,58.66%
+2,999,595,59.56%
+3,999,597,59.76%
+4,999,597,59.76%
+5,999,599,59.96%
+6,999,595,59.56%
+7,999,598,59.86%
+8,999,596,59.66%
+9,999,596,59.66%
+10,999,597,59.76%
+Average,999,594,59.46%