Show
Ignore:
Timestamp:
03/11/07 15:11:02 (2 years ago)
Author:
pernet
Message:

New algorithm for charpoly: CharpolyArithProg?

- Complete the unfinished preconditionning phase (using complementary subspace comp. and rec. call)
- Exception management for the Las Vegas failure
- set as default for charpoly

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • include/fflas-ffpack/ffpack_frobenius.inl

    r1 r3  
    1414 
    1515//--------------------------------------------------------------------- 
    16 // Frobenius: Las Vegas algorithm to compute the Frobenius normal form over a large field 
     16// CharpolyArithProg: Las Vegas algorithm to compute the Charpoly normal form over a large field 
    1717//--------------------------------------------------------------------- 
    1818 
     
    146146template <class Field, class Polynomial> 
    147147std::list<Polynomial>& 
    148 FFPACK::Frobenius (const Field& F, std::list<Polynomial>& frobeniusForm,  
    149                    const size_t N, typename Field::Element * A, const size_t lda, const size_t c){ 
     148FFPACK::CharpolyArithProg (const Field& F, std::list<Polynomial>& frobeniusForm,  
     149                           const size_t N, typename Field::Element * A, const size_t lda, const size_t c){ 
    150150         
    151151        static typename Field::Element one, zero, mone; 
     
    156156        size_t * rp = new size_t[2*N]; 
    157157 
    158         size_t noc = static_cast<size_t>(ceil(N/double(c))); 
    159  
    160         // Building the workplace matrix Aw 
     158        size_t noc = static_cast<size_t>(ceil(double(N)/double(c))); 
     159 
     160        // Building the workplace matrix  
    161161        typename Field::Element *K = new typename Field::Element[N*(noc*c)]; 
    162162        typename Field::Element *K2 = new typename Field::Element[N*(noc*c)]; 
     
    170170         
    171171        size_t *dA = new size_t[N]; //PA 
    172         size_t *dK = new size_t[N]; 
     172        //      size_t *dK = new size_t[N]; 
    173173 
    174174 
     
    185185//             K+(c-2)*noc*ldk, ldk, A, lda, zero, K+(c-1)*noc*ldk, ldk); 
    186186 
    187 //      write_field(F,cerr<<"K = "<<endl,K, c*noc,N,ldk); 
    188 //      write_field(F,cerr<<"A = "<<endl,A, N,N,ldk); 
     187        //write_field(F,cerr<<"K = "<<endl,K, c*noc,N,ldk); 
     188        //write_field(F,cerr<<"A = "<<endl,A, N,N,ldk); 
    189189        size_t * Pk = new size_t[N]; 
    190190        size_t * Qk = new size_t[c*noc]; 
     
    193193        size_t w_idx = 0; 
    194194        for (size_t i=0; i<noc; ++i) 
    195                 for (size_t j=0; j<c; ++j) 
    196                         fcopy(F, N, (K2+(w_idx++)*ldk), 1, (K+(i+j*noc)*ldk), 1); 
     195                for (size_t j=0; j<c; ++j, w_idx++) 
     196                        fcopy(F, N, (K2+(w_idx)*ldk), 1, (K+(i+j*noc)*ldk), 1); 
    197197 
    198198        for (size_t i=0; i<noc*c; ++i) 
     
    200200         
    201201        size_t R = LUdivine(F, FflasNonUnit, noc*c, N, K, ldk, Pk, Qk, FfpackLQUP); 
    202         if (R<N){ 
    203                 std::cerr<<"Preconditionning failed; not yet implemented"<<std::endl; 
    204                 exit(-1); 
    205         } 
    206          
     202 
     203        //write_field(F,cerr<<"Apres LUDivine K = "<<endl,K, c*noc,N,ldk); 
     204        // cerr<<"Q = "; 
     205//      for (size_t i=0; i<noc*c; ++i) 
     206//              cerr<<Qk[i]<<" "; 
     207//      cerr<<endl; 
    207208        size_t row_idx = 0; 
    208         size_t * degini = new size_t[noc]; 
     209        size_t * dK = new size_t[noc]; 
    209210        for (size_t i=0; i<noc; ++i) 
    210                 degini[i]=0; 
    211         // size_t * degK = new size_t[c]; 
    212 //      for (size_t i=0; i<c; ++i) 
    213 //              degK[i]=0; 
     211                dK[i]=0; 
    214212         
    215213        size_t i=0; 
    216214        row_idx=0; 
     215        size_t dold = c; 
     216        size_t nb_full_blocks = 0; 
     217        size_t Mk = 0; 
    217218        for (size_t k = 0; k<noc; ++k){ 
    218219                size_t d = 0; 
    219220                while ( (d<c) && (row_idx<R) && (Qk[row_idx] == i)) {i++; row_idx++; d++;} 
    220                 degini[k] = d; 
     221                if (d > dold){ 
     222                        std::cerr << "FAIL in preconditionning phase:" 
     223                             << " degree sequence is not monotonically not increasing" 
     224                             << std::endl; 
     225                        //exit (-1); 
     226                        throw CharpolyFailed(); 
     227                } 
     228                         
     229                dK[k] = dold = d; 
     230                Mk++; 
     231                if (d == c) 
     232                        nb_full_blocks++; 
    221233                i = Qk[row_idx]; 
    222234        } 
    223          
    224 //      for (size_t i = 0; i<N; ++i) 
    225 //              if (Qk[row_idx] == i){ 
    226 //                      degini[i % noc] ++; 
    227 //      //              degK[i/noc] ++; 
    228 //                      row_idx ++; 
     235        //cerr<<"Mk = "<<Mk<<endl; 
     236        // Selection of the last iterate of each block 
     237        size_t bk_idx = 0; 
     238        //write_field (F,cerr<<"Avant fgemm K2 = "<<endl, K2, noc*c, N, ldk); 
     239 
     240        for (size_t i = 0; i < Mk; ++i){ 
     241#if DEBUG 
     242                std::cerr<<"dK ["<<i<<"] = "<<dK[i]<<std::endl; 
     243#endif 
     244                fcopy (F, N, (K2+i*ldk), 1, (K2 + (bk_idx + dK[i]-1)*ldk), 1); 
     245                //cerr<<"(bk_idx+dK[i]-1) = "<<(bk_idx+dK[i]-1)<<endl; 
     246                bk_idx+= c; 
     247        } 
     248 
     249        typename Field::Element* K2b = K2+Mk*ldk; 
     250        // K <- K A^T  
     251 
     252        //write_field (F,cerr<<"Avant fgemm K2 = "<<endl, K2, noc*c, N, ldk); 
     253        fgemm( F, FflasNoTrans, FflasTrans, Mk, N, N, one,  K2, ldk, A, lda, zero, K2b, ldk); 
     254 
     255        //write_field (F,cerr<<"Apres fgemm K2b = "<<endl, K2b, Mk, N, ldk); 
     256 
     257        // K <- K P^T 
     258        applyP (F, FflasRight, FflasTrans, Mk, 0, R, K2b, ldk, Pk); 
     259 
     260        //write_field (F,cerr<<"Apres applyP K2b = "<<endl, K2b, Mk, N, ldk); 
     261        // K <- K U^-1 
     262        ftrsm (F, FflasRight, FflasUpper, FflasNoTrans, FflasNonUnit, Mk, R, one, K, ldk, K2b, ldk); 
     263 
     264        //write_field (F,cerr<<"Apres ftrsm K2b = "<<endl, K2b, Mk, N, ldk); 
     265        // K <- K Q^T 
     266        //applyP (F, FflasRight, FflasNoTrans, Mk, 0, R, K2b, ldk, Qk); 
     267 
     268 
     269//      row_idx = 0; 
     270//      for (size_t i=0; i<R; ++i){ 
     271//              for (size_t k=row_idx; k<Qk[i]; ++k) // iterate on the linearly dependent rows 
     272//                      for (size_t j=0; j<i; ++j) 
     273//                              F.assign( *(K+j+k*ldk),zero); 
     274//              row_idx = Qk[i]+1; 
     275//      } 
     276        //cerr<<"c, noc, row_idx, N = "<<c<<" "<<noc<<" "<<row_idx<<" "<<N<<endl; 
     277        //row_idx = noc*c -1; 
     278//      while (row_idx < noc*c){ 
     279//              for (size_t j=0; j<MIN(row_idx,N); ++j) 
     280//                      F.assign( *(K + j + (row_idx)*ldk),zero); 
     281//              row_idx++; 
     282//      } 
     283        //write_field (F,cerr<<"Avant solvelb K2b = "<<endl, K2b, Mk, N, ldk); 
     284        // K <- K L^-1 
     285        //compressing L 
     286        //      write_field (F,cerr<<"Avant compression L = "<<endl, K, noc*c, N, ldk); 
     287        applyP(F, FflasLeft, FflasNoTrans, N, 0, R, K, ldk, Qk); 
     288        //write_field (F,cerr<<"Apres compression L = "<<endl, K, noc*c, N, ldk); 
     289 
     290        ftrsm (F, FflasRight, FflasLower, FflasNoTrans, FflasUnit, Mk, R, one, K, ldk, K2b, ldk); 
     291        //undoing permutation on K 
     292        applyP(F, FflasLeft, FflasTrans, N, 0, R, K, ldk, Qk); 
     293        //      solveLB2 (F, FflasRight, Mk, noc*c, R, K, ldk, Qk, K2b, ldk); 
     294        //§!!!!! 
     295        //applyP (F, FflasRight, FflasTrans, Mk, 0, R, K2b, ldk, Qk); 
     296        //write_field (F,cerr<<"Apres solvelb K2b = "<<endl, K2b, Mk, N, ldk); 
     297         
     298        // Recovery of the completed invariant factors 
     299        //cerr<<"// Recovery of the completed invariant factors"<<endl; 
     300        size_t Ma = Mk; 
     301        size_t Ncurr = R; 
     302        size_t offset = Ncurr-1; 
     303        size_t oldNcurr = Ncurr; 
     304        Polynomial *P; 
     305        //write_field (F,cerr<<"Recovery of the completed blocks"<<endl, K2b, Mk, N, ldk); 
     306        for (size_t i=Mk-1; i>=nb_full_blocks+1;  --i) 
     307                if (dK[i] >= 1){  
     308                        Polynomial P (dK [i]); 
     309                        for (size_t j=0; j < dK [i]; ++j){ 
     310                                F.neg (P [dK [i]-j-1], *(K2b + i*ldk + (offset-j))); 
     311                                //cerr<<" "<<(*(K2b + i*ldk + (offset-j))); 
     312                        } 
     313                        //cerr<<endl; 
     314                        // for (size_t j=0; j<dK[i]; ++j) 
     315//                              cerr<<" "<<(P)[j]; 
     316                        frobeniusForm.push_front(P); 
     317                        //cerr<<"Storing polynomial "<<i<<endl; 
     318                        offset -= dK [i]; 
     319                        Ncurr -= dK [i]; 
     320                        //block_idx--; 
     321                        Ma--; 
     322                } 
     323        Mk = Ma; 
     324        //cerr<<"taille frob = "<<frobeniusForm.size()<<endl; 
     325        //write_field(F,cerr,K,oldNcurr, Mk, ldk); 
     326        // cerr<<"nb_full_blocks, Mk, Ncurr, oldNcurr, offset  = " 
     327//                  <<nb_full_blocks<<" "<<Mk<<" "<<Ncurr<<" "<<oldNcurr<<" "<<offset<<endl; 
     328 
     329//      for (size_t i= offset+1; i<oldNcurr; ++i) 
     330//              for (size_t j=0; j<nb_full_blocks+1; ++j){ 
     331//                      //              cerr<<"K + "<<i<<"*ldk + "<<j<<" = "<<(*(K+i*ldk+j))<<endl; 
     332//                      if (!F.isZero( *(K2b+i*ldk+j) )){ 
     333//                              std::cerr<<"FAIL C != 0 in preconditionning"<<std::endl; 
     334//                              exit(-1); 
     335//                      } 
    229336//              } 
    230  
    231         // Selection of the last iterate of each of the block 
    232         size_t bk_idx = 0; 
    233         for (size_t i = 0; i < noc; ++i){ 
    234 #if DEBUG 
    235                 std::cerr<<"degini ["<<i<<"] = "<<degini[i]<<std::endl; 
    236 #endif 
    237                 fcopy (F, N, (K2+i*ldk), 1, (K2 + (bk_idx + degini[i]-1)*ldk), 1); 
    238                 bk_idx+= degini[i]; 
    239         } 
    240 //      for (size_t i = 0; i < c; ++i) 
    241 //              cerr<<"degK["<<i<<"] = "<<degK[i]<<endl; 
    242  
    243         // K <- K A^T  
    244         fgemm( F, FflasNoTrans, FflasTrans, noc, N, N, one,  K2, ldk, A, lda, zero, K2+noc*ldk, ldk); 
    245  
    246         // K <- K P^T 
    247         applyP (F, FflasRight, FflasTrans, noc, 0, R, K2+noc*ldk, ldk, Pk); 
    248  
    249         // K <- K U^-1 
    250         ftrsm (F, FflasRight, FflasUpper, FflasNoTrans, FflasNonUnit, noc, R, one, K, ldk, K2+noc*ldk, ldk); 
    251          
    252         // K <- K Q^T 
    253         applyP (F, FflasRight, FflasTrans, noc, 0, R, K2+noc*ldk, ldk, Qk); 
    254  
    255         // K <- K L^-1 
    256         //ftrsm(F, FflasRight, FflasLower, FflasNoTrans, FflasUnit, N, R 
    257         solveLB (F, FflasRight, noc, N, R, K, ldk, Qk, K2+noc*ldk, ldk); 
     337         
     338        if (R<N){ 
     339                 
     340                std::cerr<<"Preconditionning failed; missing rank = "<<N-R<<" completing the Krylov matrix" 
     341                         <<std::endl; 
     342                // exit(-1); 
     343                 
     344                Nrest = N-R; 
     345                //cerr<<"Nrest = "<<Nrest<<endl; 
     346                typename Field::Element * K21 = K + R*ldk; 
     347                typename Field::Element * K22 = K21 + R; 
     348                typename Field::Element * Ki, *Ai; 
     349                //  Compute the n-k last rows of A' = P A^T P^T in K2_ 
     350                // A = A . P^t 
     351                applyP( F, FflasRight, FflasTrans, N, 0, R, A, lda, Pk); 
     352                // Copy K2_ = (A'_2)^t 
     353                for (Ki = K21, Ai = A+R; Ki != K21 + Nrest*ldk; Ai++, Ki+=ldk-N) 
     354                        for ( size_t j=0; j<N*lda; j+=lda ) 
     355                                *(Ki++) = *(Ai+j); 
     356 
     357                //write_field (F, cerr<<"A = "<<endl, A, N, N, lda); 
     358                 
     359                //write_field (F, cerr<<"K2_ = "<<endl, K21, Nrest, N, ldk); 
     360                // A = A . P : Undo the permutation on A 
     361                applyP( F, FflasRight, FflasNoTrans, N, 0, R, A, lda, Pk); 
     362                // K2_ = K2_ . P^t (=  ( P A^t P^t )2_ )  
     363                applyP( F, FflasRight, FflasTrans, Nrest, 0, R, K21, ldk, Pk); 
     364                //write_field (F, cerr<<"K2_ ( = P A^T P^T) = "<<endl, K21, Nrest, N, ldk); 
     365                // K21 = K21 . S1^-1 
     366                //write_field (F, cerr<<"S1  = "<<endl, K,R,R, ldk); 
     367                ftrsm(F, FflasRight, FflasUpper, FflasNoTrans, FflasNonUnit, Nrest, R, 
     368                      one, K, ldk, K21, ldk);   
     369                //write_field (F, cerr<<"% S1^-1 = "<<endl, K21, Nrest, N, ldk); 
     370                typename Field::Element * Arec = new typename Field::Element[Nrest*Nrest]; 
     371                size_t ldarec = Nrest; 
     372                 
     373                // Creation of the matrix A2 for recursive call  
     374                for (Ki = K22,  Ai = Arec; 
     375                     Ki != K22 + Nrest*ldk; 
     376                     Ki += (ldk-Nrest) ) 
     377                        for ( size_t j=0; j<Nrest; ++j ) 
     378                                *(Ai++) = *(Ki++); 
     379                fgemm (F, FflasNoTrans, FflasNoTrans, Nrest, Nrest, R, mone, 
     380                       K21, ldk, K+R, ldk, one, Arec, ldarec); 
     381 
     382                std::list<Polynomial> polyList; 
     383                polyList.clear(); 
     384                //write_field (F, cerr<<"Recursive call with A = "<<endl, Arec, Nrest, Nrest, Nrest); 
     385 
     386                CharpolyArithProg (F, polyList, Nrest, Arec, ldarec, 2); 
     387                //cerr<<"taille polyList = "<<polyList.size()<<endl; 
     388                //cerr<<"Apres recursive call"<<endl; 
     389                delete[] Arec; 
     390                frobeniusForm.merge(polyList); 
     391                //cerr<<"taille frob = "<<frobeniusForm.size()<<endl; 
     392                //              typename list <Polynomial>::iterator pl_it = polyList.begin(); 
     393//              while (pl_it != polyList.end()) 
     394//                      frobeniusForm.push_front(*(pl_it++)); 
     395                 
     396        } 
     397         
     398         
    258399        delete[] Pk; 
    259400        delete[] Qk; 
    260401        size_t deg = c+1; 
    261         size_t Ma = noc; 
    262         size_t Mk; 
    263         size_t Ncurr = N; 
    264         for (size_t i=0; i<noc; ++i) 
    265                 dA[i] = degini[i]; 
    266          
    267 //      size_t deg = 2; 
    268 //      size_t Ma = N; 
    269 //      size_t Mk; 
    270 //      size_t Ncurr = N; 
    271         size_t block_idx, it_idx, rp_val, nb_full_blocks; 
     402        for (size_t i=0; i<Mk; ++i) 
     403                dA[i] = dK[i]; 
     404         
    272405        bk_idx = 0; 
    273406         
    274407        //      write_field(F,cerr<<"Apres preconditionnement, K = "<<endl, K2+noc*ldk, noc,N,ldk); 
    275         typename Field::Element *Arp = new typename Field::Element[N*Ma]; 
    276         typename Field::Element *Ac = new typename Field::Element[N*Ma]; 
     408        typename Field::Element *Arp = new typename Field::Element[Ncurr*Ma]; 
     409        typename Field::Element *Ac = new typename Field::Element[Ncurr*Ma]; 
    277410        size_t ldac = Ma; 
    278         size_t ldarp = N; 
    279          
    280         for (size_t i=0; i < N; ++i) 
     411        size_t ldarp = Ncurr; 
     412         
     413        for (size_t i=0; i < Ncurr; ++i) 
    281414                for (size_t j=0; j<Ma; ++j) 
    282                         *(Ac + i*Ma +j) = *(K2 + i + (j+noc)*ldk); 
     415                        *(K+i*ldk+j) = *(Ac + i*Ma +j) = *(K2b + i + (j)*ldk); 
    283416        //      for (size_t i=0; i < noc; ++i){ 
    284417//              for (size_t k=0; k < degini[i]; ++k){ 
     
    291424//      } 
    292425 
    293         //delete[] degK; 
    294         delete[] degini; 
    295         //      write_field(F,cerr<<"Apres preconditionnement, Ac = "<<endl, Ac, N, noc, N); 
    296          
    297         do{ 
     426        //write_field(F,cerr<<"Apres preconditionnement, Ac = "<<endl, Ac, Ncurr, Ma, Ma); 
     427         
     428        size_t block_idx, it_idx, rp_val; 
     429 
     430        //cerr<<"Avant a boucle : Ma, Ncurr = "<<Ma<<" "<<Ncurr<<endl; 
     431        while ((nb_full_blocks >= 1) && (Mk > 1)) { 
    298432                delete[] K; 
    299433                delete[] K2; 
     
    313447                if (R < Ncurr){ 
    314448                        std::cerr<<"FAIL R<Ncurr"<<std::endl; 
    315                         exit(-1); 
     449                        throw CharpolyFailed(); 
     450                        //exit(-1); 
    316451                } 
    317452                // Computation of the degree vector dK 
     
    330465                        while ( /*(g<Ncurr ) &&*/ (rp[g] == rp_val) && (it_idx < deg )); 
    331466                        if ((block_idx)&&(it_idx > dK[block_idx-1])){ 
     467                                throw CharpolyFailed(); 
    332468                                std::cerr<<"FAIL d non decroissant"<<std::endl; 
    333                                 exit(-1); 
     469                                //exit(-1); 
    334470                        } 
    335471                        dK[block_idx++] = it_idx; 
     
    407543                // Copying the last rows of A times K 
    408544                //cerr<<"// Copying the last rows of k "<<nb_full_blocks<<" "<<Mk<<endl; 
    409                 size_t offset = (deg-2)*nb_full_blocks; 
     545                offset = (deg-2)*nb_full_blocks; 
    410546                for (size_t i = nb_full_blocks; i < Mk; ++i) { 
    411547                        //cerr<<"dK["<<i<<"] = "<<dK[i]<<" deg = "<<deg<<endl; 
     
    437573                size_t *Q=new size_t[Mk]; 
    438574                if (LUdivine (F, FflasNonUnit, Mk, Mk , K2 + (Ncurr-Mk)*ldk, ldk, P, Q, FfpackLQUP) < Mk){ 
     575                        // should never happen (not a LAS VEGAS check) 
    439576                        std::cerr<<"FAIL R2 < MK"<<std::endl; 
    440577                        //                      exit(-1); 
     
    469606                //write_field(F, cerr<<"K = "<<endl, K, Ncurr, Mk, ldk); 
    470607                 
     608 
    471609                // Recovery of the completed invariant factors 
    472610                //cerr<<"// Recovery of the completed invariant factors"<<endl; 
     
    476614                for (size_t i=Mk-1; i>=nb_full_blocks+1;  --i) 
    477615                        if (dK[i] >= 1){  
    478                                 Polynomial * P = new Polynomial (dK [i]); 
     616                                Polynomial  P (dK [i]); 
    479617                                for (size_t j=0; j < dK[i]; ++j) 
    480                                         F.neg( P->operator[](dK[i]-j-1), *(K + i + (offset-j)*ldk)); 
    481                                 frobeniusForm.push_front(*P); 
     618                                        F.neg( P[dK[i]-j-1], *(K + i + (offset-j)*ldk)); 
     619                                frobeniusForm.push_front(P); 
    482620                                offset -= dK[i]; 
    483621                                Ncurr -= dK[i]; 
     
    493631                                if (!F.isZero( *(K+i*ldk+j) )){ 
    494632                                        std::cerr<<"FAIL C != 0"<<std::endl; 
    495                                         exit(-1); 
     633                                        throw CharpolyFailed(); 
     634                                        //exit(-1); 
    496635                                } 
    497636                        } 
     
    523662                deg++; 
    524663                         
    525         } while ((nb_full_blocks >= 1) && (Mk > 1)); 
     664        } 
    526665 
    527666        // Recovery of the first invariant factor 
    528667        //cerr<<"// Recovery of the first invariant factor"<<endl; 
    529         Polynomial * P = new Polynomial (dK [0]); 
     668        Polynomial Pl(dK [0]); 
    530669        for (size_t j=0; j < dK[0]; ++j) 
    531                 F.neg( P->operator[](j), *(K  + j*ldk)); 
    532         frobeniusForm.push_front(*P); 
     670                F.neg( Pl[j], *(K  + j*ldk)); 
     671        frobeniusForm.push_front(Pl); 
    533672        delete[] rp; 
    534673        delete[] Arp;