1. Introduction
In the era of big data, it is often necessary to consider algorithms involving operations with large matrices defined over finite fields. These matrices appear in many applications including cryptography [
1] and topological data analysis [
2]. Linear algebra over finite fields [
3] involves matrix multiplication [
4] and matrix inversion [
2]. Matrix inversion by direct Gauss–Jordan elimination (GJE) is not harder than matrix multiplication, which has cubic time complexity [
5]. A common strategy for efficiently inverting the matrices over finite fields is to exploit Krylov subspaces [
3], and other matrix structures, including sparsity [
2,
6]. Sub-cubic matrix inversion can be also achieved by adopting various matrix decompositions, such as Cholesky, QR, and LU factorizations [
1,
2]. The factorization can be made more stable by first permuting the original matrix [
7]. The invertibility of sub-matrices in non-singular matrices is investigated in [
1,
3,
5].
The Schur complement is usually considered as a basis for blockwise recursive methods when inverting large matrices [
8]. In recursive methods, the base case matrices of smaller size are more efficiently inverted using direct Gauss–Jordan elimination (GJE) [
9]. The caveat is that sub-matrices created during the recursion must themselves be invertible. Unfortunately, for the matrices defined over finite fields, this cannot be guaranteed. This is also the key reason why the recursive methods for these matrices fails in practice. In [
1], the authors propose to circumvent this problem by representing the matrix inversion as a recursive tree, such that every node of the tree represents the matrix split into four equal-size sub-matrices. Then, starting at the bottom of the tree, the invertible sub-matrices are inverted towards the root, which becomes the inverse of the given matrix. Even though at least one path reaching the root is guaranteed to always exist for all non-singular matrices, the number of these paths, and thus the amount of redundant computations, can be large. On the other hand, the singular sub-matrices can be either randomized or permuted deterministically, as proposed in this paper. Moreover, rather than optimizing the number of computations, the matrix inversion algorithms are usually designed to run in parallel on distributed computing systems [
1,
6,
10].
The matrix inversion is closely related to matrix multiplication [
2,
3,
5]. The 1969 paper by Strassen [
11] showed that matrix multiplication can be performed with a sub-cubic complexity. More recent algorithms such as the method of Four Russians, Strassen–Winograd multiplication, and several bit-level parallelization strategies for multiplying the dense binary matrices are compared in [
12]. Efficient multiplications of matrices defined over finite fields have been considered, for example, in [
1,
4,
7,
11,
13]. However, only a few numerical software packages offer algebraic functions over finite fields. For example, Matlab, since version R2006a, allows defining and working with matrices over general Galois fields,
, [
14].
Some applications require efficiently enumerating all invertible matrices, which is only possible over finite fields. The invertible matrices of size
over a general finite field,
, form the general linear group
[
15]. The basic strategy is to define partial [
16] or total ordering of the group elements [
17]. In particular, the latter reference orders invertible matrices using a Grey encoding, so the subsequent matrices can be related by the row operations. The underlying group structure can be then studied using Cayley graphs [
17]. However, these results are mainly theoretical. There seems to be no practical algorithms for systematically and efficiently enumerating large matrices over finite fields, which would also be easy to understand and validate.
Furthermore, the probability of a large binary matrix being invertible is about
. This can be too restrictive if the matrix represents random measurements and the data processing algorithm requires solving an exact set of linear equations [
3]. One solution is to repair the singular matrix defined over a finite field by finding the nearest matrix that is invertible. Such a problem is closely related to the matrix perturbation theory [
18] and matrix rank updates [
19,
20]. There are efficient algorithms for computing the rank of finite-field matrices, for example, [
2,
3]. The bounds on the rank of random binary matrices and their construction can be found in [
4].
The goal of this paper is to devise practical algorithms that can be used to solve large-scale linear systems over binary fields. The algorithms utilize known theoretical results from linear algebra. The first algorithm performs robust and fast inversion of binary matrices. It is a top-down divide-and-conquer method, which exploits the PLU factorization [
9] at each recursive step. This guarantees that a chosen matrix sub-block is always invertible, so the bottom-up tree search and the redundant computations performed in [
1] are avoided. The idea is to deterministically swap the dependent row with a row from the bottom block that has a pivot, provided that the top sub-block is detected as being singular. The algorithm is shown to always correctly invert all non-singular binary matrices while it maintains the sub-cubic complexity of Strassen’s method. The second algorithm efficiently enumerates all invertible binary matrices. The matrices are generated one at a time, and every unique invertible matrix is generated exactly once. The method exploits the Bruhat decomposition [
21]. The third algorithm is used to repair large binary singular matrices, so they become non-singular by performing the minimum number of bit-flips. It is shown that the minimum number of required bit-flips is equal to the matrix rank-deficiency, and the bit-flips are identified by pivoting during matrix inversion.
The developed algorithms can be used for matrices defined over other finite fields. The reference implementation of the proposed algorithms in C++ is available from the Github repository [
22]. The correctness and the time complexity of all the algorithms were validated both theoretically and empirically.
The rest of this paper is organized as follows. The sequel of this section summarizes the terminology and known key results from linear algebra, which are important in understanding the paper. The subsequent three sections first summarize the relevant theoretical results, which is then followed by the algorithm outline and the implementation details. In particular,
Section 2 introduces a robust blockwise matrix inversion algorithm based on the PLU factorization. The algorithm for efficiently enumerating general linear groups is presented in
Section 3. This algorithm is based on the Bruhat decomposition. An algorithm for repairing singular binary matrices to make them invertible by performing the minimum number of bit-flips is proposed in
Section 4. The paper is concluded in
Section 5. The examples illustrating the proposed algorithms are provided in
Appendix A and
Appendix B. It should also be noted that the proofs of lemmas and theorems are sketches, and they may not be fully rigorous from a strict mathematical point of view.
Preliminaries and Notations
Matrices are denoted by bold capital letters. The symbol represents the i-th row and j-th column element of the matrix, . For binary matrices, a bit-flip at position is defined as .
The permutation matrix is created from the identity matrix by permuting its rows and/or columns. There are (n factorial) unique instances of such permutation matrices. The permutation matrices are orthogonal, i.e., .
An unit lower-triangular binary matrix, , has all diagonal entries equal to 1, while all the entries above the main diagonal are 0. Similarly, an upper-triangular binary matrix, , has all diagonal entries equal to 1, and all the entries below the main diagonal are 0.
More generally, the invertible matrices can be considered over infinite fields of all integers,
; rational numbers,
; as well as real numbers,
, respectively. Here, our focus is on invertible matrices defined over finite fields, such as
, representing modulo
p additions and multiplications, with
p being a prime, and possibly extended Galois fields,
. Note that
(isomorphism). The modular arithmetic requires that modulo operation is always performed on the last outcome of all preceding arithmetic operations [
13] (Sec. 31.3). For example, assuming integers
a and,
b, addition and multiplication in
, respectively, are defined as
The finite (Galois) fields are constructed over non-negative integers and contain elements, where p is a prime. For example, the Galois field is a ring, , with addition and multiplication. Over , addition can be replaced with logical exclusive-or (XOR), and multiplication can be replaced with logical AND. Moreover, over , addition is equivalent to subtraction, and division by the only non-zero element, which is the multiplicative unity, can be ignored.
The rank of an matrix, , is the maximum number of linearly independent rows (or, equivalently, columns). The matrix has a full rank if . The square matrix is invertible, i.e., its inverse, , exists if and only if, it has a full rank; otherwise, it is said to be singular. The singular matrix has the rank deficiency . The rank deficiency represents how many linearly independent rows or columns are missing to have a full span of the n-dimensional vector space over a given field.
The matrix inverse can be defined over any finite or infinite field, and even over a ring [
23] (Theorem 4, p. 160). If the inverse matrix exists, i.e., the matrix determinant is non-zero, then its inverse is unique. A general linear group
is the set of all invertible
matrices defined over a finite field,
, that is closed under matrix multiplication. The unit element of the group is the identity matrix,
. The group has order (i.e., the cardinality)
The matrix determinant to check whether the matrix is invertible is computed as [
23]
where
is a symmetric group of all permutations of
n integers. The multiplications and summations in (
3) are defined by the underlying field operations [
13].
The
matrix, where
n is even, can be partitioned into four equal-sized sub-matrices (sub-blocks) as
Provided that
is invertible (which is not guaranteed for matrices defined over finite fields, even if
is invertible), its Schur complement is defined as
.
2. Accelerated Inversion of Binary Matrices
The objective is to devise a fast algorithm for the robust inversion of large binary matrices. The proposed algorithm relies on the following crucial techniques. The pivoted PLU factorization enables the proper factorization of any invertible matrix. Importantly, it avoids the fundamental limitation of simpler blockwise inversion methods that often fails at singular sub-matrices for matrices defined over finite fields. The recursive blockwise inversion can be further optimized for speed by considering sub-cubic Strassen’s algorithm for matrix multiplication in order to improve the asymptotic time complexity. However, for smaller matrices, the recursion overhead exceeds the complexity of the direct GJE.
The GJE assumes the augmented matrix, , and performs the row operations until it arrives at the matrix, . In , this only involves swapping and XOR-ing the rows. If the matrix is found to be singular, i.e., there is no pivot for a given matrix column, the algorithm must report a failure. The cubic time complexity of the GJE is acceptable for smaller matrices.
For larger matrices, other algorithmic strategies, such as divide-and-conquer and dynamic programming, are required. These strategies provide much better control over the time complexity as the problem size increases. In this paper, we first consider a standard blockwise recursive inversion involving the Schur complement to show that it is fundamentally flawed when considering matrices over finite fields. This will motivate a much more robust block-recursive inversion method that is based on the PLU factorization. Note also that, in this paper, the presentation assumes binary matrices; generalizing the presented methods to other finite fields should be straightforward by modifying the underlying arithmetic operations.
The standard blockwise inversion of matrices assumes the Schur complement to reduce the
problem into the four sub-problems, each of size
. In particular, assuming that both
and its Schur complement
are non-singular, the inverse
is computed recursively using its Schur complement. The Schur complement requires two matrix multiplications, and its inverse,
, is again computed recursively. The inverse matrix is then constructed as
where
Thus, computing the matrices in (
6) requires at most six matrix multiplications.
Furthermore, in order to improve the asymptotic time complexity of the standard matrix blockwise inversion, the six required matrix multiplications can be efficiently performed using Strassen’s technique, which has a sub-cubic time complexity. Subsequently, only seven rather than eight matrix multiplications are required in computing each sub-problem in the divide-and-conquer matrix inversion method described above; the asymptotic time complexity is then reduced from to . However, and importantly, for and other finite fields, the sub-matrices and frequently become singular, which terminates the algorithm, even though the original matrix, , is non-singular. The solution is to combine the Schur complement with the PLU factorization in performing the blockwise matrix inversion, as will be described next. We also prove the correctness of this approach and analyze its time complexity.
2.1. Blockwise Inversion with PLU Factorization
The PLU factorization can be used to achieve a fast matrix inversion, as originally proposed in [
24]. Specifically, the PLU factorization theorem asserts that, for any non-singular matrix,
, there exists a permutation matrix
, such that
, where
and
are the unit lower-triangular and upper-triangular matrices, respectively, representing the LU factorization [
9]. The key idea is to first recursively compute the PLU factorization of the matrix,
, to facilitate its fast inversion, since inverting a triangular matrix amounts to solving a set of linear equations being already in the reduced row echelon form [
9].
In particular, the first step is to recursively compute the PLU factorization of the sub-matrix,
. Thus, provided that,
, then the inverse,
, is straightforward to obtain. The Schur complement can be inverted similarly using its PLU factorization,
. The inverse matrix,
, is then obtained using the structure (
5) and (
6). Most importantly, the PLU factorization is guaranteed to always yield the correct result for all non-singular binary matrices,
.
The matrix bisection that is performed repeatedly at each recursive step of the blockwise matrix inversion and Strassen’s multiplication implicitly assume that the original matrix
has the size
for some integer
. Even though the power-of-two size cannot be guaranteed, the original matrix can always be padded with zeros to such a size, i.e.,
where
and
denotes the ceiling function. The inverse of the
matrix,
, can be then written as
Once the complete factorization,
, is obtained, the matrix inverse is computed as
2.2. Complexity and Correctness of Matrix Inversion via PLU Factorization
Lemma 1 (Correctness of the PLU-based matrix inversion). The non-singular matrices over finite Galois fields can be correctly inverted using the PLU factorization at each step of the blockwise matrix decomposition. Moreover, the singular matrices are always correctly detected, and the algorithm terminates.
Proof Outline. The GJE, which is adopted for inverting the base cases, is guaranteed to find the inverse or to correctly detect that the sub-matrix is singular. The PLU factorization theorem guarantees that any non-singular matrix,
, can be factored as
[
9]. Hence, and importantly, the sub-matrices
and the Schur complements
at each step of the blockwise recursion are always invertible by the PLU factorization theorem. The PLU factorization
can always be correctly obtained by properly combining the sub-matrices
. The unit triangular matrices are always invertible [
9]. Consequently, the non-singular matrix,
, can be inverted as
. Moreover, the singular matrix is always detected when inverting the base case sub-matrices as the GJE fails to find all pivots. □
It should be noted that Lemma 1, and its proof are independent of the specific field. Thus, Lemma 1 is valid for the matrices defined over all finite fields, and even infinite fields including, for example, the field of real numbers.
Theorem 1 (Complexity of blockwise matrix inversion with PLU factorization). The blockwise recursive inversion of matrices with the PLU factorization and Strassen’s matrix multiplication has the complexity .
Proof. Let
be the time to invert an
matrix, and
be the time to multiply two
matrices. The complexity is dominated by the operations performed at the first blockwise decomposition, i.e., by the PLU factorization and the inversion of the
sub-matrix,
, and its Schur complement,
. The seven required multiplications of sub-matrices has the complexity
. Consequently, the overall complexity is dominated by the two recursive calls, and the matrix multiplications, i.e.,
where
is the total number of required sub-matrix multiplications. Strassen’s algorithm for matrix multiplication has the complexity
. The recursion (
10) can be solved by the Master Theorem [
13], which yields the total complexity
. Moreover, since the base cases are assumed to be sufficiently small, they do not affect the overall asymptotic complexity. □
The following theorem considers the invertibility of a given matrix over different fields, , where p is a prime. (Note that these are, generally, subsets, and not sub-fields.)
Theorem 2 (Invertability of a matrix over different fields). If the matrix, , defined over a field, , is invertible, then there exist infinitely many primes, , such that is also invertible over the fields .
Proof. It suffices to examine the determinant of
with respect to modular arithmetic (
1). In particular, the determinant of
over
is computed as
, where
D is the value of the sum in (
3). Consequently, the matrix
is non-singular over all fields
, for which,
, for example, all primes,
. □
Corollary 1. The matrix , which is invertible over a finite field , is also invertible over the fields and, .
2.3. Implementation
The blockwise matrix inversion with the PLU factorization and Strassen’s matrix multiplication is outlined as Algorithm 1 on the next page. It was implemented in C++ language [
22]. The implementation adopts several optimizations in order to improve the actual runtime. In particular, the low-level C++ data structure,
std::bitset<N>, is used to store the rows of binary matrices. This encourages the compiled code to exploit single-instruction, multiple-data (SIMD) CPU instructions, which provides the bit-level parallelism involving the bit arrays. In turn, this offers a substantial speed-up of adding and multiplying the rows of binary matrices on a single-core CPU. On the other hand,
std::bitset<N> must be statically allocated at the compile time, so its size is fixed. For dynamic allocation of binary matrices at runtime, the alternative data structures
std::vector<bool> and
boost::dynamic\_bitset can be considered.
The size of sub-matrices that are treated as base cases and for which the GJE instead of the blockwise recursion is used is a hyper-parameter which can be optimized to achieve a faster inversion by providing better data locality and avoiding the overhead of recursive function calls.
The matrix to be inverted is instantiated at a compile time using the C++ template, template<size_t N>. It provides the type safety and also reduces the runtime overhead. In addition, the singular matrices, for which the GJE fails to find a pivot when inverting one of the base case sub-matrices, are detected using the function signature with the std::optional parameter. This has the benefit that it avoids the complexities of exception handling.
The empirical measurements of the runtime and memory usage for inverting the binary matrices of size
,
, are shown in
Figure 1 and
Figure 2, respectively. Both metrics appear to have asymptotically linear growths on the log-log scale plots, suggesting asymptotic complexity,
. Furthermore, the empirical runtimes of the proposed blockwise matrix inversion method are compared with the runtimes of the inversion performed using the standard GJE in
Figure 3. It can be observed that the proposed method achieves a clear speedup for sufficiently large matrices, and the speedup grows further with the size of the matrix to be inverted. In particular, utilizing Strassen multiplications of sub-blocks reduces the time complexity from
to
. It is not as good as the state-of-the art method reported in [
2] with
, but it is still better than the method of Four Russians, which has the time complexity,
. Moreover, the peak memory usage is under 7 MB when processing the matrices of a size as large as
. Such a memory efficiency can be attributed to the use of the
std::vector<bool> data structure for storing the binary matrices.
| Algorithm 1: Robust blockwise inversion of a large binary matrix |
Input: matrix Output: inverse matrix , or ⊥ if is singular Parameters: base case cutoff
- 1:
function BinaryInvert(,) - 2:
- 3:
if then - 4:
return GaussJordanInverse(A) // Base cases - 5:
end if - 6:
Step 1: Search for pivots - 7:
Find index - 8:
if no such index exists then return ⊥ // Matrix is singular - 9:
end if - 10:
Step 2: Permute to move pivot to - 11:
// are permutation matrices to swap row , and col - 12:
Partition // rank-1 decomposition - 13:
Step 3: Schur complement & recursion - 14:
StrassenMul - 15:
// Addition in is XOR - 16:
BinaryInvert // Recursive call - 17:
if [ then0.5] return ⊥ - 18:
end if[0.5] - 19:
Step 4: Reconstruct - 20:
StrassenMul - 21:
StrassenMul - 22:
StrassenMul - 23:
- 24:
- 25:
Step 5: Revert permutation - 26:
- 27:
return - 28:
end function - 29:
- 30:
Output: product - 31:
function StrassenMul() // Strassen matrix multiplication - 32:
- 33:
if or n is odd then - 34:
return Mul() // standard multiplication - 35:
end if - 36:
Partition // sub-blocks - 37:
Compute 7 products - 38:
StrassenMul - 39:
... // similarly for through - 40:
combine to form , and then form - 41:
return C - 42:
end function
|
Note also that the results shown in
Figure 3 suggest that the GJE is as effective as the blockwise recursion for the binary matrices of dimensions up to about
due to the overhead of the recursive calls. Hence, the base case sub-matrices can be considered to be relatively large.
Even though the reference implementation in C++ considers specifically the matrices over , the blockwise recursive inversion with the PLU factorization can be readily modified to other fields. Note also that only the computations over finite fields are exact, whereas the algorithms involving the floating point arithmetic operations suffer from the numerical instabilities and numerically ill-conditioned problems. For example, the pivoting used in the GJE must be made more robust for inverting the real-valued matrices. Moreover, the bit-level parallelization can be much more easily exploited for the finite fields than for the real numbers, which has a noticeable impact on the practical runtime and the memory usage of the implemented algorithms.
The matrix multiplications in Strassen’s algorithm can be parallelized to support inverting very large matrices on multi-core computing platforms. For such matrices, the data structures could be further optimized to improve the data locality and to exploit the fast memory-caching mechanisms. Moreover, there can be multiple implementations that are optimized for different matrix sizes, . Similar considerations can be assumed for the high-throughput inversions of large matrices that are performed in hardware, for example, using the FPGAs.
3. Enumerating GL(n,2) Groups
The objective now is to exhaustively enumerate the unique elements of the linear group
. A naive approach may again exploit the PLU factorization assumed in the previous section. The caveat is how to avoid a considerable redundancy by removing the generated matrix duplications. Ideally, every unique invertible matrix of a given size is generated exactly once. The proposed solution is to consider the Bruhat decomposition theorem to define a unique factorization of every invertible matrix [
21]. The key idea is that every invertible matrix can be reduced to exactly one permutation pattern of pivots using the GJE. The theorem can be specifically restated for general linear groups as follows.
Theorem 3 (Bruhat decomposition of general linear groups)
. The general linear group, , is a disjoint union of double cosets of the subgroup of upper triangular invertible matrices, , i.e.,where is the symmetric group of permutation matrices and ⊔
denotes the disjoint union.
Theorem 3 allows for partitioning the group into the disjoint subgroups called Bruhat cells, which are indexed by the permutation matrices. More importantly, every invertible matrix, , has a unique factorization, , where is a permutation matrix, and and are the lower and the upper triangular matrices, respectively, having non-zero elements that are strictly constrained by the structure of . The uniqueness of this decomposition enables the effective non-redundant enumeration of all invertible matrices of a given size.
In particular, the matrix, , is defined by the so-called inversions of the permutation, , of a given permutation matrix, . The inversion is an index pair, , such that, , whereas . The matrix is only allowed to have the non-zero entries at positions . The number of inversions of permutation is denoted as . Thus, there are elements of matrix that can be freely selected from a given field, whereas other elements must be zero.
There are
disjoint cells corresponding to one permutation matrix,
. The order of each cell is a function of the number of inversions in
. For the field of cardinality,
q, the cell is a triangular matrix group having the order
where
is the cell order. The cell order is a product of the number of unconstrained upper-triangular matrices,
, and the number of constrained lower-triangular matrix,
.
The enumeration algorithm proceeds by systematically enumerating all permutations,
, which define the unique permutation matrices,
. For
, all invertible matrices in the cell,
, are generated. Assuming that the two matrix multiplications to construct a matrix,
, have the complexity
and noting that the double co-sets are disjoint and cover the whole GL group, which has the order given by (
2), the overall complexity of the complete enumeration is
For comparison, the naive enumeration of the group using the PLU factorization generates all combinations of the products between permutation matrices, and lower and upper triangular matrices, respectively. The corresponding overall complexity is dominated by the number of these products, each having complexity. In addition, each resulting matrix must be checked for whether it has already been generated previously, which has complexity . Thus, the total complexity of the naive enumeration via the PLU factorization is . Consequently, even though the complexity of the Bruhat-based enumeration is still exponential, it avoids the factorial scaling of the PLU based enumeration, and at the same time, it is guaranteed to systematically produce a sequence of unique invertible matrices.
Implementation
The proposed algorithm for enumerating all invertible binary matrices is outlined as Algorithm 2 on the next page. The reference C++ implementation again stores the rows of binary matrices in
std::vector<int> or in more efficient
std::bitset<N> data structures, which encourages the compiled C++ code to use the low-level SIMD instructions. The C++ code is available in [
22]. For complexity comparison, the inefficient PLU-based enumeration has also been implemented, and it can be validated only for matrices of size
. In the PLU-based implementation and for small
n, the uniqueness of the generated matrices can be automatically enforced by exploiting the
std::set data structure with hashing or tree-based indexing. For larger values of
n, more advanced data structures are required such as the hash-tries. Even though the complete sets of all lower and upper triangular matrices can be pre-generated, it results in a large memory footprint but faster generation.
The PLU-based enumeration is attractive, since it is already “embarrassingly parallel”, allowing for distributed implementations. There could be other strategies for modifying the PLU-based enumeration so that only unique matrices are implicitly or explicitly generated. It should also be emphasized that the exhaustive enumeration of general linear groups is only feasible for invertible matrices over finite fields, since the group order becomes infinite over infinite fields. Moreover, deciding whether the two real-valued matrices are identical is problematic, as it depends on the floating-point representation of numerical values.
| Algorithm 2: Enumeration of via Bruhat decomposition |
- 1:
function GenGL(n) - 2:
// # unit upper triangular matrices - 3:
for all do // loop over all permutations of in set - 4:
PermutationMatrix // create permutation matrix corresponding to - 5:
Step 1: Identify allowed lower inversions - 6:
- 7:
for to do - 8:
for to do - 9:
if then // standard inversion condition - 10:
- 11:
end if - 12:
end for - 13:
end for - 14:
- 15:
Step 2: Iterate over constrained lower matrices - 16:
for to do - 17:
// identity matrix - 18:
map bits of to positions in of - 19:
Step 3: Iterate over all upper matrices - 20:
// pre-compute - 21:
for to do - 22:
GenerateUnitUpper - 23:
- 24:
return A - 25:
end for - 26:
end for - 27:
end for // loop over permutations - 28:
end function - 29:
- 30:
Output: unit upper triangular matrix - 31:
function GenerateUnitUpper() - 32:
, - 33:
for to do - 34:
for to do - 35:
// right bit-shift - 36:
- 37:
end for - 38:
end for - 39:
return - 40:
end function - 41:
- 42:
Output: permutation matrix corresponding to - 43:
function PermutationMatrix() - 44:
// all-zeros matrix - 45:
for to do - 46:
- 47:
end for - 48:
return - 49:
end function
|
4. Repairing Singular Matrices to Become Invertible
In many scenarios, large binary matrices may be nearly invertible; however, they are strictly singular by definition. Such a case can be practically resolved by finding a “closest” invertible matrix that is non-singular. The problem can be formulated as follows.
Problem 1. Given an binary matrix , find the binary matrix with the minimal Hamming distance, .
In particular, in the first step, the rank deficiency, , is computed to decide whether is invertible. If is already invertible, i.e., , the algorithm terminates. Otherwise, the invertible matrix , consisting of the Hamming distance precisely, , is obtained by flipping exactly d bits in at defined positions, as explained below.
Note that the matrix repair problem stated above is a variation of the more general maximum rank matrix completion problem studied, for example, in [
19]. The rank (i.e., also the rank deficiency) can be computed by the standard GJE. The matrix rank is equal to the number of pivots [
9]. Specifically, when transforming the matrix into a row-echelon form, the
j-th column does not have a pivot, if there is no row
such that the element
. The columns without a pivot are referred to as being pivot-free. Equivalently, the row-echelon form contains exactly
d all-zero rows. At the same time, it is important to record which rows are swapped during the GJE process. The rows that were swapped and subsequently zeroed are referred as dependent rows, since they are linear combinations of the other rows. The identified pivot-free columns and the dependent rows define the bit positions, which need to be flipped in order to make the original matrix invertible.
Lemma 2 (Rank change due to single bit-flip). A single bit-flip changes the rank of a binary matrix by at most one.
Proof. Let be a square binary matrix obtained by flipping the entry of , so that, over , and have exactly one non-zero element at position . Considering the combined rows and columns of the matrices and , i.e., , where , depending on whether the non-zero row and column of appears in the span of , we must conclude that . □
Assuming Lemma 2, the task now is to find the set of d bit-flips that reduce the rank deficiency of to zero so it becomes invertible. These bit-flips are defined by the following theorem.
Theorem 4 (Minimal bit-flips to make binary matrix invertible). The binary square matrix with the rank deficiency can be made invertible by performing no less than d bit-flips at the intersection of the dependent rows and the pivot-free columns. These bit-flips can be represented as any of the permutation matrices of size .
Proof. The inverse matrix can be obtained by the GJE, which produces the row-echelon form
where
is a
invertible sub-matrix
and
is a
all-zero matrix. The last
d all-zero rows are dependent swapped rows, and the last
d columns are pivot-free columns [
9]. The matrix
becomes invertible if
in the GJE is replaced by a non-singular matrix; such a matrix must have at least
d non-zero elements. For instance, matrix
can be replaced with a
permutation matrix
. The non-zero elements of
corresponds to the
d bit-flips in
, so the GJE of the corresponding perturbed matrix
is
Consequently,
, so
is non-singular. Furthermore, by Lemma 2, such a matrix has the minimal possible Hamming distance,
, which is equal to a rank deficiency of
. □
By Lemma 2, every bit-flip can increase the matrix rank by at most one, so the minimum number of bit-flips required to make the matrix invertible is equal to its rank deficiency, d.
Since Theorem 4 allows multiple solutions, the natural question is whether additional constraints could be adopted to narrow down the choices. For instance, it may be desirable to maximize the sparsity by zeroing as many elements as possible, minimize the maximum weight of columns and rows, or make the sub-matrices also invertible.
Note also that Theorem 4.1 in [
19] asserts that changing the matrix element at a position corresponding to the basis-avoidable row and column, respectively, increases the matrix rank. Note that in Theorem 4 above, the element positions to increase the matrix rank are referred to as dependent rows and pivot-free columns instead. Such an element change is referred to as rank-one update, and it can be expressed as the product of a column and a row vector. In particular, for binary matrices, there is only one value for how the matrix element can be changed, so the rank-one update can be expressed as
For the matrices over other fields, the maximum rank updates are more evolved, since the element values, in addition to their positions, must also be determined [
19].
Implementation
The proposed algorithm for repairing singular binary matrices is outlined as Algorithm 3 on the next page. The C++ implementation again uses the
std::bitset<N> data structure to store the matrix rows and to allow the compiler to utilize the SIMD instructions for the bit-level parallelism on a single CPU [
22]. For example, a binary matrix of size
bits requires approximately
MB of memory. The time complexity of making the matrix invertible is dominated by the GJE, which has complexity
. The GJE computations can be at least partially distributed, which is important in high-throughput applications requiring the repair and then inversion of very large binary matrices, such as forward error correction coding, cryptography, and quantized algorithms in machine learning. Moreover, the GJE arithmetic operations for the matrices defined over
are amenable to the fast hardware implementations including, for example, the FPGAs.
| Algorithm 3: Singular matrix repair via GJE |
Input: matrix Output: non-singular matrix , set of bit-flips F
- 1:
function RepairMatrix() - 2:
- 3:
GaussianElimination - 4:
if then return // matrix already full-rank - 5:
end if - 6:
Identify dependent rows: - 7:
// rows permuted to the bottom are dependent - 8:
Identify free columns: - 9:
- 10:
// matrix deficiency (nullity) - 11:
Perform minimal bit-flips: - 12:
for to do - 13:
- 14:
- 15:
- 16:
- 17:
end for - 18:
return - 19:
end function - 20:
- 21:
Output: matrix rank r, set of pivots , rows pivoted - 22:
function GaussianElimination() - 23:
// work on a copy - 24:
// track row permutations - 25:
, // current rank - 26:
for to do // iterate over columns - 27:
if then break - 28:
end if - 29:
Step 1: Pivot search - 30:
Find smallest such that - 31:
if no such p exists then - 32:
continue // column j is free variable - 33:
end if - 34:
Step 2: Swap rows // move pivot to diagonal - 35:
SwapRows - 36:
SwapElements - 37:
- 38:
Step 3: Elimination - 39:
for to do - 40:
if and then - 41:
- 42:
end if - 43:
end for - 44:
- 45:
end for - 46:
return - 47:
end function
|
The empirical runtimes and the memory requirements for repairing randomly generated binary matrices to become invertible are shown in
Figure 4 and
Figure 5, respectively. Note that a binary random matrix is invertible with the probability
, for
.
It is unclear whether the required bit-flips to make the binary matrix invertible could be found more directly in order to reduce the cubic cost of the GJE. The complexity of the GJE itself can be reduced by adopting faster matrix multiplications, for example, using the Method of Four Russians and other Strassen-like algorithms [
12].