root/win32/itpp-4.0.1/itpp/base/gf2mat.h @ 129

Revision 35, 16.3 kB (checked in by mido, 16 years ago)

zasadni zmeny ve /win32

Line 
1/*!
2 * \file
3 * \brief Definition of a class for algebra on GF(2) (binary) matrices
4 * \author Erik G. Larsson and Adam Piatyszek
5 *
6 * -------------------------------------------------------------------------
7 *
8 * IT++ - C++ library of mathematical, signal processing, speech processing,
9 *        and communications classes and functions
10 *
11 * Copyright (C) 1995-2007  (see AUTHORS file for a list of contributors)
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 *
27 * -------------------------------------------------------------------------
28 *
29 * Two representations are offered: GF2mat_sparse for sparse GF(2)
30 * matrices and GF2mat for dense GF(2) matrices. Conversions between
31 * dense and sparse GF(2) are also possible.
32 *
33 * Binary vectors are represented either via the bvec class (memory
34 * typically is not an issue here) or as n*1 (or 1*n) GF(2) matrix.
35 *
36 * Note that the \c bmat class also provides some functionality for
37 * matrix algebra over GF(2) but this class is based on \c Mat<> which
38 * has a fundamentally different addressing mechanism and which is
39 * much less memory efficient (\c Mat<> uses one byte memory minimum
40 * per element).
41 */
42
43#ifndef GF2MAT_H
44#define GF2MAT_H
45
46#include <itpp/base/vec.h>
47#include <itpp/base/mat.h>
48#include <itpp/base/svec.h>
49#include <itpp/base/smat.h>
50#include <itpp/base/itfile.h>
51
52
53namespace itpp {
54
55  // ----------------------------------------------------------------------
56  // Sparse GF(2) matrix class
57  // ----------------------------------------------------------------------
58
59  //! Sparse GF(2) vector
60  typedef Sparse_Vec<bin> GF2vec_sparse;
61
62  //! Sparse GF(2) matrix
63  typedef Sparse_Mat<bin> GF2mat_sparse;
64
65
66  // ----------------------------------------------------------------------
67  // Alist parameterization of sparse GF(2) matrix class
68  // ----------------------------------------------------------------------
69
70  /*!
71    \relatesalso GF2mat_sparse
72    \brief Parameterized "alist" representation of sparse GF(2) matrix
73    \author Adam Piatyszek and Erik G. Larsson
74
75    This class is used to provide a parameterized representation of a \c
76    GF2mat_sparse class. The format is compatible with the "alist" format
77    defined by David MacKay, Matthew Davey and John Lafferty:
78    - http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html
79
80    For examples of "alist" representation visit David MacKay's Encyclopedia
81    of Sparse Graph Codes:
82    - http://www.inference.phy.cam.ac.uk/mackay/codes/data.html
83  */
84  class GF2mat_sparse_alist {
85  public:
86    //! Default constructor
87    GF2mat_sparse_alist() : data_ok(false) {}
88    //! Constructor, which reads alist data from a file named \c fname
89    GF2mat_sparse_alist(const std::string &fname);
90
91    //! Read alist data from a file named \c fname
92    void read(const std::string &fname);
93    //! Write alist data to a file named \c fname
94    void write(const std::string &fname) const;
95
96    /*!
97      \brief Convert "alist" representation to \c GF2mat_sparse
98
99      \param transpose Indicates whether a matrix should be transposed
100      during the conversion process
101    */
102    GF2mat_sparse to_sparse(bool transpose = false) const;
103
104    /*!
105      \brief Import "alist" representation from \c GF2mat_sparse
106
107      \param mat Matrix to import
108      \param transpose Indicates whether a matrix should be transposed
109      during the conversion process
110    */
111    void from_sparse(const GF2mat_sparse &mat, bool transpose = false);
112
113  protected:
114    //! Flag indicating that "alist" matrix data are properly set
115    bool data_ok;
116    //! Size of the matrix: \c M rows x \c N columns
117    int M;
118    //! Size of the matrix: \c M rows x \c N columns
119    int N;
120    //! List of integer coordinates in the m direction with non-zero entries
121    imat mlist;
122    //! List of integer coordinates in the n direction with non-zero entries
123    imat nlist;
124    //! Weight of each row m
125    ivec num_mlist;
126    //! Weight of each column n
127    ivec num_nlist;
128    //! Maximum weight of rows
129    int max_num_m;
130    //! Maximum weight of columns
131    int max_num_n;
132  };
133
134
135  // ----------------------------------------------------------------------
136  // Dense GF(2) matrix class
137  // ----------------------------------------------------------------------
138
139  /*!
140    \relatesalso bmat
141    \brief Class for dense GF(2) matrices
142    \author Erik G. Larsson
143
144    This class can be used as an alternative to \c bmat to represent
145    GF(2) matrices. It extends the functionality of \c bmat in two ways:
146
147    - \c GF2mat makes more efficient use of computer memory than \c bmat
148    (one bit in the matrix requires one bit of memory)
149    - \c GF2mat provides several functions for linear algebra and matrix
150    factorizations
151
152    See also \c GF2mat_sparse which offers an efficient representation
153    of sparse GF(2) matrices, and \c GF2mat_sparse_alist for a
154    parameterized representation of sparse GF(2) matrices.
155  */
156  class GF2mat {
157  public:
158
159    // ----------- Constructors -----------
160
161    //! Default constructor (gives an empty 1 x 1 matrix)
162    GF2mat();
163
164    //! Construct an empty (all-zero) m x n matrix
165    GF2mat(int m, int n);
166
167    //! Construct a dense GF(2) matrix from a sparse GF(2) matrix
168    GF2mat(const GF2mat_sparse &X);
169
170    /*! \brief Constructor, from subset of sparse GF(2) matrix
171
172    This constructor forms a dense GF(2) matrix from a subset (m1,n1)
173    to (m2,n2) of a sparse GF(2) matrix */
174    GF2mat(const GF2mat_sparse &X, int m1, int n1, int m2, int n2);
175
176    /*! \brief Constructor, from subset of sparse GF(2) matrix
177
178    This constructor forms a dense GF(2) matrix from a subset of
179    columns in sparse GF(2) matrix
180
181    \param X matrix to copy from
182    \param columns subset of columns to copy
183    */
184    GF2mat(const GF2mat_sparse &X, const ivec &columns);
185
186    /*!
187      \brief Create a dense GF(2) matrix from a single vector.
188
189      \param x The input vector
190      \param is_column A parameter that indicates whether the result should
191      be a row vector (false), or a column vector (true - default)
192    */
193    GF2mat(const bvec &x, bool is_column = true);
194
195    //! Create a dense GF(2) matrix from a bmat
196    GF2mat(const bmat &X);
197
198    //! Set size of GF(2) matrix. If copy = true, keep data before resizing.
199    void set_size(int m, int n, bool copy = false);
200
201    //! Create a sparse GF(2) matrix from a dense GF(2) matrix
202    GF2mat_sparse sparsify() const;
203
204    //! Create a bvec from a GF(2) matrix (must have one column or one row)
205    bvec bvecify() const;
206
207    // ----------- Elementwise manipulation and simple functions -------------
208
209    //! Getting element
210    inline bin get(int i, int j) const;
211
212    //! Getting element
213    inline bin operator()(int i, int j) const { return get(i,j); };
214
215    //! Set element i,j to s (0 or 1)
216    inline void set(int i, int j, bin s);
217
218    //! Add s (0 or 1) to element (i,j)
219    inline void addto_element(int i, int j, bin s);
220
221    //! Set column j to a binary vector x
222    void set_col(int j, bvec x);
223
224    //! Set row i to a binary vector x
225    void set_row(int i, bvec x);
226
227    //! Check whether the matrix is identical to zero
228    bool is_zero() const;
229
230    //! Swap rows i and j
231    void swap_rows(int i, int j);
232
233    //! Swap columns i and j
234    void swap_cols(int i, int j);
235
236    /*! \brief Multiply from left with permutation matrix (permute rows).
237
238    \param perm Permutation vector
239    \param I Parameter that determines permutation.
240    I=0: apply permutation, I=1: apply inverse permutation
241    */
242    void permute_rows(ivec &perm, bool I);
243
244    /*! \brief Multiply a matrix from right with a permutation matrix
245      (i.e., permute the columns).
246
247    \param perm Permutation vector
248    \param I Parameter that determines permutation.
249    I=0: apply permutation, I=1: apply inverse permutation
250    */
251    void permute_cols(ivec &perm, bool I);
252
253    //! Transpose
254    GF2mat transpose() const;
255
256    //! Submatrix from (m1,n1) to (m2,n2)
257    GF2mat get_submatrix(int m1, int n1, int m2, int n2) const;
258
259    //! Concatenate horizontally (append X on the right side of matrix)
260    GF2mat concatenate_horizontal(const GF2mat &X) const;
261
262    //! Concatenate vertically (append X underneath)
263    GF2mat concatenate_vertical(const GF2mat &X) const;
264
265    //! Get row
266    bvec get_row(int i) const;
267
268    //! Get column
269    bvec get_col(int j) const;
270
271    //! Compute the matrix density (fraction of elements equal to "1")
272    double density() const;
273
274    //! Get number of rows
275    int rows() const { return nrows; }
276
277    //! Get number of columns
278    int cols() const { return ncols; }
279
280    /*! \brief Add (or equivalently, subtract) rows
281
282    This function updates row i according to row_i = row_i+row_j
283
284    \param i Row to add to. This row will be modified
285    \param j Row to add. This row will <b>not</b> be modified.
286    */
287    void add_rows(int i, int j);
288
289    // ---------- Linear algebra --------------
290
291    /*!  \brief Inversion.
292
293    The matrix must be invertible, otherwise the
294      function will terminate with an error.
295    */
296    GF2mat inverse() const;
297
298    //! Returns the number of linearly independent rows
299    int row_rank() const;
300
301    /*! \brief TXP factorization.
302
303    Given X, compute a factorization of the form U=TXP, where U is
304      upper triangular, T is square and invertible, and P is a
305      permutation matrix.  This is basically an "LU"-factorization,
306      but not called so here because T is not necessarily lower
307      trianglular.  The matrix X may have any dimension. The
308      permutation matrix P is represented as a permutation vector.
309
310      The function returns the row rank of X.  (If X is full row rank,
311      then the number of rows is returned.)
312
313      The function uses Gaussian elimination combined with
314      permutations.  The computational complexity is O(m*m*n) for an
315      m*n matrix.
316    */
317    int T_fact(GF2mat &T, GF2mat &U, ivec &P) const;
318
319    /*! \brief TXP factorization update, when bit is flipped.
320
321    Update upper triangular factor U in the TXP-factorization (U=TXP)
322    when the bit at position (r,c) is changed (0->1 or 1->0). The
323    purpose of this function is to avoid re-running a complete
324    T-factorization when a single bit is changed. The function assumes
325    that T, U, and P already exist and that U=TXP before the function
326    is called. The function also assumes that the rank provided is
327    correct. The function updates T, U and P these matrices.  The
328    function returns the new rank of the matrix after the bitflip.
329
330    \note T, U, P and the rank value supplied to the function must be
331    correct one. This is not checked by the function (for reasons of
332    efficiency).
333
334    The function works by performing permutations to bring the matrix
335    to a form where the Gaussian eliminated can be restarted from the
336    point (rank-1,rank-1). The function is very fast for matrices with
337    close to full rank but it is generally slower for non-full rank
338    matrices.
339    */
340    int T_fact_update_bitflip(GF2mat &T, GF2mat &U,
341                              ivec &P, int rank, int r, int c) const;
342
343    /*!  \brief TXP factorization update, when column is added
344
345    Update upper triangular factor U in the T-factorization (U=TXP)
346    when a column (newcol) is appended at the right side of the
347    matrix.  The purpose of this function is to avoid re-running a
348    complete T-factorization when a column is added. The function ONLY
349    adds the column if it improves the rank of the matrix (nothing is
350    done otherwise).  The function returns "true" if the column was
351    added, and "false" otherwise.
352
353    \note This function does not actually add the column newcol to the
354    GF2 matrix. It only checks whether doing so would increase the
355    rank, and if this is the case, it updates the T-factorization.  A
356    typical calling sequence would be
357    \code
358    bool rank_will_improve =  X.T_fact_update_addcol(T,U,perm,c);
359    if (rank_will_improve) { X = X.concatenate_horizontal(c); }
360    \endcode
361
362    The complexity is O(m^2) for an m*n matrix.
363    */
364    bool T_fact_update_addcol(GF2mat &T, GF2mat &U,
365                              ivec &P, bvec newcol) const;
366
367    // ----- Operators -----------
368
369    //! Assignment operator
370    void operator=(const GF2mat &X);
371
372    //! Check if equal
373    bool operator==(const GF2mat &X) const;
374
375    // ----- Friends ------
376
377    //! Multiplication operator
378    friend GF2mat operator*(const GF2mat &X, const GF2mat &Y);
379
380    //! Multiplication operator with binary vector
381    friend bvec operator*(const GF2mat &X, const bvec &y);
382
383    /*! \brief Addition operator
384
385    Subtraction is not implemented because it is
386      equivalent to addition. */
387    friend GF2mat operator+(const GF2mat &X, const GF2mat &Y);
388
389    //! Output stream operator (plain text)
390    friend std::ostream &operator<<(std::ostream &os, const GF2mat &X);
391
392    //! Write the matrix to file
393    friend it_file &operator<<(it_file &f, const GF2mat &X);
394
395    //! Read the matrix from file
396    friend it_ifile &operator>>(it_ifile &f, GF2mat &X);
397
398    //!Multiplication X*Y' where X and Y are GF(2) matrices
399    friend GF2mat mult_trans(const GF2mat &X, const GF2mat &Y);
400
401  private:
402    int nrows, ncols;            // number of rows and columns of matrix
403    int nwords;                  // number of bytes used
404    Mat<unsigned char> data;             // data structure
405
406    // This value is used to perform division by bit shift and is equal to
407    // log2(8)
408    static const unsigned char shift_divisor = 3;
409
410    // This value is used as a mask when computing the bit position of the
411    // division remainder
412    static const unsigned char rem_mask = (1 << shift_divisor) - 1;
413  };
414
415
416  // ----------------------------------------------------------------------
417  // GF2mat related functions
418  // ----------------------------------------------------------------------
419
420  /*!
421    /relatesalso GF2mat
422    /brief Write GF(2) matrix to file.
423  */
424  it_file &operator<<(it_file &f, const GF2mat &X);
425
426  /*!
427    /relatesalso GF2mat
428    /brief Read GF(2) matrix from file.
429  */
430  it_ifile &operator>>(it_ifile &f, GF2mat &X);
431
432  /*!
433    \relatesalso GF2mat
434    \brief GF(2) matrix multiplication
435  */
436  GF2mat operator*(const GF2mat &X, const GF2mat &Y);
437
438  /*!
439    \relatesalso GF2mat
440    \brief GF(2) matrix multiplication with "regular" binary vector
441  */
442  bvec operator*(const GF2mat &X, const bvec &y);
443
444  /*!
445    \relatesalso GF2mat
446    \brief GF(2) matrix addition
447  */
448  GF2mat operator+(const GF2mat &X, const GF2mat &Y);
449
450  /*!
451    \relatesalso GF2mat
452    \brief Output stream (plain text) operator for dense GF(2) matrices
453  */
454  std::ostream &operator<<(std::ostream &os, const GF2mat &X);
455
456  /*!
457    \relatesalso GF2mat
458    \brief GF(2) Identity matrix
459  */
460  GF2mat gf2dense_eye(int m);
461
462  /*!
463    \relatesalso GF2mat
464    \brief Multiplication X*Y' where X and Y are GF(2) matrices
465  */
466  GF2mat mult_trans(const GF2mat &X, const GF2mat &Y);
467
468
469  // ----------------------------------------------------------------------
470  // Inline implementations
471  // ----------------------------------------------------------------------
472
473  inline void GF2mat::addto_element(int i, int j, bin s)
474  {
475    it_assert_debug(i >= 0 && i < nrows, "GF2mat::addto_element()");
476    it_assert_debug(j >= 0 && j < ncols, "GF2mat::addto_element()");
477    if (s == 1)
478      data(i, (j >> shift_divisor)) ^= (1 << (j & rem_mask));
479  }
480
481  inline bin GF2mat::get(int i, int j) const
482  {
483    it_assert_debug(i >= 0 && i < nrows, "GF2mat::get_element()");
484    it_assert_debug(j >= 0 && j < ncols, "GF2mat::get_element()");
485    return (data(i, (j >> shift_divisor)) >> (j & rem_mask)) & 1;
486  }
487
488  inline void GF2mat::set(int i, int j, bin s)
489  {
490    it_assert_debug(i >= 0 && i < nrows, "GF2mat::set_element()");
491    it_assert_debug(j >= 0 && j < ncols, "GF2mat::set_element()");
492    if (s == 1) // set bit to one
493      data(i, (j >> shift_divisor)) |= (1 << (j & rem_mask));
494    else // set bit to zero
495      data(i, (j >> shift_divisor)) &= (~(1 << (j & rem_mask)));
496  }
497
498} // namespace itpp
499
500#endif // #ifndef GF2MAT_H
Note: See TracBrowser for help on using the browser.