\newcommand{\CLASSINPUTtoptextmargin}{2cm}
\newcommand{\CLASSINPUTbottomtextmargin}{2cm}
\documentclass[journal,10pt,a4paper]{IEEEtran}
\usepackage{graphicx}
\usepackage{chngpage}
\usepackage{amsmath}
\usepackage{multirow}
\newcommand{\subparagraph}{}
% \usepackage [english]{babel}
% \usepackage [autostyle, english = american]{csquotes}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepackage{mathtools}
\usepackage{multicol}
\usepackage{titlesec}
\usepackage{gensymb}
\usepackage[justification=centering]{caption}
\usepackage{amsmath}
\usepackage{algorithm}
\usepackage[noend]{algpseudocode}
\usepackage{url}
\usepackage[final]{pdfpages}
%\usepackage{appendix}
\usepackage{float}
\usepackage{listings}
\usepackage{subfig}
 \usepackage[
    backend=biber,
    style=ieee,
  ]{biblatex}
\addbibresource{main.bib}
\setlength{\parskip}{0.5
em}

\renewcommand{\baselinestretch}{1.5}

\definecolor{mygreen}{rgb}{0,0.6,0}
\definecolor{mygray}{rgb}{0.5,0.5,0.5}
\definecolor{mymauve}{rgb}{0.58,0,0.82}

\lstset{language=python,
breaklines=true,
commentstyle=\color{mygreen},
 keywordstyle=\color{blue},
 stringstyle=\color{mymauve},
 morecomment=[l]{//}}

% *** GRAPHICS RELATED PACKAGES ***
%
\ifCLASSINFOpdf
  % \usepackage[pdftex]{graphicx}
  % declare the path(s) where your graphic files are
  % \graphicspath{{../pdf/}{../jpeg/}}
  % and their extensions so you won't have to specify these with
  % every instance of \includegraphics
  % \DeclareGraphicsExtensions{.pdf,.jpeg,.png}
\else
  % or other class option (dvipsone, dvipdf, if not using dvips). graphicx
  % will default to the driver specified in the system graphics.cfg if no
  % driver is specified.
  % \usepackage[dvips]{graphicx}
  % declare the path(s) where your graphic files are
  % \graphicspath{{../eps/}}
  % and their extensions so you won't have to specify these with
  % every instance of \includegraphics
  % \DeclareGraphicsExtensions{.eps}
\fi

% correct bad hyphenation here
\hyphenation{op-tical net-works semi-conduc-tor}

\graphicspath{{imgs/}{}}
\begin{document}
%
% paper title
% Titles are generally capitalized except for words such as a, an, and, as,
% at, but, by, for, in, nor, of, on, or, the, to and up, which are usually
% not capitalized unless they are the first or last word of the title.
% Linebreaks \\ can be used within to get better formatting as desired.
% Do not put math or special symbols in the title.
\title{A Comparison of MPI Two-Sided and One-Sided Communication Performance}

\author{Junaid Dawood (1094837), Xongile Nghatsane (1110680), Marissa van Wyngaardt (719804)}% <-this % stops a space

\maketitle

% As a general rule, do not put math, special symbols or citations
% in the abstract or keywords.

\begin{abstract}
This report presents a performance comparison of MPI's one-sided and two-sided approaches to inter-process communication. This performance comparison is made with reference to implementations of a parallel block-based matrix transposition algorithm which scales with the number of processes used. Results from the testing conducted suggest that the two-sided approach offers superior performance for sufficiently large matrices. In addition, it is found that the use of a collective I/O based scheme is a viable alternative to the two main strategies presented within this report, regardless of the communication method used.

\end{abstract}

\IEEEpeerreviewmaketitle

\section{Introduction}
Message Passing Interface (MPI) is a message passing standard which is designed to function on a diverse range of parallel computing architectures \cite{MPIAMess20:online}. Message passing typically achieves parallelism through messages passed between processes in order to transfer data. Popular implementations of the MPI standard for message passing include OpenMPI and MPICH \cite{ompi,mpich}.

MPI typically facilitates the use of the `single-program-multiple-data' (SPMD) parallelism model, as all nodes essentially run the same program. However, this is not required as many MPI implementations allow for multiple executables to exist within one MPI job.

This report presents a performance comparison of two MPI-based implementations of block-based matrix transposition \cite{transp}, parallelised amongst many processes. These implementations differ in the type of communication used: the first makes use of MPI's typical two-sided communication, using \textit{Send} and \textit{Recv}. The second implementation uses MPI's one-sided communication \cite{one}, making use of \textit{Windows} and \textit{Get}.

\section{Background}

MPI's communication model is typically point-to-point in nature. That is, inter-process communication wherein both the receiver and sender are specified. That said, MPI also allows for \textit{broadcast} and \textit{receive-from-any} communication. MPI communication is typically two-sided i.e. it consists of distinct send and receive stages. For every send there must be an associated receive (if data is to actually reach its destination). Depending on the MPI implementation, a process may need its sent message to be acknowledged by a receiver, through a \textit{Recv} call, before it can continue with the rest of its processing.

In addition, MPI allows for one-sided communication, which was included in the MPI-2 standard \cite{one,one1}. One-sided communication removes the necessity for the acknowledgement that exists within the conventional two-sided approach. Essentially, one-sided communication consists of making a \textit{Window} of a process' address space accessible to other processes; with the host process facilitating the opening and closing of the \textit{Window}. Other processes can then write or read from the \textit{Window}, as long as it remains open. This removes the need for the host process to wait for acknowledgements from those processes which require data that it holds.

\subsection{Problem Description and Success Criteria}

The brief problem statement included in the introduction must be expanded so as to fully describe the nature of this research. The matrix transposition implementation is intended to work on large data sets; which are to be stored, out-of-core, in external files. Note: matrices are stored in row major order within binary files for all implementations; individual matrix items are of the \textit{short} data type.

The transposition implementations must be parallelised using the two MPI approaches mentioned earlier, i.e. both one-sided and two-sided communication.

As described in the introduction, the algorithms discussed in this report pertain specifically to `block-based' matrix transposition algorithms. This essentially entails splitting a large matrix into equally sized submatrices, transposing these submatrices, and then performing the appropriate submatrix swaps.

Assuming there is a $N\times N$ matrix $A$ which can be written in terms of its $K \times K$ submatrices:

\begin{equation}
A=
\begin{bmatrix}
    W       & X \\
   Y&Z \\
\end{bmatrix}
\end{equation}

it can be proved that:
\begin{equation}
    A^T=
\begin{bmatrix}
    W^T       & Y^T \\
   X^T&Z^T \\
\end{bmatrix}
\end{equation}

This can be generalised to any square matrix which can be split into submatrices of equal size. However, this research focuses on square matrices of dimension $2^x$ by $2^x$, where $x$ is an integer satisfying $x\geq 3$. The block-based approach is limited to a minimum submatrix dimension of $2\times 2$, as there is no smaller meaningful block size. That said, it is likely that splitting input matrices into such small submatrices will involve larger communication overhead, leading to lower performance. However, this is more formally discussed later in this report.

\section{Conventional Implementation}

This implementation of the block-based transposition can be discussed in 4 stages: 1) Generation of matrix data, 2) Performing per-process transpositions, 3) Transmission of data to the master node, and 4) Writing of results to a file by the master node. Essentially, each process generates its own submatrix, transposes it, and passes the transposed matrix to the master process, which subsequently writes the entire transposed matrix to a file.

%Note that the differences between the one-sided and two-sided communication approaches only manifests within the third stage of the implementation.

\subsection{Generating Matrix Data}

Matrix data is generated on a per-process basis, through typical random number generation techniques. Each process generates its own, equally sized, submatrix. The size of the submatrices is determined by the desired size of the overall matrix which is being transposed. If the number of available processes is so large that an even distribution would yield submatrices smaller than $2 \times 2$, then some processes are left out of the transposition entirely, in order to impose the $2 \times 2$ minimum submatrix size. Similarly, processes are sometimes excluded to ensure that each process only ever performs a transposition on a single square submatrix.

%The reading operations used within this implementation are MPI's collective I/O functions, specifically the \textit{MPI File read all} function. Each process defines its own file view based on a common \textit{filetype}, as described below, and different offset value. In doing so, each process is able to appropriately read the data for its associated submatrix, despite reads being done collectively.

\subsection{Performing Submatrix Transpositions}

Each process, upon completing its submatrix generation, then performs a transposition on said submatrix. This submatrix transposition is done using a naive approach, which is parallelised using OpenMP \cite{omp}. The naive approach entails the typical per-element row-to-column coordinate transformation swaps.

\subsection{Data Transmission}

Within this two-sided communication approach, all participating processes will send their submatrices to the master node (rank 0) upon completing their respective transpositions. This is done through typical \textit{Send} and \textit{Recv} semantics. Essentially, the master node will receive each submatrix as a contiguous buffer, storing all of the received submatrices within a single, larger, contiguous buffer which is held locally.

