%-------------------------------------------------------------------------------
% The QuickStart.tex file.
%-------------------------------------------------------------------------------

\documentclass[11pt]{article}

\newcommand{\m}[1]{{\bf{#1}}}       % for matrices and vectors
\newcommand{\tr}{^{\sf T}}          % transpose

\topmargin 0in
\textheight 8.5in
\oddsidemargin 0pt
\evensidemargin 0pt
\textwidth 6.5in

\begin{document}

\author{Timothy A. Davis \\
DrTimothyAldenDavis@gmail.com, http://www.suitesparse.com}
\title{UMFPACK Quick Start Guide}
\date{VERSION 5.7.1, Oct 10, 2014}
\maketitle

%-------------------------------------------------------------------------------
\begin{abstract}
    UMFPACK is a set of routines for solving unsymmetric sparse linear
    systems, $\m{Ax}=\m{b}$, using the Unsymmetric-pattern MultiFrontal method
    and direct sparse LU factorization.  It is written in ANSI/ISO C, with a
    MATLAB interface.  UMFPACK relies on the Level-3
    Basic Linear Algebra Subprograms (dense matrix multiply) for its
    performance.  This code works on Windows and many versions of Unix (Sun
    Solaris, Red Hat Linux, IBM AIX, SGI IRIX, and Compaq Alpha).
    This is a ``quick start'' guide for Unix users of the C interface.
\end{abstract}
%-------------------------------------------------------------------------------

Copyright\copyright 1995-2013 by Timothy A. Davis.
All Rights Reserved.  Refer to the UMFPACK User Guide
for the License. See http://www.suitesparse.com
for the code and full documentation.

%-------------------------------------------------------------------------------
\section{Overview}
%-------------------------------------------------------------------------------

UMFPACK is a set of routines for solving systems of linear
equations, $\m{Ax}=\m{b}$, when $\m{A}$ is sparse and unsymmetric.
The sparse matrix $\m{A}$ can be square or rectangular, singular
or non-singular, and real or complex (or any combination).  Only square
matrices $\m{A}$ can be used to solve $\m{Ax}=\m{b}$ or related systems.
Rectangular matrices can only be factorized.

UMFPACK is a built-in routine in MATLAB used by the forward and
backslash operator, and the {\tt lu} routine.
The following is a short
introduction to Unix users of the C interface of UMFPACK.

%-------------------------------------------------------------------------------

The C-callable UMFPACK library consists of 32 user-callable routines and one
include file.  Twenty-eight of the routines come in four versions, with
different sizes of integers and for real or complex floating-point numbers.
This Quick Start Guide assumes you are working with real matrices
(not complex) and with {\tt int}'s as integers (not {\tt long}'s).
Refer to the User Guide for information about the complex and
long integer versions.  The include file {\tt umfpack.h}
must be included in any C program that uses UMFPACK.

For more details, see:
{\em A column pre-ordering strategy for the unsymmetric-pattern multifrontal method},
Davis, T. A.,
ACM Trans. Math. Software, vol 30. no 2, 2004, pp. 165-195, and
{\em Algorithm 832:  {UMFPACK}, an unsymmetric-pattern multifrontal method},
same issue, pp. 196-199.

%-------------------------------------------------------------------------------
\section{Primary routines, and a simple example}
%-------------------------------------------------------------------------------

Five primary UMFPACK routines are required to factorize $\m{A}$ or
solve $\m{Ax}=\m{b}$.  An overview of the primary features of the routines
is given in Section~\ref{Primary}.
Additional routines are available for passing a different column ordering
to UMFPACK, changing default parameters, manipulating sparse matrices,
getting the LU factors, save and loading the LU factors from a file,
computing the determinant,
and reporting results.  See the User Guide for more information.

\begin{itemize}
\item {\tt umfpack\_di\_symbolic}:

    Pre-orders the columns of $\m{A}$ to reduce fill-in and performs a
    symbolic analysis.
    Returns an opaque {\tt Symbolic} object as a {\tt void *}
    pointer.  The object contains the symbolic analysis and is needed for the
    numerical factorization.

\item {\tt umfpack\_di\_numeric}:

    Numerically scales and then factorizes a sparse matrix
    $\m{PAQ}$, $\m{PRAQ}$, or $\m{PR}^{-1}\m{AQ}$ into the product $\m{LU}$,
    where
    $\m{P}$ and $\m{Q}$ are permutation matrices, $\m{R}$ is a diagonal
    matrix of scale factors, $\m{L}$ is lower triangular with unit diagonal,
    and $\m{U}$ is upper triangular.  Requires the
    symbolic ordering and analysis computed by {\tt umfpack\_di\_symbolic}.
    Returns an opaque {\tt Numeric} object as a
    {\tt void *} pointer.  The object contains the numerical factorization and
    is used by {\tt umfpack\_di\_solve}.

\item {\tt umfpack\_di\_solve}:

    Solves a sparse linear system ($\m{Ax}=\m{b}$, $\m{A}\tr\m{x}=\m{b}$, or
    systems involving just $\m{L}$ or $\m{U}$), using the numeric factorization
    computed by {\tt umfpack\_di\_numeric}.

\item {\tt umfpack\_di\_free\_symbolic}:

    Frees the {\tt Symbolic} object created by {\tt umfpack\_di\_symbolic}.

\item {\tt umfpack\_di\_free\_numeric}:

    Frees the {\tt Numeric} object created by {\tt umfpack\_di\_numeric}.

\end{itemize}

The matrix $\m{A}$ is represented in compressed column form, which is
identical to the sparse matrix representation used by MATLAB.  It consists
of three arrays, where the matrix is {\tt m}-by-{\tt n},
with {\tt nz} entries:

{\footnotesize
\begin{verbatim}
     int Ap [n+1] ;
     int Ai [nz] ;
     double Ax [nz] ;
\end{verbatim}
}

All nonzeros are entries, but an entry may be numerically zero.  The row indices
of entries in column {\tt j} are stored in
    {\tt Ai[Ap[j]} ... {\tt Ap[j+1]-1]}.
The corresponding numerical values are stored in
    {\tt Ax[Ap[j]} ... {\tt Ap[j+1]-1]}.

No duplicate row indices may be present, and the row indices in any given
column must be sorted in ascending order.  The first entry {\tt Ap[0]} must be
zero.  The total number of entries in the matrix is thus {\tt nz = Ap[n]}.
Except for the fact that extra zero entries can be included, there is thus a
unique compressed column representation of any given matrix $\m{A}$.

Here is a simple main program, {\tt umfpack\_simple.c}, that illustrates the
basic usage of UMFPACK.

{\footnotesize
\begin{verbatim}
    #include <stdio.h>
    #include "umfpack.h"

    int    n = 5 ;
    int    Ap [ ] = {0, 2, 5, 9, 10, 12} ;
    int    Ai [ ] = { 0,  1,  0,   2,  4,  1,  2,  3,   4,  2,  1,  4} ;
    double Ax [ ] = {2., 3., 3., -1., 4., 4., -3., 1., 2., 2., 6., 1.} ;
    double b [ ] = {8., 45., -3., 3., 19.} ;
    double x [5] ;

    int main (void)
    {
        double *null = (double *) NULL ;
        int i ;
        void *Symbolic, *Numeric ;
        (void) umfpack_di_symbolic (n, n, Ap, Ai, Ax, &Symbolic, null, null) ;
        (void) umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, null, null) ;
        umfpack_di_free_symbolic (&Symbolic) ;
        (void) umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, x, b, Numeric, null, null) ;
        umfpack_di_free_numeric (&Numeric) ;
        for (i = 0 ; i < n ; i++) printf ("x [%d] = %g\n", i, x [i]) ;
        return (0) ;
    }
\end{verbatim}
}

The {\tt Ap}, {\tt Ai}, and {\tt Ax} arrays represent the matrix
\[
\m{A} = \left[
\begin{array}{rrrrr}
 2 &  3 &  0 &  0 &  0 \\
 3 &  0 &  4 &  0 &  6 \\
 0 & -1 & -3 &  2 &  0 \\
 0 &  0 &  1 &  0 &  0 \\
 0 &  4 &  2 &  0 &  1 \\
\end{array}
\right].
\]
and the solution is $\m{x} = [1 \, 2 \, 3 \, 4 \, 5]\tr$.  The program uses
default control settings and does not return any statistics about the ordering,
factorization, or solution ({\tt Control} and {\tt Info} are both
{\tt (double *) NULL}).

For routines to manipulate a simpler ``triplet-form'' data structure for your
sparse matrix $\m{A}$, refer to the UMFPACK User Guide.

%-------------------------------------------------------------------------------
\section{Synopsis of primary C-callable routines}
\label{Synopsis}
%-------------------------------------------------------------------------------

The matrix $\m{A}$ is {\tt m}-by-{\tt n} with {\tt nz} entries.
The optional {\tt umfpack\_di\_defaults} routine loads the default control
parameters into the {\tt Control} array.  The settings can then be modified
before passing the array to the other routines.  Refer to Section~\ref{Primary}
for more details.

{\footnotesize
\begin{verbatim}
    #include "umfpack.h"
    int status, sys, n, m, nz, Ap [n+1], Ai [nz] ;
    double Control [UMFPACK_CONTROL], Info [UMFPACK_INFO], Ax [nz], X [n], B [n] ;
    void *Symbolic, *Numeric ;

    umfpack_di_defaults (Control) ;
    status = umfpack_di_symbolic (m, n, Ap, Ai, Ax, &Symbolic, Control, Info) ;
    status = umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, Control, Info) ;
    status = umfpack_di_solve (sys, Ap, Ai, Ax, X, B, Numeric, Control, Info) ;
    umfpack_di_free_symbolic (&Symbolic) ;
    umfpack_di_free_numeric (&Numeric) ;
\end{verbatim}
}

%-------------------------------------------------------------------------------
\section{Installation}
\label{Install}
%-------------------------------------------------------------------------------

You will need to install both UMFPACK and AMD to use UMFPACK.
The {\tt UMFPACK} and {\tt AMD} subdirectories must be placed side-by-side
within the same parent directory.  AMD is a stand-alone package that
is required by UMFPACK.  UMFPACK can be compiled without the
BLAS
but your performance will be much less than what it should be.

UMFPACK also requires CHOLMOD, CCAMD, CCOLAMD, COLAMD, and metis-4.0
by default.  You can remove this dependency by compiling with
{\tt -DNCHOLMOD}.  Add this to the {\tt UMFPACK\_CONFIG} definition
in {\tt SuiteSparse\_config/SuiteSparse\_config.mk}.

System-dependent configurations are in the {\tt SuiteSparse\_config/SuiteSparse\_config.mk}
file.  The default
settings will work on most systems, except for the BLAS definition.
Sample configurations are provided
for Linux, Mac, Sun Solaris, SGI IRIX, IBM AIX, and the DEC/Compaq Alpha.

To compile and install both packages,
go to the {\tt UMFPACK} directory and type {\tt make}.  This will compile the
libraries ({\tt AMD/Lib/libamd.a} and {\tt UMFPACK/Lib/libumfpack.a}).
A demo of the AMD ordering routine will be compiled and tested in
the {\tt AMD/Demo} directory, and five demo programs will then be
compiled and tested in the {\tt UMFPACK/Demo} directory.
The outputs of these demo programs will then be compared with output
files in the distribution.  Expect to see a few differences, such as
residual norms, compile-time control settings, and perhaps memory usage
differences.

If you have trouble with {\tt make} for UMFPACK,
try using the plain {\tt Makefile} instead of {\tt GNUmakefile}.
Go to the UMFPACK/Lib directory and type {\tt make -f Makefile}.

Use the MATLAB command {\tt umfpack\_make} in the MATLAB directory
to compile UMFPACK and AMD for use in MATLAB.

