Ticket #655: sparsegfp.patch

File sparsegfp.patch, 12.8 KB (added by malb, 2 years ago)
  • sage/libs/linbox/linbox.pxd

    # HG changeset patch
    # User Martin Albrecht <malb@informatik.uni-bremen.de>
    # Date 1189866063 -3600
    # Node ID faf211fd9c6707064e1649a7eb1fb7e374d9654e
    # Parent  2cce131bce328a2ca283d5fb590b7aa8ddab5200
    first steps towards faster sparse linear algerba over GF(p)
    
    diff -r 2cce131bce32 -r faf211fd9c67 sage/libs/linbox/linbox.pxd
    a b  
    11include "../../ext/cdefs.pxi" 
    22 
    3 cdef extern from "../libs/m4ri/packedmatrix.h": 
    4     ctypedef struct packedmatrix 
     3include '../../modules/vector_modn_sparse_h.pxi' 
    54 
    65ctypedef size_t mod_int 
    76 
     
    1817                                size_t B_nr, size_t B_nc) 
    1918    cdef unsigned long rank(self) except -1 
    2019 
     20cdef class Linbox_modn_sparse: 
     21    cdef c_vector_modint *rows 
     22    cdef size_t nrows 
     23    cdef size_t ncols 
     24    cdef unsigned int modulus 
    2125 
    22 ## cdef class Linbox_mod2_dense: 
    23 ##     cdef packedmatrix *matrix 
    24      
    25 ##     cdef set(self, packedmatrix *matrix) 
    26 ##     cdef int echelonize(self) 
    27 ##     cdef matrix_matrix_multiply(self, packedmatrix *ans, packedmatrix *B) 
    28 ##     cdef unsigned long rank(self) except -1 
     26    cdef set(self, int modulus, size_t nrows, size_t ncols, c_vector_modint *rows) 
     27    cdef object rank(self, int reorder) 
     28    #cdef void solve(self, void *x, void *b) 
     29 
    2930 
    3031cdef class Linbox_integer_dense: 
    3132    cdef mpz_t** matrix 
  • sage/libs/linbox/linbox.pyx

    diff -r 2cce131bce32 -r faf211fd9c67 sage/libs/linbox/linbox.pyx
    a b  
    8787        r = linbox_modn_dense_rank(self.n,   self.matrix, self.nrows, self.ncols) 
    8888        return r 
    8989 
    90  
    91  
    92  
    93  
    94  
    95 ########################################################################## 
    96 ## Dense matrices GF(2) 
    97 ########################################################################## 
    98  
    99 ## cdef extern from "linbox_wrap.h": 
    100 ##     ctypedef struct packedmatrix 
    101  
    102 ##     cdef int linbox_mod2_dense_echelonize(packedmatrix *m) 
    103      
    104 ##     cdef void linbox_mod2_dense_minpoly(mod_int **mp, size_t* degree, packedmatrix *matrix, int do_minpoly) 
    105      
    106 ##     cdef int linbox_mod2_dense_matrix_matrix_multiply(packedmatrix *ans, packedmatrix *A, packedmatrix *B) 
    107  
    108 ##     cdef int linbox_mod2_dense_rank(packedmatrix *m) 
    109  
    110 ## cdef class Linbox_mod2_dense: 
    111 ##     cdef set(self, packedmatrix *matrix): 
    112 ##         self.matrix = matrix 
    113  
    114 ##     cdef int echelonize(self): 
    115 ##         cdef int r 
    116 ##         r = linbox_mod2_dense_echelonize(self.matrix) 
    117 ##         return r 
    118      
    119 ##     def minpoly(self): 
    120 ##         return self._poly(True) 
    121  
    122 ##     def charpoly(self): 
    123 ##         return self._poly(False) 
    124  
    125 ##     def _poly(self, minpoly): 
     90########################################################################## 
     91## Sparse matices modulo p. 
     92########################################################################## 
     93 
     94cdef extern from "linbox_wrap.h": 
     95    int linbox_modn_sparse_matrix_rank(unsigned long modulus, size_t nrows, size_t ncols, void* rows, int reorder) #, int **pivots) 
     96    void linbox_modn_sparse_matrix_solve(unsigned long modulus, size_t numrows, size_t numcols, void **x, void *a,  void *b) 
     97 
     98cdef class Linbox_modn_sparse: 
     99    cdef set(self, int modulus, size_t nrows, size_t ncols, c_vector_modint *rows): 
     100        self.rows = rows 
     101        self.nrows = nrows 
     102        self.ncols = ncols 
     103        self.modulus = modulus 
     104 
     105    cdef object rank(self, int reorder): 
     106        #cdef int *_pivots 
     107        cdef int r 
     108        r = linbox_modn_sparse_matrix_rank(self.modulus, self.nrows, self.ncols, self.rows, reorder) 
     109         
     110        #pivots = [_pivots[i] for i in range(r)] 
     111        #free(_pivots) 
     112        return r#, pivots 
     113 
     114##     cdef void solve(self, void *x, void *b): 
    126115##         """ 
    127 ##         INPUT: 
    128 ##             as given 
    129              
    130 ##         OUTPUT: 
    131 ##             coefficients of charpoly or minpoly as a Python list 
    132116##         """ 
    133 ##         cdef mod_int *f 
    134 ##         cdef size_t degree 
    135 ##         linbox_mod2_dense_minpoly(&f, &degree, self.matrix, minpoly) 
    136  
    137 ##         v = [] 
    138 ##         cdef Py_ssize_t i 
    139 ##         for i from 0 <= i <= degree: 
    140 ##             v.append(f[i]) 
    141 ##         linbox_modn_dense_delete_array(f) 
    142 ##         return v 
    143          
    144 ##     cdef matrix_matrix_multiply(self, 
    145 ##                                 packedmatrix *ans, 
    146 ##                                 packedmatrix *B): 
    147 ##         cdef int e 
    148  
    149 ##         e = linbox_mod2_dense_matrix_matrix_multiply(ans, self.matrix,  B) 
    150 ##         if e: 
    151 ##             raise RuntimeError, "error doing matrix matrix multiply mod2 using linbox" 
    152  
    153 ##     cdef unsigned long rank(self) except -1: 
    154 ##         cdef unsigned long r 
    155 ##         r = linbox_mod2_dense_rank(self.matrix) 
    156 ##         return r 
    157          
    158  
    159 ########################################################################## 
    160 ## Sparse matices modulo p. 
    161 ########################################################################## 
    162 cdef class Linbox_modn_sparse: 
    163     pass 
    164  
    165  
     117##         linbox_modn_sparse_matrix_solve(self.modulus, self.nrows, self.ncols, &x, self.rows, b)  
     118     
    166119########################################################################## 
    167120## Sparse matrices over ZZ 
    168121########################################################################## 
  • sage/matrix/matrix_modn_sparse.pxd

    diff -r 2cce131bce32 -r faf211fd9c67 sage/matrix/matrix_modn_sparse.pxd
    a b  
    66    cdef c_vector_modint* rows 
    77    cdef public int p 
    88    cdef swap_rows_c(self, Py_ssize_t n1, Py_ssize_t n2) 
     9 
     10    cdef _init_linbox(self) 
  • sage/matrix/matrix_modn_sparse.pyx

    diff -r 2cce131bce32 -r faf211fd9c67 sage/matrix/matrix_modn_sparse.pyx
    a b  
    7979 
    8080from sage.misc.misc import verbose, get_verbose, graphics_filename 
    8181 
     82from sage.rings.integer import Integer 
     83 
     84from sage.matrix.matrix0 import Matrix as Matrix0 
     85from sage.rings.arith import is_prime 
     86 
     87from sage.structure.element import is_Vector 
     88 
    8289################ 
    8390# TODO: change this to use extern cdef's methods. 
    8491from sage.ext.arith cimport arith_int 
     
    8895 
    8996import sage.ext.multi_modular 
    9097MAX_MODULUS = sage.ext.multi_modular.MAX_MODULUS 
     98 
     99from sage.libs.linbox.linbox cimport Linbox_modn_sparse 
     100cdef Linbox_modn_sparse linbox 
     101linbox = Linbox_modn_sparse() 
    91102 
    92103cdef class Matrix_modn_sparse(matrix_sparse.Matrix_sparse):    
    93104 
     
    462473            for j from 0 <= j < self.rows[i].num_nonzero: 
    463474                k+=1 
    464475        return QQ(k)/QQ(self.nrows()*self.ncols()) 
     476 
     477    cdef _init_linbox(self): 
     478        _sig_on 
     479        linbox.set(self.p, self._nrows, self._ncols,  self.rows) 
     480        _sig_off 
     481 
     482    def _rank_linbox(self): 
     483        """ 
     484        See self.rank(). 
     485        """ 
     486        if is_prime(self.p): 
     487            x = self.fetch('rank') 
     488            if not x is None: 
     489                return x 
     490            self._init_linbox() 
     491            _sig_on 
     492            # the returend pivots list is currently wrong 
     493            #r, pivots = linbox.rank(1) 
     494            r = linbox.rank(1) 
     495            r = Integer(r) 
     496            _sig_off 
     497            self.cache('rank', r) 
     498            return r 
     499        else: 
     500            raise TypeError, "only GF(p) supported via LinBox" 
     501 
     502    def rank(self, gauss=False): 
     503        """ 
     504        Compute the rank of self. 
     505 
     506        INPUT: 
     507            gauss -- if True Gaussian elimination is used. If False 
     508                     'Symbolic Reordering' as implemented in LinBox 
     509                     is used. (default: False) 
     510 
     511        EXAMPLE: 
     512            sage: A = random_matrix(GF(127),200,200,density=0.01,sparse=True) 
     513            sage: r1 = A.rank(gauss=False) 
     514            sage: r2 = A.rank(gauss=True) 
     515            sage: r1 == r2 
     516            True 
     517 
     518        ALGORITHM: Uses LinBox or native implementation. 
     519 
     520        REFERENCES: Jean-Guillaume Dumas and Gilles Villars. 'Computing the 
     521            Rank of Large Sparse Matrices over Finite Fields'. Proc. CASC'2002, 
     522            The Fifth International Workshop on Computer Algebra in Scientific Computing, 
     523            Big Yalta, Crimea, Ukraine, 22-27 sept. 2002, Springer-Verlag, 
     524            http://perso.ens-lyon.fr/gilles.villard/BIBLIOGRAPHIE/POSTSCRIPT/rankjgd.ps 
     525 
     526        NOTE: 
     527            For very sparse matrices Gaussian elimination is faster because 
     528            it barly has anything to do. If the fill in needs to be considered, 
     529            'Symbolic Reordering' is usually much faster. 
     530        """ 
     531        x = self.fetch('rank') 
     532        if not x is None: return x 
     533 
     534        if is_prime(self.p) and not gauss: 
     535            return self._rank_linbox() 
     536        else: 
     537            return Matrix0.rank(self) 
     538 
     539    def transpose(self): 
     540        """ 
     541        Return the transpose of self. 
     542 
     543        EXAMPLE: 
     544            sage: A = matrix(GF(127),3,3,[0,1,0,2,0,0,3,0,0],sparse=True) 
     545            sage: A 
     546            [0 1 0] 
     547            [2 0 0] 
     548            [3 0 0] 
     549            sage: A.transpose() 
     550            [0 2 3] 
     551            [1 0 0] 
     552            [0 0 0] 
     553        """ 
     554        cdef int i, j 
     555        cdef c_vector_modint row 
     556        cdef Matrix_modn_sparse B 
     557         
     558        B = self.new_matrix(nrows = self.ncols(), ncols = self.nrows()) 
     559        for i from 0 <= i < self._nrows: 
     560            row = self.rows[i] 
     561            for j from 0 <= j < row.num_nonzero: 
     562                set_entry(&B.rows[row.positions[j]], i, row.entries[j]) 
     563        return B 
     564                                 
     565    def matrix_from_rows(self, rows): 
     566        """ 
     567        Return the matrix constructed from self using rows with indices 
     568        in the rows list. 
     569 
     570        INPUT: 
     571            rows -- list or tuple of row indices 
     572 
     573        EXAMPLE: 
     574            sage: M = MatrixSpace(GF(127),3,3,sparse=True) 
     575            sage: A = M(range(9)); A 
     576            [0 1 2] 
     577            [3 4 5] 
     578            [6 7 8] 
     579            sage: A.matrix_from_rows([2,1]) 
     580            [6 7 8] 
     581            [3 4 5] 
     582        """ 
     583        cdef int i,k 
     584        cdef Matrix_modn_sparse A 
     585        cdef c_vector_modint row 
     586 
     587        if not isinstance(rows, (list, tuple)): 
     588            raise TypeError, "rows must be a list of integers" 
     589 
     590 
     591        A = self.new_matrix(nrows = len(rows)) 
     592 
     593        k = 0 
     594        for ii in rows: 
     595            i = ii 
     596            if i < 0 or i >= self.nrows(): 
     597                raise IndexError, "row %s out of range"%i 
     598 
     599            row = self.rows[i] 
     600            for j from 0 <= j < row.num_nonzero: 
     601                set_entry(&A.rows[k], row.positions[j], row.entries[j]) 
     602            k += 1 
     603        return A 
     604             
     605 
     606    def matrix_from_columns(self, cols): 
     607        """ 
     608        Return the matrix constructed from self using columns with 
     609        indices in the columns list. 
     610 
     611        EXAMPLES: 
     612            sage: M = MatrixSpace(GF(127),3,3,sparse=True) 
     613            sage: A = M(range(9)); A 
     614            [0 1 2] 
     615            [3 4 5] 
     616            [6 7 8] 
     617            sage: A.matrix_from_columns([2,1]) 
     618            [2 1] 
     619            [5 4] 
     620            [8 7] 
     621        """ 
     622        cdef int i,j 
     623        cdef Matrix_modn_sparse A 
     624        cdef c_vector_modint row 
     625 
     626        if not isinstance(cols, (list, tuple)): 
     627            raise TypeError, "rows must be a list of integers" 
     628 
     629        A = self.new_matrix(ncols = len(cols)) 
     630 
     631        cols = dict(zip([int(e) for e in cols],range(len(cols)))) 
     632 
     633        for i from 0 <= i < self.nrows(): 
     634            row = self.rows[i] 
     635            for j from 0 <= j < row.num_nonzero: 
     636                if int(row.positions[j]) in cols: 
     637                    set_entry(&A.rows[i], cols[int(row.positions[j])], row.entries[j]) 
     638        return A 
     639 
     640##     def _solve(self, Matrix_modn_sparse B): 
     641##         """ 
     642##         """ 
     643##         cdef c_vector_modint *X 
     644 
     645##         cdef Matrix_modn_sparse C 
     646 
     647##         if not self.is_square(): 
     648##             raise NotImplementedError, "input matrix must be square" 
     649         
     650##         if self.rank() != self.nrows(): 
     651##             raise ValueError, "input matrix must have full rank but it doesn't" 
     652 
     653##         self._init_linbox() 
     654 
     655##         matrix = True 
     656##         if is_Vector(B): 
     657##             matrix = False 
     658##         C = self.matrix_space(1,self.nrows())(B.list()) 
     659 
     660##         #_sig_on 
     661##         linbox.solve(&X, C.rows) 
     662##         #_sig_off 
     663         
     664## ##         X = None 
     665## ##         if not matrix: 
     666## ##             # Convert back to a vector 
     667## ##             return (X.base_ring() ** X.nrows())(X.list()) 
     668## ##         else: 
     669## ##             return X