Ticket #655: sparsegfq-solve.patch

File sparsegfq-solve.patch, 12.7 KB (added by malb, 3 years ago)
  • sage/libs/linbox/linbox.pxd

    # HG changeset patch
    # User Martin Albrecht <malb@informatik.uni-bremen.de>
    # Date 1189891035 -3600
    # Node ID d15301877558fef32fd25d2693258450d337ef1f
    # Parent  5d306ed9a715f185e88b94ed7206ca49e508f78e
    Matrix_modn_dense.solve_right implemented via LinBox.
    
    diff -r 5d306ed9a715 -r d15301877558 sage/libs/linbox/linbox.pxd
    a b  
    2424    cdef unsigned int modulus 
    2525 
    2626    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) 
     27    cdef object rank(self, int gauss) 
     28    cdef void solve(self, c_vector_modint **x, c_vector_modint *b, int method) 
    2929 
    3030 
    3131cdef class Linbox_integer_dense: 
  • sage/libs/linbox/linbox.pyx

    diff -r 5d306ed9a715 -r d15301877558 sage/libs/linbox/linbox.pyx
    a b  
    9191## Sparse matices modulo p. 
    9292########################################################################## 
    9393 
    94 cdef extern from "linbox_wrap.h": 
     94include '../../modules/vector_modn_sparse_c.pxi' 
     95include '../../ext/stdsage.pxi' 
     96 
     97cdef extern from "linbox_wrap.h": 
     98    ctypedef struct vector_uint "std::vector<unsigned int>": 
     99        void (*push_back)(unsigned int) 
     100        int (*get "operator[]") (size_t i) 
     101        int (*size)() 
     102     
    95103    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) 
     104    vector_uint linbox_modn_sparse_matrix_solve(unsigned long modulus, size_t numrows, size_t numcols, void *a,  void *b, int method) 
    97105 
    98106cdef class Linbox_modn_sparse: 
    99107    cdef set(self, int modulus, size_t nrows, size_t ncols, c_vector_modint *rows): 
     
    102110        self.ncols = ncols 
    103111        self.modulus = modulus 
    104112 
    105     cdef object rank(self, int reorder): 
     113    cdef object rank(self, int gauss): 
    106114        #cdef int *_pivots 
    107115        cdef int r 
    108         r = linbox_modn_sparse_matrix_rank(self.modulus, self.nrows, self.ncols, self.rows, reorder) 
     116        r = linbox_modn_sparse_matrix_rank(self.modulus, self.nrows, self.ncols, self.rows, gauss) 
    109117         
    110118        #pivots = [_pivots[i] for i in range(r)] 
    111119        #free(_pivots) 
    112120        return r#, pivots 
    113121 
    114 ##     cdef void solve(self, void *x, void *b): 
    115 ##         """ 
    116 ##         """ 
    117 ##         linbox_modn_sparse_matrix_solve(self.modulus, self.nrows, self.ncols, &x, self.rows, b)  
     122    cdef void solve(self, c_vector_modint **x, c_vector_modint *b, int method): 
     123        """ 
     124        """ 
     125        cdef vector_uint X 
     126        X = linbox_modn_sparse_matrix_solve(self.modulus, self.nrows, self.ncols, self.rows, b, method) 
     127 
     128        for i from 0 <= i < X.size(): 
     129            set_entry(x[0], i, X.get(i)) 
     130             
    118131     
    119132########################################################################## 
    120133## Sparse matrices over ZZ 
  • sage/matrix/matrix_modn_sparse.pyx

    diff -r 5d306ed9a715 -r d15301877558 sage/matrix/matrix_modn_sparse.pyx
    a b  
    8181 
    8282from sage.rings.integer import Integer 
    8383 
    84 from sage.matrix.matrix0 import Matrix as Matrix0 
     84from sage.matrix.matrix2 import Matrix as Matrix2 
    8585from sage.rings.arith import is_prime 
    8686 
    8787from sage.structure.element import is_Vector 
     
    474474                k+=1 
    475475        return QQ(k)/QQ(self.nrows()*self.ncols()) 
    476476 
    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  
    539477    def transpose(self): 
    540478        """ 
    541479        Return the transpose of self. 
     
    637575                    set_entry(&A.rows[i], cols[int(row.positions[j])], row.entries[j]) 
    638576        return A 
    639577 
    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 
     578    cdef _init_linbox(self): 
     579        _sig_on 
     580        linbox.set(self.p, self._nrows, self._ncols,  self.rows) 
     581        _sig_off 
     582 
     583    def _rank_linbox(self, method): 
     584        """ 
     585        See self.rank(). 
     586        """ 
     587        if is_prime(self.p): 
     588            x = self.fetch('rank') 
     589            if not x is None: 
     590                return x 
     591            self._init_linbox() 
     592            _sig_on 
     593            # the returend pivots list is currently wrong 
     594            #r, pivots = linbox.rank(1) 
     595            r = linbox.rank(method) 
     596            r = Integer(r) 
     597            _sig_off 
     598            self.cache('rank', r) 
     599            return r 
     600        else: 
     601            raise TypeError, "only GF(p) supported via LinBox" 
     602 
     603    def rank(self, gauss=False): 
     604        """ 
     605        Compute the rank of self. 
     606 
     607        INPUT: 
     608            gauss -- if True LinBox' Gaussian elimination is used. If False 
     609                     'Symbolic Reordering' as implemented in LinBox 
     610                     is used. If 'native' the native SAGE implementation 
     611                     is used. (default: False) 
     612 
     613        EXAMPLE: 
     614            sage: A = random_matrix(GF(127),200,200,density=0.01,sparse=True) 
     615            sage: r1 = A.rank(gauss=False) 
     616            sage: r2 = A.rank(gauss=True) 
     617            sage: r3 = A.rank(gauss='native') 
     618            sage: r1 == r2 == r3 
     619            True 
     620 
     621        ALGORITHM: Uses LinBox or native implementation. 
     622 
     623        REFERENCES: Jean-Guillaume Dumas and Gilles Villars. 'Computing the 
     624            Rank of Large Sparse Matrices over Finite Fields'. Proc. CASC'2002, 
     625            The Fifth International Workshop on Computer Algebra in Scientific Computing, 
     626            Big Yalta, Crimea, Ukraine, 22-27 sept. 2002, Springer-Verlag, 
     627            http://perso.ens-lyon.fr/gilles.villard/BIBLIOGRAPHIE/POSTSCRIPT/rankjgd.ps 
     628 
     629        NOTE: 
     630            For very sparse matrices Gaussian elimination is faster because 
     631            it barly has anything to do. If the fill in needs to be considered, 
     632            'Symbolic Reordering' is usually much faster. 
     633        """ 
     634        x = self.fetch('rank') 
     635        if not x is None: return x 
     636 
     637        if is_prime(self.p): 
     638            if gauss is False: 
     639                return self._rank_linbox(0) 
     640            elif gauss is True: 
     641                return self._rank_linbox(1) 
     642            elif gauss == "native": 
     643                return Matrix2.rank(self) 
     644            else: 
     645                raise TypeError, "parameter 'gauss' not understood" 
     646        else: 
     647            return Matrix2.rank(self) 
     648 
     649    def solve_right(self, B, algorithm=None, check_rank = True): 
     650        """ 
     651        If self is a matrix $A$, then this function returns a vector 
     652        or matrix $X$ such that $A X = B$.  If $B$ is a vector then 
     653        $X$ is a vector and if $B$ is a matrix, then $X$ is a matrix. 
     654 
     655        NOTE: In SAGE one can also write \code{A \ B} for 
     656        \code{A.solve_right(B)}, i.e., SAGE implements the ``the 
     657        MATLAB/Octave backslash operator''. 
     658 
     659        INPUT: 
     660            B -- a matrix or vector 
     661            algorithm -- one of the following: 
     662                         'LinBox:BlasElimination' -- dense elimination 
     663                         'LinBox:Blackbox' -- LinBox chooses a Blackbox algorithm 
     664                         'LinBox:Wiedemann' -- Wiedemann's algorithm 
     665                         'generic' -- use generic implementation (inversion) 
     666                         None -- LinBox chooses an algorithm (default) 
     667            check_rank -- check rank before attempting to solve (default: True) 
     668 
     669        OUTPUT: 
     670            a matrix or vector 
     671 
     672        EXAMPLES: 
     673            sage: A = matrix(GF(127), 3, [1,2,3,-1,2,5,2,3,1], sparse=True) 
     674            sage: b = vector(GF(127),[1,2,3]) 
     675            sage: x = A \ b; x 
     676            (73, 76, 10)  
     677            sage: A * x 
     678            (1, 2, 3) 
     679 
     680        """ 
     681        cdef Matrix_modn_sparse A = self 
     682        cdef Matrix_modn_sparse b 
     683        cdef Matrix_modn_sparse X 
     684        cdef c_vector_modint *x 
     685 
     686        if algorithm == "generic" or not is_prime(self.p): 
     687            return Matrix2.solve_right(self, B) 
     688 
     689        if check_rank and self.rank() < self.nrows(): 
     690            raise ValueError, "self must be of full rank." 
     691 
     692        if not self.is_square(): 
     693            raise NotImplementedError, "input matrix must be square" 
     694         
     695        self._init_linbox() 
     696 
     697        matrix = True 
     698        if is_Vector(B): 
     699            matrix = False 
     700            b = <Matrix_modn_sparse>self.matrix_space(1, self.ncols(),sparse=True)(B.list()) 
     701        if PY_TYPE_CHECK(B,Matrix_modn_sparse) and B.base_ring() == self.base_ring(): 
     702            b = <Matrix_modn_sparse>B 
     703        else: 
     704            try: 
     705                b = <Matrix_modn_sparse>self.matrix_space(1, self.ncols(),sparse=True)(B.list()) 
     706            except (TypeError, AttributeError): 
     707                raise TypeError, "parameter 'b' not understood." 
     708 
     709        X = self.new_matrix(b.nrows(),A.ncols()) 
     710 
     711        if b.nrows() > 1: # such that we can walk through it easily 
     712            b = b.transpose() 
     713 
     714        if algorithm is None: 
     715            algorithm = 0 
     716        elif algorithm == "LinBox:BlasElimination": 
     717            algorithm = 1 
     718        elif algorithm == "LinBox:Blackbox": 
     719            algorithm = 2 
     720        elif algorithm == "LinBox:Wiedemann": 
     721            algorithm = 3 
     722        else: 
     723            raise TypeError, "parameter 'algorithm' not understood" 
     724 
     725        for i in range(X.nrows()): 
     726            _sig_on 
     727            x = &X.rows[i] 
     728            linbox.solve(&x, &b.rows[i], algorithm) 
     729            _sig_off 
     730 
     731        if not matrix: 
     732            # Convert back to a vector 
     733            return (X.base_ring() ** X.ncols())(X.list()) 
     734        else: 
     735            return X.transpose()