#2190: [with bundle, positive review] implement a ZZ-module saturation 
algorithm:
this is the key thing needed to compute kernels over ZZ, etc.
----------------------------------+---------------------------
       Reporter:  was             |        Owner:  was
           Type:  enhancement     |       Status:  closed
       Priority:  major           |    Milestone:  sage-2.10.2
      Component:  linear algebra  |   Resolution:  fixed
       Keywords:                  |    Merged in:
        Authors:                  |    Reviewers:
Report Upstream:  N/A             |  Work issues:
         Branch:                  |       Commit:
   Dependencies:                  |     Stopgaps:
----------------------------------+---------------------------
Changes (by chapoton):

 * upstream:   => N/A


Old description:

> Saturation of a matrix, i.e., this command in Magma:
> {{{
>     (<Mtrx> X) -> Mtrx
>
>     The basis of the saturation w.r.t. Q of the space spanned by the rows
> of X.
> }}}
> is really important to a huge amount of my modular forms research.
> In Magma this command exists and is quite fast, because I specifically
> needed it for my work and Allan spent a lot of time on making it quite
> good.  In Sage, it's built on top of PARI's {{{matkerint}}} command (one
> can -reduce computing saturation to computing the
> kernel over ZZ of the transpose matrix).   As a result, Sage is almost
> completely and totally useless at doing any saturations when the size
> is at all interesting for research.  For example, a very tiny example
> below is nearly a hundred times slower in Sage than in Magma!
>
> {{{
> sage: a = random_matrix(ZZ, 40, 42)
> sage: w = a.row_space()
> sage: time s =w.saturation()
> CPU times: user 0.79 s, sys: 0.07 s, total: 0.86 s
> Wall time: 0.89
> sage: b = magma(a)
> sage: magma.eval('time c := Saturation(%s);'%b.name())
> 'Time: 0.010'
> sage: 0.89 / 0.01
> 89.0000000000000
> }}}
>
> Here are some more examples:
>
> {{{
> sage: a = random_matrix(ZZ, 150,150)
> sage: w = a.row_space()
> sage: time s = w.saturation()
> CPU times: user 1.36 s, sys: 0.21 s, total: 1.57 s
> Wall time: 1.64
> sage: m = magma(a)
> sage: magma.eval('time c := Saturation(%s);'%m.name())
> 'Time: 0.290'
> }}}
>
> and a very typical one for my research would look like this:
> {{{
> sage: a = random_matrix(ZZ, 100,300)
> sage: w = a.row_space()
> sage: time s = w.saturation()
> CPU times: user 17653.78 s, sys: 360.28 s, total: 18014.06 s
> Wall time: 18241.30
> sage: 18014/3600.0    # FIVE HOURS!!
> 5.00388888888889
> sage: a = random_matrix(ZZ, 100,300)
> sage: m = magma(a)
> sage: magma.eval('time c := Saturation(%s);'%m.name())
> 'Time: 0.810'
> }}}
>
> I just want to pause to emphasize that:
>   1. there is no open source code in the world as far as I know that
> can do saturations quickly; only Magma does them right now, and
>   2. doing these reasonably quickly is utterly essential to my modular
> computational forms research.
>   3. The current situation is that what should be an easy everyday
> calculation for me -- e.g., saturating a 100x300 -- takes FIVE HOURS in
> Sage, but less than one second in Magma!
>