If you compile UMFPACK and AMD and then later change the
{\tt SuiteSparse\_config/SuiteSparse\_config.mk} file
then you should type {\tt make purge} and then {\tt make} to recompile.

Here are the various parameters that you can control in your
{\tt SuiteSparse\_config/SuiteSparse\_config.mk} file:

\begin{itemize}
\item {\tt CC = } your C compiler, such as {\tt cc}.
\item {\tt RANLIB = } your system's {\tt ranlib} program, if needed.
\item {\tt CFLAGS = } optimization flags, such as {\tt -O}.
\item {\tt UMFPACK\_CONFIG = } configuration settings for the BLAS,
    memory allocation routines, and timing routines.
\item {\tt LIB = } your libraries, such as {\tt -lm} or {\tt -lblas}.
\item {\tt RM =} the command to delete a file.
\item {\tt MV =} the command to rename a file.
\item {\tt F77 =} the command to compile a Fortran program (optional).
\item {\tt F77FLAGS =} the Fortran compiler flags (optional).
\item {\tt F77LIB =} the Fortran libraries (optional).
\end{itemize}

The {\tt UMFPACK\_CONFIG} string can include combinations of the following;
most deal with how the BLAS are called:
\begin{itemize}
\item {\tt -DNBLAS} if you do not have any BLAS at all.
\item {\tt -DNSUNPERF} if you are on Solaris but do not have the Sun
    Performance Library.
\item {\tt -DLONGBLAS} if your BLAS takes non-{\tt int} integer arguments.
\item {\tt -DBLAS\_INT = } the integer used by the BLAS.

\item {\tt -DBLAS\_NO\_UNDERSCORE}
    for controlling how C calls the Fortran BLAS.
    This is set automatically for Windows,
    Sun Solaris, SGI Irix, Red Hat Linux, Compaq Alpha, and
    AIX (the IBM RS 6000).

\item {\tt -DNRECIPROCAL} controls a trade-off between speed and accuracy.
    This is off by default (speed preferred over accuracy) except when
    compiling for MATLAB.
\end{itemize}

When you compile your program that uses the C-callable UMFPACK library,
you need to link your program with all libraries
({\tt UMFPACK/Lib/libumfpack.a} and {\tt AMD/Lib/libamd.a},
and unless you compile with \verb'-DNCHOLMOD' you also must link with
{\tt CHOLMOD/Lib/libcholmod.a}, \newline
{\tt COLAMD/Lib/libcolamd.a},
{\tt CCOLAMD/Lib/libccolamd.a},
{\tt CAMD/Lib/libcamd.a},
and \newline
{\tt metis-4.0/libmetis.a}).
You need to tell your compiler to look in the
directories {\tt UMFPACK/Include} and {\tt AMD/Include} for include
files.  See {\tt UMFPACK/Demo/Makefile} for an example.
You do not need to directly include any AMD include files in your
program, unless you directly call AMD routines.  You only need the
\begin{verbatim}
#include "umfpack.h"
\end{verbatim}
statement, as described in Section~\ref{Synopsis}.

%-------------------------------------------------------------------------------
\newpage
\section{The primary UMFPACK routines}
\label{Primary}
%-------------------------------------------------------------------------------

\subsection{umfpack\_di\_symbolic}