\subsection{Writing of Transposed Matrix to File}

The master node is responsible for writing the transposed matrix to an output file. This is implemented using the \textit{File-write} and \textit{File-write-at} functions. The master node performs the necessary calculations for transforming its continuous buffer representation of the matrix to the final row-major ordered contents of the output file. This involves calculating write offsets for each submatrix and writing these submatrices at the locations specified by said offsets. Each row of each submatrix is written consecutively; applying an offset equivalent to the size of the original matrix ($N$), after writing each row.

\section{One-Sided Approach}

The implementation of the one-sided approach is largely the same as the conventional \textit{Send} and \textit{Recv} implementation. The one-sided implementation differs only in the way in which data is exchanged between processes and the way in which data is written to the output file.

\subsection{Generating Matrix Data}
Like the two-sided approach, submatrices are generated on a per-process basis. As before, processes are sometimes excluded to maintain a minimum block size of $2 \times 2$, or to maintain square submatrices.

\subsection{Performing Submatrix Transpositions}
For accurate performance comparison, the one-sided approach does not attempt to improve on the parallelised naive approach used in the two-sided implementation.

\subsection{Data Transmission}
This implementation makes use of MPI's one-sided communications for data transmission. All participating processes open a \textit{Window}; placing their local submatrix buffers within their respective \textit{Windows}. The master node then performs \textit{Get} operations on the contents of all of these windows, such that it acquires all of the transposed submatrices required to construct the overall transposed matrix. The submatrices obtained through the \textit{Get} operations are stored within a single contiguous buffer on the master node.

\subsection{Writing of Transposed Matrix to File}

Like before, the master node is responsible for writing the contents of a contiguous buffer to an output file. However, this approach makes use of an MPI derived type in order to do so. Specifically, the MPI \textit{Vector} derived type is used to set a \textit{file view} for the writing of each submatrix to the output file. The stride length used for this derived data type is equal to the row length of the overall matrix $N$, the block length is equal to the row length of the submatrices $k$, and the count is equal to $N \times k$, as shown in figure \ref{fig:stride}. Constructing the file view in this way allows each submatrix to be written to the file within a single write call; unlike the I/O strategy used in the two-sided approach.

\begin{figure}[H]
    \centering
    \includegraphics[width=0.35\textwidth]{stride.pdf}
    \caption{Derived type file view mapping.}
    \label{fig:stride}
\end{figure}

% \section{PGAS (UPC) Implementation}
% The UPC implementation is almost entirely the same as the MPI implementation discussed earlier. The only difference is the way in which inter-process data sharing is implemented. That is, the writing and reading of transposed matrices to a global array as opposed to fetching the matrices directly, from corresponding processes.

% \subsection{Reading Input Data}
% The reading of input data is implemented in manner which is almost identical to the MPI approach. All of UPC's I/O read/write functions are collective; thus an accurate comparison can be made between the UPC implementation and the MPI implementation.

% Achieving non-contiguous file reading in BUPC, using its LIST I/O functions, is far more complex than the use of file views and offsets. Indeed, the process is more manual in nature, to the extent that no real simplification is offered. Thus, within this implementation \textit{strided} reading and writing of files is implemented manually using typical BUPC collective I/O functions as opposed to the LIST I/O functionality present.

% \subsection{Submatrix Transpositions}
% The transposition of submatrices in the UPC implementation is implemented in exactly the same way as the submatrix transposition of the MPI implementation, i.e. a naive approach. This is done so as to ensure no bias in performance comparisons.

% \subsection{Writing to the Shared Array}
% After transposing their respective submatrices, processes will write the contents of said submatrices in row-major order. The write locations are based on the intended output locations of the submatrix i.e. the write locations incorporate the block swapping step implicitly. That is, the offset used in this write step is equivalent to the offset used by the corresponding process in the reading-in phase.

% \subsection{Writing Output Data}

% Again, the writing of output data is almost identical to the MPI implementation, with the exception of the use of an explicit \textit{seek} method as described earlier. Data is copied directly from the shared array to the file using the \textit{upc all fwrite shared} function. That is, there is no need to copy the shared data to a local buffer before writing said data to a file.

% \subsection{Limitations}
% As is the case for the MPI implementation, submatrices must be at least $2x2$ in size.

\section{Alternative Collective I/O Implementations}

Two alternative approaches are implemented to demonstrate the use of collective I/O in MPI \cite{io,io2} i.e. \textit{Read all} and \textit{Write all}. It is thought that these implementations will be able to highlight the bottleneck which occurs when a single node is responsible for performing I/O. These two alternatives differ in that one makes use of one-sided communication and the other, two-sided. This is done to afford fair, independent, comparisons of the use of collective I/O with the implementations discussed earlier.

\subsection{Input Data Generation}

Both of the collective I/O alternatives source their matrix data from an external file. This file is read from using a non-contiguous \textit{file view}: these \textit{file views} are consistent across all involved processes, except for the offsets used. The involved processes make use of a single collective \textit{Read all} call to populate their local submatrix buffers with values read from the file.

%This is very similar the approach used for the writing of output data for the original one-sided communication approach.

\subsection{Submatrix Transposition}
Submatrix transposition remains unchanged from the parallelised naive approach discussed earlier. This ensures fairness of comparison between the alternatives and the two original approaches.

\subsection{Data Transmission}

Since the goal of these alternatives is the use of collective I/O, neither of the two alternatives require the sending of data to a master node for I/O purposes. Thus, processes need only swap their transposed submatrices with those of corresponding processes. The mapping of these swaps is described by the diagram shown below: there is essentially a block-level transposition which occurs in this process.

\begin{figure}[H]
    \centering
    \includegraphics[width=0.3\textwidth]{block.pdf}
    \caption{Mapping of inter-process block swapping.}
    \label{fig:my_label}
\end{figure}

Of course, one of the alternatives does this through typical MPI \textit{Send} and \textit{Recv} commands, whilst the other makes use of \textit{Windows} and \textit{Get} operations.

% That said, this is no different to the two approaches.

\subsection{Writing Output Data}

This step is very similar to the initial input data reading step. Once a process has obtained its corresponding block data, it is able to write this block to the output file. This is done through the use of a derived data type (\textit{Vector}) used to create a \textit{file view} such that each process can write its entire submatrix to a file within a single collective \textit{Write all} call.% Again, MPI's collective I/O is used in the form of the \texit{MPI File write all} function.

It should be noted that the offsets and file type used to define file views used when writing to the output file are the same as those used when reading data from the input file, for any given process. The following two diagrams contrast the nature of the collective I/O approaches and the two approaches discussed earlier.

\begin{figure}[H]
    \centering
    \includegraphics[width=0.3\textwidth]{norm.pdf}
    \caption{General structure of two main approaches.}
    \label{fig:my_label}
\end{figure}

\begin{figure}[H]
    \centering
    \includegraphics[width=0.45\textwidth]{col.pdf}
    \caption{General structure of two collective approaches.}
    \label{fig:my_label}
\end{figure}

\subsection{Limitations}
Since both of these approaches rely, inflexibly, on evenly distributing blocks amongst threads, they are incapable of catering to scenarios in which the number of available processes is greater than the number of $2\times 2$ blocks which can be yielded from the input matrix.

\section{Testing Environment and Procedure}

The implementations were sequentially tested on a cluster with NFS support. The number of processes used included 16, 32, and 64. Input matrices ranged in size from $8\times 8$ to $128\times 128$. Combinations of process count and matrix size were constrained to comply with the minimum $2\times 2$ block size for the two collective I/O alternatives discussed earlier. In addition, work divisions which do not yield square submatrices were not used for these two approaches.

%The two reference implementations do not require such restrictions.

\section{Results and Discussion}

This section contains the results of benchmarking the performance of the implemented approaches. This includes comparisons relating to the number of processes used for a single implementation, as well as inter-implementation comparisons. In addition, results are shown for some tests in which OpenMP compiler flags were not included, i.e. tests in which intra-process transpositions ran serially.

It is clear from figures \ref{fig:2s} and \ref{fig:1s} that there is a lack of scaling of performance with respect to process count. This is thought to be as a result of the somewhat small input matrix sizes used. That is, the communication overhead incurred as a result of the higher process count is not outweighed by the extra computing power available, due to the limited complexity of the work done by each process.

In a similar vein, the use of OpenMP to parallelise the intra-block transpositions incurs a significant overhead considering the small size of the individual submatrices. This is confirmed by the graph in figure \ref{fig:omp}.

A performance comparison which considers slightly larger matrix sizes can be seen in the figures \ref{fig:big} and \ref{fig:big1}. These results surprisingly confirm the trend observed within the original result set with respect to scaling with the number of processes used. In addition, disabling OpenMP within these tests yielded superior performance, similar to earlier results.

\vspace*{0.5cm}

