Added figures to proximal improvement section; Minor other changes

This commit is contained in:
2023-04-09 23:05:09 +02:00
parent 50d55af046
commit 7af0eaea5b
17 changed files with 996 additions and 16 deletions

View File

@@ -690,7 +690,7 @@ while $\sum_{j\in\mathcal{J}} \lVert \boldsymbol{T}_j\tilde{\boldsymbol{c}} - \b
\Big) - \frac{\gamma_i}{\mu} \right)$
end for
end while
\end{genericAlgorithm}
\end{genericAlgorithm}
%
\footnotetext{$\epsilon_{\text{pri}} > 0$ and $\epsilon_{\text{dual}} > 0$
are additional parameters
@@ -700,7 +700,7 @@ $\boldsymbol{z}_j$ in the previous iteration.}%
%
\noindent The $\boldsymbol{z}_j$- and $\boldsymbol{\lambda}_j$-updates can be understood as
a check-node update step (lines $3$-$6$) and the $\tilde{c}_i$-updates can be understood as
a variable-node update step (lines $7$-$9$ in figure \ref{fig:lp:message_passing}).
a variable-node update step (lines $7$-$9$ in figure \ref{alg:admm}).
The updates for each variable- and check-node can be perfomed in parallel.
The main computational effort in solving the linear program then amounts to

View File