{\footnotesize
\begin{verbatim}
int umfpack_di_symbolic
(
    int n_row,
    int n_col,
    const int Ap [ ],
    const int Ai [ ],
    const double Ax [ ],
    void **Symbolic,
    const double Control [UMFPACK_CONTROL],
    double Info [UMFPACK_INFO]
) ;

Purpose:

    Given nonzero pattern of a sparse matrix A in column-oriented form,
    umfpack_di_symbolic performs a column pre-ordering to reduce fill-in
    (using COLAMD or AMD) and a symbolic factorization.  This is required
    before the matrix can be numerically factorized with umfpack_di_numeric.

    For the following discussion, let S be the submatrix of A obtained after
    eliminating all pivots of zero Markowitz cost.  S has dimension
    (n_row-n1-nempty_row) -by- (n_col-n1-nempty_col), where
    n1 = Info [UMFPACK_COL_SINGLETONS] + Info [UMFPACK_ROW_SINGLETONS],
    nempty_row = Info [UMFPACK_NEMPTY_ROW] and
    nempty_col = Info [UMFPACK_NEMPTY_COL].

Returns:

    The status code is returned.  See Info [UMFPACK_STATUS], below.

Arguments:

    int n_row ;         Input argument, not modified.
    int n_col ;         Input argument, not modified.

        A is an n_row-by-n_col matrix.  Restriction: n_row > 0 and n_col > 0.

    int Ap [n_col+1] ;  Input argument, not modified.

        Ap is an integer array of size n_col+1.  On input, it holds the
        "pointers" for the column form of the sparse matrix A.  Column j of
        the matrix A is held in Ai [(Ap [j]) ... (Ap [j+1]-1)].  The first
        entry, Ap [0], must be zero, and Ap [j] <= Ap [j+1] must hold for all
        j in the range 0 to n_col-1.  The value nz = Ap [n_col] is thus the
        total number of entries in the pattern of the matrix A.  nz must be
        greater than or equal to zero.

    int Ai [nz] ;       Input argument, not modified, of size nz = Ap [n_col].

        The nonzero pattern (row indices) for column j is stored in
        Ai [(Ap [j]) ... (Ap [j+1]-1)].  The row indices in a given column j
        must be in ascending order, and no duplicate row indices may be present.
        Row indices must be in the range 0 to n_row-1 (the matrix is 0-based).

    double Ax [nz] ;    Optional input argument, not modified.

        The numerical values of the sparse matrix A.  The nonzero pattern (row
        indices) for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and
        the corresponding numerical values are stored in
        Ax [(Ap [j]) ... (Ap [j+1]-1)].  Used only by the 2-by-2 strategy to
        determine whether entries are "large" or "small".  You do not have to
        pass the same numerical values to umfpack_di_numeric.  If Ax is not
        present (a (double *) NULL pointer), then any entry in A is assumed to
        be "large".

    void **Symbolic ;   Output argument.

        **Symbolic is the address of a (void *) pointer variable in the user's
        calling routine (see Syntax, above).  On input, the contents of this
        variable are not defined.  On output, this variable holds a (void *)
        pointer to the Symbolic object (if successful), or (void *) NULL if
        a failure occurred.

    double Control [UMFPACK_CONTROL] ;  Input argument, not modified.

        If a (double *) NULL pointer is passed, then the default control
        settings are used.  Only the primary parameters are listed below:

        Control [UMFPACK_STRATEGY]:  This is the most important control
            parameter.  It determines what kind of ordering and pivoting
            strategy that UMFPACK should use.  It is new to Version 4.1
            There are 4 options:

            UMFPACK_STRATEGY_AUTO:  This is the default.  The input matrix is
                analyzed to determine how symmetric the nonzero pattern is, and
                how many entries there are on the diagonal.  It then selects one
                of the following strategies.  Refer to the User Guide for a
                description of how the strategy is automatically selected.

            UMFPACK_STRATEGY_UNSYMMETRIC:  Use the unsymmetric strategy.  COLAMD
                is used to order the columns of A, followed by a postorder of
                the column elimination tree.  No attempt is made to perform
                diagonal pivoting.  The column ordering is refined during
                factorization.  This strategy was the only one provided with
                UMFPACK V4.0.

                In the numerical factorization, the
                Control [UMFPACK_SYM_PIVOT_TOLERANCE] parameter is ignored.  A
                pivot is selected if its magnitude is >=
                Control [UMFPACK_PIVOT_TOLERANCE] (default 0.1) times the
                largest entry in its column.

            UMFPACK_STRATEGY_SYMMETRIC:  Use the symmetric strategy (new to
                Version 4.1).  In this method, the approximate minimum degree
                ordering (AMD) is applied to A+A', followed by a postorder of
                the elimination tree of A+A'.  UMFPACK attempts to perform
                diagonal pivoting during numerical factorization.  No refinement
                of the column preordering is performed during factorization.

                In the numerical factorization, a nonzero entry on the diagonal
                is selected as the pivot if its magnitude is >= Control
                [UMFPACK_SYM_PIVOT_TOLERANCE] (default 0.001) times the largest
                entry in its column.  If this is not acceptable, then an
                off-diagonal pivot is selected with magnitude >= Control
                [UMFPACK_PIVOT_TOLERANCE] (default 0.1) times the largest entry
                in its column.

        Control [UMFPACK_SCALE]:  This parameter is new to V4.1.  See
            umfpack_numeric.h for a description.  Only affects the 2-by-2
            strategy.  Default: UMFPACK_SCALE_SUM.

    double Info [UMFPACK_INFO] ;        Output argument, not defined on input.

        Contains statistics about the symbolic analysis.  If a (double *) NULL
        pointer is passed, then no statistics are returned in Info (this is not
        an error condition).  The entire Info array is cleared (all entries set
        to -1) and then the following statistics are computed (only the
        primary statistics are listed):

        Info [UMFPACK_STATUS]: status code.  This is also the return value,
            whether or not Info is present.

            UMFPACK_OK

                Each column of the input matrix contained row indices
                in increasing order, with no duplicates.  Only in this case
                does umfpack_di_symbolic compute a valid symbolic factorization.
                For the other cases below, no Symbolic object is created
                (*Symbolic is (void *) NULL).

            UMFPACK_ERROR_n_nonpositive

                n is less than or equal to zero.

            UMFPACK_ERROR_invalid_matrix

                Number of entries in the matrix is negative, Ap [0] is nonzero,
                a column has a negative number of entries, a row index is out of
                bounds, or the columns of input matrix were jumbled (unsorted
                columns or duplicate entries).

            UMFPACK_ERROR_out_of_memory

                Insufficient memory to perform the symbolic analysis.  If the
                analysis requires more than 2GB of memory and you are using
                the 32-bit ("int") version of UMFPACK, then you are guaranteed
                to run out of memory.  Try using the 64-bit version of UMFPACK.

            UMFPACK_ERROR_argument_missing

                One or more required arguments is missing.

            UMFPACK_ERROR_internal_error

                Something very serious went wrong.  This is a bug.
                Please contact the author (DrTimothyAldenDavis@gmail.com).

        Info [UMFPACK_SIZE_OF_UNIT]:  the number of bytes in a Unit,
            for memory usage statistics below.

        Info [UMFPACK_SYMBOLIC_PEAK_MEMORY]:  the amount of memory (in Units)
            required for umfpack_di_symbolic to complete.  This count includes
            the size of the Symbolic object itself, which is also reported in
            Info [UMFPACK_SYMBOLIC_SIZE].

        Info [UMFPACK_NUMERIC_SIZE_ESTIMATE]:  an estimate of the final size (in
            Units) of the entire Numeric object (both fixed-size and variable-
            sized parts), which holds the LU factorization (including the L, U,
            P and Q matrices).

        Info [UMFPACK_PEAK_MEMORY_ESTIMATE]:  an estimate of the total amount of
            memory (in Units) required by umfpack_di_symbolic and
            umfpack_di_numeric to perform both the symbolic and numeric
            factorization.  This is the larger of the amount of memory needed
            in umfpack_di_numeric itself, and the amount of memory needed in
            umfpack_di_symbolic (Info [UMFPACK_SYMBOLIC_PEAK_MEMORY]).  The
            count includes the size of both the Symbolic and Numeric objects
            themselves.  It can be a very loose upper bound, particularly when
            the symmetric or 2-by-2 strategies are used.

        Info [UMFPACK_FLOPS_ESTIMATE]:  an estimate of the total floating-point
            operations required to factorize the matrix.  This is a "true"
            theoretical estimate of the number of flops that would be performed
            by a flop-parsimonious sparse LU algorithm.  It assumes that no
            extra flops are performed except for what is strictly required to
            compute the LU factorization.  It ignores, for example, the flops
            performed by umfpack_di_numeric to add contribution blocks of
            frontal matrices together.  If L and U are the upper bound on the
            pattern of the factors, then this flop count estimate can be
            represented in MATLAB (for real matrices, not complex) as:

                Lnz = full (sum (spones (L))) - 1 ;     % nz in each col of L
                Unz = full (sum (spones (U')))' - 1 ;   % nz in each row of U
                flops = 2*Lnz*Unz + sum (Lnz) ;

            The actual "true flop" count found by umfpack_di_numeric will be
            less than this estimate.

        Info [UMFPACK_LNZ_ESTIMATE]:  an estimate of the number of nonzeros in
            L, including the diagonal.  Since L is unit-diagonal, the diagonal
            of L is not stored.  This estimate is a strict upper bound on the
            actual nonzeros in L to be computed by umfpack_di_numeric.

        Info [UMFPACK_UNZ_ESTIMATE]:  an estimate of the number of nonzeros in
            U, including the diagonal.  This estimate is a strict upper bound on
            the actual nonzeros in U to be computed by umfpack_di_numeric.

        Info [UMFPACK_SYMBOLIC_TIME]:  The CPU time taken, in seconds.

        Info [UMFPACK_STRATEGY_USED]: The ordering strategy used:
            UMFPACK_STRATEGY_SYMMETRIC or UMFPACK_STRATEGY_UNSYMMETRIC
\end{verbatim}
}

%-------------------------------------------------------------------------------
\newpage
\subsection{umfpack\_di\_numeric}

{\footnotesize
\begin{verbatim}
int umfpack_di_numeric
(
    const int Ap [ ],
    const int Ai [ ],
    const double Ax [ ],
    void *Symbolic,
    void **Numeric,
    const double Control [UMFPACK_CONTROL],
    double Info [UMFPACK_INFO]
) ;

Purpose:

    Given a sparse matrix A in column-oriented form, and a symbolic analysis
    computed by umfpack_di_symbolic, the umfpack_di_numeric routine performs the
    numerical factorization, PAQ=LU, PRAQ=LU, or P(R\A)Q=LU, where P and Q are
    permutation matrices (represented as permutation vectors), R is the row
    scaling, L is unit-lower triangular, and U is upper triangular.  This is
    required before the system Ax=b (or other related linear systems) can be
    solved.  umfpack_di_numeric can be called multiple times for each call to
    umfpack_di_symbolic, to factorize a sequence of matrices with identical
    nonzero pattern.  Simply compute the Symbolic object once, with
    umfpack_di_symbolic, and reuse it for subsequent matrices.
    umfpack_di_numeric safely detects if the pattern changes, and sets an
    appropriate error code.

Returns:

    The status code is returned.  See Info [UMFPACK_STATUS], below.

Arguments:

    int Ap [n_col+1] ;  Input argument, not modified.

        This must be identical to the Ap array passed to umfpack_di_symbolic.
        The value of n_col is what was passed to umfpack_di_symbolic (this is
        held in the Symbolic object).

    int Ai [nz] ;       Input argument, not modified, of size nz = Ap [n_col].

        This must be identical to the Ai array passed to umfpack_di_symbolic.

    double Ax [nz] ;    Input argument, not modified, of size nz = Ap [n_col].

        The numerical values of the sparse matrix A.  The nonzero pattern (row
        indices) for column j is stored in Ai [(Ap [j]) ... (Ap [j+1]-1)], and
        the corresponding numerical values are stored in
        Ax [(Ap [j]) ... (Ap [j+1]-1)].

    void *Symbolic ;    Input argument, not modified.

        The Symbolic object, which holds the symbolic factorization computed by
        umfpack_di_symbolic.  The Symbolic object is not modified by
        umfpack_di_numeric.

    void **Numeric ;    Output argument.

        **Numeric is the address of a (void *) pointer variable in the user's
        calling routine (see Syntax, above).  On input, the contents of this
        variable are not defined.  On output, this variable holds a (void *)
        pointer to the Numeric object (if successful), or (void *) NULL if
        a failure occurred.

    double Control [UMFPACK_CONTROL] ;   Input argument, not modified.

        If a (double *) NULL pointer is passed, then the default control
        settings are used.  Only the primary parameters are listed below:

        Control [UMFPACK_PIVOT_TOLERANCE]:  relative pivot tolerance for
            threshold partial pivoting with row interchanges.  In any given
            column, an entry is numerically acceptable if its absolute value is
            greater than or equal to Control [UMFPACK_PIVOT_TOLERANCE] times
            the largest absolute value in the column.  A value of 1.0 gives true
            partial pivoting.  If less than or equal to zero, then any nonzero
            entry is numerically acceptable as a pivot (this is changed from
            Version 4.0).  Default: 0.1.

            Smaller values tend to lead to sparser LU factors, but the solution
            to the linear system can become inaccurate.  Larger values can lead
            to a more accurate solution (but not always), and usually an
            increase in the total work.

        Control [UMFPACK_SYM_PIVOT_TOLERANCE]:  This parameter is new to V4.1.
            If diagonal pivoting is attempted (the symmetric
            strategy is used) then this parameter is used to control when the
            diagonal entry is selected in a given pivot column.  The absolute
            value of the entry must be >= Control [UMFPACK_SYM_PIVOT_TOLERANCE]
            times the largest absolute value in the column.  A value of zero
            will ensure that no off-diagonal pivoting is performed, except that
            zero diagonal entries are not selected if there are any off-diagonal
            nonzero entries.

            If an off-diagonal pivot is selected, an attempt is made to restore
            symmetry later on.  Suppose A (i,j) is selected, where i != j.
            If column i has not yet been selected as a pivot column, then
            the entry A (j,i) is redefined as a "diagonal" entry, except that
            the tighter tolerance (Control [UMFPACK_PIVOT_TOLERANCE]) is
            applied.  This strategy has an effect similar to 2-by-2 pivoting
            for symmetric indefinite matrices.  If a 2-by-2 block pivot with
            nonzero structure

                       i j
                    i: 0 x
                    j: x 0

            is selected in a symmetric indefinite factorization method, the
            2-by-2 block is inverted and a rank-2 update is applied.  In
            UMFPACK, this 2-by-2 block would be reordered as

                       j i
                    i: x 0
                    j: 0 x

            In both cases, the symmetry of the Schur complement is preserved.

        Control [UMFPACK_SCALE]:  This parameter is new to V4.1.  Version 4.0
            did not scale the matrix.  Note that the user's input matrix is
            never modified, only an internal copy is scaled.

            There are three valid settings for this parameter.  If any other
            value is provided, the default is used.

            UMFPACK_SCALE_NONE:  no scaling is performed.

            UMFPACK_SCALE_SUM:  each row of the input matrix A is divided by
                the sum of the absolute values of the entries in that row.
                The scaled matrix has an infinity norm of 1.

            UMFPACK_SCALE_MAX:  each row of the input matrix A is divided by
                the maximum the absolute values of the entries in that row.
                In the scaled matrix the largest entry in each row has
                a magnitude exactly equal to 1.

            Scaling is very important for the "symmetric" strategy when
            diagonal pivoting is attempted.  It also improves the performance
            of the "unsymmetric" strategy.

            Default: UMFPACK_SCALE_SUM.

    double Info [UMFPACK_INFO] ;        Output argument.

        Contains statistics about the numeric factorization.  If a
        (double *) NULL pointer is passed, then no statistics are returned in
        Info (this is not an error condition).  The following statistics are
        computed in umfpack_di_numeric (only the primary statistics are listed):

        Info [UMFPACK_STATUS]: status code.  This is also the return value,
            whether or not Info is present.

            UMFPACK_OK

                Numeric factorization was successful.  umfpack_di_numeric
                computed a valid numeric factorization.

            UMFPACK_WARNING_singular_matrix

                Numeric factorization was successful, but the matrix is
                singular.  umfpack_di_numeric computed a valid numeric
                factorization, but you will get a divide by zero in
                umfpack_di_solve.  For the other cases below, no Numeric object
                is created (*Numeric is (void *) NULL).

            UMFPACK_ERROR_out_of_memory

                Insufficient memory to complete the numeric factorization.

            UMFPACK_ERROR_argument_missing

                One or more required arguments are missing.

            UMFPACK_ERROR_invalid_Symbolic_object

                Symbolic object provided as input is invalid.

            UMFPACK_ERROR_different_pattern

                The pattern (Ap and/or Ai) has changed since the call to
                umfpack_di_symbolic which produced the Symbolic object.

        Info [UMFPACK_NUMERIC_SIZE]:  the actual final size (in Units) of the
            entire Numeric object, including the final size of the variable
            part of the object.  Info [UMFPACK_NUMERIC_SIZE_ESTIMATE],
            an estimate, was computed by umfpack_di_symbolic.  The estimate is
            normally an upper bound on the actual final size, but this is not
            guaranteed.

        Info [UMFPACK_PEAK_MEMORY]:  the actual peak memory usage (in Units) of
            both umfpack_di_symbolic and umfpack_di_numeric.  An estimate,
            Info [UMFPACK_PEAK_MEMORY_ESTIMATE], was computed by
            umfpack_di_symbolic.  The estimate is normally an upper bound on the
            actual peak usage, but this is not guaranteed.  With testing on
            hundreds of matrix arising in real applications, I have never
            observed a matrix where this estimate or the Numeric size estimate
            was less than the actual result, but this is theoretically possible.
            Please send me one if you find such a matrix.

        Info [UMFPACK_FLOPS]:  the actual count of the (useful) floating-point
            operations performed.  An estimate, Info [UMFPACK_FLOPS_ESTIMATE],
            was computed by umfpack_di_symbolic.  The estimate is guaranteed to
            be an upper bound on this flop count.  The flop count excludes
            "useless" flops on zero values, flops performed during the pivot
            search (for tentative updates and assembly of candidate columns),
            and flops performed to add frontal matrices together.

        Info [UMFPACK_LNZ]: the actual nonzero entries in final factor L,
            including the diagonal.  This excludes any zero entries in L,
            although some of these are stored in the Numeric object.  The
            Info [UMFPACK_LU_ENTRIES] statistic does account for all
            explicitly stored zeros, however.  Info [UMFPACK_LNZ_ESTIMATE],
            an estimate, was computed by umfpack_di_symbolic.  The estimate is
            guaranteed to be an upper bound on Info [UMFPACK_LNZ].

        Info [UMFPACK_UNZ]: the actual nonzero entries in final factor U,
            including the diagonal.  This excludes any zero entries in U,
            although some of these are stored in the Numeric object.  The
            Info [UMFPACK_LU_ENTRIES] statistic does account for all
            explicitly stored zeros, however.  Info [UMFPACK_UNZ_ESTIMATE],
            an estimate, was computed by umfpack_di_symbolic.  The estimate is
            guaranteed to be an upper bound on Info [UMFPACK_UNZ].

        Info [UMFPACK_NUMERIC_TIME]:  The CPU time taken, in seconds.
\end{verbatim}
}

%-------------------------------------------------------------------------------
\newpage
\subsection{umfpack\_di\_solve}

{\footnotesize
\begin{verbatim}
int umfpack_di_solve
(
    int sys,
    const int Ap [ ],
    const int Ai [ ],
    const double Ax [ ],
    double X [ ],
    const double B [ ],
    void *Numeric,
    const double Control [UMFPACK_CONTROL],
    double Info [UMFPACK_INFO]
) ;

Purpose:

    Given LU factors computed by umfpack_di_numeric (PAQ=LU, PRAQ=LU, or
    P(R\A)Q=LU) and the right-hand-side, B, solve a linear system for the
    solution X.  Iterative refinement is optionally performed.  Only square
    systems are handled.  Singular matrices result in a divide-by-zero for all
    systems except those involving just the matrix L.  Iterative refinement is
    not performed for singular matrices.

    In the discussion below, n is equal to n_row and n_col, because only
    square systems are handled.

Returns:

    The status code is returned.  See Info [UMFPACK_STATUS], below.

Arguments:

    int sys ;           Input argument, not modified.

        Defines which system to solve.  (') is the linear algebraic transpose.

            sys value       system solved

            UMFPACK_A       Ax=b
            UMFPACK_At      A'x=b
            UMFPACK_Pt_L    P'Lx=b
            UMFPACK_L       Lx=b
            UMFPACK_Lt_P    L'Px=b
            UMFPACK_Lt      L'x=b
            UMFPACK_U_Qt    UQ'x=b
            UMFPACK_U       Ux=b
            UMFPACK_Q_Ut    QU'x=b
            UMFPACK_Ut      U'x=b

        Iterative refinement can be optionally performed when sys is any of
        the following:

            UMFPACK_A       Ax=b
            UMFPACK_At      A'x=b

        For the other values of the sys argument, iterative refinement is not
        performed (Control [UMFPACK_IRSTEP], Ap, Ai, and Ax are ignored).

    int Ap [n+1] ;      Input argument, not modified.
    int Ai [nz] ;       Input argument, not modified.
    double Ax [nz] ;    Input argument, not modified.

        If iterative refinement is requested (Control [UMFPACK_IRSTEP] >= 1,
        Ax=b or A'x=b is being solved, and A is nonsingular), then
        these arrays must be identical to the same ones passed to
        umfpack_di_numeric.  The umfpack_di_solve routine does not check the
        contents of these arguments, so the results are undefined if Ap, Ai, Ax,
        are modified between the calls the umfpack_di_numeric and
        umfpack_di_solve.  These three arrays do not need to be present (NULL
        pointers can be passed) if Control [UMFPACK_IRSTEP] is zero, or if a
        system other than Ax=b or A'x=b is being solved, or if A is
        singular, since in each of these cases A is not accessed.

    double X [n] ;      Output argument.

        The solution to the linear system, where n = n_row = n_col is the
        dimension of the matrices A, L, and U.

    double B [n] ;      Input argument, not modified.

        The right-hand side vector, b, stored as a conventional array of size n
        (or two arrays of size n for complex versions).  This routine does not
        solve for multiple right-hand-sides, nor does it allow b to be stored in
        a sparse-column form.

    void *Numeric ;             Input argument, not modified.

        Numeric must point to a valid Numeric object, computed by
        umfpack_di_numeric.

    double Control [UMFPACK_CONTROL] ;  Input argument, not modified.

        If a (double *) NULL pointer is passed, then the default control
        settings are used.

        Control [UMFPACK_IRSTEP]:  The maximum number of iterative refinement
            steps to attempt.  A value less than zero is treated as zero.  If
            less than 1, or if Ax=b or A'x=b is not being solved, or
            if A is singular, then the Ap, Ai, and Ax arguments are not
            accessed.  Default: 2.

    double Info [UMFPACK_INFO] ;        Output argument.

        Contains statistics about the solution factorization.  If a
        (double *) NULL pointer is passed, then no statistics are returned in
        Info (this is not an error condition).  The following statistics are
        computed in umfpack_di_solve (only the primary statistics are listed):

        Info [UMFPACK_STATUS]: status code.  This is also the return value,
            whether or not Info is present.

            UMFPACK_OK

                The linear system was successfully solved.

            UMFPACK_WARNING_singular_matrix

                A divide-by-zero occurred.  Your solution will contain Inf's
                and/or NaN's.  Some parts of the solution may be valid.  For
                example, solving Ax=b with

                A = [2 0]  b = [ 1 ]  returns x = [ 0.5 ]
                    [0 0]      [ 0 ]              [ Inf ]

            UMFPACK_ERROR_out_of_memory

                Insufficient memory to solve the linear system.

            UMFPACK_ERROR_argument_missing

                One or more required arguments are missing.  The B and X
                arguments are always required.  Info and Control are not
                required.  Ap, Ai and Ax are required if Ax=b or
                A'x=b is to be solved, the (default) iterative
                refinement is requested, and the matrix A is nonsingular.

            UMFPACK_ERROR_invalid_system

                The sys argument is not valid, or the matrix A is not square.

            UMFPACK_ERROR_invalid_Numeric_object

                The Numeric object is not valid.

        Info [UMFPACK_SOLVE_FLOPS]:  the number of floating point operations
            performed to solve the linear system.  This includes the work
            taken for all iterative refinement steps, including the backtrack
            (if any).

        Info [UMFPACK_SOLVE_TIME]:  The time taken, in seconds.
\end{verbatim}
}

%-------------------------------------------------------------------------------
\newpage

\subsection{umfpack\_di\_free\_symbolic}
{\footnotesize
\begin{verbatim}
void umfpack_di_free_symbolic
(
    void **Symbolic
) ;

Purpose:

    Deallocates the Symbolic object and sets the Symbolic handle to NULL.

Arguments:

    void **Symbolic ;           Input argument, deallocated and Symbolic is
                                set to (void *) NULL on output.
\end{verbatim}
}

%-------------------------------------------------------------------------------
\subsection{umfpack\_di\_free\_numeric}

{\footnotesize
\begin{verbatim}
void umfpack_di_free_numeric
(
    void **Numeric
) ;

Purpose:

    Deallocates the Numeric object and sets the Numeric handle to NULL.

Arguments:

    void **Numeric ;            Input argument, deallocated and Numeric is
                                set to (void *) NULL on output.
\end{verbatim}
}

%-------------------------------------------------------------------------------
\subsection{umfpack\_di\_defaults}

{\footnotesize
\begin{verbatim}
void umfpack_di_defaults
(
    double Control [UMFPACK_CONTROL]
) ;

Purpose:

    Sets the default control parameter settings.

Arguments:

    double Control [UMFPACK_CONTROL] ;  Output argument.

        Control is set to the default control parameter settings.
\end{verbatim}
}
\end{document}


Since the corrections are directly effectued on the \textit{primitive symbols} the choice that seemed to be the simplest was to use the top-down parser as basis for the implementation of the error correction parser.

\section{Implementation of the character replacement}

The first step was to implement the character replacement, this is a modified version of the previous code of the top-down parser:

\FloatBarrier
\begin{algorithm}
    \caption{Top-down parser character modification}
    \label{parse}
    \begin{algorithmic}[1]
        \State $table$ is a 3d array of 0
        \State $s \gets input\_string$
        \Procedure{parse}{$var, i, j$} \Comment{Recursive parser function}
            \If{$table[var, i, j] != 0$}
                \State \textbf{return} $(table[var, i, j] == 1)$
            \EndIf
            \If{$i == j - 1$}
                \ForAll{$t \in terminal\_rule[var]$}
                    \If{$t == s[i]$}
                        \State $table[var, i, j] \gets \textcolor{red}{1}$
                        \State \textbf{return} \textcolor{red}{$table[var, i, j]$}
                    \EndIf
                \EndFor
                \textcolor{red}{\If{$terminal\_rule[var].size() > 0$}
                    \State $table[var, i, j] \gets 2$
                    \State \textbf{return} $table[var, i, j]$
                \EndIf}
            \Else
                \State \textcolor{red}{$min \gets INT\_MAX$}
                \ForAll{$nt \in non\_terminal\_rules[var]$}
                    \For{$k \gets i + 1; k < j$}
                        \State \textcolor{red}{$declare \text{ } res\_1 \text{ } and \text{ } res\_2$}
                        \textcolor{red}{\If{$(res\_1 \gets parse(nt[0], i, k)) < INT\_MAX \text{ } \land \text{ } (res\_2 \gets parse(nt[1], k, j)) < INT\_MAX$}
                            \If{$res\_1 + res\_2 - 1 < min$}
                                \State $min \gets res\_1 + res\_2 - 1$
                            \EndIf
                        \EndIf}
                    \EndFor
                \EndFor
                \State \textcolor{red}{$table[var, i, j] \gets min$}
                \State \textcolor{red}{\textbf{return} $table[var, i, j]$}
            \EndIf
            \State $table[var, i, j] \gets \textcolor{red}{INT\_MAX}$
            \State \textbf{return} \textcolor{red}{$table[var, i, j]$}
        \EndProcedure
    \end{algorithmic}
\end{algorithm}
\FloatBarrier

All the differences with the initial top-down parser are in red on this pseudo-code.

With those modifications the top-down parser now returns an integer when it parses a string:
\begin{itemize}
    \item[$-$] If the value is 1 it means that the string can be parsed without any modifications.
    \item[$-$] If the value is $x > 1$ it means that the string can be parsed with $x - 1$ modifications.
    \item[$-$] If the value is $INT\_MAX$, the maximum value of an integer, it means that the string cannot be parsed, no matter how much modifications could be made.
\end{itemize}

\section{Implementation of the character deletion}

Once the character modification is done the next step is to implement character deletion.

\FloatBarrier
\begin{algorithm}
    \caption{Top-down parser character deletion}
    \label{parse}
    \begin{algorithmic}[1]
        \State $table$ is a 3d array of 0
        \State $s \gets input\_string$
        \Procedure{parse}{$var, i, j$} \Comment{Recursive parser function}
            \If{$table[var, i, j] != 0$}
                \State \textbf{return} $(table[var, i, j] == 1)$
            \EndIf
            \If{$i == j - 1$}
                \ForAll{$t \in terminal\_rule[var]$}
                    \If{$t == s[i]$}
                        \State $table[var, i, j] \gets 1$
                        \State \textbf{return} $table[var, i, j]$
                    \EndIf
                \EndFor
                \If{$terminal\_rule[var].size() > 0$}
                    \State $table[var, i, j] \gets 2$
                    \State \textbf{return} $table[var, i, j]$
                \EndIf
            \Else
                \State $min \gets INT\_MAX$
                \State \textcolor{red}{$del\_1 \gets parse(var, i + 1, j)$}
                \State \textcolor{red}{$del\_2 \gets parse(var, i, j - 1)$}
                \ForAll{$nt \in non\_terminal\_rules[var]$}
                    \For{$k \gets i + 1; k < j$}
                        \State $declare \text{ } res\_1 \text{ } and \text{ } res\_2$
                        \If{\begin{varwidth}[t]{\linewidth}$(res\_1 \gets parse(nt[0], i, k)) < INT\_MAX \text{ } \land \text{ } (res\_2 \gets parse(nt[1], k, j)) < INT\_MAX$}\end{varwidth}
                            \If{$res\_1 + res\_2 - 1 < min$}
                                \State $min \gets res\_1 + res\_2 - 1$
                            \EndIf
                        \EndIf
                    \EndFor
                \EndFor
                \textcolor{red}{\If{$del\_2 < del\_1$}
                    \State $del\_1 \gets del\_2$
                \EndIf
                \If{$del\_1 < min$}
                    \State $min \gets del\_1$
                \EndIf}
                \State $table[var, i, j] \gets min$
                \State \textbf{return} $table[var, i, j]$
            \EndIf
            \State $table[var, i, j] \gets INT\_MAX$
            \State \textbf{return} $table[var, i, j]$
        \EndProcedure
    \end{algorithmic}
\end{algorithm}
\FloatBarrier

That algorithm returns the number of modifications plus deletions, the next step is to be able to return the corrected version of the input string.
Once such corrected string can be generated it will be trivial to know how much deletions and modifications were both needed.

\section{Recuperation of the corrected string}

In order to proceed to the recuperation of the corrected string a structure is used to contain the result of the parse function plus the corresponding corrected string.
The memoization table of the top-down parser will now contains datas of this structure.
The parse function will also now return a $parse\_result$ structure, it will also take the corrected string at its actual state as parameter.

This is is the pseudo-code with the modifications needed to be able to retrieve the corrected string.

\FloatBarrier
\begin{algorithm}
    \caption{Top-down parser correction and string recuperation}
    \label{parse}
    \begin{algorithmic}[1]
        \State $table$ is a 3d array of $parse\_result$
        \State $s \gets input\_string$
        \Procedure{parse}{$var, i, j, \textcolor{red}{sc}$} \Comment{Recursive parser function}
            \If{$table[var, i, j] != 0$}
                \State \textbf{return} $(table[var, i, j] == 1)$
            \EndIf
            \If{$i == j - 1$}
                \ForAll{$t \in terminal\_rule[var]$}
                    \If{$t == s[i]$}
                        \State \textcolor{red}{$table[var, i, j].result \gets 1$}
                        \State \textcolor{red}{$table[var, i, j].string \gets sc$}
                        \State \textbf{return} $table[var, i, j]$
                    \EndIf
                \EndFor
                \If{$terminal\_rule[var].size() > 0$}
                    \State \textcolor{red}{$table[var, i, j].result \gets 2$}
                    \State \textcolor{red}{$table[var, i, j].string \gets terminal\_rule[var][0]$}
                    \State \textbf{return} $table[var, i, j]$
                \EndIf
            \Else
                \State $min \gets INT\_MAX$
                \State \textcolor{red}{$new\_s \gets ""$}
                \State \textcolor{red}{$del\_1 \gets parse(var, i + 1, j, sc.substr(1, sc.size() - 1))$}
                \State \textcolor{red}{$del\_2 \gets parse(var, i, j - 1, sc.substr(0, sc.size() - 1))$}
                \ForAll{$nt \in non\_terminal\_rules[var]$}
                    \For{$k \gets i + 1; k < j$}
                        \State $res\_1 \gets parse(nt[0], i, k, \textcolor{red}{sc.substr(0, k - i)})$
                        \If{$res\_1\textcolor{red}{.result} < INT\_MAX$}
                            \State $res\_2 \gets parse(nt[1], k, j, \textcolor{red}{sc.substr(k - i, j - k)})$
                            \If{$res\_2\textcolor{red}{.result} < INT\_MAX$}
                                \If{$res\_1\textcolor{red}{.result} + res\_2\textcolor{red}{.result} - 1 < min$}
                                    \State $min \gets res\_1\textcolor{red}{.result} + res\_2\textcolor{red}{.result} - 1$
                                    \State \textcolor{red}{$new\_s \gets res\_1.string + res\_2.string$}
                                \EndIf
                            \EndIf
                        \EndIf
                    \EndFor
                \EndFor
                \State $table[var, i, j] \gets \textcolor{red}{min\_parse\_result(del\_1, del\_2, min, new\_string)}$
                \State \textbf{return} $table[var, i, j]$
            \EndIf
            \State \textcolor{red}{$table[var, i, j].result \gets INT\_MAX$}
            \State \textcolor{red}{$table[var, i, j].string \gets sc$}
            \State \textbf{return} $table[var, i, j]$
        \EndProcedure
    \end{algorithmic}
\end{algorithm}
\FloatBarrier

Such an algorithm will end by returning the corrected string plus the sum of all needed corrections and deletions to arrive to this result.
It is then trivial to separate the number of needed deletions from the number of modifications, just by comparing the size from the initial string to the size of the corrected string.

The running time of this algorithm will always be longer than for the top-down parser since the algorithm has to test the two possible deletions before entering the main loop, which the top-down parser does not do.
However the complexity of this algorithm remains the same as for the top-down parser, $O(n^3)$.

\section{Obtained results}

\subsection{Well balanced parenthesis}

The goal of the new parser is to correct an input string to make it match the given grammar if it is possible, the first experimentation is realised on the well balanced parenthesis.

Initially it was planned to check the parser's performances on the following cases:

\begin{itemize}
    \item[$-$] Strings in which the parser must modify half of the characters, that case corresponds to whatever pattern gives a string that does not contain any substring that would match the grammar, for example `$)\string^ n$', or `$(\string^ n$', or `$)\string^ n / 2 \text{ } (\string^ n / 2$'.
    \item[$-$] Strings that match the grammar, then the parser does not have to modify the input string.
    \item[$-$] Strings that match the grammar or not, containing an odd number of characters so the parser needs to delete one.
\end{itemize}

It was interesting to notice that the correction top-down parser followed exactly the same behaviour no matter what pattern the given string follows.

\FloatBarrier
\begin{figure}[h]
\begin{tikzpicture}
\begin{groupplot}[group style={group size=2 by 1},height=0.5\textwidth,width=0.5\textwidth]
    \nextgroupplot[title=Number of recursive calls, xlabel=string size, ylabel=recursive calls, legend pos=north west]
    \addplot coordinates {
        (50, 171256)
        (100, 1352506)
        (200, 10745006)
        (300, 36177506)
        (400, 85650006)
        (500, 167162506)};
    \nextgroupplot[title=Running time, xlabel=string size, ylabel=seconds, legend pos=north west]
    \addplot coordinates {
        (50, 0.009821)
        (100, 0.084296)
        (200, 0.705466)
        (300, 2.82136)
        (400, 7.1228)
        (500, 14.8394)};
\end{groupplot}
\end{tikzpicture}
\end{figure}
\FloatBarrier

The running time plot follows exactly the same curve as the number of recursive calls, which was expected.

Here is the verification of the complexity of the correction parser.

\begin{align*}
    &y = 1.187152 \cdot 10^{-7} \cdot x^3
\end{align*}

\FloatBarrier
\begin{figure}[h]
\centering
\begin{tikzpicture}
\begin{groupplot}[group style={group size=1 by 1},height=0.5\textwidth,width=0.5\textwidth]
    \nextgroupplot[title=correction parser, xlabel=string size, ylabel=seconds, legend pos=north west]
    \addplot[domain=0:500, samples=100, line width=1.5pt, green] {1.187152*(10^(-7))*(x^3)};
    \addlegendentry{Theory}
    \addplot[only marks, mark=*, mark size=2pt] coordinates {
        (50, 0.009821)
        (100, 0.084296)
        (200, 0.705466)
        (300, 2.82136)
        (400, 7.1228)
        (500, 14.8394)};
    \addlegendentry{Real}
\end{groupplot}
\end{tikzpicture}
\caption{Checking theorical fit, correction parser}
\end{figure}
\FloatBarrier

The running time behaviour of the correction parser follows exactly the theorical fit, which proves that its complexity is $O(n^3)$.

\subsection{Strings starting with an `a'}

The next expimentation is on the grammar that matches strings that start with an `a'.
With that grammar the parser follows exactly the same behaviour as before, it always need the same amount of recursive calls for a string of size $n$, no matter the pattern.

\FloatBarrier
\begin{figure}[h]
\begin{tikzpicture}
\begin{groupplot}[group style={group size=2 by 1},height=0.5\textwidth,width=0.5\textwidth]
    \nextgroupplot[title=Number of recursive calls, xlabel=string size, ylabel=recursive calls, legend pos=north west]
    \addplot coordinates {
        (50, 88005)
        (100, 686005)
        (200, 5412005)
        (300, 18178005)
        (400, 42984005)
        (500, 83830005)};
    \nextgroupplot[title=Running time, xlabel=string size, ylabel=seconds, legend pos=north west]
    \addplot coordinates {
        (50, 0.004987)
        (100, 0.04377)
        (200, 0.420274)
        (300, 1.56265)
        (400, 3.8529)
        (500, 8.30812)};
\end{groupplot}
\end{tikzpicture}
\end{figure}
\FloatBarrier

Here the parser does not need as much recursive calls as with the previous grammar but it still follows exactly the same behaviour.

The number of solved subproblems solved for this grammar follows the next sequence, with $n$ the size of the input string.

$$
1 + \dfrac{(n - 1) \cdot (3 \cdot (n - 1) + 1)}{2} + (n - 1) \cdot 2
$$

It has no use to keep going with the experimentation since no matter the grammar or the given string this parser always follows the same behaviour.


%
% API Documentation for QSTK
% Module QSTK.qstklearn.hmm
%
% Generated by epydoc 3.0.1
% [Mon Mar  5 00:49:20 2012]
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                          Module Description                           %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}|(}
\section{Module QSTK.qstklearn.hmm}

    \label{QSTK:qstklearn:hmm}
This package includes code for representing and learning HMM's.

Most of the code in this package was derived from the descriptions provided
in 'A Tutorial on Hidden Markov Models and Selected Applications in Speach
Recognition' by Lawence Rabiner.

Conventions: The keyword argument elem\_size will be passed in when
creating numpy array objects.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                               Functions                               %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  \subsection{Functions}

    \label{QSTK:qstklearn:hmm:calcalpha}
    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.calcalpha \textit{(function)}}

    \vspace{0.5ex}

\hspace{.8\funcindent}\begin{boxedminipage}{\funcwidth}

    \raggedright \textbf{calcalpha}(\textit{stateprior}, \textit{transition}, \textit{emission}, \textit{observations}, \textit{numstates}, \textit{elem\_size}={\tt {\textless}type 'numpy.float128'{\textgreater}})

    \vspace{-1.5ex}

    \rule{\textwidth}{0.5\fboxrule}
\setlength{\parskip}{2ex}
    Calculates 'alpha' the forward variable.

    The alpha variable is a numpy array indexed by time, then state (TxN).
    alpha[t][i] = the probability of being in state 'i' after observing the
    first t symbols.

\setlength{\parskip}{1ex}
    \end{boxedminipage}

    \label{QSTK:qstklearn:hmm:forwardbackward}
    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.forwardbackward \textit{(function)}}

    \vspace{0.5ex}

\hspace{.8\funcindent}\begin{boxedminipage}{\funcwidth}

    \raggedright \textbf{forwardbackward}(\textit{stateprior}, \textit{transition}, \textit{emission}, \textit{observations}, \textit{numstates}, \textit{elem\_size}={\tt {\textless}type 'numpy.float128'{\textgreater}})

    \vspace{-1.5ex}

    \rule{\textwidth}{0.5\fboxrule}
\setlength{\parskip}{2ex}
    Calculates the probability of a sequence given the HMM.

\setlength{\parskip}{1ex}
    \end{boxedminipage}

    \label{QSTK:qstklearn:hmm:calcbeta}
    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.calcbeta \textit{(function)}}

    \vspace{0.5ex}

\hspace{.8\funcindent}\begin{boxedminipage}{\funcwidth}

    \raggedright \textbf{calcbeta}(\textit{transition}, \textit{emission}, \textit{observations}, \textit{numstates}, \textit{elem\_size}={\tt {\textless}type 'numpy.float128'{\textgreater}})

    \vspace{-1.5ex}

    \rule{\textwidth}{0.5\fboxrule}
\setlength{\parskip}{2ex}
    Calculates 'beta' the backward variable.

    The beta variable is a numpy array indexed by time, then state (TxN).
    beta[t][i] = the probability of being in state 'i' and then observing
    the symbols from t+1 to the end (T).

\setlength{\parskip}{1ex}
    \end{boxedminipage}

    \label{QSTK:qstklearn:hmm:calcxi}
    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.calcxi \textit{(function)}}

    \vspace{0.5ex}

\hspace{.8\funcindent}\begin{boxedminipage}{\funcwidth}

    \raggedright \textbf{calcxi}(\textit{stateprior}, \textit{transition}, \textit{emission}, \textit{observations}, \textit{numstates}, \textit{alpha}={\tt None}, \textit{beta}={\tt None}, \textit{elem\_size}={\tt {\textless}type 'numpy.float128'{\textgreater}})

    \vspace{-1.5ex}

    \rule{\textwidth}{0.5\fboxrule}
\setlength{\parskip}{2ex}
    Calculates 'xi', a joint probability from the 'alpha' and 'beta'
    variables.

    The xi variable is a numpy array indexed by time, state, and state
    (TxNxN). xi[t][i][j] = the probability of being in state 'i' at time
    't', and 'j' at time 't+1' given the entire observation sequence.

\setlength{\parskip}{1ex}
    \end{boxedminipage}

    \label{QSTK:qstklearn:hmm:calcgamma}
    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.calcgamma \textit{(function)}}

    \vspace{0.5ex}

\hspace{.8\funcindent}\begin{boxedminipage}{\funcwidth}

    \raggedright \textbf{calcgamma}(\textit{xi}, \textit{seqlen}, \textit{numstates}, \textit{elem\_size}={\tt {\textless}type 'numpy.float128'{\textgreater}})

    \vspace{-1.5ex}

    \rule{\textwidth}{0.5\fboxrule}
\setlength{\parskip}{2ex}
    Calculates 'gamma' from xi.

    Gamma is a (TxN) numpy array, where gamma[t][i] = the probability of
    being in state 'i' at time 't' given the full observation sequence.

\setlength{\parskip}{1ex}
    \end{boxedminipage}

    \label{QSTK:qstklearn:hmm:baumwelchstep}
    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.baumwelchstep \textit{(function)}}

    \vspace{0.5ex}