\begin{figure}[H]
    \centering
    \begin{tikzpicture}
	\begin{axis}[
		    width= 0.4\textwidth,
		xlabel=Matrix Size (N),
		ylabel= Runtime (s),
		legend style={at={(0.97,0.5)},anchor=east}
	]
	\addplot coordinates {
		(8,0.224177)
		(16,0.280450)
		(32,0.213982)
		(64,0.198379)
		(128,0.233636)
	};
	\addplot coordinates {
		(8,0.478097)
		(16,0.518854)
		(32,0.489009)
		(64,0.488895)
		(128,0.436166)
	};
		\addplot coordinates {
		(8,0.762709)
		(16,0.966094)
		(32,1.188930)
		(64,0.946254)
		(128,0.962705)
	};
	\legend{16 P , 32 P, 64 P}

	\end{axis}
\end{tikzpicture}
    \caption{Performance of two-sided approach (OpenMP enabled).}
    \label{fig:2s}
\end{figure}

\newpage

\begin{figure}[H]
    \centering
    \begin{tikzpicture}
	\begin{axis}[
		    width= 0.4\textwidth,
		xlabel=Matrix Size (N),
		ylabel= Runtime (s),
		legend style={at={(0.97,0.5)},anchor=east}
	]
	\addplot coordinates {
		(8,0.228269)
		(16,0.242761)
		(32,0.326208)
		(64,0.218681)
		(128,0.258782)
	};
	\addplot coordinates {
		(8,0.551051)
		(16,0.508958)
		(32,0.484323)
		(64,0.542927)
		(128,0.482365)
	};
		\addplot coordinates {
		(8,0.862081)
		(16,1.130423)
		(32,1.081878)
		(64,1.177069)
		(128,1.066901)
	};
	\legend{16 P , 32 P, 64 P}

	\end{axis}
\end{tikzpicture}
    \caption{Performance of one-sided approach (OpenMP enabled).}
    \label{fig:1s}
\end{figure}

\vspace*{0.5cm}

\begin{figure}[H]
    \centering
    \begin{tikzpicture}
	\begin{axis}[
	    width= 0.4\textwidth,
		xlabel=Matrix Size (N),
		ylabel= Runtime (s),
		legend style={nodes={scale=0.7, transform shape}},
		legend pos= north east
	]
	\addplot coordinates {
		(8,0.105187)
		(16,0.104198)
		(32,0.132922)
		(64,0.109620)
		(128,0.129877)
	};
	\addplot coordinates {
		(8,0.224177)
		(16,0.280450)
		(32,0.213982)
		(64,0.198379)
		(128,0.233636)
	};

		\addplot coordinates {
		(8,0.115883)
		(16,0.165516)
		(32,0.148850)
		(64,0.129649)
		(128,0.146684)
	};
	\addplot coordinates {
		(8,0.228269)
		(16,0.242761)
		(32,0.326208)
		(64,0.218681)
		(128,0.258782)
	};

	\legend{Disabled (2-S), Enabled (2-S), Disabled  (1-S), Enabled (1-S)}

	\end{axis}
\end{tikzpicture}
    \caption{Performance comparison between OpenMP disabled and enabled for 16 processes.}
    \label{fig:omp}
\end{figure}

\vspace*{0.5cm}

\begin{figure}[H]
    \centering
    \begin{tikzpicture}
	\begin{axis}[
		    width= 0.4\textwidth,
		xlabel=Matrix Size (N),
		ylabel= Runtime (s),
		legend style={nodes={scale=0.7, transform shape}},
		legend pos = north west,
		ymax=0.5
	]
	\addplot coordinates {
		(256,0.231613)
		(512,0.260713)
	};

	\addplot coordinates {
		(256,0.299458)
		(512,0.363528)
	};

	\addplot coordinates {
		(256,0.146664)
		(512,0.204521)
	};

	\addplot coordinates {
		(256,0.176657)
		(512,0.168012)
	};

	\legend{16 P (Enabled) (2-S) , 	16 P (Enabled) (1-S) , 	16 P (Disabled) (2-S) ,
	16 P (Disabled) (1-S)
	}

	\end{axis}
\end{tikzpicture}
    \caption{Performance on larger input matrices on 16 processes.}
    \label{fig:big}
\end{figure}
\clearpage

\begin{figure}[H]
    \centering
    \begin{tikzpicture}
	\begin{axis}[
		    width= 0.4\textwidth,
		xlabel=Matrix Size (N),
		ylabel= Runtime (s),
		legend style={nodes={scale=0.7, transform shape}},
		legend pos = north west
	]

	\addplot coordinates {
		(256,1.296295)
		(512,1.381453)
		(1024,1.575437)
	};

	\addplot coordinates {
		(256,1.692052)
		(512,1.964053)
		(1024,3.092419)
	};

	\addplot coordinates {
		(256,0.943346)
		(512,0.999363)
		(1024,0.897483)
	};

	\addplot coordinates {
		(256,1.080550)
		(512,1.365825)
		(1024,2.704662)
	};

	\legend{64 P (Enabled) (2-S),
	64 P (Enabled) (1-S),
	 64 P (Disabled) (2-S),
	 64 P (Disabled) (1-S)
	}

	\end{axis}
\end{tikzpicture}
    \caption{Performance on larger input matrices on 64 processes.}
    \label{fig:big1}
\end{figure}

 From the gathered results, there is seemingly a significant performance increase granted by the use of a conventional two-sided approach, for sufficiently large matrix sizes. This is surprising given the motivation for the use of one-sided communication discussed earlier. However, this is thought to be due to the presented one-sided implementation not exercising the non-blocking nature of one-sided communication in a meaningful way. That is, the master node still waits for the submatrix data from all involved process before writing the submatrices to an output file.

The following two graphs contain the results of the final area of testing, with respect to the two collective I/O alternative implementations discussed earlier. These tests also involved considerations of the overhead incurred through the use of OpenMP.

\begin{figure}[H]
    \centering
    \begin{tikzpicture}
	\begin{axis}[
		    width= 0.4\textwidth,
		xlabel=Matrix Size (N),
		ylabel= Runtime (s),
		legend pos = north east,
		legend style={nodes={scale=0.7, transform shape}}
	]
	\addplot coordinates {
		(8,0.270321)
		(16,0.270978)
		(32,0.246758)
		(64,0.235585)
		(128,0.249943)
	};

	\addplot coordinates {
		(8,0.346623)
		(16,0.249385)
		(32,0.240413)
		(64,0.248359)
		(128,0.250362)
	};

	%%%%%%omp disabled
		\addplot coordinates {
		(8,0.150964)
		(16,0.131235)
		(32,0.150148)
		(64,0.149216)
		(128,0.133470)
	};

	\addplot coordinates {
		(8,0.158397)
		(16,0.102384)
		(32,0.141484)
		(64,0.163831)
		(128,0.15932)
	};

	\legend{OpenMP Enabled(2-S),OpenMP Enabled(1-S),
	OpenMP Disabled(2-S) ,OpenMP Disabled(1-S)
	}

	\end{axis}
\end{tikzpicture}
    \caption{Performance of Collective I/O alternatives for 16 processes.}
    \label{fig:my_label}
\end{figure}

\begin{figure}[H]
    \centering
    \begin{tikzpicture}
	\begin{axis}[
	    width= 0.4\textwidth,
		xlabel=Matrix Size (N),
		ylabel= Runtime (s),
		ymax=2.5,
		legend pos = north west,
		legend style={nodes={scale=0.7, transform shape}}
	]

		\addplot coordinates {
		(32,1.249711)
		(64,1.275041)
		(128,1.285603)
	};

	\addplot coordinates {
	(32,1.360132)
	(64,1.564082)
	(128,1.575504)
	};
	%%%%%%omp disabled

		\addplot coordinates {
		(32,0.980119)
		(64,0.980997)
		(128,0.894097)
	};

	\addplot coordinates {
	(32,0.960419)
	(64,0.743439)
	(128,0.853294)
	};

	\legend{OpenMP Enabled(2-S),OpenMP Enabled(1-S),
	OpenMP Disabled(2-S) ,OpenMP Disabled(1-S)
	}

	\end{axis}
\end{tikzpicture}
    \caption{Performance of Collective I/O alternatives for 64 processes.}
    \label{fig:my_label}
\end{figure}

The collective I/O alternative tests largely confirm the trends observed within the core performance analysis with reference to scaling, the use of OpenMP, and the communication method employed. One notable aspect is the similarity of the actual performance of the collective I/O approaches and the original two implementations. This is despite the fact that the collective I/O implementation reads input data from an external file, which would presumably involve greater latency.

\section{Critique and Future Improvements}
This section discusses the possible critiques that could be made of the presented implementations. Where possible, potential solutions or improvements are described alongside these critiques.

\subsection{No Redundancy in Implementations}