@@ -246,7 +246,7 @@ return $\boldsymbol{\hat{c}}$
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Implementation Details}%
\section{Implementation Details (``A Selection of Implementation Considerations?'')}%
\label{sec:prox:Implementation Details}
The algorithm was first implemented in Python because of the fast development
@@ -302,8 +302,8 @@ the gradient can be written as%
\boldsymbol{v}
,\end{align*}
%
enabling the computation of the gradient primarily with element-wise
operations and matrix-vector multiplication.
enabling its computation primarily with element-wise operations and
matrix-vector multiplication.
This is beneficial, as the libraries used for the implementation are
heavily optimized for such calculations (e.g., through vectorization of the
operations).
@@ -848,14 +848,15 @@ the frame errors may largely be attributed to decoding failures.
\subsection{Convergence Properties}
\label{subsec:prox:conv_properties}
The previous observation, that the \ac{FER} arises mainly due to the
The previous observation, that the \ac{FER} may arise mainly due to the
non-convergence of the algorithm instead of convergence to the wrong codeword,
raises the question why the decoding process does not converge so often.
In figure \ref{fig:prox:convergence}, the iterative process is visualized.
In order to be able to simultaneously consider all components of the vectors
being dealt with, a BCH code with $n=7$ and $k=4$ is chosen.
Each chart shows one component of the current estimates during a given
being dealt with, a BCH code with $n=7$ and $k=4$ has been chosen.
Each chart shows one component of the current estimate during a given
iteration (alternating between $\boldsymbol{r}$ and $\boldsymbol{s}$), as well
as the gradients of the negative log-likelihood and the code-constraint
polynomial, which influence the next estimate.
@@ -1271,11 +1272,35 @@ This gives rise to the notion that some property or behaviour of
$\nabla h\left( \tilde{\boldsymbol{x}} \right) $ may be related in its
magnitude to the confidence that a given bit is correct.
And indeed, the magnitude of the oscillation of
$\nabla h\left( \tilde{\boldsymbol{x}} \right)$ (introduced in a previous
section) and the probability of having a bit error are strongly correlated,
a relationship depicted in figure \ref{fig:prox:correlation}.
$\nabla h\left( \tilde{\boldsymbol{x}} \right)$ (introduced previously in
section \ref{subsec:prox:conv_properties}) and the probability of having a bit
error are strongly correlated, a relationship depicted in figure
\ref{fig:prox:correlation}.
\begin{figure}[H]
\centering
TODO: Figure
\begin{tikzpicture}
\begin{axis}[point meta min = -1,
point meta max = 1,
grid=both,
xlabel={$Var\left( \nabla h\left( \boldsymbol{x} \right) \right) $},
ylabel={Bit error (bool)},
ytick={0, 1},
width=8cm,
height=3cm,
%colormap/viridis,
scale only axis,]
\addplot [RoyalPurple, only marks,]
table [col sep=comma, x=grad_h_vars, y=bit_error]
{res/proximal/extreme_components_20433484_variance.csv};
\end{axis}
\end{tikzpicture}
\caption{Correlation between bit error and amplitude of oscillation}
\label{fig:prox:correlation}
\end{figure}
\noindent The y-axis depicts whether there is a bit error and the x-axis the
variance in $\nabla h\left( \tilde{\boldsymbol{x}} \right)$ past the iteration
@@ -1289,25 +1314,179 @@ probably wrong bits, all variations of the estimate with those bits modified
can be generated.
An \ac{ML}-in-the-List step can then be performed in order to determine the
most likely candidate.
This process is outlined in figure \ref{fig:prox:improved_algorithm}.
This process is outlined in algorithm \ref{alg:prox:improved}.
Its only difference to algorithm \ref{alg:prox} is that instead of returning
the last estimate when no valid result is reached, an ML-in-the-List step is
performed (highlighted in blue).
Figure \ref{fig:prox:improved_results} shows the gain that can be achieved.
\begin{genericAlgorithm}[caption={Improved proximal decoding algorithm},
label={alg:prox:improved},]
$\boldsymbol{s} \leftarrow \boldsymbol{0}$
for $K$ iterations do
$\boldsymbol{r} \leftarrow \boldsymbol{s} - \omega \nabla L \left( \boldsymbol{y} \mid \boldsymbol{s} \right) $
$\boldsymbol{s} \leftarrow \boldsymbol{r} - \gamma \nabla h\left( \boldsymbol{r} \right) $
$\boldsymbol{\hat{x}} \leftarrow \text{sign}\left( \boldsymbol{s} \right) $
if $\boldsymbol{H}\boldsymbol{\hat{c}} = \boldsymbol{0}$
return $\boldsymbol{\hat{c}}$
end if
end for
$\textcolor{KITblue}{\text{Find }N\text{ most probably wrong bits}}$
$\textcolor{KITblue}{\text{Generate variations } \boldsymbol{\tilde{c}}_i\text{ of }\boldsymbol{\hat{c}}\text{ with the }N\text{ bits modified}}$
$\textcolor{KITblue}{\text{Compute }d_H\left( \boldsymbol{ \tilde{c}}_i, \boldsymbol{\hat{c}} \right) \text{ for all valid codewords } \boldsymbol{\tilde{c}}_i}$
$\textcolor{KITblue}{\text{Output }\boldsymbol{\tilde{c}}_i\text{ with lowest }d_H\left( \boldsymbol{ \tilde{c}}_i, \boldsymbol{\hat{c}} \right)}$
\end{genericAlgorithm}
\todo{Not hamming distance, correlation}
Figure \ref{fig:prox:improved_results} shows the gain that can be achieved,
when the number $N$ is chosen to be 12.
Again, three values of gamma are chosen, for which the \ac{BER}, \ac{FER}
and decoding failure rate is plotted.
The simulation results for the original proximal decoding algorithm are shown
with solid lines and the results for the improved version are shown with
dashed lines.
For the case of $\gamma = 0.05$, the number of frame errors produced for the
datapoints at $\SI{6}{dB}$, $\SI{6.5}{dB}$ and $\SI{7}{dB}$ are
70, 17 and 2, respectively. \todo{Redo simulation with higher number of iterations}
The gain seems to depend on the value of $\gamma$, as well as become more
pronounced for higher \ac{SNR} values.
This is to be expected, since with higher \ac{SNR} values the number of bit
errors decreases, making the correction of those errors in the ML-in-the-List
step more likely.
In figure \ref{fig:prox:improved_results_multiple} the decoding performance
In figure \ref{fig:prox:improved:comp} the decoding performance
between proximal decoding and the improved algorithm is compared for a number
of different codes.
Similar behaviour can be observed in all cases, with varying improvement over
standard proximal decoding.
\begin{figure}[H]
\centering
\begin{tikzpicture}
\begin{axis}[
grid=both,
xlabel={$E_b / N_0$}, ylabel={BER},
ymode=log,
width=0.48\textwidth,
height=0.36\textwidth,
ymax=1.5, ymin=3e-8,
]
\addplot[ForestGreen, mark=*, solid]
table [x=SNR, y=BER, col sep=comma, discard if not={gamma}{0.15}]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[Emerald, mark=triangle, densely dashed]
table [x=SNR, y=BER, col sep=comma, discard if not={gamma}{0.15}]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\addplot[NavyBlue, mark=*, solid]
table [x=SNR, y=BER, col sep=comma, discard if not={gamma}{0.01}]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[RoyalPurple, mark=triangle, densely dashed]
table [x=SNR, y=BER, col sep=comma, discard if not={gamma}{0.01}]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\addplot[RedOrange, mark=*, solid]
table [x=SNR, y=BER, col sep=comma, discard if not={gamma}{0.05}]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[red, mark=triangle, densely dashed]
table [x=SNR, y=BER, col sep=comma, discard if not={gamma}{0.05}]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
grid=both,
xlabel={$E_b / N_0$}, ylabel={FER},
ymode=log,
width=0.48\textwidth,
height=0.36\textwidth,
ymax=1.5, ymin=3e-8,
]
\addplot[ForestGreen, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[Emerald, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\addplot[NavyBlue, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[RoyalPurple, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\addplot[RedOrange, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[red, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[
grid=both,
xlabel={$E_b / N_0$}, ylabel={Decoding Failure Rate},
ymode=log,
width=0.48\textwidth,
height=0.36\textwidth,
ymax=1.5, ymin=3e-8,
]
\addplot[ForestGreen, mark=*, solid]
table [x=SNR, y=DFR, col sep=comma, discard if not={gamma}{0.15}]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[Emerald, mark=triangle, densely dashed]
table [x=SNR, y=DFR, col sep=comma, discard if not={gamma}{0.15}]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\addplot[NavyBlue, mark=*, solid]
table [x=SNR, y=DFR, col sep=comma, discard if not={gamma}{0.01}]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[RoyalPurple, mark=triangle, densely dashed]
table [x=SNR, y=DFR, col sep=comma, discard if not={gamma}{0.01}]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\addplot[RedOrange, mark=*, solid]
table [x=SNR, y=DFR, col sep=comma, discard if not={gamma}{0.05}]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[red, mark=triangle, densely dashed]
table [x=SNR, y=DFR, col sep=comma, discard if not={gamma}{0.05}]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}[hide axis,
xmin=10, xmax=50,
ymin=0, ymax=0.4,
legend columns=3,
legend style={draw=white!15!black,legend cell align=left}]
\addlegendimage{ForestGreen, mark=*, solid}
\addlegendentry{proximal, $\gamma = 0.15$}
\addlegendimage{NavyBlue, mark=*, solid}
\addlegendentry{proximal, $\gamma = 0.01$}
\addlegendimage{RedOrange, mark=*, solid}
\addlegendentry{proximal, $\gamma = 0.05$}
\addlegendimage{Emerald, mark=triangle, densely dashed}
\addlegendentry{improved, $\gamma = 0.15$}
\addlegendimage{RoyalPurple, mark=triangle, densely dashed}
\addlegendentry{improved, $\gamma = 0.01$}
\addlegendimage{red, mark=triangle, densely dashed}
\addlegendentry{improved, $\gamma = 0.05$}
\end{axis}
\end{tikzpicture}
\caption{Simulation results for $\gamma = 0.05, \omega = 0.05, K=200, N=12$}
\label{fig:prox:improved_results}
\end{figure}
Interestingly, the improved algorithm does not have much different time
complexity than proximal decoding.
This is the case, because the ML-in-the-List step is only performed when the
@@ -1317,11 +1496,339 @@ This is illustrated in figure \ref{fig:prox:time_complexity_comp}, where the
average time needed to decode a single received frame is visualized for
proximal decoding as well as for the improved algorithm.
\begin{figure}[H]
\centering
\begin{tikzpicture}
\begin{axis}[grid=both,
xlabel={$n$}, ylabel={Time per frame (s)},
legend style={at={(0.05,0.77)},anchor=south west},
legend cell align={left},]
\addplot[RedOrange, only marks, mark=*]
table [col sep=comma, x=n, y=spf]
{res/proximal/fps_vs_n.csv};
\addlegendentry{proximal}
\addplot[RoyalPurple, only marks, mark=triangle*]
table [col sep=comma, x=n, y=spf]
{res/hybrid/fps_vs_n.csv};
\addlegendentry{improved ($N = 12$)}
\end{axis}
\end{tikzpicture}
\caption{Time Complexity of Proximal Decoding and Modified Implementation%
\protect\footnotemark{}}
\label{fig:prox:time_complexity_comp}
\end{figure}%
%
\footnotetext{The datapoints depicted were calculated by evaluating the
metadata of \ac{FER} simulation results from the following codes:
BCH (31, 11); BCH (31, 26); \cite[\text{96.3.965; 204.33.484; 204.55.187;
408.33.844; PEGReg252x504}]{mackay_enc}
}%
%
In conclusion, the decoding performance of proximal decoding can be improved
by appending an ML-in-the-List step when the algorithm does not produce a
valid result.
The gain is in some cases as high as $\SI{1}{dB}$ and can be achieved with
The gain can in some cases be as high as $\SI{1}{dB}$ and is achievable with
negligible computational performance penalty.
The improvement is mainly noticable for higher \ac{SNR} values and depends on
the code as well as the chosen parameters.
\begin{figure}[H]
\centering
\begin{subfigure}[c]{0.48\textwidth}
\centering
\begin{tikzpicture}
\begin{axis}[
grid=both,
xlabel={$E_b / N_0$}, ylabel={FER},
ymode=log,
legend columns=1,
legend pos=outer north east,
ymax=1.5, ymin=8e-5,
width=\textwidth,
height=0.75\textwidth,
]
\addplot[ForestGreen, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/proximal/2d_ber_fer_dfr_963965.csv};
\addplot[Emerald, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/hybrid/2d_ber_fer_dfr_963965.csv};
\addplot[NavyBlue, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/proximal/2d_ber_fer_dfr_963965.csv};
\addplot[RoyalPurple, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/hybrid/2d_ber_fer_dfr_963965.csv};
\addplot[RedOrange, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/proximal/2d_ber_fer_dfr_963965.csv};
\addplot[red, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/hybrid/2d_ber_fer_dfr_963965.csv};
\end{axis}
\end{tikzpicture}
\caption{$\left( 3, 6 \right)$-regular LDPC code with $n=96, k=48$ \cite[\text{96.3.965}]{mackay_enc}}
\end{subfigure}%
\hfill%
\begin{subfigure}[c]{0.48\textwidth}
\centering
\begin{tikzpicture}
\begin{axis}[
grid=both,
xlabel={$E_b / N_0$}, ylabel={FER},
ymode=log,
legend columns=1,
legend pos=outer north east,
xmin=0.5, xmax=6, xtick={1, ..., 5},
ymax=1.5, ymin=8e-5,
width=\textwidth,
height=0.75\textwidth,
]
\addplot[ForestGreen, mark=*, solid,]
table [x=SNR, y=FER, col sep=comma,
discard if not={gamma}{0.15},
discard if gt={SNR}{5.5},]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[Emerald, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma,
discard if not={gamma}{0.15},
discard if gt={SNR}{5.5},]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\addplot[NavyBlue, mark=*, solid]
table [x=SNR, y=FER, col sep=comma,
discard if not={gamma}{0.01},
discard if gt={SNR}{5.5},]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[RoyalPurple, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma,
discard if not={gamma}{0.01},
discard if gt={SNR}{5.5},]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\addplot[RedOrange, mark=*, solid]
table [x=SNR, y=FER, col sep=comma,
discard if not={gamma}{0.05},
discard if gt={SNR}{5.5},]
{res/proximal/2d_ber_fer_dfr_20433484.csv};
\addplot[red, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma,
discard if not={gamma}{0.05},
discard if gt={SNR}{5.5},]
{res/hybrid/2d_ber_fer_dfr_20433484.csv};
\end{axis}
\end{tikzpicture}
\caption{$\left( 3, 6 \right)$-regular LDPC code with $n=204, k=102$ \cite[\text{204.33.484}]{mackay_enc}}
\end{subfigure}%
\begin{subfigure}[c]{0.48\textwidth}
\centering
\begin{tikzpicture}
\begin{axis}[
grid=both,
xlabel={$E_b / N_0$}, ylabel={FER},
ymode=log,
legend columns=1,
legend pos=outer north east,
%legend columns=2,
%legend style={at={(0.5,-0.45)},anchor=south},
ymax=1.5, ymin=8e-5,
width=\textwidth,
height=0.75\textwidth,
]
\addplot[ForestGreen, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/proximal/2d_ber_fer_dfr_40833844.csv};
\addplot[Emerald, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/hybrid/2d_ber_fer_dfr_40833844.csv};
\addplot[NavyBlue, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/proximal/2d_ber_fer_dfr_40833844.csv};
\addplot[RoyalPurple, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/hybrid/2d_ber_fer_dfr_40833844.csv};
\addplot[RedOrange, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/proximal/2d_ber_fer_dfr_40833844.csv};
\addplot[red, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/hybrid/2d_ber_fer_dfr_40833844.csv};
\end{axis}
\end{tikzpicture}
\caption{$\left( 3, 6 \right)$-regular LDPC code with $n=408, k=204$ \cite[\text{408.33.844}]{mackay_enc}}
\end{subfigure}%
\hfill%
\begin{subfigure}[c]{0.48\textwidth}
\centering
\begin{tikzpicture}
\begin{axis}[
grid=both,
xlabel={$E_b / N_0$}, ylabel={FER},
ymode=log,
legend columns=1,
legend pos=outer north east,
%legend columns=2,
%legend style={at={(0.5,-0.45)},anchor=south},
ymax=1.5, ymin=8e-5,
width=\textwidth,
height=0.75\textwidth,
]
\addplot[ForestGreen, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/proximal/2d_ber_fer_dfr_bch_31_26.csv};
\addplot[Emerald, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/hybrid/2d_ber_fer_dfr_bch_31_26.csv};
\addplot[NavyBlue, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/proximal/2d_ber_fer_dfr_bch_31_26.csv};
\addplot[RoyalPurple, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/hybrid/2d_ber_fer_dfr_bch_31_26.csv};
\addplot[RedOrange, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/proximal/2d_ber_fer_dfr_bch_31_26.csv};
\addplot[red, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/hybrid/2d_ber_fer_dfr_bch_31_26.csv};
\end{axis}
\end{tikzpicture}
\caption{BCH code with $n=31, k=26$\\[\baselineskip]}
\end{subfigure}%
\begin{subfigure}[c]{0.48\textwidth}
\centering
\begin{tikzpicture}
\begin{axis}[
grid=both,
xlabel={$E_b / N_0$}, ylabel={FER},
ymode=log,
legend columns=1,
legend pos=outer north east,
%legend columns=2,
%legend style={at={(0.5,-0.45)},anchor=south},
ymax=1.5, ymin=8e-5,
width=\textwidth,
height=0.75\textwidth,
]
\addplot[ForestGreen, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/proximal/2d_ber_fer_dfr_20455187.csv};
\addplot[Emerald, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/hybrid/2d_ber_fer_dfr_20455187.csv};
\addplot[NavyBlue, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/proximal/2d_ber_fer_dfr_20455187.csv};
\addplot[RoyalPurple, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/hybrid/2d_ber_fer_dfr_20455187.csv};
\addplot[RedOrange, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/proximal/2d_ber_fer_dfr_20455187.csv};
\addplot[red, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/hybrid/2d_ber_fer_dfr_20455187.csv};
\end{axis}
\end{tikzpicture}
\caption{$\left( 5, 10 \right)$-regular LDPC code with $n=204, k=102$ \cite[\text{204.55.187}]{mackay_enc}}
\end{subfigure}%
\hfill%
\begin{subfigure}[c]{0.48\textwidth}
\centering
\begin{tikzpicture}
\begin{axis}[
grid=both,
xlabel={$E_b / N_0$}, ylabel={FER},
ymode=log,
legend columns=1,
legend pos=outer north east,
ymax=1.5, ymin=8e-5,
width=\textwidth,
height=0.75\textwidth,
]
\addplot[ForestGreen, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/proximal/2d_ber_fer_dfr_pegreg252x504.csv};
\addplot[Emerald, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.15}]
{res/hybrid/2d_ber_fer_dfr_pegreg252x504.csv};
\addplot[NavyBlue, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/proximal/2d_ber_fer_dfr_pegreg252x504.csv};
\addplot[RoyalPurple, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.01}]
{res/hybrid/2d_ber_fer_dfr_pegreg252x504.csv};
\addplot[RedOrange, mark=*, solid]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/proximal/2d_ber_fer_dfr_pegreg252x504.csv};
\addplot[red, mark=triangle, densely dashed]
table [x=SNR, y=FER, col sep=comma, discard if not={gamma}{0.05}]
{res/hybrid/2d_ber_fer_dfr_pegreg252x504.csv};
\end{axis}
\end{tikzpicture}\\
\caption{LDPC code (Progressive Edge Growth Construction) with $n=504, k=252$ \cite[\text{PEGReg252x504}]{mackay_enc}}
\end{subfigure}%
\vspace{1cm}
\begin{subfigure}[c]{\textwidth}
\centering
\begin{tikzpicture}
\begin{axis}[hide axis,
xmin=10, xmax=50,
ymin=0, ymax=0.4,
legend columns=3,
legend style={draw=white!15!black,legend cell align=left}]
\addlegendimage{ForestGreen, mark=*, solid}
\addlegendentry{proximal, $\gamma = 0.15$}
\addlegendimage{NavyBlue, mark=*, solid}
\addlegendentry{proximal, $\gamma = 0.01$}
\addlegendimage{RedOrange, mark=*, solid}
\addlegendentry{proximal, $\gamma = 0.05$}
\addlegendimage{Emerald, mark=triangle, densely dashed}
\addlegendentry{improved, $\gamma = 0.15$}
\addlegendimage{RoyalPurple, mark=triangle, densely dashed}
\addlegendentry{improved, $\gamma = 0.01$}
\addlegendimage{red, mark=triangle, densely dashed}
\addlegendentry{improved, $\gamma = 0.05$}
\end{axis}
\end{tikzpicture}
\end{subfigure}
\caption{Comparison of improvement in decoding performance for various
codes}
\label{fig:prox:improved:comp}
\end{figure}