\hspace{.8\funcindent}\begin{boxedminipage}{\funcwidth}

    \raggedright \textbf{baumwelchstep}(\textit{stateprior}, \textit{transition}, \textit{emission}, \textit{observations}, \textit{numstates}, \textit{numsym}, \textit{elem\_size}={\tt {\textless}type 'numpy.float128'{\textgreater}})

    \vspace{-1.5ex}

    \rule{\textwidth}{0.5\fboxrule}
\setlength{\parskip}{2ex}
    Given an HMM model and a sequence of observations, computes the
    Baum-Welch update to the parameters using gamma and xi.

\setlength{\parskip}{1ex}
    \end{boxedminipage}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                               Variables                               %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  \subsection{Variables}

    \vspace{-1cm}
\hspace{\varindent}\begin{longtable}{|p{\varnamewidth}|p{\vardescrwidth}|l}
\cline{1-2}
\cline{1-2} \centering \textbf{Name} & \centering \textbf{Description}& \\
\cline{1-2}
\endhead\cline{1-2}\multicolumn{3}{r}{\small\textit{continued on next page}}\\\endfoot\cline{1-2}
\endlastfoot\raggedright \_\-\_\-p\-a\-c\-k\-a\-g\-e\-\_\-\_\- & \raggedright \textbf{Value:}
{\tt \texttt{'}\texttt{QSTK.qstklearn}\texttt{'}}&\\
\cline{1-2}
\end{longtable}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                           Class Description                           %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.HMMLearner \textit{(class)}|(}
\subsection{Class HMMLearner}

    \label{QSTK:qstklearn:hmm:HMMLearner}