None of the presented implementations incorporates fail-safe functionality which would ensure that all jobs are completed despite the loss of a process or node. This is primarily because of the implicit mapping which has been used in all implementations; to link submatrices to individual processes. A more robust approach would be to make use of a job queue coordinated by a master process; wherein jobs are taken by idle processes and ultimately removed upon completion. If a process were to become unavailable, then the job of that process could be re-added to the queue, such that another process would perform said job. This redundancy would allow for the matrix transposition to be completed in the event of a loss of processes.

\subsection{Inefficient Work-Sharing}
The job queue strategy mentioned above would also be of help with respect to the ease with which fair work sharing can be achieved.

There are two drawbacks in the current work sharing implementation: 1) the exclusion of processes to maintain at least $2\times2$ submatrices, and 2) the exclusion of processes to maintain square submatrices. The exclusion of processes is, of course, only an inefficiency for significantly large matrices. That is, based on the results of the tests conducted this is not really a concern for small matrices.

A job queue strategy would do little to assist with the issue of maintaining a minimum submatrix size. However, with respect to the second issue, the use of a job queue would guarantee that more of the requested process actually perform a task within the MPI job. This would, however, be at the expense of the use of smaller submatrices, whereas excluding processes obviously has the opposite effect. Thus, further testing would be required to verify whether a performance increase is actually granted by this alternative, as there may be (communication) overhead incurred due to the use of smaller submatrices.

\vspace*{-0.3 cm}

\subsection{Inefficient Implementations of Submatrix Transpositions}

As discussed earlier, the algorithm used to transpose the submatrices is a parallelised naive approach. Given the size of the input matrices tested, this approach achieves sufficient performance. Moreover, a more complex approach would likely involve increased overhead, outweighing the performance benefits for small submatrices. That said, for scalability, the submatrix transpositions could instead make use of further block partitioning wherein the block transpositions and swaps are parallelised.

\subsection{Scalability for Extremely Large Matrices}

One of the common use cases for distributed computing in big data applications is the inability of any one process to store all of the input data at any point in time, due to the size of said data. The two main approaches presented in this report require the master process to gather all of the submatrices, thereby storing them in the memory associated with a single process. Obviously, there are concerns related to extremely large matrices as a result of this implementation.

The collective I/O approach does away with the need for this centralisation of the input data. Therefore, these approaches are more applicable for very large datasets. Of course, there may be cases in which the input data is so large that even storing entire submatrices is problematic. Such scenarios require increased partitioning of input data; splitting submatrix transpositions into multi-stage operations.

\subsection{Unnecessary Data Sharing Between Processes}
It could be suggested that the inter-process data sharing found in both of the collective I/O implementations is superfluous. Realistically, neither of these implementations actually require inter-process data sharing since processes could simply write their transposed submatrix to the output file, as collective I/O is used in any case.

That said, it would be hard to achieve a fair comparison between the collective I/O approaches and the two main approaches if the collective I/O approaches did not incorporate any data transfer between processes.

\section{Conclusion}
Two matrix transposition implementations have been presented. These implementations make use of a block-based approach using MPI, incorporating either one-sided or two-sided communications. The two-sided implementation was found to achieve superior performance in the tests conducted. Additionally, a collective I/O approach was found to be a viable alternative to the two presented implementations, especially if reading of matrix data from a file is required. The two main implementations which have been presented in this report could be improved in terms of the redundancy they achieve and, in addition, the efficiency and scalability of the submatrix transposition algorithms they incorporate.

\clearpage
\onecolumn

\printbibliography

%\setlength{\parskip}{0.6em}

\ifCLASSOPTIONcaptionsoff
  \newpage
\fi

% trigger a \newpage just before the given reference
% number - used to balance the columns on the last page
% adjust value as needed - may need to be readjusted if
% the document is modified later
%\IEEEtriggeratref{8}
% The triggered command can be changed if desired:
%\IEEEtriggercmd{\enlargethispage{-5in}}

% references section

% can use a bibliography generated by BibTeX as a .bbl file
% BibTeX documentation can be easily obtained at:
% http://www.ctan.org/tex-archive/biblio/bibtex/contrib/doc/
% The IEEEtran BibTeX style support page is at:
% http://www.michaelshell.org/tex/ieeetran/bibtex/
%\bibliographystyle{IEEEtran}
% argument is your BibTeX string definitions and bibliography database(s)
%\bibliography{IEEEabrv,../bib/paper}
%
% <OR> manually copy in the resultant .bbl file
% set second argument of \begin to the number of references
% (used to reserve space for the reference number labels box)
%\begin{thebibliography}{1}

%\bibitem{IEEEhowto:kopka}

% H.~Kopka and P.~W. Daly, \emph{A Guide to \LaTeX}, 3rd~ed.\hskip 1em plus
%   0.5em minus 0.4em\relax Harlow, England: Addison-Wesley, 1999.

%\end{thebibliography}

% biography section
%
% If you have an EPS/PDF photo (graphicx package needed) extra braces are
% needed around the contents of the optional argument to biography to prevent
% the LaTeX parser from getting confused when it sees the complicated
% \includegraphics command within an optional argument. (You could create
% your own custom macro containing the \includegraphics command to make things
% simpler here.)
%\begin{IEEEbiography}[{\includegraphics[width=1in,height=1.25in,clip,keepaspectratio]{mshell}}]{Michael Shell}
% or if you just want to reserve a space for a photo:

% \begin{IEEEbiography}
% Biography text here.
% \end{IEEEbiography}

% if you will not have a photo at all:
% \begin{IEEEbiographynophoto}{John Doe}
% Biography text here.
% \end{IEEEbiographynophoto}

% insert where needed to balance the two columns on the last page with
% biographies
%\newpage

% \begin{IEEEbiographynophoto}{Jane Doe}
% Biography text here.
% \end{IEEEbiographynophoto}

% You can push biographies down or up by placing
% a \vfill before or after them. The appropriate
% use of \vfill depends on what kind of text is
% on the last page and whether or not the columns
% are being equalized.

%\vfill

% Can be used to pull up biographies so that the bottom of the last one
% is flush with the other column.
%\enlargethispage{-5in}

% that's all folks
\end{document}


\clearpage
\subsection{Array} % (fold)
\label{sub:array}

An array is a special kind of \nameref{sub:variable}, one that stores multiple values instead of a single value. The values within an array, called elements, are all of the same \nameref{sub:type}.

\begin{figure}[h]
   \centering
   \includegraphics[width=\textwidth]{./topics/arrays/diagrams/Array}
   \caption{Arrays allow you to store multiple values in a variable}
   \label{fig:type-decl-array}
\end{figure}

\mynote{
\begin{itemize}
  \item An array is an \textbf{artefact}, a kind of variable that you can create in your code.
  \item Each array has a number of elements.
  \item The elements of an array are accessed via an index. The first element has the index~\textbf{0}, the second has the index \textbf{1}, etc. See \nameref{ssub:arrays_in_memory}.
  \item Individual elements of an array are much like a standard variable.
  \item You can store a value in an element of an array using an \nameref{sub:assignment_statement_with_arrays_}.
  \item You can use a the value from an element of an array using \nameref{sub:expressions_with_arrays_}.
  \item The \nameref{sub:for_loop} can be used to perform an action \emph{for each element of an array}.
\end{itemize}
}
\clearpage
\subsubsection{Arrays in Memory} % (fold)
\label{ssub:arrays_in_memory}

Arrays store multiple values, with an index that provides access to the individual elements within the array. Conceptually this can be viewed as a \nameref{sub:variable} that contains multiple slots (the elements) into which the values are stored.

Many languages have \textbf{0} as the index of the first element. This reflects how the values are actually stored in memory. \fref{fig:type-decl-array-idx} shows how an array (named \texttt{arr} in this Figure) is stored in memory. The array is a \textbf{contiguous} area in memory, with the elements being next to each other. You can think of the array as starting at the first element, so you need to skip \emph{0} elements to access the first element. The second element is accessed by skipping \emph{1} element, so it has index \emph{1}. The third element is accessed by skipping \emph{2} elements, so it has the index \emph{2}, etc.

The size of each of the elements of the array can then be used to quickly locate each element, given its index. If you have an array of \texttt{Integer} values then these are each 32 bits (4 bytes), so the element at index 3 is $3 \times 32bits$ (96 bits) past the start of the array.

The great thing is that you do not need to think about these details, but knowing this should you remember that the first\footnote{Some languages allow you to start at other values, but many use 0 based arrays which map more closely to how the data is stored in memory.} element of an array is at index 0.

\begin{figure}[h]
   \centering
   \includegraphics[width=\textwidth]{./topics/arrays/diagrams/ArrayIndex}
   \caption{Arrays occupy a contiguous area of memory, with elements next to each other in memory }
   \label{fig:type-decl-array-idx}
\end{figure}

