00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00095
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
00118 i = 0;
00119 while(i < q.nrows())
00120 {
00121
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
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;
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
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
00176
00177
00178
00179
00180
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++;
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
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;
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
00230
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
00260
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
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;
00310
00311
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();
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
00350 current_ost = q.nrows();
00351
00352
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
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
00378 ctrler.zero_solution();
00379
00380 f.resize(0, n);
00381
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
00391 ctrler.corollary_inequality();
00392
00393 a.erase_row(current_column);
00394 q.erase_col(current_column);
00395 m--;
00396 continue;
00397 }
00398
00399
00400
00401
00402
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
00445
00446
00447
00448 }
00449 }
00450 }
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 }
00552
00553
00554 #endif