\begin{alltt}

A class for modeling and learning HMMs.

This class conveniently wraps the module level functions. Class objects hold 6
data members:
- num\_states                    number of hidden states in the HMM
- num\_symbols                   number of possible symbols in the observation
                                sequence
- precision                     precision of the numpy.array elements (defaults to
                                longdouble)
- prior                         The prior probability of starting in each state
                                (Nx1 array)
- transition\_matrix             The probability of transitioning between each state
                                (NxN matrix)
- emission\_matrix               The probability of each symbol in each state
                                (NxO matrix)
You can set the 3 matrix parameters as you wish, but make sure the shape of
the arrays matches num\_states and num\_symbols, as these are used internally

Typical usage of this class is to create an HMM with a set number of states
and external symbols, train the HMM using addEvidence(...), and then use
the sequenceProb(...) method to see how well a specific sequence matches
the trained HMM.
\end{alltt}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                                Methods                                %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

  \subsubsection{Methods}

    \label{QSTK:qstklearn:hmm:HMMLearner:__init__}
    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.HMMLearner \textit{(class)}!QSTK.qstklearn.hmm.HMMLearner.\_\_init\_\_ \textit{(method)}}

    \vspace{0.5ex}

\hspace{.8\funcindent}\begin{boxedminipage}{\funcwidth}

    \raggedright \textbf{\_\_init\_\_}(\textit{self}, \textit{num\_states}, \textit{num\_symbols}, \textit{init\_type}={\tt \texttt{'}\texttt{uniform}\texttt{'}}, \textit{precision}={\tt {\textless}type 'numpy.float128'{\textgreater}})

    \vspace{-1.5ex}

    \rule{\textwidth}{0.5\fboxrule}