\mynote{
\begin{itemize}
  \item Arrays are allocated a contiguous area of memory, with the elements next to each other.
  \item The array index is used to determine how many elements (values) are skipped to access the element you require.
  \item The index of the first element of an array is \textbf{0}.
  \item The last index of the array is therefore \textbf{n - 1}, where \emph{n} is the number of elements in the array.
\end{itemize}
}

% subsubsection arrays_in_memory (end)

% subsection array (end)


\documentclass[11pt, oneside]{article}   	% use "amsart" instead of "article" for AMSLaTeX format
\usepackage[utf8]{inputenc}
\usepackage{geometry}                			% See geometry.pdf to learn the layout options. There are lots.
\geometry{letterpaper}                   			% ... or a4paper or a5paper or ...
%\geometry{landscape}                			% Activate for rotated page geometry
%\usepackage[parfill]{parskip}    			% Activate to begin paragraphs with an empty line rather than an indent
\usepackage{graphicx}							% Use pdf, png, jpg, or eps§ with pdflatex; use eps in DVI mode
																% TeX will automatically convert eps --> pdf in pdflatex
\usepackage{amssymb}
\usepackage{listings}
\usepackage{xcolor}
\usepackage[export]{adjustbox}
\usepackage{booktabs}
\usepackage{float}
\usepackage{tikz}
\usepackage{pgfplots}
\usepgfplotslibrary{fillbetween}
\usetikzlibrary{patterns}
\pgfplotsset{compat=1.16}

\definecolor{codegreen}{rgb}{0,0.6,0}
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
\definecolor{codepurple}{rgb}{0.58,0,0.82}
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}

\lstdefinestyle{mystyle}{
	backgroundcolor=\color{backcolour},
	commentstyle=\color{codegreen},
	keywordstyle=\color{magenta},
	numberstyle=\tiny\color{codegray},
	stringstyle=\color{codepurple},
	basicstyle=\ttfamily\footnotesize,
	breakatwhitespace=false,
	breaklines=true,
	captionpos=b,
	keepspaces=true,
	numbers=left,
	numbersep=5pt,
	showspaces=false,
	showstringspaces=false,
	showtabs=false,
	tabsize=2
}

\lstset{style=mystyle}

\title{Functional Testing}
\author{Zelin Cai, Patrick Silvestre}
\date{}

\begin{document}
\maketitle

\section{Input Domain}
The input domain of the unit \texttt{nextDate} consists of dates formatted as follows: $MM/DD/YYYY$. For months, $MM$, the input condition specifies the range $[1, 12]$. If $MM = 2$ and the year is not a leap year, then the input condition range for dates, $DD$ is $[1, 28]$ (a year is a leap year if divisible by 4 and not divisible by 100 (unless divisible by 400)). If $MM = 2$  and the year is a leap year, then the input condition range for $DD$ is $[1, 29]$. If $MM = 4, 6, 9,$ or $11$, then the input condition range for $DD$ is $[1, 30]$. If $MM = 1, 3, 5, 7, 8, 10,$ or $12$, then the input condition range for $DD$ is $[1, 31]$.

\section{Equivalence Classes}
In order to identify equivalence classes (ECs), the following strategy was used: input conditions typically specified a range $[a, b]$, thus one EC valid input was identified for $a \leq X \leq b$, and two others with invalid input were identified for $X < a$ and $b < X$.

\subsection{Months}
	\begin{itemize}
		\item{EC-01: $01 \leq MM \leq 12$}
		\item{EC-02: $MM < 01$}
		\item{EC-03: $12 < MM$}
	\end{itemize}

\subsection{Dates}
\subsubsection{MM = 2, YY is not a leap year}
	\begin{itemize}
		\item{EC-04: $01 \leq DD \leq 28$}
		\item{EC-05: $DD < 01$}
		\item{EC-06: $28 < DD$}
	\end{itemize}

\subsubsection{MM = 2, YY is a leap year}
	\begin{itemize}
		\item{EC-07: $01 \leq DD \leq 29$}
		\item{EC-08: $DD < 01$}
		\item{EC-09: $29 < DD$}
	\end{itemize}

\subsubsection{MM = 4, 6, 9, or 11}
	\begin{itemize}
		\item{EC-10: $01 \leq DD \leq 30$}
		\item{EC-11: $DD < 01$}
		\item{EC-12: $30 < DD$}
	\end{itemize}

\subsubsection{MM = 1, 3, 5, 7, 8, 10, or 12}
	\begin{itemize}
		\item{EC-13: $01 \leq DD \leq 31$}
		\item{EC-14: $DD < 01$}
		\item{EC-15: $31 < DD$}
	\end{itemize}

\subsection{Years}
	\begin{itemize}
		\item{EC-16: $1900 \leq YYYY \leq 2099$}
		\item{EC-17: $YYYY < 1900$}
		\item{EC-18: $2099 < YYYY$}
	\end{itemize}

\newpage
\section{Test Cases}
\subsection{Test Cases from Equivalence Classes}
In order to identify test cases (TCs) from ECs, the following strategy is used: For each EC with valid input that has not been covered by a TC, write a TC covering as many uncovered ECs as possible. Then, for each EC with invalid input that has been covered, write a new TC that covers only that EC.

\subsubsection{Test Cases for ECs with Valid Input}
Valid Input ECs: EC-01, EC-04, EC-07, EC-10, EC-13, EC-16

\begin{table}[!htb]
\centering
\begin{tabular}{|l|l|l|l|l|l|l|l|l|}
\hline
TC & Test Value & Expected Result & EC-01      & EC-04      & EC-07      & EC-10      & EC-13      & EC-16      \\ \hline
01 & 02/01/1999 & 02/02/1999      & \checkmark & \checkmark &            &            &            & \checkmark \\ \hline
02 & 02/01/2000 & 02/02/2000      & \checkmark &            & \checkmark &            &            & \checkmark \\ \hline
03 & 04/01/2000 & 04/02/2000      & \checkmark &            &            & \checkmark &            & \checkmark \\ \hline
04 & 01/01/2000 & 01/02/2000      & \checkmark &            &            &            & \checkmark & \checkmark \\ \hline
\end{tabular}
\end{table}

\newpage
\subsubsection{Test Cases for ECs with Invalid Input}
Invalid Input ECs: EC-02, EC-03, EC-05, EC-06, EC-08, EC-09, EC-11, EC-12, EC-14 EC-15, EC-17, EC-18

\begin{table}[!htb]
\begin{tabular}{|l|l|l|l|l|l|}
\hline
TC & Test Value & Expected Result                              & EC-02      & EC-03      & EC-05      \\ \hline
05 & 00/01/2000 & ERROR: The month needs to be between 1 to 12 & \checkmark &            &            \\ \hline
06 & 13/01/2000 & ERROR: The month needs to be between 1 to 12 &            & \checkmark &            \\ \hline
07 & 02/00/1999 & ERROR: The day needs to be between 1 to 28   &            &            & \checkmark \\ \hline
\end{tabular}
\end{table}

\begin{table}[!htb]
\begin{tabular}{|l|l|l|l|l|l|}
\hline
TC & Test Value & Expected Result                            & EC-06      & EC-08      & EC-09      \\ \hline
08 & 02/29/1999 & ERROR: This year isn't a leap year         & \checkmark &            &            \\ \hline
09 & 02/00/2000 & ERROR: The day needs to be between 1 to 29 &            & \checkmark &            \\ \hline
10 & 02/30/2000 & ERROR: The day needs to be between 1 to 29 &            &            & \checkmark \\ \hline
\end{tabular}
\end{table}

\begin{table}[!htb]
\begin{tabular}{|l|l|l|l|l|l|}
\hline
TC & Test Value & Expected Result                            & EC-11      & EC-12      & EC-14      \\ \hline
11 & 04/00/2000 & ERROR: The day needs to be between 1 to 30 & \checkmark &            &            \\ \hline
12 & 04/31/2000 & ERROR: This month only has 30 days         &            & \checkmark &            \\ \hline
13 & 01/00/2000 & ERROR: The day needs to be between 1 to 30 &            &            & \checkmark \\ \hline
\end{tabular}
\end{table}

\begin{table}[!htb]
\begin{tabular}{|l|l|l|l|l|l|}
\hline
TC & Test Value & Expected Result                                  & EC-15      & EC-17      & EC-18      \\ \hline
14 & 01/32/2000 & ERROR: The day needs to be between 1 to 31       & \checkmark &            &            \\ \hline
15 & 01/01/1899 & ERROR: The year needs to be between 1900 to 2099 &            & \checkmark &            \\ \hline
16 & 01/01/2100 & ERROR: The year needs to be between 1900 to 2099 &            &            & \checkmark \\ \hline
\end{tabular}
\end{table}

\newpage
\subsection{Test Cases for Boundary Value Analysis}
In order to identify test cases for boundary value analysis (BVA), the following strategy is used: Since ECs specify ranges, test cases are constructed by considering the boundary points of the range and points just beyond the boundaries of the range.

