Guest User

f4main.cpp

a guest
May 2nd, 2016
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.64 KB | None | 0 0
  1. /**
  2. \file
  3. Реализация алгоритма F4
  4. */
  5. #include "f4main.h"
  6. #include "commonpolyops.h"
  7. #include "outputroutines.h"
  8. #include "conversions.h"
  9. #include "matrixinfoimpl.h"
  10. #include "<time.h>"
  11.  
  12. using namespace std;
  13. namespace F4MPI{
  14.  
  15. /**реализация алгоритма Update.
  16. \param G промежуточный базис. В него добавляется новый многочлен и выкидываются некоторые старые
  17. \param P набор рассматриваемых S-пар, который модифицируется в соответсвии с критериями Бухбергера
  18. \param h новый многочлен, добавляемый в промежуточный базис
  19. */
  20. void Update(PolynomSet& G, SPairSet& P, const CPolynomial& h)
  21. {  
  22.     //MEASURE_TIME_IN_BLOCK("Update");
  23.     vector<int> D;
  24.     D.reserve(G.size());   
  25.     vector<int> Pnew;
  26.     Pnew.reserve(G.size());
  27.     CMonomial HMh = h.HM();
  28.     CMonomial HMg1;
  29.     CMonomial LCM_HMh_HMg1;
  30.     CMonomial HMg2;
  31.     CMonomial LCM_HMh_HMg2;
  32.     for(int i = 0; i<int(G.size()); i++)
  33.     {
  34.         HMg1 = G[i].HM();
  35.         bool Condition = false;
  36.         bool gcdOne = false;
  37.         if(CMonomial::gcd(HMh, HMg1).getDegree()==0)
  38.         {
  39.             Condition = true;
  40.             gcdOne = true;
  41.         }
  42.         else{      
  43.             Condition = true;
  44.             LCM_HMh_HMg1 = CMonomial::lcm(HMh, HMg1);          
  45.             for(int j = i+1; Condition && j<int(G.size()); ++j)
  46.             {
  47.                 HMg2 = G[j].HM();
  48.                 LCM_HMh_HMg2 = CMonomial::lcm(HMh, HMg2);
  49.                 if(LCM_HMh_HMg1.divisibleBy(LCM_HMh_HMg2))
  50.                     Condition = false;
  51.             }          
  52.             for(int j = 0; Condition && j<int(D.size()); j++)
  53.             {
  54.                 HMg2 = G[D[j]].HM();
  55.                 LCM_HMh_HMg2 = CMonomial::lcm(HMh, HMg2);
  56.                 if(LCM_HMh_HMg1.divisibleBy(LCM_HMh_HMg2))
  57.                     Condition = false;
  58.             }
  59.         }
  60.         if(Condition)
  61.         {
  62.             D.push_back(i);        
  63.             if(!gcdOne)
  64.                 Pnew.push_back(i);             
  65.         }
  66.     }  
  67.     vector<bool> Mark(P.size()+Pnew.size());
  68.     fill(Mark.begin(), Mark.end(), true);
  69.  
  70.     {
  71.         //MEASURE_TIME_IN_BLOCK("SecondCriteria");
  72.         CMonomial LCM_HMg1_HMg2;
  73.         for(int i = 0; i<int(P.size()); i++)
  74.         {
  75.             LCM_HMg1_HMg2 = CMonomial::lcm(P[i].first.HM(), P[i].second.HM());
  76.             if( LCM_HMg1_HMg2.divisibleBy(HMh) &&        
  77.                 CMonomial::lcm(HMh, P[i].first.HM())!=LCM_HMg1_HMg2 &&
  78.                 CMonomial::lcm(HMh, P[i].second.HM())!=LCM_HMg1_HMg2)
  79.             {
  80.                 Mark[i] = false;
  81.                 continue;
  82.             }      
  83.         }
  84.     }
  85.  
  86.     {
  87.         //MEASURE_TIME_IN_BLOCK("MakeNewSPairs");
  88.         for(int i = 0; i<int(Pnew.size()); i++)
  89.             P.push_back(MakeSPair(h, G[Pnew[i]]));
  90.     }
  91.     {
  92.         //MEASURE_TIME_IN_BLOCK("EraseMarkedFromP");
  93.         EraseAll<SPair>(P, Mark);
  94.     }
  95.     {
  96.         //MEASURE_TIME_IN_BLOCK("CheckDivisibility");
  97.         Mark.resize(G.size());
  98.         for(int i = 0; i<int(G.size()); i++)
  99.         {
  100.             if(!G[i].HM().divisibleBy(HMh))
  101.                 Mark[i] = true;
  102.             else
  103.                 Mark[i] = false;
  104.         }
  105.     }
  106.     {
  107.         //MEASURE_TIME_IN_BLOCK("EraseMarkedFromG");
  108.         G.push_back(h);
  109.         Mark.push_back(true);
  110.         EraseAll<CPolynomial>(G, Mark);
  111.     }
  112. }
  113.  
  114.    
  115. ///Приводит матрицу \a m к ступенчатому/сильно ступенчатому виду в соответствии с \a f4options
  116. void doReduceMatrix(CMatrix& m, const F4AlgData* f4options){
  117.     if(f4options->diagonalEachStep){
  118.         m.toDiagonalNormalForm(f4options);
  119.     }else{
  120.         m.toRowEchelonForm(f4options);
  121.     }
  122. }
  123.  
  124. long mtime()
  125. {
  126. struct timeval t;
  127.  
  128. gettimeofday(&t, NULL);
  129. long mt = (long)t.tv_sec * 1000 + t.tv_usec / 1000;
  130. return mt;
  131. }
  132.  
  133. ///Редуцирует матрицу, собирая статистику по ней при необходимости
  134. void ReduceMatrix(CMatrix& m, const F4AlgData* f4options){
  135.     long t;
  136.     t = mtime();
  137.     f4options->stats->totalNumberOfReducedMatr++;
  138.     m.doMatrixStatsPre(f4options);
  139.     doReduceMatrix(m,f4options);
  140.     m.doMatrixStatsPost(f4options);
  141.     t = mtime() - t;
  142.     printf("Reduce matrix: %ld millisec", GetTickCount()-start);
  143.     if (f4options->mpi_start_info.isMainProcess() && f4options->showInfoToStdout){
  144.         printf("%d matrices complete\n", f4options->stats->totalNumberOfReducedMatr);
  145.         fflush(stdout);
  146.     }
  147. }
  148.  
  149. /**
  150. Подготавливает S-пару к обработке.
  151. Домножает многочлены S-пары на (минимально возможные) мономы таким образом, чтоб старшие их мономы стали равны друг другу
  152. */
  153. void SPolynomial2(SPair& sp)
  154. {
  155.     CMonomial lcm = CMonomial::lcm(sp.first.HM(), sp.second.HM());
  156.     CMonomial M1;
  157.     CMonomial M2;
  158.    
  159.     lcm.tryDivide(sp.first.HM(), M1);
  160.     lcm.tryDivide(sp.second.HM(), M2);
  161.     sp.first*= M1;
  162.     sp.second*= M2;
  163. }
  164.  
  165. /**
  166. Выбирает S-пары для рассмотрения на следующем шаге.
  167. На основе S-пар выбранных из множества \a sPairs формируются многочлены, записываемые в \a ret.
  168. Из исходного множеcтва S-пар выбранные выкидываются.
  169. */
  170. void SelectSPairs(SPairSet &sPairs, PolynomSet& ret)
  171. {      
  172.     //MEASURE_TIME_IN_BLOCK("SelectSPairs");
  173.     vector<bool> Mark(sPairs.size());
  174.     int minDeg = 2000000000;
  175.    
  176.     for(int i = 0; i<int(sPairs.size()); i++)
  177.     {
  178.         int d = CMonomial::lcm(sPairs[i].first.HM(), sPairs[i].second.HM()).getDegree();   
  179.         if(d<minDeg)minDeg = d;
  180.     }
  181.     int count = 0;
  182.  
  183.     for(int i = 0; i<int(sPairs.size()); i++)
  184.     {      
  185.         if(CMonomial::lcm(sPairs[i].first.HM(), sPairs[i].second.HM()).getDegree() == minDeg)
  186.         {      
  187.             count++;
  188.             Mark[i] = false;
  189.         }
  190.         else
  191.             Mark[i] = true;
  192.     }  
  193.     for(int i = 0; i<int(sPairs.size()); i++)if(!Mark[i])
  194.     {
  195.         SPolynomial2(sPairs[i]);
  196.         ret.push_back(sPairs[i].first);
  197.         ret.push_back(sPairs[i].second);
  198.     }
  199.     EraseAll<SPair>(sPairs, Mark);     
  200. }
  201.  
  202. /**реализация алгоритма Reduce (см теоретическую документацию).
  203. \param polysToReduce множество многочленов, представляющее S-пары, которое нужно редуцировать.
  204. Значение аргумента после возврата из процедуры неопределено (портится)
  205. \param reducers множество многочленов-редукторов
  206. \param result место для записи результата
  207. \param f4options параметры F4: порядок сортировки многочленов перед помещением в матрицу и параметры матричных операций.
  208. */
  209. void ReduceF4(PolynomSet& polysToReduce, PolynomSet& reducers, PolynomSet& result, const F4AlgData* f4options)
  210. {  
  211.     //MEASURE_TIME_IN_BLOCK("Reduce");
  212.     Preprocess(polysToReduce, reducers);
  213.    
  214.     MonomialMap preprocessedHM;
  215.  
  216.     {
  217.         //MEASURE_TIME_IN_BLOCK("storeMonomial");
  218.         for(PolynomSet::iterator i = polysToReduce.begin(); i!=polysToReduce.end(); ++i)
  219.         {
  220.             preprocessedHM.storeMonomial(i->HM());
  221.         }
  222.     }
  223.  
  224.     CMatrix mainMatrix;
  225.  
  226.     {
  227.         //MEASURE_TIME_IN_BLOCK("sort");
  228.         if(f4options->useSizesForSelectingRow){
  229.             sort(polysToReduce.begin(),polysToReduce.end(),cmpForReduceBySize);
  230.         }else{
  231.             sort(polysToReduce.begin(),polysToReduce.end(),cmpForReduceByOrder);
  232.         }
  233.     }
  234.     {
  235.         //MEASURE_TIME_IN_BLOCK("polyToMatrix");
  236.         polyToMatrix(polysToReduce, mainMatrix);
  237.     }
  238.  
  239.     {
  240.         //MEASURE_TIME_IN_BLOCK("reduceMatrix");
  241.         ReduceMatrix(mainMatrix, f4options);
  242.     }
  243.  
  244.     {
  245.         //MEASURE_TIME_IN_BLOCK("matrixToPoly");
  246.         matrixToPoly(mainMatrix, result, preprocessedHM);
  247.     }
  248. }
  249.  
  250.  
  251. /**реализация алгоритма F4
  252. \param F множество многочленов, для которого нужно найти базис
  253. \param f4options параметры различных этапов алгоритма и сбора статистики.
  254. \retval базис Грёбнера для \a F
  255. */
  256. PolynomSet F4(PolynomSet F, const F4AlgData* f4options){
  257.     //MEASURE_TIME_IN_BLOCK("F4");
  258.     PolynomSet basis;
  259.     basis.reserve(100000);
  260.     SPairSet sPairs;
  261.     sPairs.reserve(100000);
  262.     for(PolynomSet::iterator i = F.begin(); i!=F.end(); ++i)
  263.     {  
  264.         Update(basis, sPairs, *i);
  265.     }
  266.     PolynomSet newBasisElements;
  267.     newBasisElements.reserve(100000);
  268.     PolynomSet sPolynomials;
  269.     sPolynomials.reserve(100000);
  270.        
  271.     while(!sPairs.empty())
  272.     {      
  273.         // Selecting SPairs    
  274.         sPolynomials.clear();
  275.         SelectSPairs(sPairs, sPolynomials);
  276.        
  277.         newBasisElements.clear();      
  278.         ReduceF4(sPolynomials, basis, newBasisElements, f4options);    
  279.         sort(newBasisElements.begin(),newBasisElements.end(),cmpForUpdaters);
  280.         // Updating basis and sPairs
  281.         for(const auto& newBasisElement: newBasisElements)
  282.             Update(basis, sPairs, newBasisElement);
  283.        
  284.     }
  285.     if(f4options->autoReduceBasis){
  286.         AutoReduceBasis(basis, f4options);
  287.     }
  288.     Normalize(basis);
  289.     return basis;
  290. }
  291.  
  292. } //namespace F4MPI
Advertisement
Add Comment
Please, Sign In to add comment