> Fortunately, there is a fast algorithm for saturation that depends mainly
> on kernels over GF(p) and HNF, and we now have very fast HNF because of
> #174.
>
> Here's some code in Magma that does p-satuation.  This combined with
> other tricks should lead to a saturation algorithm.  Porting this to Sage
> is definitely step 1.
>
> {{{
> function pAdicSaturation(B,p)
>     if Type(B[1]) eq SeqEnum then
>         V := RSpace(Rationals(),#B[1]);
>         B := [ V | v : v in B];
>     end if;
>     V := Universe(B);
>     n := Degree(V);
>     for i in [1..#B] do
>         B[i] *:= LCM([ Denominator(c) : c in Eltseq(B[i]) ]);
>     end for;
>     ZZ := Integers();
>     FF := FiniteField(p);
>     B := RMatrixSpace(ZZ,#B,n)!Matrix(B);
>     m := Rank(B);
>     B := Submatrix(HermiteForm(B),1,1,m,n);
>     N := RMatrixSpace(FF,m,n)!B;
>     while Rank(N) lt m do
>         K := Kernel(N);
>         vprintf pAdicSaturation :
>             "Rank(N) + Rank(K) = %o + %o = %o\n", Rank(N), Rank(K), m;
>         C := RMatrixSpace(ZZ,#Basis(K),n)!
>         Matrix([ (1/p)*V!&+[ ZZ!u[i]*B[i] : i in [1..m] ] : u in Basis(K)
> ]);
>         vtime pAdicSaturation, 2 :
>             B := Submatrix(HermiteForm(VerticalJoin(B,C)),1,1,m,n);
>         N := RMatrixSpace(FF,m,n)!B;
>     end while;
>     vprintf pAdicSaturation : "Rank(N) = %o \n", Rank(N), m;
>     return [ B[i] : i in [1..m] ];
> end function;
> }}}

New description:

 Saturation of a matrix, i.e., this command in Magma:
 {{{
     (<Mtrx> X) -> Mtrx

     The basis of the saturation w.r.t. Q of the space spanned by the rows
 of X.
 }}}
 is really important to a huge amount of my modular forms research.
 In Magma this command exists and is quite fast, because I specifically
 needed it for my work and Allan spent a lot of time on making it quite
 good.  In Sage, it's built on top of PARI's {{{matkerint}}} command (one
 can -reduce computing saturation to computing the
 kernel over ZZ of the transpose matrix).   As a result, Sage is almost
 completely and totally useless at doing any saturations when the size
 is at all interesting for research.  For example, a very tiny example
 below is nearly a hundred times slower in Sage than in Magma!

 {{{
 sage: a = random_matrix(ZZ, 40, 42)
 sage: w = a.row_space()
 sage: time s =w.saturation()
 CPU times: user 0.79 s, sys: 0.07 s, total: 0.86 s
 Wall time: 0.89
 sage: b = magma(a)
 sage: magma.eval('time c := Saturation(%s);'%b.name())
 'Time: 0.010'
 sage: 0.89 / 0.01
 89.0000000000000
 }}}

 Here are some more examples:

 {{{
 sage: a = random_matrix(ZZ, 150,150)
 sage: w = a.row_space()
 sage: time s = w.saturation()
 CPU times: user 1.36 s, sys: 0.21 s, total: 1.57 s
 Wall time: 1.64
 sage: m = magma(a)
 sage: magma.eval('time c := Saturation(%s);'%m.name())
 'Time: 0.290'
 }}}

 and a very typical one for my research would look like this:
 {{{
 sage: a = random_matrix(ZZ, 100,300)
 sage: w = a.row_space()
 sage: time s = w.saturation()
 CPU times: user 17653.78 s, sys: 360.28 s, total: 18014.06 s
 Wall time: 18241.30
 sage: 18014/3600.0    # FIVE HOURS!!
 5.00388888888889
 sage: a = random_matrix(ZZ, 100,300)
 sage: m = magma(a)
 sage: magma.eval('time c := Saturation(%s);'%m.name())
 'Time: 0.810'
 }}}

 I just want to pause to emphasize that:
   1. there is no open source code in the world as far as I know that
 can do saturations quickly; only Magma does them right now, and
   2. doing these reasonably quickly is utterly essential to my modular
 computational forms research.
   3. The current situation is that what should be an easy everyday
 calculation for me -- e.g., saturating a 100x300 -- takes FIVE HOURS in
 Sage, but less than one second in Magma!


 Fortunately, there is a fast algorithm for saturation that depends mainly
 on kernels over GF(p) and HNF, and we now have very fast HNF because of
 #174.

 Here's some code in Magma that does p-satuation.  This combined with other
 tricks should lead to a saturation algorithm.  Porting this to Sage is
 definitely step 1.

 {{{
 function pAdicSaturation(B,p)
     if Type(B[1]) eq SeqEnum then
         V := RSpace(Rationals(),#B[1]);
         B := [ V | v : v in B];
     end if;
     V := Universe(B);
     n := Degree(V);
     for i in [1..#B] do
         B[i] *:= LCM([ Denominator(c) : c in Eltseq(B[i]) ]);
     end for;
     ZZ := Integers();
     FF := FiniteField(p);
     B := RMatrixSpace(ZZ,#B,n)!Matrix(B);
     m := Rank(B);
     B := Submatrix(HermiteForm(B),1,1,m,n);
     N := RMatrixSpace(FF,m,n)!B;
     while Rank(N) lt m do
         K := Kernel(N);
         vprintf pAdicSaturation :
             "Rank(N) + Rank(K) = %o + %o = %o\n", Rank(N), Rank(K), m;
         C := RMatrixSpace(ZZ,#Basis(K),n)!
         Matrix([ (1/p)*V!&+[ ZZ!u[i]*B[i] : i in [1..m] ] : u in Basis(K)
 ]);
         vtime pAdicSaturation, 2 :
             B := Submatrix(HermiteForm(VerticalJoin(B,C)),1,1,m,n);
         N := RMatrixSpace(FF,m,n)!B;
     end while;
     vprintf pAdicSaturation : "Rank(N) = %o \n", Rank(N), m;
     return [ B[i] : i in [1..m] ];
 end function;
 }}}

--

--
Ticket URL: <http://trac.sagemath.org/ticket/2190#comment:9>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac.
For more options, visit https://groups.google.com/d/optout.

Reply via email to