\subsubsection{EC-01: $01 \leq MM \leq 12$}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                              \\ \hline
01 & 00/01/2000 & ERROR: The month needs to be between 1 to 12 \\ \hline
02 & 01/01/2000 & 01/02/2000                                   \\ \hline
03 & 02/01/2000 & 02/02/2000                                   \\ \hline
04 & 11/01/2000 & 11/02/2000                                   \\ \hline
05 & 12/01/2000 & 12/02/2000                                   \\ \hline
06 & 13/01/2000 & ERROR: The month needs to be between 1 to 12 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-02: $MM < 01$}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                              \\ \hline
01 & 00/01/2000 & ERROR: The month needs to be between 1 to 12 \\ \hline
02 & 01/01/2000 & 01/02/2000                                   \\ \hline
03 & 02/01/2000 & 02/02/2000                                   \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-03: $12 < MM$}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                              \\ \hline
01 & 11/01/2000 & 11/02/2000                                   \\ \hline
02 & 12/01/2000 & 12/02/2000                                   \\ \hline
03 & 13/01/2000 & ERROR: The month needs to be between 1 to 12 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-04: $01 \leq DD \leq 28$ (MM = 2, YY is not a leap year)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                            \\ \hline
01 & 02/00/1999 & ERROR: The day needs to be between 1 to 28 \\ \hline
02 & 02/01/1999 & 02/02/1999                                 \\ \hline
03 & 02/02/1999 & 02/03/1999                                 \\ \hline
04 & 02/27/1999 & 02/28/1999                                 \\ \hline
05 & 02/28/1999 & 03/01/1999                                 \\ \hline
06 & 02/29/1999 & ERROR: This year isn't a leap year         \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-05: $DD < 01$ (MM = 2, YY is not a leap year)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                            \\ \hline
01 & 02/00/1999 & ERROR: The day needs to be between 1 to 28 \\ \hline
02 & 02/01/1999 & 02/02/1999                                 \\ \hline
03 & 02/02/1999 & 02/03/1999                                 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-06: $28 < DD$ (MM = 2, YY is not a leap year)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
04 & 02/27/1999 & 02/28/1999                                 \\ \hline
05 & 02/28/1999 & 03/01/1999                                 \\ \hline
06 & 02/29/1999 & ERROR: This year isn't a leap year         \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-07: $01 \leq DD \leq 29$ (MM = 2, YY is a leap year)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                            \\ \hline
01 & 02/00/2000 & ERROR: The day needs to be between 1 to 29 \\ \hline
02 & 02/01/2000 & 02/02/2000                                 \\ \hline
03 & 02/02/2000 & 02/03/2000                                 \\ \hline
04 & 02/28/2000 & 02/29/2000                                 \\ \hline
05 & 02/29/2000 & 03/01/2000                                 \\ \hline
06 & 02/30/2000 & ERROR: The day needs to be between 1 to 29 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-08: $DD < 01$ (MM = 2, YY is a leap year)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                            \\ \hline
01 & 02/00/2000 & ERROR: The day needs to be between 1 to 29 \\ \hline
02 & 02/01/2000 & 02/02/2000                                 \\ \hline
03 & 02/02/2000 & 02/03/2000                                 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-09: $29 < DD$ (MM = 2, YY is a leap year)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                            \\ \hline
01 & 02/28/2000 & 02/29/2000                                 \\ \hline
02 & 02/29/2000 & 03/01/2000                                 \\ \hline
03 & 02/30/2000 & ERROR: The day needs to be between 1 to 29 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-10: $01 \leq DD \leq 30$ (MM = 4, 6, 9, or 11)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                            \\ \hline
01 & 04/00/2000 & ERROR: The day needs to be between 1 to 30 \\ \hline
02 & 04/01/2000 & 04/02/2000                                 \\ \hline
03 & 04/02/2000 & 04/03/2000                                 \\ \hline
04 & 04/29/2000 & 04/30/2000                                 \\ \hline
05 & 04/30/2000 & 05/01/2000                                 \\ \hline
06 & 04/31/2000 & ERROR: The day needs to be between 1 to 30 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-11: $DD < 01$ (MM = 4, 6, 9, or 11)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                            \\ \hline
01 & 04/00/2000 & ERROR: The day needs to be between 1 to 30 \\ \hline
02 & 04/01/2000 & 04/02/2000                                 \\ \hline
03 & 04/02/2000 & 04/03/2000                                 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-12: $30 < DD$(MM = 4, 6, 9, or 11)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                            \\ \hline
01 & 04/29/2000 & 04/30/2000                                 \\ \hline
02 & 04/30/2000 & 05/01/2000                                 \\ \hline
03 & 04/31/2000 & ERROR: The day needs to be between 1 to 30 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-13: $01 \leq DD \leq 31$ (MM = 1, 3, 5, 7, 8, 10, or 12)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                            \\ \hline
01 & 01/00/2000 & ERROR: The day needs to be between 1 to 31 \\ \hline
02 & 01/01/2000 & 01/02/2000                                 \\ \hline
03 & 01/02/2000 & 01/03/2000                                 \\ \hline
04 & 01/30/2000 & 01/31/2000                                 \\ \hline
05 & 01/31/2000 & 02/01/2000                                 \\ \hline
06 & 01/32/2000 & ERROR: The day needs to be between 1 to 31 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-14: $DD < 01$ (MM = 1, 3, 5, 7, 8, 10, or 12)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                            \\ \hline
01 & 01/00/2000 & ERROR: The day needs to be between 1 to 31 \\ \hline
02 & 01/01/2000 & 01/02/2000                                 \\ \hline
03 & 01/02/2000 & 01/03/2000                                 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-15: $31 < DD$ (MM = 1, 3, 5, 7, 8, 10, or 12)}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                            \\ \hline
01 & 01/30/2000 & 01/31/2000                                 \\ \hline
02 & 01/31/2000 & 02/01/2000                                 \\ \hline
03 & 01/32/2000 & ERROR: The day needs to be between 1 to 31 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-16: $1900 \leq YYYY \leq 2099$}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                                  \\ \hline
01 & 01/01/1899 & ERROR: The year needs to be between 1900 to 2099 \\ \hline
02 & 01/01/1900 & 01/02/1900                                       \\ \hline
03 & 01/01/1901 & 01/02/1901                                       \\ \hline
04 & 01/01/2098 & 01/02/2098                                       \\ \hline
05 & 01/01/2099 & 01/02/2099                                       \\ \hline
06 & 01/01/2100 & ERROR: The year needs to be between 1900 to 2099 \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-17: $YYYY < 1900$}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                                  \\ \hline
01 & 01/01/1899 & ERROR: The year needs to be between 1900 to 2099 \\ \hline
02 & 01/01/1900 & 01/02/1900                                       \\ \hline
03 & 01/01/1901 & 01/02/1901                                       \\ \hline
\end{tabular}
\end{table}

\subsubsection{EC-18: $2099 < YYYY$}
\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                                  \\ \hline
01 & 01/01/2098 & 01/02/2098                                       \\ \hline
02 & 01/01/2099 & 01/02/2099                                       \\ \hline
03 & 01/01/2100 & ERROR: The year needs to be between 1900 to 2099 \\ \hline
\end{tabular}
\end{table}

\subsection{Test Cases for Random Testing}
Typically, in random testing, test inputs are randomly generated according to some operational profile. In this case, we generate 16 test cases using a random number generator via \texttt{random.org}. MM is limited to the range $[00, 13]$, DD $[00, 32]$, and YYYY $[1899, 2100]$.

\begin{table}[H]
\begin{tabular}{|l|l|l|}
\hline
TC & Test Value & Expected Result                              \\ \hline
01 & 13/15/2040 & ERROR: The month needs to be between 1 to 12 \\ \hline
02 & 00/31/1909 & ERROR: The month needs to be between 1 to 12 \\ \hline
03 & 06/08/2053 & 06/09/2053                                   \\ \hline
04 & 01/05/1986 & 01/06/1986                                   \\ \hline
05 & 04/23/1977 & 04/24/1977                                   \\ \hline
06 & 13/10/2024 & ERROR: The month needs to be between 1 to 12 \\ \hline
07 & 11/27/1955 & 11/28/1955                                   \\ \hline
08 & 13/03/2084 & ERROR: The month needs to be between 1 to 12 \\ \hline
09 & 11/08/2059 & 11/09/2059                                   \\ \hline
10 & 12/04/1912 & 12/05/1912                                   \\ \hline
11 & 11/14/1902 & 11/15/1902                                   \\ \hline
12 & 10/15/1972 & 10/16/1972                                   \\ \hline
13 & 13/21/1985 & ERROR: The month needs to be between 1 to 12 \\ \hline
14 & 11/27/2039 & 11/28/2039                                   \\ \hline
15 & 08/29/2035 & 08/30/2035                                   \\ \hline
16 & 00/02/2031 & ERROR: The month needs to be between 1 to 12 \\ \hline
\end{tabular}
\end{table}