\setlength{\parskip}{2ex}
    Creates a new HMMLearner object with the given number of internal
    states, and external symbols.

    calls self.reset(init\_type=init\_type)

\setlength{\parskip}{1ex}
    \end{boxedminipage}

    \label{QSTK:qstklearn:hmm:HMMLearner:reset}
    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.HMMLearner \textit{(class)}!QSTK.qstklearn.hmm.HMMLearner.reset \textit{(method)}}

    \vspace{0.5ex}

\hspace{.8\funcindent}\begin{boxedminipage}{\funcwidth}

    \raggedright \textbf{reset}(\textit{self}, \textit{init\_type}={\tt \texttt{'}\texttt{uniform}\texttt{'}})

    \vspace{-1.5ex}

    \rule{\textwidth}{0.5\fboxrule}
\setlength{\parskip}{2ex}
\begin{alltt}

Resets the 3 arrays using the given initialization method.

Wipes out the old arrays. You can use this method to change the shape
of the arrays by first changing num\_states and/or num\_symbols, and then
calling this method.

Currently supported initialization methods:
uniform         prior, transition, and emission probabilities are all
                        uniform (default)
\end{alltt}

\setlength{\parskip}{1ex}
    \end{boxedminipage}

    \label{QSTK:qstklearn:hmm:HMMLearner:sequenceProb}
    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.HMMLearner \textit{(class)}!QSTK.qstklearn.hmm.HMMLearner.sequenceProb \textit{(method)}}

    \vspace{0.5ex}

\hspace{.8\funcindent}\begin{boxedminipage}{\funcwidth}

    \raggedright \textbf{sequenceProb}(\textit{self}, \textit{newData})

    \vspace{-1.5ex}

    \rule{\textwidth}{0.5\fboxrule}
\setlength{\parskip}{2ex}
    Returns the probability that this HMM generated the given sequence.

    Uses the forward-backward algorithm.  If given an array of sequences,
    returns a 1D array of probabilities.

\setlength{\parskip}{1ex}
    \end{boxedminipage}

    \label{QSTK:qstklearn:hmm:HMMLearner:addEvidence}
    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.HMMLearner \textit{(class)}!QSTK.qstklearn.hmm.HMMLearner.addEvidence \textit{(method)}}

    \vspace{0.5ex}

\hspace{.8\funcindent}\begin{boxedminipage}{\funcwidth}

    \raggedright \textbf{addEvidence}(\textit{self}, \textit{newData}, \textit{iterations}={\tt 1}, \textit{epsilon}={\tt 0.0})

    \vspace{-1.5ex}

    \rule{\textwidth}{0.5\fboxrule}
\setlength{\parskip}{2ex}
    Updates this HMMs parameters given a new set of observed sequences
    using the Baum-Welch algorithm.

    newData can either be a single (1D) array of observed symbols, or a 2D
    matrix, each row of which is a seperate sequence. The Baum-Welch update
    is repeated 'iterations' times, or until the sum absolute change in
    each matrix is less than the given epsilon.  If given multiple
    sequences, each sequence is used to update the parameters in order, and
    the sum absolute change is calculated once after all the sequences are
    processed.

\setlength{\parskip}{1ex}
    \end{boxedminipage}

    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}!QSTK.qstklearn.hmm.HMMLearner \textit{(class)}|)}
    \index{QSTK \textit{(package)}!QSTK.qstklearn \textit{(package)}!QSTK.qstklearn.hmm \textit{(module)}|)}


%!TEX root = morusAC.tex

\section{Analysis on Initialization and Finalization of Reduced \texorpdfstring{\MORUS}{MORUS}}
\label{sec/IniFin}

The bias in the previous sections analysed the encryption part of the \MORUS. In this section, for comprehensive security analysis of \MORUS, we provide new attacks on reduced version of the initialization and the finalization. We emphasize that the results in this section do not threaten any security claim by the designers. However, we believe that investigating all parts of the design with different approaches from the existing work on \MORUS provides a better understanding and will be useful especially when the design will be tweaked in future.

\subsection{Forgery with Reduced Finalization}
\label{subsec/Fin}
We present forgery attacks on 3 out of 10 steps of \MORUS[1280] that claims 128-bit security for integrity. The attack only works for a limited number of steps, while it works in the nonce-respecting setting. As far as we know, this is the first attempt to evaluate integrity of \MORUS in the nonce-respecting setting.

\subsubsection{Overview.}
A general strategy for forgery attacks in the nonce-respecting setting is to inject some difference in a message block and propagate it so that it can be canceled by a difference in another message block. However this approach does not work well against \MORUS due to its large state size which prevents an attacker from easily controlling the differences in different registers.

Here we focus on the property that the padding for an associated data $A$ and a message $M$ is the zero-padding, hence $A$ and $A'=A\|0^*$ and $M$ and $M'=M\|0$ result in identical states after the associated data processing and the encryption parts, as long as $A,A'$ and $M,M'$ fit in the same number of blocks. During the finalization, since $A,A'$ (resp. $M,M'$) have different lengths, the corresponding 64-bit values $\adlen$ (resp. $\msglen$) are different, which appears as $\Delta \adlen$ (resp. $\Delta \msglen$) during the finalization, and is injected through the message input interface. Our strategy is to propagate this difference to the 128-bit tags $T$ and $T'$ such that their difference $\Delta T$ appears with higher probability than $2^{-128}$. All in all, the forgery succeeds as long as the desired $\Delta T$ is obtained or in other words, the attacker does not have to cancel the state difference, which is the main advantage of attacking the finalization part of the scheme.

Note that if the attacker uses different messages $M,M'$, not only the new tag $T'$ but also new ciphertext $C'$ must be guessed correctly. Because the encryption of \MORUS is a simple XOR of the key stream, $C'$ can be easily guessed. For this purpose, the attacker should first query a longer message $M'=M\|0^*$ to obtain $C'$. Then, $C$ can be obtained by truncating $C'$.

\subsubsection{Differential Trails.}
Recall that the message input during the finalization of \MORUS[1280] is $\adlen\mathrel\|\msglen\mathrel\|0^{128}$ where $\adlen$ and $\msglen$ are 64-bit strings. We set $\Delta \adlen$ to be of low Hamming weight, e.g.,~{\tt 0x0000000000000001}.
%Hereafter, we use {\tt typefont} denote hexadecimal numbers.
This difference propagates through 3 steps as specified in \Cref{Tbl:fin_diff}.

Recall that each step consists of 5 rounds and the input message is absorbed to the state in rounds 2 to 5. The trail in \Cref{Tbl:fin_diff} initially does not have any difference and the same continues even after round 1. Differences start to appear from round 2 and they will go through the bitwise-AND operation from round 4. We need to pay 1 bit to control each active AND gate. The probability evaluation for round 15 can be ignored since in this round only $S_4$ is non-linearly updated, while $S_4$ is never used for computing the tag. Finally, bitwise-AND in the tag computation is taken into account. Note that the tag is only 128 LSBs, thus the number of active AND gates should be counted only for those bits. As shown in \Cref{Tbl:fin_diff}, we can have a particular tag difference $\Delta T$ with probability $2^{-88}$. Thus after observing $A$ and corresponding $T$, $A\|0$ and $(T \oplus \Delta T)$ is a valid pair with probability $2^{-88}$.

