motzkin_burger.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002     
00003     motzkin_burger.cpp -- see motzkin_burger.hpp
00004 
00005     This file is a part of the Arageli library.
00006 
00007     Copyright (C) Nikolai Yu. Zolotykh, 1999--2006
00008     Copyright (C) Sergey S. Lyalin, 2006
00009     University of Nizhni Novgorod, Russia
00010 
00011 *****************************************************************************/
00012 
00013 #include "config.hpp"
00014 
00015 #if !defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE) || \
00016     defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_MOTZKIN_BURGER)
00017 
00018 #include <cstddef>
00019 
00020 #include "exception.hpp"
00021 #include "cmp.hpp"
00022 #include "gcd.hpp"
00023 #include "vector.hpp"
00024 #include "matrix.hpp"
00025 
00026 #include "motzkin_burger.hpp"
00027 
00028 
00029 namespace Arageli
00030 {
00031 
00032 namespace _Internal
00033 {
00034 
00035 const int mm_no_modification  = 0;
00036 const int mm_min_modification = 1;
00037 const int mm_max_modification = 2;
00038 
00039 template
00040 <
00041     typename A, typename F,
00042     typename Q, typename E,
00043     typename Ctrler
00044 >
00045 class motzkin_burger_algorithm
00046 {
00047 public:
00048 
00049     motzkin_burger_algorithm
00050     (A& a_a, F& f_a, Q& q_a, E& e_a, const Ctrler& ctrler_a, int modif)
00051     : a(a_a), f(f_a), q(q_a), e(e_a), ctrler(ctrler_a), modification(modif)
00052     {}
00053 
00054     void run ();
00055 
00056 private:
00057 
00058     A& a; F& f; Q& q; E& e;
00059 
00060     typedef typename A::size_type index;
00061     typedef typename type_traits<Q>::element_type QT;
00062     
00063     int modification;
00064     Ctrler ctrler;
00065 
00066     void gauss();
00067     bool reroof (index row);
00068     bool balanced (index j_plus, index j_minus);
00069     index min_modification ();
00070     index max_modification ();
00071     index no_modification ();
00072 
00073     index select_column ()
00074     {
00075         switch(modification)
00076         {
00077             case mm_no_modification: return current_column;
00078             case mm_min_modification: return min_modification();
00079             case mm_max_modification: return max_modification();
00080             default: ARAGELI_ASSERT_ALWAYS(!"It's impossible.");
00081         }
00082     }
00083 
00084     index fun (index j);
00085 
00086     void movie_print3 ()
00087     { ctrler.show_matrices(a, f, q); }
00088 
00089     vector<index> common_zero;
00090     index n, m, r, current_ost, current_column;
00091 };
00092 
00093 
00094 /*  Finds diagonal shape of matrix a through elementary elementary transformation,
00095     strores in q, after call q = f*transpose(a). */
00096 template
00097 <
00098     typename A, typename F,
00099     typename Q, typename E,
00100     typename Ctrler
00101 >
00102 void motzkin_burger_algorithm<A, F, Q, E, Ctrler>::gauss ()
00103 {
00104     index i, j;
00105 
00106     f.resize(n, n);
00107     e.resize(0, n);
00108 
00109     f.assign_eye(n);
00110     q = transpose(a);
00111 
00112     ctrler.preamble(a, f, q, e);
00113 
00114     ctrler.begin_gauss();
00115     movie_print3();
00116 
00117     /* main loop */
00118     i = 0;
00119     while(i < q.nrows())
00120     {
00121         /* find non-zero entry in the i-th row beginning from i-th entry */
00122         ctrler.find_non_zero(i);
00123         j = i;
00124 
00125         while(j < m)
00126         {
00127             if(!is_null(q(i, j)))break;
00128             j++;
00129         }
00130 
00131         if(j >= m)
00132         {
00133             /* it's a zero row */
00134             q.erase_row(i);
00135             e.insert_row(e.nrows(), f.take_row(i));
00136 
00137             ctrler.zero_row();
00138             movie_print3();
00139             continue; // main loop
00140         }
00141 
00142         if(i != j)
00143         {
00144             q.swap_cols(i, j);
00145             a.swap_rows(i, j);
00146 
00147             ctrler.swap_cols_rows(i, j);
00148             movie_print3();
00149         }
00150 
00151         if(is_negative(q(i, i)))
00152         {
00153             q.mult_row(i, -1);
00154             f.mult_row(i, -1);
00155         }
00156 
00157         // form zero column i
00158         QT b = q(i, i);
00159         index ii;
00160 
00161         for(ii = 0; ii < q.nrows(); ii++)
00162             if(ii != i)
00163             {
00164                 QT b_ii = q(ii, i);
00165                 QT alpha = gcd(b, b_ii);
00166                 QT b_i = b / alpha;
00167                 b_ii = -b_ii / alpha;
00168                 q.mult_row(ii, b_i);
00169                 q.addmult_rows(ii, i, b_ii);
00170                 f.mult_row(ii, b_i);
00171                 f.addmult_rows(ii, i, b_ii);
00172 
00173                 alpha = gcd(gcd(q.copy_row(ii)), gcd(f.copy_row(ii)));
00174 
00175                 //ctrler.stream
00176                 //  << "\nq.copy_row(ii) = " << q.copy_row(ii)
00177                 //  << "\ngcd(q.copy_row(ii)) = " << gcd(q.copy_row(ii))
00178                 //  << "\nf.copy_row(ii) = " << f.copy_row(ii)
00179                 //  << "\ngcd(f.copy_row(ii)) = " << gcd(f.copy_row(ii))
00180                 //  << "\nalpha = " << alpha << ", while i = " << i << " and ii = " << ii << "\n";
00181 
00182                 q.div_row(ii, alpha);
00183                 f.div_row(ii, alpha);
00184             }
00185 
00186         ctrler.eliminate_col(i);
00187         movie_print3();
00188         i++; //next row
00189     }
00190     ctrler.end_gauss();
00191 }
00192 
00193 
00194 template
00195 <
00196     typename A, typename F,
00197     typename Q, typename E,
00198     typename Ctrler
00199 >
00200 typename motzkin_burger_algorithm<A, F, Q, E, Ctrler>::index
00201 motzkin_burger_algorithm<A, F, Q, E, Ctrler>::fun (index j)
00202 {
00203     index plus = 0;
00204     index minus = 0;
00205 
00206     //the number of positive and negative entries in the j - th column
00207 
00208     for(index i = 0; i < current_ost; i++)
00209     {
00210         if(is_positive(q(i, j)))plus++;
00211         else if(is_negative(q(i, j)))minus++;
00212     }
00213 
00214     return plus * minus;    // WARNING!
00215 }
00216 
00217 
00218 template
00219 <
00220     typename A, typename F,
00221     typename Q, typename E,
00222     typename Ctrler
00223 >
00224 typename motzkin_burger_algorithm<A, F, Q, E, Ctrler>::index
00225 motzkin_burger_algorithm<A, F, Q, E, Ctrler>::min_modification ()
00226 {
00227     index min_column, jj, min_fun, cur_fun;
00228 
00229     /* the column with minimal product of the number of positive
00230     and the number of negative entries */
00231 
00232     min_column = current_column;
00233     min_fun = fun(min_column);
00234     for(jj = current_column + 1; jj < m; jj++)
00235     {
00236         cur_fun = fun(jj);
00237         if(cur_fun < min_fun)
00238         {
00239             min_column = jj;
00240             min_fun = cur_fun;
00241         }
00242     }
00243 
00244     return min_column;
00245 }
00246 
00247 
00248 template
00249 <
00250     typename A, typename F,
00251     typename Q, typename E,
00252     typename Ctrler
00253 >
00254 typename motzkin_burger_algorithm<A, F, Q, E, Ctrler>::index
00255 motzkin_burger_algorithm<A, F, Q, E, Ctrler>::max_modification ()
00256 {
00257     index max_column, jj, max_fun, cur_fun;
00258 
00259     /* the column with maximal product of the number of positive
00260     and the number of negative entries */
00261 
00262     max_column = current_column;
00263     max_fun = fun(max_column);
00264     for(jj = current_column + 1; jj < m; jj++)
00265     {
00266         cur_fun = fun(jj);
00267         if(cur_fun > max_fun)
00268         {
00269             max_column = jj;
00270             max_fun = cur_fun;
00271         }
00272     }
00273     return max_column;
00274 }
00275 
00276 
00277 template
00278 <
00279     typename A, typename F,
00280     typename Q, typename E,
00281     typename Ctrler
00282 >
00283 bool motzkin_burger_algorithm<A, F, Q, E, Ctrler>::reroof (index row)
00284 {
00285     for(index i = 0; i < common_zero.size(); i++)
00286     {
00287         index j = common_zero[i];
00288         if(!is_null(q(row, j)))return false;
00289     }
00290 
00291     return true;
00292 }
00293 
00294 
00295 template
00296 <
00297     typename A, typename F,
00298     typename Q, typename E,
00299     typename Ctrler
00300 >
00301 bool motzkin_burger_algorithm<A, F, Q, E, Ctrler>::balanced (index j_plus, index j_minus)
00302 {
00303     //fist we construct the set common_zero
00304     for(index j = 0; j < current_column; j++)
00305         if(is_null(q(j_plus, j)) && is_null(q(j_minus, j)))
00306             common_zero.push_back(j);
00307 
00308     if(common_zero.size()< r - 2)
00309         return false;   // number of common zeros is low
00310 
00311     // zeros intersection detection
00312     for(index row = 0; row < current_ost; row++)
00313         if
00314         (
00315             row != j_plus  &&
00316             row != j_minus  &&
00317             reroof(row)
00318         )
00319             return false;
00320 
00321     return true;
00322 }
00323 
00324 
00325 template
00326 <
00327     typename A, typename F,
00328     typename Q, typename E,
00329     typename Ctrler
00330 >
00331 void motzkin_burger_algorithm<A, F, Q, E, Ctrler>::run ()
00332 {
00333     m = a.nrows();
00334     n = a.ncols();
00335 
00336     gauss();    // ctrler.preamble is in gauss
00337 
00338     ctrler.begin_motzkin();
00339 
00340     movie_print3();
00341 
00342     r = n - e.nrows();
00343     current_column = r;
00344 
00345     while(current_column < a.nrows())
00346     {
00347         vector<index> j_minus, j_plus;
00348 
00349         //for each inequality from a, beginning from(r + 1) th
00350         current_ost = q.nrows();
00351 
00352         //taking a new inequality depends upon modification
00353         index new_column = select_column();
00354 
00355         ctrler.select_col(current_column, new_column);
00356 
00357         if(current_column != new_column)
00358         {
00359             q.swap_cols(current_column, new_column);
00360             a.swap_rows(current_column, new_column);
00361 
00362             ctrler.swap_cols_rows(current_column, new_column);
00363             movie_print3();
00364         }
00365 
00366         //now we are constructing the sets j_plus, j_minus
00367         for(index ii = 0; ii < current_ost; ii++)
00368         {
00369             if(is_negative(q(ii, current_column)))
00370                 j_minus.push_back(ii);
00371             else if(is_positive(q(ii, current_column)))
00372                 j_plus.push_back(ii);
00373         }
00374 
00375         if(j_minus.size() == current_ost)
00376         {
00377             //there is no solution except 0
00378             ctrler.zero_solution();
00379 
00380             f.resize(0, n);
00381             //e.resize(0, n);   // WARNING
00382             q.resize(0, m);
00383             ctrler.end_motzkin();
00384             ctrler.conclusion(a, f, q, e);
00385             return;
00386         }
00387 
00388         if(j_minus.size() == 0)
00389         {
00390             // this is corollary inequality
00391             ctrler.corollary_inequality();
00392 
00393             a.erase_row(current_column);
00394             q.erase_col(current_column);
00395             m--;
00396             continue; //new inequality
00397         }
00398 
00399         //cerr << "Current column: " << current_column
00400         //  << " ost: " << current_ost 
00401         //  << " J_plus: " << j_plus.ncols()
00402         //  << " J_minus: " << j_minus.ncols() << endl;
00403 
00404         ctrler.begin_row_balancing();
00405 
00406         for(index jj_m = 0; jj_m < j_minus.size(); jj_m++)
00407         {
00408             index j_m = j_minus[jj_m];
00409             for(index jj_p = 0; jj_p < j_plus.size(); jj_p++)
00410             {
00411                 index j_p = j_plus[jj_p];
00412                 common_zero.resize(0);
00413                 if(balanced(j_p, j_m))
00414                 {
00415                     ctrler.balanced_rows(j_p, j_m);
00416 
00417                     QT b_minus = q(j_m, current_column);
00418                     QT b_plus = q(j_p, current_column);
00419                     QT delta = gcd(b_minus, b_plus);
00420                     QT alpha_plus = -b_minus / delta;
00421                     QT alpha_minus = b_plus / delta;
00422                     
00423                     f.insert_row
00424                     (
00425                         f.nrows(),
00426                         f.copy_row(j_p)*alpha_plus + f.copy_row(j_m)*alpha_minus
00427                     );
00428 
00429                     q.insert_row
00430                     (
00431                         q.nrows(),
00432                         q.copy_row(j_p)*alpha_plus + q.copy_row(j_m)*alpha_minus
00433                     );
00434 
00435                     delta = gcd
00436                     (
00437                         gcd(f.copy_row(f.nrows() - 1)),
00438                         gcd(q.copy_row(q.nrows() - 1))
00439                     );
00440                     
00441                     f.div_row(f.nrows() - 1, delta);
00442                     q.div_row(q.nrows() - 1, delta);
00443 
00444                     //delta = gcd(gcd(f.row(f.nrows() - 1)), gcd(q.row(q.nrows() - 1)));
00445                     //delta = gcd(f.row(f.nrows() - 1));
00446                     //f.div_row(f.nrows() - 1, delta);
00447                     //q.div_row(q.nrows() - 1, delta);
00448                 }
00449             } //Iterate J_plus
00450         } //Iterate J_minus
00451 
00452         ctrler.end_row_balancing();
00453         movie_print3();
00454         ctrler.delete_negates();
00455 
00456         f.erase_rows(j_minus);
00457         q.erase_rows(j_minus);
00458 
00459         movie_print3();
00460 
00461         current_column++;
00462     }
00463 
00464     ctrler.end_motzkin();
00465     ctrler.conclusion(a, f, q, e);
00466 }
00467 
00468 }
00469 
00470 
00471 template
00472 <
00473     typename A, typename F,
00474     typename Q, typename E,
00475     typename Ctrler
00476 >
00477 void skeleton_motzkin_burger
00478 (
00479     A& a, F& f, Q& q, E& e,
00480     Ctrler ctrler
00481 )
00482 {
00483     _Internal::motzkin_burger_algorithm<A, F, Q, E, Ctrler>
00484         alg(a, f, q, e, ctrler, _Internal::mm_no_modification);
00485     alg.run();
00486 }
00487 
00488 
00489 template
00490 <
00491     typename A, typename F,
00492     typename Q, typename E,
00493     typename Ctrler
00494 >
00495 void skeleton_motzkin_burger_min
00496 (
00497     A& a, F& f, Q& q, E& e,
00498     Ctrler ctrler
00499 )
00500 {
00501     _Internal::motzkin_burger_algorithm<A, F, Q, E, Ctrler>
00502         alg(a, f, q, e, ctrler, _Internal::mm_min_modification);
00503     alg.run();
00504 }
00505 
00506 
00507 template
00508 <
00509     typename A, typename F,
00510     typename Q, typename E,
00511     typename Ctrler
00512 >
00513 void skeleton_motzkin_burger_max
00514 (
00515     A& a, F& f, Q& q, E& e,
00516     Ctrler ctrler
00517 )
00518 {
00519     _Internal::motzkin_burger_algorithm<A, F, Q, E, Ctrler>
00520         alg(a, f, q, e, ctrler, _Internal::mm_max_modification);
00521     alg.run();
00522 }
00523 
00524 
00525 template
00526 <
00527     typename A, typename F,
00528     typename Q, typename E
00529 >
00530 void integer_conv_motzkin_burger (A& a, F& f, Q& q, E& e)
00531 {
00532     A aa = a;
00533     skeleton_motzkin_burger(a, f, q, e);
00534     std::size_t not_integer = f.nrows();
00535     
00536     for(std::size_t i = 0; i < f.nrows(); ++i)
00537         if(!is_null(f(i, 0)) && !is_unit(f(i, 0)))
00538         {
00539             not_integer = i;
00540             break;
00541         }
00542 
00543 
00544 
00545     
00546 
00547 }
00548 
00549 
00550 
00551 } // namesapce Arageli
00552 
00553 
00554 #endif

Generated on Thu Aug 31 17:38:08 2006 for Arageli by  doxygen 1.4.7