\end{document}


\section{Logic and Program flow mistakes}

These are a set of mistakes that may or may not make sense within the context of the program.

\subsection{Equal vs. Equality}

Confusingly in C, the assignment operator also returns the assigned value.
Most of the time it is ignored.
We can use it to initialize multiple things on the same line.

\begin{lstlisting}[language=C]
int p1, p2;
p1 = p2 = 0;
\end{lstlisting}

More confusingly, if we forget an equals sign in the equality operator we will end up assigning that variable.
Most of the time this isn't what we want to do.

\begin{lstlisting}[language=C]
int answer = 3; // Will print out the answer.
if (answer = 42) { printf("I've solved the answer! It's %d", answer);}
\end{lstlisting}

The quick way to fix that is to get in the habit of putting constants first.
This mistake is common enough in while loop conditions, that most modern programming languages do not let you assign in a while loop without some kind of warning, and some do not allow it at all.

\begin{lstlisting}[language=C]
if (42 = answer) { printf("I've solved the answer! It's %d", answer);}
\end{lstlisting}

There are cases where we want to do it.
A common example is getline.

\begin{lstlisting}[language=C]
while ((nread = getline(&line, &len, stream)) != -1)
\end{lstlisting}

This piece of code calls getline, and assigns the return value or the number of bytes read to nread.
It also in the same line checks if that value is -1 and if so terminates the loop.
It is always good practice to put parenthesis around any assignment condition.

\subsection{Undeclared or incorrectly prototyped functions}

You may see code do something like this.

\begin{lstlisting}[language=C]
time_t start = time();
\end{lstlisting}

The system function `time' actually takes a parameter a pointer to some memory that can receive the time\_t structure or NULL.
The compiler did not catch this error because the programmer did not provide a valid function prototype by including \keyword{time.h}.

More confusingly this could compile, work for decades and then crash.
The reason for that is that time would be found at link time, not compile time in the C standard library which almost surely is already in memory.
Since a parameter isn't being passed, we are hoping the arguments on the stack (any garbage) is zeroed out because if it isn't, time will try to write the result of the function to that garbage which will cause the program to SEGFAULT.

\subsection{Extra Semicolons}

This is a pretty simple one, don't put semicolons when not needed.

\begin{lstlisting}[language=C]
for(int i = 0; i < 5; i++) ; printf("I'm printed once");
while(x < 10); x++ ; // X is never incremented
\end{lstlisting}

However, the following code is perfectly OK.

\begin{lstlisting}[language=C]
for(int i = 0; i < 5; i++){
  printf("%d\n", i);;;;;;;;;;;;;
}
\end{lstlisting}

It is OK to have this kind of code, because the C language uses semicolons (;) to separate statements.
If there is no statement in between semicolons, then there is nothing to do and the compiler moves on to the next statement
To save a lot of confusion, \textbf{always use braces.}
It increases the number of lines of code, which is a great productivity metric.


% !TEX options=--shell-escape
\documentclass [12pt]{article}

\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{float}
\usepackage{multirow}
\usepackage{xcolor}
\usepackage{algorithmic}
\usepackage [ruled,vlined,commentsnumbered,titlenotnumbered]{algorithm2e} \usepackage{array}
\usepackage{booktabs}
\usepackage{url}
\usepackage{parskip}
\usepackage [margin=1in]{geometry}
\usepackage [T1]{fontenc}
\usepackage{cmbright}
\usepackage [many]{tcolorbox}
\usepackage [colorlinks = true,
            linkcolor = blue,
            urlcolor  = blue,
            citecolor = blue,
            anchorcolor = blue]{hyperref}
\usepackage{enumitem}
\usepackage{xparse}
\usepackage{verbatim}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{csquotes}
\usepackage[cache=false]{minted}
\usepackage{mdframed}
\usepackage{tikz}
\usetikzlibrary{shapes.symbols}
\newtheorem{theorem}{Theorem}

\BeforeBeginEnvironment{minted}{\begin{mdframed}}
\AfterEndEnvironment{minted}{\end{mdframed}}

\DeclareTColorBox{Solution}{}{breakable, title={Solution}}
\DeclareTColorBox{Solution*}{}{breakable, title={Solution (provided)}}
\DeclareTColorBox{Instruction}{}{boxrule=0pt, boxsep=0pt, left=0.5em, right=0.5em, top=0.5em, bottom=0.5em, arc=0pt, toprule=1pt, bottomrule=1pt}
\DeclareDocumentCommand{\Expecting }{+m}{\textbf {[We are expecting:} #1\textbf {]}}
\DeclareDocumentCommand {\Points }{m}{\textbf {(#1 pt.)}}
\newcommand {\hint }[1]{\noindent {[\textbf {HINT:} \em #1 \em ]}} \newcommand {\pts }[1]{\textbf {(#1 pt.)}}

\begin{document}

{\LARGE \textbf {COMP 285 (NC A\&T, Spr `22)}\hfill \textbf {Homework 7} }
\vspace {1em}
\begin{Instruction}

\paragraph {Due.} Friday, April 1st, 2022 @ 11:59 PM!
\end{Instruction}