\begin{table}[!tb]
\begin{center}
\caption{Differential propagation through 3 Steps. Five lines for round $i$ denote the difference of $S_0, \cdots, S_4$ after the round $i$ transformation.} %Weight is a Hamming weight of the state difference and accumulated probability is a probability to satisfy the trail from the beginning.}
\label{Tbl:fin_diff}
{%
\iflncsmargins
\tiny
\else
\scriptsize
\renewcommand{\arraystretch}{0.9}
\fi
\begin{tabular}{ccccccc} \hline
Round & \multicolumn{4}{c}{State difference} & Weight & Accumulated probability \\ \hline
%      & & & &                                &        &
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
Ini   & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & $-$ \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\ \hline

      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
1     & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & $1$\\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\ \hline

      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
      & {\tt 0000400000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 1  & \\
2     & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & $1$\\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\ \hline

      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
      & {\tt 0000400000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 1  & \\
3     & {\tt 0000004000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 1  & $1$\\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\ \hline

      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000400000000000} & {\tt 0000000000000000} & 1  & \\
4     & {\tt 0000004000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 1  & $1$\\
      & {\tt 0020000000000080} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 2  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\ \hline

      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 0  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000400000000000} & {\tt 0000000000000000} & 1  & \multirow{3}{*}{$2^{-1}$}\\
5     & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000004000000000} & 1  & \\
      & {\tt 0020000000000080} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 2  & \\
      & {\tt 0000040000000010} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 2  & \\ \hline

      & {\tt 0000000000100004} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 2  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000400000000000} & {\tt 0000000000000000} & 1  & \multirow{3}{*}{$2^{-3}$}\\
6     & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000004000000000} & 1 & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0020000000000080} & 2  & \\
      & {\tt 0000040000000010} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 2  & \\ \hline

      & {\tt 0000000000100004} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & 2  & \\
      & {\tt 0004400001000000} & {\tt 0000000000000000} & {\tt 0000000010000000} & {\tt 0000000000000000} & 4  & \multirow{3}{*}{$2^{-6}$}\\
7     & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000004000000000} & 1  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0020000000000080} & 2  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000040000000010} & {\tt 0000000000000000} & 2  & \\ \hline

      & {\tt 0000000000000000} & {\tt 0000000000100004} & {\tt 0000000000000000} & {\tt 0000000000000000} & 2  & \\
      & {\tt 0004400001000000} & {\tt 0000000000000000} & {\tt 0000000010000000} & {\tt 0000000000000000} & 4  & \multirow{3}{*}{$2^{-10}$}\\
8     & {\tt 0400014000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000001000} & 4  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0020000000000080} & 2  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000040000000010} & {\tt 0000000000000000} & 2  & \\ \hline

      & {\tt 0000000000000000} & {\tt 0000000000100004} & {\tt 0000000000000000} & {\tt 0000000000000000} & 2  & \\
      & {\tt 0000000010000000} & {\tt 0000000000000000} & {\tt 0004400001000000} & {\tt 0000000000000000} & 4  & \multirow{3}{*}{$2^{-14}$}\\
9     & {\tt 0400014000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000001000} & 4  & \\
      & {\tt 0220000080000080} & {\tt 0000000000000000} & {\tt 0000000800000000} & {\tt 1000000000004000} & 7  & \\
      & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000040000000010} & {\tt 0000000000000000} & 2  & \\ \hline

      & {\tt 0000000000000000} & {\tt 0000000000100004} & {\tt 0000000000000000} & {\tt 0000000000000000} & 2  & \\
      & {\tt 0000000010000000} & {\tt 0000000000000000} & {\tt 0004400001000000} & {\tt 0000000000000000} & 4  & \multirow{3}{*}{$2^{-20}$}\\
10    & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000001000} & {\tt 0400014000000000} & 4  & \\
      & {\tt 0220000080000080} & {\tt 0000000000000000} & {\tt 0000000800000000} & {\tt 1000000000004000} & 7  & \\
      & {\tt 4000140000000010} & {\tt 0000000000000000} & {\tt 0000400000000100} & {\tt 0000000000010000} & 7  & \\ \hline

      & {\tt 0000100000100044} & {\tt 0000000200008000} & {\tt 0001000000000000} & {\tt 0000000008000200} & 9  & \\
      & {\tt 0000000010000000} & {\tt 0000000000000000} & {\tt 0004400001000000} & {\tt 0000000000000000} & 4  &\multirow{3}{*}{$2^{-28}$} \\
11    & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000001000} & {\tt 0400014000000000} & 4  & \\
      & {\tt 0000000000000000} & {\tt 0000000800000000} & {\tt 1000000000004000} & {\tt 0220000080000080} & 7  & \\
      & {\tt 4000140000000010} & {\tt 0000000000000000} & {\tt 0000400000000100} & {\tt 0000000000010000} & 7  & \\ \hline

      & {\tt 0000100000100044} & {\tt 0000000200008000} & {\tt 0001000000000000} & {\tt 0000000008000200} & 9  & \\
      & {\tt 0004500005000400} & {\tt 0000000000000000} & {\tt 0040000100000040} & {\tt 4000000000000000} & 10 & \multirow{3}{*}{$2^{-39}$}\\
12    & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000001000} & {\tt 0400014000000000} & 4  & \\
      & {\tt 0000000000000000} & {\tt 0000000800000000} & {\tt 1000000000004000} & {\tt 0220000080000080} & 7  & \\
      & {\tt 0000400000000100} & {\tt 0000000000010000} & {\tt 4000140000000010} & {\tt 0000000000000000} & 7  & \\ \hline

      & {\tt 0000000008000200} & {\tt 0000100000100044} & {\tt 0000000200008000} & {\tt 0001000000000000} & 9  & \\
      & {\tt 0004500005000400} & {\tt 0000000000000000} & {\tt 0040000100000040} & {\tt 4000000000000000} & 10 & \multirow{3}{*}{$2^{-53}$}\\
13    & {\tt 0400114000040000} & {\tt 0020000000000080} & {\tt 0004000000400000} & {\tt 0000800100005002} & 14 &\\
      & {\tt 0000000000000000} & {\tt 0000000800000000} & {\tt 1000000000004000} & {\tt 0220000080000080} & 7  & \\
      & {\tt 0000400000000100} & {\tt 0000000000010000} & {\tt 4000140000000010} & {\tt 0000000000000000} & 7  & \\ \hline

      & {\tt 0000000008000200} & {\tt 0000100000100044} & {\tt 0000000200008000} & {\tt 0001000000000000} & 9  & \\
      & {\tt 0040000100000040} & {\tt 4000000000000000} & {\tt 0004500005000400} & {\tt 0000000000000000} & 10 & \multirow{3}{*}{$2^{-69}$}\\
14    & {\tt 0400114000040000} & {\tt 0020000000000080} & {\tt 0004000000400000} & {\tt 0000800100005002} & 14 & \\
      & {\tt 0228000280020080} & {\tt 0000040000000000} & {\tt 2000008000202008} & {\tt 1000004000004021} & 18 & \\
      & {\tt 0000400000000100} & {\tt 0000000000010000} & {\tt 4000140000000010} & {\tt 0000000000000000} & 7  & \\ \hline

%Weight: 69
      & {\tt 0000000008000200} & {\tt 0000100000100044} & {\tt 0000000200008000} & {\tt 0001000000000000} & 9  & \\
      & {\tt 0040000100000040} & {\tt 4000000000000000} & {\tt 0004500005000400} & {\tt 0000000000000000} & 10 & \\
15    & {\tt 0020000000000080} & {\tt 0004000000400000} & {\tt 0000800100005002} & {\tt 0400114000040000} & 14 & $-$\\
      & {\tt 0228000280020080} & {\tt 0000040000000000} & {\tt 2000008000202008} & {\tt 1000004000004021} & 18 & \\
      & {\tt 0000400000000100} & {\tt 0000000000010000} & {\tt 4000140000000010} & {\tt 0000000000000000} & 7  & \\ \hline

$\Delta T$ &                   &                        & {\tt 600080830020f00a} & {\tt 1405414005044421} & & $2^{-88}$ \\ \hline
\end{tabular}
}
\end{center}
\end{table}

\subsubsection{Remarks.} The fact that the $S_4$ is updated in the last round but is not used in the tag generation implies that the \MORUS finalization generally includes unnecessary computations with respect to security. It may be interesting to tweak the design such that the tag can also depend on $S_4$. Indeed in \Cref{Tbl:fin_diff}, we can observe some jump-up of the probability in the tag computation. This is because the non-linearly involved terms are $S_2 \cdot S_3$, and $S_3$ that was updated 2 rounds before has a high Hamming weight. In this sense, involving $S_4$ in non-linear terms of the tag computation imposes more difficulties for the attacker.

\subsection{Extending State Recovery to Key Recovery}
\label{subsec/Ini}
Kales et al.~\cite{cryptoeprint:2017:1137} showed that the internal state of \MORUS[640] can be recovered under the nonce-misuse scenario using $2^5$ plaintext-ciphertext pairs. As claimed by \cite{cryptoeprint:2017:1137} the attack is naturally extended to \MORUS[1280] though Kales et al. \cite{cryptoeprint:2017:1137} did not demonstrate specific attacks. The recovered state allows the attacker to mount a universal forgery attack under the same nonce. However, the key still cannot be recovered because the key is used both at the beginning and end of the initialization, which prevents the attacker from backtracking the state value to the initial state. In this section, we show that meet-in-the-middle attacks allow the attacker to recover the key faster than exhaustive search for a relatively large number of steps, i.e., 10 out of 16 steps in \MORUS[1280].

\subsubsection{Overview.}
We divide the 10 steps of the initialization computation into two subsequent parts $F_0$ and $F_1$. (We later set that $F_0$ is the first 4 steps and $F_1$ is the last 6 steps.) Let $S^{-10}$ be the initial state value before setting the key, i.e., $S^{-10} = (\IV\mathrel\|0^{128},0^{256},1^{256},0^{256},\const_0\mathrel\|\const_1)$. Also let $S^0$ be 1280-bit state value after the initialization, which is now assumed to be recovered with the nonce-misuse analysis~\cite{cryptoeprint:2017:1137}. We then have the following relation.
\begin{align*}
%F_1 \circ F_0 \bigl(S^{-10} \oplus (0, K\|K, 0, 0, 0)\bigr) \oplus (0,K\|K,0,0,0) = S^0.
F_1 \circ F_0 \bigl(S^{-10} \oplus (0, K, 0, 0, 0)\bigr) \oplus (0,K,0,0,0) = S^0.
\end{align*}
We target the variant \MORUS[1280-128], where $K = K_{128} \mathrel\| K_{128}$.

Here, our strategy is to recover $K_{128}$ by independently processing $F_0$ and $F_1^{-1}$ to find the following match.
\begin{align*}
  F_0 (S^{-10} \oplus (0, K_{128}\|K_{128}, 0, 0, 0)) \stackrel{?}{=} F_1^{-1} (S^0 \oplus (0,K_{128}\|K_{128},0,0,0)).
\end{align*}

To evaluate the attack complexity, we consider the following parameters.
\begin{itemize}
\item $G_0$: a set of bits of $K_{128}$ that are guessed for computing $F_0$.
\item $G_1$: a set of bits of $K_{128}$ that are guessed for computing $F_1^{-1}$.
\item $G_2$: a set of bits in the intersection of $G_0$ and $G_1$.
\item $x$ bits can match after processing $F_0$ and $F_1^{-1}$.
\end{itemize}
Suppose that the union of $G_0$ and $G_1$ covers all the bits of $K_{128}$. The attack exhaustively guesses $G_2$ and performs the following procedure for each guess.
\begin{enumerate}
\item $F_0$ is computed $2^{|G_0|-|G_2|}$ times and the results are stored in a table $T$. (Because $|G_1|-|G_2|$ bits are unknown, only a part of the state is computed.)
\item $F_1^{-1}$ is computed $2^{|G_1|-|G_2|}$ times and for each result we check the match with any entry in $T$.
\item The number of possible combinations is $2^{|G_0|-|G_2| + |G_1|-|G_2|}$, and the number of valid matches reduces to $2^{|G_0|-|G_2| + |G_1|-|G_2| - x}$ after matching the $x$ bits.
\item Check the correctness of the guess by using one plaintext-ciphertext pair.
\end{enumerate}