\vspace {1em}
\begin{Instruction} \paragraph {Homework Expectations:} Please see \href{https://www.comp285.ml/homework/#general-homework-information}{Homework}.
\end{Instruction}

\vspace {1em}
\begin{Instruction}

\paragraph {Exercises} The following questions are exercises. We encourage you to work with a group and discuss solutions to make sure you understand the material.

\paragraph {Points} This assignment is graded out of 50 points. However, you can get up to 60 points if you complete everything. These are not bonus points, but rather points to help make-up any parts you miss.

\end{Instruction}

\begin{centering}
\section*{More Fun with Graphs and Dynamic Programming}
\end{centering}

\begin{Instruction}

\paragraph{Written Problems} The following questions are to be submitted in written/typed form to gradescope.

\end{Instruction}

\section{Interview Practice: Wake up, Sheeple! \Points{10}}

You arrive on an island with $n$ sheep. The sheep have developed a pretty sophisticated society, and have a social media platform called Baaaahtter (it's like Twitter but for sheep\footnote {Also my new start-up idea}). Some sheep follow other sheep on this platform. Being sheep, they believe and repeat anything that they hear. That is, they will re-post anything that any sheep they are following said. We can represent this by a graph, where $(a) \to (b)$ means that $(b)$ will re-post anything that $(a)$ posted. For example, if the social dynamics on the island were: \begin{center}
  \begin{tikzpicture}[xscale=2]
    \node (a) at (0,0){\includegraphics [width=2cm]{sheep}};
    \node at (0,-1){Shifra the sheep};
    \node (b) at (2,2){\includegraphics [width=2cm]{sheep}};
    \node (bb) at (2,1){Shakira the sheep};
    \node (c) at (2,-2){\includegraphics [width=2cm]{sheep}};
    \node at (2,-3){Sugar the sheep};
    \node (d) at (4,0){\includegraphics [width=2cm]{sheep}};
    \node at (4,-1){Sherman the sheep};
    \draw [thick,->] (a) to (b);
    \draw [thick,->] (b) to[bend right] (a);
    \draw [thick,->] (a) to (c);
    \draw [thick,->] (bb) to (c);
    \draw [thick,->] (c) to (d);
  \end{tikzpicture}
\end{center}

then Sherman the Sheep follows Sugar the Sheep, and Sugar follows both Shakira and Shifra, and so on. This means that Sherman will re-post anything that Sugar posts, Sugar will re-post anything by Shifra and Shikira, and so on. (If there is a cycle then each sheep will only re-post a post once).

For the parts below, let $G$ denote this directed, unweighted graph on the $n$ sheep. Let $m$ denote the number of edges in $G$.

\subsection{The influencer circle \Points{4}}

Call a sheep an \textbf{influencer} if anything that they post eventually gets re-posted by every other sheep on the island. In the example above, both Shifra and Shakira are influencers.

Argue that, if there is at least one influencer, then all influencers are in the same strongly connected component of $G$, and every sheep in that component is an influencer.
\Expecting{A short argument explaning why the above is true.}

\subsection{Who is the influencer? \Points{6}}

Suppose that there is at least one influencer. Give an algorithm that runs in time $O(n + m)$ and finds an influencer. You may use any algorithm we have seen in class as a subroutine.

\Expecting{Pseudocode or a very clear English description of your algorithm, an informal justification that your algorithm is correct , an informal justification that the running time is $O(n+m)$.}

\pagebreak
\section{Interview Practice: Arbitrage in the Market \Points{10}}

Suppose the various economies of the world use a set of currencies $C_1, \cdots , C_n$ — think of these as dollars, pounds, bitcoins, etc. Your bank allows you to trade each currency $C_i$ for any other currency $C_j$ at an exchange rate $r_{ij}$, that is, you can exchange each unit of $C_i$ for $r_{ij} > 0$ units of $C_j$. Due to fluctuations in the markets, it is occasionally possible to find a sequence of exchanges that lets you start with currency A, change into currencies, B, C, D, etc., and then end up changing back to currency A in such a way that you end up with more money than you started with. That is, there are currencies $C_{i_1} , \cdots , C_{i_k}$ such that
$$
r_{i_1i_2} \times r_{i_2i_3} \times \cdots \times r_{i_{k-1}i_k} \times r_{i_k i_1} > 1
$$.

This is called an arbitrage opportunity, but to take advantage of it you need to be able to identify it quickly (before other investors leverage it and the exchange rates balance out again)! Devise an efficient algorithm to determine whether an arbitrage opportunity exists. Justify the correctness of your algorithm and its runtime.

\Expecting{Pseudocode of your algorithm along with the running time and a short explanation.}

\section{Concept Questions: A Clever Trick for Dijkstra's Algorithm \Points{5}}

Pepper and Plucky have been talking. They’re working out whether they can modify Dijkstra’s algorithm to deal with negative edge weights. Here’s what they came up with:

Let $G = (V, E)$ be a weighted graph with negative edge weights, and let $w^*$ be the smallest (most negative) weight that appears in $G$. Consider a graph $G' = (V, E')$ with the same vertices as $G$. Then to construct the edges $E'$, we do the following: for every edge $e \in E$ with weight $w$, we add an edge $e' \in E'$ with weight $w - w^*$.

Now all of the weights in $G'$ are non-negative, so we can apply Dijkstra’s algorithm. The shortest path in $G'$ will be the shortest path in $G$.

Does this suggestion work? (That is, does it always return a shortest path from s to t in G if it exists?) Either prove that it is correct (that is, prove that this algorithm correctly finds shortest paths in weighted directed graphs), or give a counter-example.

\Expecting{Either a proof that this modification to Dijkstra's Algorithm works and lets us handle negative edge weights, or a single example of a graph for which this does not work.}

\section {Pruning Trees \Points{10}}
\label{sec:last}

Suppose you are given a \textbf {binary} tree with $n$ nodes, and each node has an associated weight, which is a positive integer. You would like to remove nodes from this tree such that the resulting tree has at most $k$ nodes, and you would like to maximize the sum of the weights of the remaining nodes. Additionally, at the end of the pruning, you must still have a tree rooted at the original root; in other words, if you remove a node, then all of that node's children/descendants must also be removed.

\begin{enumerate}
  \item \Points{5} For any node $u$ of the original tree, and any positive integer $i \le k$, let $A[u,i]$ denote the maximum weight of any subtree rooted at node $u$ having at most $i$ nodes. Letting $r_u$ and $\ell _u$ denote the right and left children of node $u$ (they are NULL if $u$ does not have that child), and letting $w_u$ be the weight of node $u$, formally describe the optimal structure by giving a recurrence that expresses $A[u,i]$ in terms of the quantities $A[r_u,1],A[r_u,2],\ldots $ and $A[\ell _u,1],A[\ell _u,2],\ldots $.

  \Expecting {An expression for the recurrence relation for $A[u, i]$. If you find it convenient, you may additionally define $A[u, 0]$ and/or $A[NULL, i]$ to be an appropriate value, and use them in the recurrence.}

  \item \Points{5} Using the recurrence relation from the previous problem, define a dynamic programming algorithm that will efficiently solve the problem. (The algorithm only has to return the weight of the best tree. It doesn't have to return that best tree.) What is the runtime of your algorithm?

  \Expecting {A brief description or pseudocode of your algorithm, no justification of correctness required. Additionally, the runtime and a brief description of how you arrived at your answer.}
\end{enumerate}

\pagebreak
\begin{Instruction}

\paragraph{Coding Problems} The following questions are to be submitted as a ".zip" file on Gradescope.

\end{Instruction}

\section{Coding \Points{25}}
After completing the written portion of the assignment, you should submit it to \href{https://www.gradescope.com/courses/350304}{Gradescope}.

For the coding portion, get your starter \href{https://replit.com/team/COMP285/HW7-Code}{C++ code} or \href{https://replit.com/team/COMP285/HW7-Code-Python}{Python code}.

Note that the starter code also include a few test cases you can run on repl.it. However, the full test suite is the one run on Gradescope.

Please reference the \texttt{README.md} included in your starter code for detailed instructions.

\section*{Submitting the Assignment}

This assignment is a combination of written and programming questions. Both portions of the assignment should be submitted through \href{https://www.gradescope.com/courses/350304}{Gradescope}.

The "Homework 7: More Fun with Graphs and Dynamic Programming" assignment is the written portion, for which you should submit a \textbf{typed} response to the non-coding questions (questions 1-\ref{sec:last}). Each response should clearly be marked with its corresponding number. You are free to use the provided templates, print the questions and write your answers, or to simply type your responses on a blank document (whatever works for you).

The "Homework 7: Coding" is the programming portion of the assignment. For this portion, download the ".zip" file from replit and upload this ".zip" file as your answer to \href{https://www.gradescope.com/courses/350304}{Gradescope}. You can upload the assignment as many times as you want.

\end{document}


% Latest version available here:  https://github.com/LIKS/phd_report_template_en
% Any suggestions or contributions are welcome!  Also see: http://latex.liks.lt!
\documentclass[11pt, a4paper]{article}
\usepackage[utf8]{inputenc}
\def\LTfontencoding{L7x}
\usepackage[\LTfontencoding]{fontenc}
\usepackage[english]{babel}
\usepackage{PhDReportEN}
\usepackage{amsmath}
\usepackage{bm}
\usepackage{amsfonts}
\usepackage{float}
\usepackage{graphicx}
\usepackage{color}
\usepackage{listings}
\usepackage{wrapfig}
\usepackage{algpseudocode}
\usepackage{algorithm}
\usepackage{algorithmicx}
\usepackage{caption}
\usepackage{subfig}
\usepackage{datetime}
\usepackage{cite}

\universitytitle{Vilnius University}
\departmenttitle{Institute of Mathematics and Informatics}
\departmentdetails{VU Institute of Mathematics and Informatics, Akademijos str.
4, Vilnius LT-08663, \\ Lithuania \\ \href{http://www.mii.lt}{www.mii.lt}}
\universitylogo{img/vu_logo}
\departmentlogo{img/mii_logo}
\date{\monthname\ \the\year}
\scientifictrend{Informatics (09 P)}
\reportid{MII-DS-09P-\shortyear-<report nr.>} % report nr. usually is doctoral study year

\title{<Thesis title>}
\author{<Author>}

\begin{document}

\maketitle

\sectionnonumnocontent{Abstract}
.........

\keywords{.........}

\tableofcontents

\section{Introduction}

\section{<main part of the report >}
The report should contain material, which the author was committed to prepare
for the reporting period (write a thesis section, create some kind of
methodology etc.; texts of papers ready for publishing can be included).
Preparation of the report is optional if the author did not have this kind of
commitments.

\section{Conclusions}

\section*{\emph{References}}% If you use \cite at least once, comment this line;
                            % Uncomment the next line and lines in Makefile.
% \bibliography{bibliografija}

\appendix
\section{Algorithm experimental comparison results}
% tablesgenerator.com - converts calculators, e.g. excel, tables to LaTeX
\begin{table}[H]
  \centering
  \caption{Table example.}
  {\begin{tabular}{|l|c|c|} \hline
    Algorithm    & $\bar{x}$ & $\sigma^{2}$ \\
    \hline
    Algorithm A  & 1.6335    & 0.5584       \\
    Algorithm B  & 1.7395    & 0.5647       \\
    \hline
  \end{tabular}}
  \label{tab:table example}
\end{table}

\section{Multilayer perceptron structure}
\begin{figure}[H]
    \centering
\includegraphics[scale=0.5]{img/MLP}
\caption{Image example}
\label{img:mlp}
\end{figure}

\newpage
\section{\texttt{ALGORITHM\_EXAMPLE} algorithm pseudocode}
\begin{algorithm}[H]
\caption{Algorithm pseudocode example}
\begin{algorithmic}[1]
    \Procedure{ALGORITHM\_EXAMPLE}{$n, d, A$}
    \State $i \gets d $
    \While{$i < n$}
        \ForAll{$r \in A $}
            \State $v \gets f(r)$  \Comment{see fig. \ref{img:mlp}.}
        \EndFor
        \State $i \gets i + 1$
    \EndWhile
\EndProcedure
\end{algorithmic}
\label{alg:multivariate pseudocode}
\end{algorithm}

\end{document}


% r.9 introduction
\cleardoublepage
\chapter{Mathematics}
\label{ch:math}

\newthought{This chapter} reviews some of the fundamental principles of mathematics for a deeper understanding of basic concepts in electrical engineering.

%-- FUNCTIONS
\input{content/section-math-functions}