In the end,
$F_0$ is computed $2^{|G_2|} \cdot 2^{|G_0|-|G_2|} = 2^{|G_0|}$ times.
Similarly, $F_1^{-1}$ is computed $2^{|G_1|}$ times. The number of the total candidates after the $x$-bit match is $2^{|G_2|} \cdot 2^{|G_0|-|G_2| + |G_1|-|G_2| - x} = 2^{|G_0| + |G_1| - |G_2| - x}$. Hence, the key $K_{128}$ is recovered with complexity $$\max( 2^{|G_0|}, 2^{|G_1|}, 2^{|G_0| + |G_1| - |G_2| - x}).$$
Suppose that we choose $|G_0|$ and $|G_1|$ to be balanced i.e., $|G_0|=|G_1|$. Then, the complexity is $$\max( 2^{|G_0|}, 2^{2|G_0| - |G_2| - x}).$$
Two terms are balanced when $x = |G_0| - |G_2|$. Hence, the number of matched bits in the middle of two functions must be greater than or equal to the number of independently guessed bits to compute $F_0$ and $F_1^{-1}$.

In the attack below, we choose $|G_0|=|G_1|=127$ and $|G_2|=126$ (equivalently $|G_2|-|G_0| = |G_2|-|G_1| = 1$) in order to aim $x=1$-bit match in the middle, which maximizes the number of attacked rounds.

\begin{table}
\caption{Analysis of the diffusion and matching bits over 10 steps. `0' and `1' denote that the state bit can and cannot be computed from a partial knowledge of $K_{128}$, respectively. After the partial computations from each direction, 4 bits of $S^{-6}$ can match.}
\label{Tbl:ini_diffuse}
\centering
{
\iflncsmargins
\tiny
\else
\footnotesize
\renewcommand{\arraystretch}{0.9}
\fi
\begin{tabular}{ccccc} \hline
Round & \multicolumn{4}{c}{State Difference}\\ \hline
                         & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} \\
\multirow{3}{*}{$S^{-10}\oplus K_{128}$} & {\tt 0000000000000000} & {\tt 0000000000000001} & {\tt 0000000000000000} & {\tt 0000000000000001} \\
  & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} \\
                         & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} \\
                         & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} \\ \hline

      & {\tt 0000000000002000} & {\tt 0000000000000000} & {\tt 0000000000002000} & {\tt 0000000000000000} \\
      & {\tt 0000000000000000} & {\tt 0000400000000000} & {\tt 0000000000000000} & {\tt 0000400000000000} \\
1     & {\tt 0008000000000000} & {\tt 0000000000000000} & {\tt 0008000000000000} & {\tt 0000000000000000} \\
      & {\tt 0000000000100000} & {\tt 0020000000000000} & {\tt 0000000000100000} & {\tt 0020000000000000} \\
      & {\tt 0000000000020000} & {\tt 0084000000000000} & {\tt 0000000000020000} & {\tt 0084000000000000} \\ \hline

      & {\tt 0800000000000004} & {\tt 0000000204000001} & {\tt 0800000000000004} & {\tt 0000000204000001} \\
      & {\tt 8000000a00000000} & {\tt 0000002110000004} & {\tt 8000000a00000000} & {\tt 0000002110000004} \\
2     & {\tt 0400010221000000} & {\tt 008000400a000081} & {\tt 0400010221000000} & {\tt 008000400a000081} \\
      & {\tt 1000050001000244} & {\tt 4200118a08000280} & {\tt 1000050001000244} & {\tt 4200118a08000280} \\
      & {\tt 880004a0a0200858} & {\tt 4840123350000050} & {\tt 880004a0a0200858} & {\tt 4840123350000050} \\ \hline

      & {\tt 023d63c00050a850} & {\tt 00a1442000489380} & {\tt 023d63c00050a850} & {\tt 00a1442000489380} \\
      & {\tt 02b63380056aaa48} & {\tt 00b5563005dcd6c0} & {\tt 02b63380056aaa48} & {\tt 00b5563005dcd6c0} \\
3     & {\tt d42ab556bf5dfcd6} & {\tt 5a26f633a8556aaa} & {\tt d42ab556bf5dfcd6} & {\tt 5a26f633a8556aaa} \\
      & {\tt 5fbbf556bd556c65} & {\tt 7aab99aaee6bea2c} & {\tt 5fbbf556bd556c65} & {\tt 7aab99aaee6bea2c} \\
      & {\tt abff7f3ad7feafad} & {\tt cfff777ffddffd6d} & {\tt abff7f3ad7feafad} & {\tt cfff777ffddffd6d} \\ \hline

      & {\tt fff77dfffffdcf57} & {\tt fefad7efffdffbf7} & {\tt fff77dfffffdcf57} & {\tt fefad7efffdffbf7} \\
      & {\tt ffffffffffffbfff} & {\tt fffbf7fffddfff77} & {\tt ffffffffffffbfff} & {\tt fffbf7fffddfff77} \\
4     & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} \\
      & {\tt ffffffffffffffff} & {\tt fffbffffefffffff} & {\tt ffffffffffffffff} & {\tt fffbffffefffffff} \\
      & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} \\ \hline
%
%
      &                        & 2-bits match           & {\tt                 } & 2-bits match            \\ \hline
%
%
      & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} \\
      & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} \\
5     & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} & {\tt ffffffffffffffff} \\
      & {\tt fffff7ffedfffff7} & {\tt ffffffffedffffff} & {\tt fffff7ffedfffff7} & {\tt ffffffffedffffff} \\
      & {\tt ffffffffedffffff} & {\tt fffff7ffedfffff7} & {\tt ffffffffedffffff} & {\tt fffff7ffedfffff7} \\ \hline

      & {\tt ffffffffedffffff} & {\tt fffff7ffedfffff7} & {\tt ffffffffedffffff} & {\tt fffff7ffedfffff7} \\
      & {\tt fffbf5e7cdfffbf7} & {\tt fffff7bfcdfff757} & {\tt fffbf5e7cdfffbf7} & {\tt fffff7bfcdfff757} \\
6     & {\tt fffbf5e7cdfffbf7} & {\tt fffff7bfcdfff757} & {\tt fffbf5e7cdfffbf7} & {\tt fffff7bfcdfff757} \\
      & {\tt 7ffd75b6cdfff357} & {\tt fffbf5a6ccfcfb73} & {\tt 7ffd75b6cdfff357} & {\tt fffbf5a6ccfcfb73} \\
      & {\tt 7ffbf5a6ccfcf373} & {\tt 7ff975b6ccfff353} & {\tt 7ffbf5a6ccfcf373} & {\tt 7ff975b6ccfff353} \\ \hline

      & {\tt 7efbf5a6cc7cf353} & {\tt 7fd975a6cceff353} & {\tt 7efbf5a6cc7cf353} & {\tt 7fd975a6cceff353} \\
      & {\tt 7eb950a4cc78e353} & {\tt 7dd07184cced7153} & {\tt 7eb950a4cc78e353} & {\tt 7dd07184cced7153} \\
7     & {\tt 7eb950a4cc78e353} & {\tt 7dd07184ccec7153} & {\tt 7eb950a4cc78e353} & {\tt 7dd07184ccec7153} \\
      & {\tt 7cd051044c6c3153} & {\tt 3e985024cc48a313} & {\tt 7cd051044c6c3153} & {\tt 3e985024cc48a313} \\
      & {\tt 3c905004cc482313} & {\tt 7c9051044c6c2113} & {\tt 3c905004cc482313} & {\tt 7c9051044c6c2113} \\ \hline

      & {\tt 2c905004c4482113} & {\tt 7c9050040c682113} & {\tt 2c905004c4482113} & {\tt 7c9050040c682113} \\
      & {\tt 2810100444082112} & {\tt 5c1010040c402113} & {\tt 2810100444082112} & {\tt 5c1010040c402113} \\
8     & {\tt 2810100444082112} & {\tt 1c1010040c402113} & {\tt 2810100444082112} & {\tt 1c1010040c402113} \\
      & {\tt 0c00100404400113} & {\tt 2800000404082112} & {\tt 0c00100404400113} & {\tt 2800000404082112} \\
      & {\tt 0800000404002112} & {\tt 0800100404400113} & {\tt 0800000404002112} & {\tt 0800100404400113} \\ \hline

      & {\tt 0800000404002112} & {\tt 0800100004000112} & {\tt 0800000404002112} & {\tt 0800100004000112} \\
      & {\tt 0000000404000102} & {\tt 0000100004000110} & {\tt 0000000404000102} & {\tt 0000100004000110} \\
9     & {\tt 0000000404000102} & {\tt 0000000004000110} & {\tt 0000000404000102} & {\tt 0000000004000110} \\
      & {\tt 0000000004000110} & {\tt 0000000000000102} & {\tt 0000000004000110} & {\tt 0000000000000102} \\
      & {\tt 0000000000000100} & {\tt 0000000004000110} & {\tt 0000000000000100} & {\tt 0000000004000110} \\ \hline

      & {\tt 0000000000000100} & {\tt 0000000004000100} & {\tt 0000000000000100} & {\tt 0000000004000100} \\
      & {\tt 0000000000000000} & {\tt 0000000004000100} & {\tt 0000000000000000} & {\tt 0000000004000100} \\
10    & {\tt 0000000000000000} & {\tt 0000000000000100} & {\tt 0000000000000000} & {\tt 0000000000000100} \\
      & {\tt 0000000000000100} & {\tt 0000000000000000} & {\tt 0000000000000100} & {\tt 0000000000000000} \\
      & {\tt 0000000000000000} & {\tt 0000000000000100} & {\tt 0000000000000000} & {\tt 0000000000000100} \\ \hline

                     & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} \\
\multirow{3}{*}{$S^0\oplus K_{128} $} & {\tt 0000000000000000} & {\tt 0000000000000100} & {\tt 0000000000000000} & {\tt 0000000000000100} \\
                     & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} \\
                     & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} \\
                     & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} & {\tt 0000000000000000} \\ \hline

\end{tabular}
}
\end{table}

\subsubsection{Full Diffusion Rounds.}
We found that {\tt StepUpdate} was designed to have good diffusion in the forward direction. Thus, once the state is recovered, the attacker can perform the partial computation in the backward direction longer than the forward direction. We set $G_0$ and $G_1$ as follows.
\begin{align*}
G_0 &= \{1, 2, \cdots, 127\} & \textrm {Bit position 0 is unknown.}\\
G_1 &= \{0, 1, \cdots, 7, 9, 10, \cdots, 127\} & \textrm {Bit position 8 is unknown.}
\end{align*}
Those will lead to 4 matching bits after the 4-step forward computation and the 6-step backward computation. The analysis of the diffusion is given in \Cref{Tbl:ini_diffuse}. In the end, $K_{128}$ can be recovered faster than the exhaustive search by 1 bit, i.e., with complexity $2^{127}$.

\subsubsection{Remarks.}
The matching state does not have to be a border of a step. It can be defined on a border of a round, or even in some more complicated way. We did not find the extension of the number of attacked steps even with this way.

As can be seen in \Cref{Tbl:ini_diffuse}, the updated register in step $i$ is independent of the update function in step $i+1$ in the forward direction, and starts to impact from step $i+2$. By modifying this point, the diffusion speed can increase faster, which makes this attack harder.