00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef _ARAGELI_SIMPLEX_METHOD_HPP_
00014 #define _ARAGELI_SIMPLEX_METHOD_HPP_
00015
00016
00025 #include "config.hpp"
00026
00027 #include <cstddef>
00028 #include <iostream>
00029 #include <iomanip>
00030 #include <algorithm>
00031
00032 #include "factory.hpp"
00033 #include "exception.hpp"
00034 #include "cmp.hpp"
00035 #include "vector.hpp"
00036 #include "matrix.hpp"
00037 #include "gauss.hpp"
00038
00039 #include "std_import.hpp"
00040
00041 namespace Arageli
00042 {
00043 namespace simplex_method
00044 {
00045
00046
00047
00049
00050
00052
00059 template <typename T1, bool REFCNT1, typename T2, bool REFCNT2>
00060 inline typename matrix<T1, REFCNT1>::size_type find_row_notallow
00061 (const matrix<T1, REFCNT1>& a, const vector<T2, REFCNT2>& basis)
00062 {
00063 for(std::size_t i = 0; i < basis.size(); ++i)
00064 {
00065 T2 j = basis[i];
00066 for(std::size_t r = 0; r < a.nrows(); ++r)
00067 if
00068 (!(
00069 (r == i+1 && is_unit(a(r, j))) ||
00070 is_null(a(r, j))
00071 ))
00072 return i;
00073 }
00074
00075 return basis.size();
00076 }
00077
00078
00080
00087 template <typename T1, bool REFCNT1, typename T2, bool REFCNT2>
00088 inline typename matrix<T1, REFCNT1>::size_type find_col_notallow
00089 (const matrix<T1, REFCNT1>& a, const vector<T2, REFCNT2>& nonbasis)
00090 {
00091 for(std::size_t i = 0; i < nonbasis.size(); ++i)
00092 {
00093 T2 j = nonbasis[i];
00094 for(std::size_t s = 0; s < a.ncols(); ++s)
00095 if
00096 (!(
00097 (s == i+1 && is_opposite_unit(a(j, s))) ||
00098 is_null(a(j, s))
00099 ))
00100 return i;
00101 }
00102
00103 return nonbasis.size();
00104 }
00105
00106
00107
00109
00111 template <typename T1, bool REFCNT1>
00112 inline typename matrix<T1, REFCNT1>::size_type find_primal_notallow
00113 (const matrix<T1, REFCNT1>& a)
00114 {
00115 ARAGELI_ASSERT_0(a.ncols() > 0);
00116
00117 for(std::size_t i = 1; i < a.nrows(); ++i)
00118 if(is_negative(a(i, 0)))return i;
00119 return a.nrows();
00120 }
00121
00122
00124
00126 template <typename T1, bool REFCNT1>
00127 inline typename matrix<T1, REFCNT1>::size_type find_dual_notallow
00128 (const matrix<T1, REFCNT1>& a)
00129 {
00130 ARAGELI_ASSERT_0(a.ncols() > 0);
00131
00132 return std::find_if
00133 (
00134 a.begin() + 1, a.begin() + a.ncols(),
00135 func::is_negative<T1>()
00136 ) - a.begin();
00137 }
00138
00140
00141
00143
00144
00146 template <typename T1, bool REFCNT1, typename T2, bool REFCNT2>
00147 inline bool is_row_allow
00148 (const matrix<T1, REFCNT1>& a, const vector<T2, REFCNT2>& basis)
00149 { return find_row_notallow(a, basis) == basis.size(); }
00150
00151
00153 template <typename T1, bool REFCNT1, typename T2, bool REFCNT2>
00154 inline bool is_col_allow
00155 (const matrix<T1, REFCNT1>& a, const vector<T2, REFCNT2>& nonbasis)
00156 { return find_col_notallow(a, nonbasis) == nonbasis.size(); }
00157
00158
00160 template <typename T1, bool REFCNT1>
00161 inline bool is_primal_allow
00162 (const matrix<T1, REFCNT1>& a)
00163 { return find_primal_notallow(a) == a.nrows(); }
00164
00165
00167 template <typename T1, bool REFCNT1>
00168 inline bool is_dual_allow
00169 (const matrix<T1, REFCNT1>& a)
00170 { return find_dual_notallow(a) == a.ncols(); }
00171
00173
00174
00176 enum result_kind
00177 {
00178 rk_found,
00179 rk_empty,
00180 rk_infinite,
00181 rk_nonoptimal
00182
00183 };
00184
00185
00186
00188
00189
00191 struct rule_s_primal_first
00192 {
00193 template <typename T_Q, bool REFCNT_Q, typename T_basis, bool REFCNT_basis>
00194 typename matrix<T_Q, REFCNT_Q>::size_type
00195 operator()
00196 (
00197 const matrix<T_Q, REFCNT_Q>& Q,
00198 const vector<T_basis, REFCNT_basis>& basis
00199 ) const
00200 { return find_dual_notallow(Q); }
00201 };
00202
00203
00205 struct rule_r_primal_first
00206 {
00207 template <typename T_Q, bool REFCNT_Q, typename T_basis, bool REFCNT_basis>
00208 typename matrix<T_Q, REFCNT_Q>::size_type
00209 operator()
00210 (
00211 const matrix<T_Q, REFCNT_Q>& Q,
00212 const vector<T_basis, REFCNT_basis>& basis,
00213 typename matrix<T_Q, REFCNT_Q>::size_type s
00214 ) const
00215 {
00216 ARAGELI_ASSERT_0(s > 0);
00217 ARAGELI_ASSERT_0(s < Q.ncols());
00218 ARAGELI_ASSERT_0(Q.nrows() > 0);
00219
00220 typedef typename matrix<T_Q, REFCNT_Q>::size_type size_type;
00221 size_type r = 1;
00222 for(; r < Q.nrows() && !is_positive(Q(r, s)); ++r);
00223 if(r == Q.nrows())return r;
00224
00225 T_Q min = Q(r, 0)/Q(r, s);
00226
00227 for(size_type i = r + 1; i < Q.nrows(); ++i)
00228 if(is_positive(Q(i, s)))
00229 {
00230 T_Q t = Q(i, 0)/Q(i, s);
00231 if(t < min)
00232 {
00233 min = t;
00234 r = i;
00235 }
00236 }
00237
00238 return r;
00239 }
00240 };
00241
00242
00244 struct rule_r_primal_lex
00245 {
00246 template <typename T_Q, bool REFCNT_Q, typename T_basis, bool REFCNT_basis>
00247 typename matrix<T_Q, REFCNT_Q>::size_type
00248 operator()
00249 (
00250 const matrix<T_Q, REFCNT_Q>& Q,
00251 const vector<T_basis, REFCNT_basis>& basis,
00252 typename matrix<T_Q, REFCNT_Q>::size_type s
00253 ) const
00254 {
00255 ARAGELI_ASSERT_0(s > 0);
00256 ARAGELI_ASSERT_0(s < Q.ncols());
00257 ARAGELI_ASSERT_0(Q.nrows() > 0);
00258
00259 typedef typename matrix<T_Q, REFCNT_Q>::size_type size_type;
00260 size_type r = 1;
00261 for(; r < Q.nrows() && !is_positive(Q(r, s)); ++r);
00262 if(r == Q.nrows())return r;
00263
00264 T_Q min = Q(r, 0)/Q(r, s);
00265
00266 for(size_type i = r + 1; i < Q.nrows(); ++i)
00267 if(is_positive(Q(i, s)))
00268 {
00269 T_Q t = Q(i, 0)/Q(i, s);
00270 if(t < min)
00271 {
00272 min = t;
00273 r = i;
00274 }
00275 else if(t == min)
00276 for(size_type j = 1; j < Q.ncols(); ++j)
00277 {
00278 t = Q(i, j)/Q(i, s);
00279
00280
00281
00282
00283 T_Q oldt = Q(r, j)/Q(r, s);
00284 if(t < oldt)
00285 {
00286 r = i;
00287 break;
00288 }
00289 else if(t > oldt)break;
00290 }
00291 }
00292
00293 return r;
00294 }
00295 };
00296
00297
00299 struct rule_r_dual_first
00300 {
00301 template <typename T_Q, bool REFCNT_Q, typename T_nonbasis, bool REFCNT_nonbasis>
00302 typename matrix<T_Q, REFCNT_Q>::size_type
00303 operator()
00304 (
00305 const matrix<T_Q, REFCNT_Q>& Q,
00306 const vector<T_nonbasis, REFCNT_nonbasis>& basis
00307 ) const
00308 { return find_primal_notallow(Q); }
00309 };
00310
00311
00313 struct rule_s_dual_first
00314 {
00315 template <typename T_Q, bool REFCNT_Q, typename T_nonbasis, bool REFCNT_nonbasis>
00316 typename matrix<T_Q, REFCNT_Q>::size_type
00317 operator()
00318 (
00319 const matrix<T_Q, REFCNT_Q>& Q,
00320 const vector<T_nonbasis, REFCNT_nonbasis>& basis,
00321 typename matrix<T_Q, REFCNT_Q>::size_type r
00322 ) const
00323 {
00324 ARAGELI_ASSERT_0(r > 0);
00325 ARAGELI_ASSERT_0(r < Q.nrows());
00326 ARAGELI_ASSERT_0(Q.ncols() > 0);
00327
00328 typedef typename matrix<T_Q, REFCNT_Q>::size_type size_type;
00329 size_type s = 1;
00330 for(; s < Q.ncols() && !is_negative(Q(r, s)); ++s);
00331 if(s == Q.ncols())return s;
00332
00333 T_Q max = Q(0, s)/Q(r, s);
00334
00335 for(size_type i = s + 1; i < Q.ncols(); ++i)
00336 if(is_negative(Q(r, i)))
00337 {
00338 T_Q t = Q(0, i)/Q(r, i);
00339 if(t > max)
00340 {
00341 max = t;
00342 s = i;
00343 }
00344 }
00345
00346 return s;
00347 }
00348 };
00349
00350
00351
00353
00354
00356
00361 template
00362 <
00363 typename T_q, bool REFCNT_q,
00364 typename T_basis, bool REFCNT_basis,
00365 typename T_pivot,
00366 typename Rule_s, typename Rule_r
00367 >
00368 result_kind primal_row_iter
00369 (
00370 matrix<T_q, REFCNT_q>& q,
00371 vector<T_basis, REFCNT_basis>& basis,
00372 T_pivot& prow,
00373 T_pivot& pcol,
00374 Rule_s rule_s,
00375 Rule_r rule_r
00376 )
00377 {
00378 ARAGELI_ASSERT_0(is_row_allow(q, basis));
00379 ARAGELI_ASSERT_0(is_primal_allow(q));
00380 typedef typename matrix<T_q, REFCNT_q>::size_type size_type;
00381
00382 size_type s = rule_s(q, basis);
00383 if(s == q.ncols())
00384 return rk_found;
00385 pcol = s;
00386 size_type r = rule_r(q, basis, s);
00387 if(r == q.nrows())
00388 return rk_infinite;
00389 prow = r;
00390 gauss_field_row_iter(q, r, s);
00391 basis[r-1] = s;
00392 return rk_nonoptimal;
00393 }
00394
00395
00397
00398 template
00399 <
00400 typename T_q, bool REFCNT_q,
00401 typename T_basis, bool REFCNT_basis
00402 >
00403 inline result_kind primal_row_iter
00404 (
00405 matrix<T_q, REFCNT_q>& q,
00406 vector<T_basis, REFCNT_basis>& basis
00407 )
00408 {
00409 typename matrix<T_q, REFCNT_q>::size_type t;
00410
00411 return primal_row_iter
00412 (
00413 q, basis, t, t,
00414 rule_s_primal_first(),
00415 rule_r_primal_lex()
00416 );
00417 }
00418
00419
00421
00422 template
00423 <
00424 typename T_q, bool REFCNT_q,
00425 typename T_basis, bool REFCNT_basis,
00426 typename Rule_s, typename Rule_r
00427 >
00428 inline result_kind primal_row_iter
00429 (
00430 matrix<T_q, REFCNT_q>& q,
00431 vector<T_basis, REFCNT_basis>& basis,
00432 Rule_s rule_s, Rule_r rule_r
00433 )
00434 {
00435 int t;
00436 return primal_row_iter(q, basis, t, t, rule_s, rule_r);
00437 }
00438
00439
00441
00443 template
00444 <
00445 typename T_q, bool REFCNT_q,
00446 typename T_basis, bool REFCNT_basis,
00447 typename T_pivot
00448 >
00449 inline result_kind primal_row_iter_pivotout
00450 (
00451 matrix<T_q, REFCNT_q>& q,
00452 vector<T_basis, REFCNT_basis>& basis,
00453 T_pivot& prow, T_pivot& pcol
00454 )
00455 {
00456 return primal_row_iter
00457 (
00458 q, basis, prow, pcol,
00459 rule_s_primal_first(),
00460 rule_r_primal_lex()
00461 );
00462 }
00463
00464
00465
00466 }
00467
00468 namespace ctrl
00469 {
00470 namespace simplex_method
00471 {
00472
00473 using namespace Arageli::simplex_method;
00474
00476 struct primal_row_iters_idler
00477 {
00478 class abort : public ctrl::abort {};
00479
00480 template <typename Q, typename Basis>
00481 void preamble (const Q& q, const Basis& basis) const {}
00482
00483 template <typename Q, typename Basis>
00484 void conclusion (const Q& q, const Basis& basis, result_kind rk) const {}
00485
00486 template <typename Q, typename Basis>
00487 void before_iter (const Q& q, const Basis& basis) const {}
00488
00489 template <typename Q, typename Basis, typename Pivot>
00490 void after_iter
00491 (
00492 const Q& q, const Basis& basis,
00493 Pivot prow, Pivot pcol,
00494 result_kind rk
00495 ) const {}
00496 };
00497
00498 }}
00499
00500
00501 namespace simplex_method
00502 {
00503
00505
00507 template
00508 <
00509 typename T_q, bool REFCNT_q,
00510 typename T_basis, bool REFCNT_basis,
00511 typename Rule_s, typename Rule_r,
00512 typename Ctrler
00513 >
00514 result_kind primal_row_iters
00515 (
00516 matrix<T_q, REFCNT_q>& q,
00517 vector<T_basis, REFCNT_basis>& basis,
00518 Rule_s rule_s, Rule_r rule_r,
00519 Ctrler ctrler
00520 )
00521 {
00522 ARAGELI_ASSERT_0(is_row_allow(q, basis));
00523 ARAGELI_ASSERT_0(is_primal_allow(q));
00524 typedef typename matrix<T_q, REFCNT_q>::size_type size_type;
00525 typedef vector<T_basis, REFCNT_basis> Basis;
00526
00527 ctrler.preamble(q, basis);
00528 result_kind res = rk_nonoptimal;
00529
00530
00531 ARAGELI_DEBUG_EXEC_2(std::list<Basis> bases);
00532
00533 while(res == rk_nonoptimal)
00534 {
00535 ARAGELI_ASSERT_2
00536 (
00537 std::find(bases.begin(), bases.end(), basis)
00538 == bases.end()
00539 );
00540
00541 ARAGELI_DEBUG_EXEC_2(bases.push_back(basis));
00542
00543 ctrler.before_iter(q, basis);
00544 size_type prow, pcol;
00545 res = primal_row_iter(q, basis, prow, pcol, rule_s, rule_r);
00546 ctrler.after_iter(q, basis, prow, pcol, res);
00547 }
00548
00549 ctrler.conclusion(q, basis, res);
00550 return res;
00551 }
00552
00553
00555
00556 template
00557 <
00558 typename T_q, bool REFCNT_q,
00559 typename T_basis, bool REFCNT_basis
00560 >
00561 inline result_kind primal_row_iters
00562 (
00563 matrix<T_q, REFCNT_q>& q,
00564 vector<T_basis, REFCNT_basis>& basis
00565 )
00566 {
00567 return primal_row_iters
00568 (
00569 q, basis,
00570 rule_s_primal_first(),
00571 rule_r_primal_lex(),
00572 ::Arageli::ctrl::simplex_method::primal_row_iters_idler()
00573 );
00574 }
00575
00576
00578
00579 template
00580 <
00581 typename T_q, bool REFCNT_q,
00582 typename T_basis, bool REFCNT_basis,
00583 typename Ctrler
00584 >
00585 inline result_kind primal_row_iters
00586 (
00587 matrix<T_q, REFCNT_q>& q,
00588 vector<T_basis, REFCNT_basis>& basis,
00589 Ctrler ctrler
00590 )
00591 {
00592 return primal_row_iters
00593 (
00594 q, basis,
00595 rule_s_primal_first(),
00596 rule_r_primal_lex(),
00597 ctrler
00598 );
00599 }
00600
00602
00603
00604 }
00605
00606
00607 namespace ctrl
00608 {
00609 namespace simplex_method
00610 {
00611
00613
00614
00615
00616
00618 struct primal_col_iter_idler
00619 {
00620 void preamble () const {}
00621 void conclusion () const {}
00622
00623 template <typename Q, typename Basis>
00624 void current_table (const Q& q, const Basis& basis) const {}
00625
00626 template <typename R, typename S>
00627 void pivot_item (const R& r, const S& s) const {}
00628
00629 void found () const {}
00630 void infinite () const {}
00631 void nonoptimal () const {}
00632 };
00633
00634
00636 template <typename Stream>
00637 struct primal_col_iter_slog
00638 {
00639 Stream& stream;
00640
00641 primal_col_iter_slog (Stream& stream_a)
00642 : stream(stream_a) {}
00643
00644 void preamble () const
00645 { stream << "Find pivot item.\n"; }
00646
00647 void conclusion () const
00648 {}
00649
00650 template <typename Q, typename Basis>
00651 void current_table (const Q& q, const Basis& basis) const
00652 {
00653 output_aligned(stream << "Q =\n", q);
00654 stream << "basis = " << basis << ".\n";
00655 }
00656
00657 template <typename R, typename S>
00658 void pivot_item (const R& r, const S& s) const
00659 { stream << "Pivot item: r = " << r << ", s = " << s << ".\n"; }
00660
00661 void found () const { stream << "The table is optimal.\n"; }
00662 void infinite () const { stream << "The function isn't limited.\n"; }
00663 void nonoptimal () const {}
00664 };
00665
00666 }}
00667
00668 namespace simplex_method
00669 {
00670 #if 0 // WARNING! TEMPORARY DISABLED!
00672
00674 template
00675 <
00676 typename T_Q, bool REFCNT_Q,
00677 typename T_nonbasis, bool REFCNT_nonbasis,
00678 typename Rule_s, typename Rule_r,
00679 typename Ctrler
00680 >
00681 result_kind primal_col_iter
00682 (
00683 matrix<T_Q, REFCNT_Q>& Q,
00684 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis,
00685 Rule_s rule_s, Rule_r rule_r,
00686 Ctrler ctrler
00687 )
00688 {
00689 ARAGELI_ASSERT_0(is_col_allow(Q, nonbasis));
00690 ARAGELI_ASSERT_0(is_primal_allow(Q));
00691 typedef typename matrix<T_Q, REFCNT_Q>::size_type size_type;
00692
00693 ctrler.preamble();
00694 ctrler.current_table(Q, nonbasis);
00695
00696 size_type s = rule_s(Q, nonbasis);
00697 if(s == Q.ncols())
00698 {
00699 ctrler.found();
00700 ctrler.conclusion();
00701 return rk_found;
00702 }
00703
00704 size_type r = rule_r(Q, nonbasis, s);
00705 if(r == Q.nrows())
00706 {
00707 ctrler.infinite();
00708 ctrler.conclusion();
00709 return rk_infinite;
00710 }
00711
00712 ctrler.pivot_item(r, s);
00713
00714 gauss_field_col_iter(Q, r, s);
00715
00716 for(std::size_t i = 0; i < Q.nrows(); ++i)
00717 opposite(&Q(i, s));
00718
00719 nonbasis[s-1] = r;
00720
00721 ctrler.nonoptimal();
00722 ctrler.conclusion();
00723
00724 return rk_nonoptimal;
00725 }
00726
00727
00729
00730 template
00731 <
00732 typename T_Q, bool REFCNT_Q,
00733 typename T_nonbasis, bool REFCNT_nonbasis
00734 >
00735 inline result_kind primal_col_iter
00736 (
00737 matrix<T_Q, REFCNT_Q>& Q,
00738 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis
00739 )
00740 {
00741 return primal_col_iter
00742 (
00743 Q, nonbasis, rule_s_primal_first(),
00744 rule_r_primal_first(), ::Arageli::ctrl::simplex_method::primal_col_iter_idler()
00745 );
00746 }
00747
00748
00750
00751 template
00752 <
00753 typename T_Q, bool REFCNT_Q,
00754 typename T_nonbasis, bool REFCNT_nonbasis,
00755 typename Rule_s, typename Rule_r
00756 >
00757 inline result_kind primal_col_iter
00758 (
00759 matrix<T_Q, REFCNT_Q>& Q,
00760 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis,
00761 Rule_s rule_s, Rule_r rule_r
00762 )
00763 {
00764 return primal_col_iter
00765 (
00766 Q, nonbasis, rule_s, rule_r,
00767 ::Arageli::ctrl::simplex_method::primal_row_iter_idler()
00768 );
00769 }
00770
00771 #endif
00772
00773
00774
00775
00776 }
00777
00778 namespace ctrl
00779 {
00780 namespace simplex_method
00781 {
00782
00784 struct primal_col_iters_idler
00785 {
00786 void preamble () const {}
00787 void conclusion () const {}
00788
00789 primal_col_iter_idler iter_ctrl () const
00790 { return primal_col_iter_idler(); }
00791
00792 template <typename TQ, typename Tb>
00793 bool stop (const TQ&, const Tb&) const { return false; }
00794 };
00795
00796
00797 }}
00798
00799 namespace simplex_method
00800 {
00801
00802
00804
00806 template
00807 <
00808 typename T_Q, bool REFCNT_Q,
00809 typename T_nonbasis, bool REFCNT_nonbasis,
00810 typename Rule_s, typename Rule_r,
00811 typename Ctrler
00812 >
00813 result_kind primal_col_iters
00814 (
00815 matrix<T_Q, REFCNT_Q>& Q,
00816 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis,
00817 Rule_s rule_s, Rule_r rule_r,
00818 Ctrler ctrler
00819 )
00820 {
00821 ARAGELI_ASSERT_0(is_col_allow(Q, nonbasis));
00822 ARAGELI_ASSERT_0(is_primal_allow(Q));
00823 typedef typename matrix<T_Q, REFCNT_Q>::size_type size_type;
00824
00825 ctrler.preamble();
00826 result_kind res = rk_nonoptimal;
00827
00828 while(res == rk_nonoptimal && !ctrler.stop(Q, nonbasis))
00829 res = primal_col_iter(Q, nonbasis, rule_s, rule_r, ctrler.iter_ctrl());
00830
00831 ctrler.conclusion();
00832 return res;
00833 }
00834
00835
00837
00838 template
00839 <
00840 typename T_Q, bool REFCNT_Q,
00841 typename T_nonbasis, bool REFCNT_nonbasis
00842 >
00843 inline result_kind primal_col_iters
00844 (
00845 matrix<T_Q, REFCNT_Q>& Q,
00846 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis
00847 )
00848 {
00849 return primal_col_iters
00850 (
00851 Q, nonbasis, rule_s_primal_first(), rule_r_primal_first(),
00852 ::Arageli::ctrl::simplex_method::primal_col_iters_idler()
00853 );
00854 }
00855
00857
00858
00861
00863
00864 }
00865
00866 namespace ctrl
00867 {
00868 namespace simplex_method
00869 {
00870
00872 struct dual_col_iter_idler
00873 {
00874 void preamble () const {}
00875 void conclusion () const {}
00876
00877 template <typename Q, typename Nonbasis>
00878 void current_table (const Q& q, const Nonbasis& nonbasis) const {}
00879
00880 template <typename R, typename S>
00881 void pivot_item (const R& r, const S& s) const {}
00882
00883 void found () const {}
00884 void infinite () const {}
00885 void nonoptimal () const {}
00886 void empty () const {}
00887 };
00888
00889
00891 template <typename Stream>
00892 struct dual_col_iter_slog : public dual_col_iter_idler
00893 {
00894 Stream& stream;
00895
00896 dual_col_iter_slog (Stream& stream_a)
00897 : stream(stream_a) {}
00898
00899 void preamble () const
00900 { stream << "Find pivot item.\n"; }
00901
00902 void conclusion () const
00903 {}
00904
00905 template <typename Q, typename Nonbasis>
00906 void current_table (const Q& q, const Nonbasis& nonbasis) const
00907 {
00908 output_aligned(stream << "Q =\n", q);
00909 stream << "nonbasis = " << nonbasis << ".\n";
00910 }
00911
00912 template <typename R, typename S>
00913 void pivot_item (const R& r, const S& s) const
00914 { stream << "Pivot item: r = " << r << ", s = " << s << ".\n"; }
00915
00916 void found () const { stream << "The table is optimal.\n"; }
00917 void infinite () const { stream << "The function isn't limited.\n"; }
00918 void nonoptimal () const {}
00919 void empty () const { stream << "Set of allowable vectors is empty."; }
00920 };
00921
00922 }}
00923
00924 namespace simplex_method
00925 {
00926
00928
00930 template
00931 <
00932 typename T_Q, bool REFCNT_Q,
00933 typename T_nonbasis, bool REFCNT_nonbasis,
00934 typename Rule_s, typename Rule_r,
00935 typename Ctrler
00936 >
00937 result_kind dual_col_iter
00938 (
00939 matrix<T_Q, REFCNT_Q>& Q,
00940 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis,
00941 Rule_s rule_s, Rule_r rule_r,
00942 Ctrler ctrler
00943 )
00944 {
00945 ARAGELI_ASSERT_0(is_col_allow(Q, nonbasis));
00946 ARAGELI_ASSERT_0(is_dual_allow(Q));
00947 typedef typename matrix<T_Q, REFCNT_Q>::size_type size_type;
00948
00949 ctrler.preamble();
00950 ctrler.current_table(Q, nonbasis);
00951
00952 size_type r = rule_r(Q, nonbasis);
00953 if(r == Q.nrows())
00954 {
00955 ctrler.found();
00956 ctrler.conclusion();
00957 return rk_found;
00958 }
00959
00960 size_type s = rule_s(Q, nonbasis, r);
00961 if(s == Q.ncols())
00962 {
00963 ctrler.empty();
00964 ctrler.conclusion();
00965 return rk_empty;
00966 }
00967
00968 ctrler.pivot_item(r, s);
00969
00970 gauss_field_col_iter(Q, r, s);
00971 for(std::size_t i = 0; i < Q.nrows(); ++i)
00972 opposite(&Q(i, s));
00973
00974 nonbasis[s-1] = r;
00975
00976 ctrler.nonoptimal();
00977 ctrler.conclusion();
00978
00979 return rk_nonoptimal;
00980 }
00981
00982
00984
00985 template
00986 <
00987 typename T_Q, bool REFCNT_Q,
00988 typename T_nonbasis, bool REFCNT_nonbasis
00989 >
00990 inline result_kind dual_col_iter
00991 (
00992 matrix<T_Q, REFCNT_Q>& Q,
00993 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis
00994 )
00995 {
00996 return dual_col_iter
00997 (
00998 Q, nonbasis, rule_s_dual_first(),
00999 rule_r_dual_first(), ::Arageli::ctrl::simplex_method::dual_col_iter_idler()
01000 );
01001 }
01002
01003
01005
01006 template
01007 <
01008 typename T_Q, bool REFCNT_Q,
01009 typename T_nonbasis, bool REFCNT_nonbasis,
01010 typename Rule_s, typename Rule_r
01011 >
01012 inline result_kind dual_col_iter
01013 (
01014 matrix<T_Q, REFCNT_Q>& Q,
01015 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis,
01016 Rule_s rule_s, Rule_r rule_r
01017 )
01018 {
01019 return dual_col_iter
01020 (
01021 Q, nonbasis, rule_s, rule_r,
01022 ::Arageli::ctrl::simplex_method::dual_col_iter_idler()
01023 );
01024 }
01025
01026
01027
01028 }
01029
01030 namespace ctrl
01031 {
01032 namespace simplex_method
01033 {
01034
01035
01037 struct dual_col_iters_idler
01038 {
01039 void preamble () const {}
01040 void conclusion () const {}
01041
01042 dual_col_iter_idler iter_ctrl () const
01043 { return dual_col_iter_idler(); }
01044
01045 template <typename TQ, typename Tb>
01046 bool stop (const TQ&, const Tb&) const { return false; }
01047 };
01048
01049
01050 }}
01051
01052 namespace simplex_method
01053 {
01054
01055
01057
01059 template
01060 <
01061 typename T_Q, bool REFCNT_Q,
01062 typename T_nonbasis, bool REFCNT_nonbasis,
01063 typename Rule_s, typename Rule_r,
01064 typename Ctrler
01065 >
01066 result_kind dual_col_iters
01067 (
01068 matrix<T_Q, REFCNT_Q>& Q,
01069 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis,
01070 Rule_s rule_s, Rule_r rule_r,
01071 Ctrler ctrler
01072 )
01073 {
01074 ARAGELI_ASSERT_0(is_col_allow(Q, nonbasis));
01075 ARAGELI_ASSERT_0(is_dual_allow(Q));
01076 typedef typename matrix<T_Q, REFCNT_Q>::size_type size_type;
01077
01078 ctrler.preamble();
01079 result_kind res = rk_nonoptimal;
01080
01081 while(res == rk_nonoptimal && !ctrler.stop(Q, nonbasis))
01082 res = dual_col_iter(Q, nonbasis, rule_s, rule_r, ctrler.iter_ctrl());
01083
01084 ctrler.conclusion();
01085 return res;
01086 }
01087
01088
01090
01092 template
01093 <
01094 typename T_q, bool REFCNT_q,
01095 typename T_nonbasis, bool REFCNT_nonbasis,
01096 typename Ctrler
01097 >
01098 inline result_kind dual_col_iters
01099 (
01100 matrix<T_q, REFCNT_q>& q,
01101 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis,
01102 Ctrler ctrler
01103 )
01104 {
01105 return dual_col_iters
01106 (
01107 q, nonbasis,
01108 rule_s_dual_first(),
01109 rule_r_dual_first(),
01110 ctrler
01111 );
01112 }
01113
01114
01116
01117 template
01118 <
01119 typename T_q, bool REFCNT_q,
01120 typename T_nonbasis, bool REFCNT_nonbasis
01121 >
01122 inline result_kind dual_col_iters
01123 (
01124 matrix<T_q, REFCNT_q>& q,
01125 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis
01126 )
01127 {
01128 return dual_col_iters
01129 (
01130 q, nonbasis,
01131 rule_s_dual_first(), rule_r_dual_first(),
01132 ::Arageli::ctrl::simplex_method::dual_col_iters_idler()
01133 );
01134 }
01135
01137
01138
01140
01141
01143
01144 template <typename T1, bool REFCNT1, typename T2, bool REFCNT2>
01145 void artificial_basis_create (matrix<T1, REFCNT1>& a, vector<T2, REFCNT2>& basis)
01146 {
01147 ARAGELI_ASSERT_0(!a.is_empty());
01148
01149 T1& pattern = a(0, 0);
01150 std::fill_n(a.begin(), a.ncols(), null(pattern));
01151
01152 for(std::size_t i = 1; i < a.nrows(); ++i)
01153 a.sub_rows(0, i);
01154
01155
01156 a.insert_cols(1, a.nrows() - 1, null<T1>(pattern));
01157
01158 basis.resize(a.nrows() - 1);
01159
01160 for(std::size_t i = 1; i <= a.nrows() - 1; ++i)
01161 {
01162 a(i, i) = unit<T1>(pattern);
01163 basis[i-1] = i;
01164 }
01165 }
01166
01167 }
01168
01169 namespace ctrl
01170 {
01171 namespace simplex_method
01172 {
01173
01174
01175
01176
01178 struct basis_create_by_artificial_idler
01179 {
01180 class abort : public ctrl::abort {};
01181
01182 template <typename Q, typename Basis>
01183 void preamble (const Q& q, const Basis& basis) const {}
01184
01185 template <typename Q, typename Basis>
01186 void conclusion (const Q& q, const Basis& basis) const {}
01187
01188 template <typename Q, typename Basis, typename Index>
01189 void artif_in_basis
01190 (const Q& q, const Basis& basis, const Index& index) const {}
01191
01192 template <typename I>
01193 void negligible_row (const I& i) const {}
01194
01195 template <typename Q, typename Basis, typename Index>
01196 void replace_basis_item
01197 (
01198 const Q& q, const Basis& basis,
01199 const Index& iold, const Index& r, const Index& inew
01200 ) const {}
01201
01202 template <typename Q, typename Basis>
01203 void before_erase_artif (const Q& q, const Basis& basis) const {}
01204 };
01205
01206
01207 }}
01208
01209 namespace simplex_method
01210 {
01211
01213
01214 template
01215 <
01216 typename T1, bool REFCNT1,
01217 typename T2, bool REFCNT2,
01218 typename Ctrler
01219 >
01220 void basis_create_by_artificial
01221 (
01222 matrix<T1, REFCNT1>& q,
01223 vector<T2, REFCNT2>& basis,
01224 Ctrler ctrler
01225 )
01226 {
01227 ARAGELI_ASSERT_0(!q.is_empty());
01228 ARAGELI_ASSERT_0(is_null(q(0, 0)));
01229 ARAGELI_ASSERT_0(is_row_allow(q, basis));
01230 ARAGELI_ASSERT_0(is_primal_allow(q));
01231 ARAGELI_ASSERT_0(is_dual_allow(q));
01232
01233 ctrler.preamble(q, basis);
01234
01235 std::size_t m = q.nrows();
01236
01237 for(std::size_t i = 0; i < basis.size(); ++i)
01238 {
01239 ARAGELI_ASSERT_0(is_positive(basis[i]));
01240
01241 if(basis[i] < m)
01242 {
01243 std::size_t r = i+1;
01244 ctrler.artif_in_basis(q, basis, i);
01245
01246 ARAGELI_ASSERT_0(is_null(q(r, 0)));
01247 std::size_t j;
01248 for(j = m; j < q.ncols(); ++j)
01249 if(!is_null(q(r, j)))break;
01250
01251 if(j == q.ncols())
01252 {
01253
01254 ctrler.negligible_row(r);
01255 q.erase_row(r);
01256 basis.erase(i);
01257 }
01258 else
01259 {
01260 ctrler.replace_basis_item(q, basis, i, r, j);
01261 gauss_field_row_iter(q, r, j);
01262 basis[i] = j;
01263 }
01264 }
01265 }
01266
01267 ctrler.before_erase_artif(q, basis);
01268
01269 q.erase_cols(1, m-1);
01270 basis -= m-1;
01271 ctrler.conclusion(q, basis);
01272 }
01273
01274
01276
01277 template <typename T1, bool REFCNT1, typename T2, bool REFCNT2>
01278 inline void basis_create_by_artificial
01279 (
01280 matrix<T1, REFCNT1>& a,
01281 vector<T2, REFCNT2>& basis
01282 )
01283 {
01284 return basis_create_by_artificial
01285 (a, basis, ::Arageli::ctrl::simplex_method::basis_create_by_artificial_idler());
01286 }
01287
01288 }
01289
01290 namespace ctrl
01291 {
01292 namespace simplex_method
01293 {
01294 using namespace Arageli::simplex_method;
01295
01297 struct basis_artificial_idler
01298 {
01299 class abort : public ctrl::abort {};
01300
01301 template <typename Q>
01302 void preamble (const Q& q) const {}
01303
01304 template <typename Q, typename Basis>
01305 void conclusion (const Q& q, const Basis& basis, result_kind rk) const {}
01306
01307 primal_row_iters_idler ctrl_primal_row_iters () const
01308 { return primal_row_iters_idler(); }
01309
01310 basis_create_by_artificial_idler ctrl_basis_create_by_artificial () const
01311 { return basis_create_by_artificial_idler(); }
01312
01313 template <typename Q, typename Basis>
01314 void after_artif (const Q& q, const Basis& basis) const {}
01315
01316 template <typename Q, typename Basis>
01317 void after_iters (const Q& q, const Basis& basis) const {}
01318
01319 template <typename Q, typename Basis>
01320 void before_orig (const Q& q, const Basis& basis) const {}
01321
01322 template <typename Q, typename Basis>
01323 void after_orig (const Q& q, const Basis& basis) const {}
01324 };
01325
01326
01327 }
01328 }
01329
01330 namespace simplex_method
01331 {
01332
01333
01335
01336 template
01337 <
01338 typename T1, bool REFCNT1,
01339 typename T3, bool REFCNT3,
01340 typename Rule_s, typename Rule_r,
01341 typename Ctrler
01342 >
01343 result_kind basis_artificial
01344 (
01345 matrix<T1, REFCNT1>& q,
01346 vector<T3, REFCNT3>& basis,
01347 Rule_s rule_s, Rule_r rule_r,
01348 Ctrler ctrler
01349 )
01350 {
01351 ARAGELI_ASSERT_0(is_primal_allow(q));
01352
01353 ctrler.preamble(q);
01354 artificial_basis_create(q, basis);
01355 ctrler.after_artif(q, basis);
01356
01357 result_kind rk = primal_row_iters
01358 (
01359 q, basis, rule_s, rule_r,
01360 ctrler.ctrl_primal_row_iters()
01361 );
01362
01363 ARAGELI_ASSERT_1(rk == rk_found);
01364
01365 ctrler.after_iters(q, basis);
01366
01367 if(!is_null(q(0, 0)))
01368 rk = rk_empty;
01369 else
01370 {
01371 basis_create_by_artificial
01372 (
01373 q, basis,
01374 ctrler.ctrl_basis_create_by_artificial()
01375 );
01376
01377 ctrler.after_orig(q, basis);
01378 rk = rk_found;
01379 }
01380
01381 ARAGELI_ASSERT_1(is_primal_allow(q));
01382
01383 ctrler.conclusion(q, basis, rk);
01384 return rk;
01385 }
01386
01387
01389
01390 template
01391 <
01392 typename T1, bool REFCNT1,
01393 typename T3, bool REFCNT3,
01394 typename Ctrler
01395 >
01396 inline result_kind basis_artificial
01397 (
01398 matrix<T1, REFCNT1>& q,
01399 vector<T3, REFCNT3>& basis,
01400 Ctrler ctrler
01401 )
01402 {
01403 return basis_artificial
01404 (
01405 q, basis,
01406 rule_s_primal_first(),
01407 rule_r_primal_lex(),
01408 ctrler
01409 );
01410 }
01411
01412
01414
01415 template
01416 <
01417 typename T1, bool REFCNT1,
01418 typename T3, bool REFCNT3
01419 >
01420 inline result_kind basis_artificial
01421 (
01422 matrix<T1, REFCNT1>& q,
01423 vector<T3, REFCNT3>& basis
01424 )
01425 {
01426 return basis_artificial
01427 (
01428 q, basis,
01429 rule_s_primal_first(),
01430 rule_r_primal_lex(),
01431 ::Arageli::ctrl::simplex_method::basis_artificial_idler()
01432 );
01433 }
01434
01435
01437
01438
01439
01441
01442 }
01443
01444 namespace ctrl
01445 {
01446 namespace simplex_method
01447 {
01448
01450 struct primal_row_with_artificial_basis_idler
01451 {
01452 void preamble () const {}
01453
01454 template <typename A, typename B, typename C>
01455 void input_data (const A& a, const B& b, const C& c) const {}
01456
01457 template <typename T>
01458 void table_for_artificial (const T& table) const {}
01459
01460 template <typename T, typename B>
01461 void artificial_table (const T& table, const B& basis) const {}
01462
01463 primal_row_iters_idler ctrl_for_artificial () const
01464 { return primal_row_iters_idler(); }
01465
01466 template <typename T, typename B>
01467 void optimal_artificial_table (const T& table, const B& basis) const {}
01468
01469 basis_create_by_artificial_idler
01470 ctrl_for_basis_create_by_artificial () const
01471 { return basis_create_by_artificial_idler(); }
01472
01473 template <typename T>
01474 void first_table (const T& table) const {}
01475
01476 template <typename T>
01477 void pre_first_table (const T& table) const {}
01478
01479 primal_row_iters_idler ctrl_for_main_row_iters () const
01480 { return primal_row_iters_idler(); }
01481
01482 void result (result_kind rk) const {}
01483
01484 void conclusion () const {}
01485 };
01486
01487 }}
01488
01489 namespace simplex_method
01490 {
01491
01492
01494
01495 template
01496 <
01497 typename T1, bool REFCNT1,
01498 typename T2, bool REFCNT2,
01499 typename T3, bool REFCNT3
01500 >
01501 void row_table_create
01502 (
01503 const matrix<T1, REFCNT1>& a,
01504 const vector<T2, REFCNT2>& b,
01505 matrix<T3, REFCNT3>& q
01506 )
01507 {
01508 ARAGELI_ASSERT_0(b.size() == a.nrows());
01509 q.assign_fromsize(a.nrows() + 1, a.ncols() + 1);
01510
01511 for(std::size_t i = 1; i < q.nrows(); ++i)
01512 {
01513 q(i, 0) = b[i-1];
01514 for(std::size_t j = 1; j < q.ncols(); ++j)
01515 q(i, j) = a(i-1, j-1);
01516 }
01517 }
01518
01519
01520 template
01521 <
01522 typename T1, bool REFCNT1,
01523 typename T2, bool REFCNT2
01524 >
01525 void row_table_place_c
01526 (
01527 const vector<T1, REFCNT1>& c,
01528 matrix<T2, REFCNT2>& q
01529 )
01530 {
01531 ARAGELI_ASSERT_0(c.size() == q.ncols() - 1);
01532
01533 for(std::size_t j = 1; j < q.ncols(); ++j)
01534 q(0, j) = -c[j-1];
01535 }
01536
01537
01538 template
01539 <
01540 typename T1, bool REFCNT1,
01541 typename T2, bool REFCNT2
01542 >
01543 void row_table_extract_c
01544 (
01545 vector<T1, REFCNT1>& c,
01546 const matrix<T2, REFCNT2>& q
01547 )
01548 {
01549 c.resize(q.ncols() - 1);
01550
01551 for(std::size_t j = 1; j < q.ncols(); ++j)
01552 c[j-1] = -q(0, j);
01553 }
01554
01555
01556 template
01557 <
01558 typename T1, bool REFCNT1,
01559 typename T2, bool REFCNT2
01560 >
01561 void row_table_pivot_basis_c
01562 (
01563 matrix<T1, REFCNT1>& q,
01564 const vector<T2, REFCNT2>& basis
01565 )
01566 {
01567 for(std::size_t i = 0; i < basis.size(); ++i)
01568 q.addmult_rows(0, i+1, -q(0, basis[i]));
01569 }
01570
01571
01572 template
01573 <
01574 typename T1, bool REFCNT1,
01575 typename T2, bool REFCNT2,
01576 typename T3, bool REFCNT3
01577 >
01578 void row_table_extract_solution
01579 (
01580 const matrix<T1, REFCNT1>& q,
01581 const vector<T2, REFCNT2>& basis,
01582 vector<T3, REFCNT3>& x
01583 )
01584 {
01585 x.assign(q.ncols()-1, null(q(0, 0)));
01586 for(std::size_t i = 0; i < basis.size(); ++i)
01587 x[basis[i]-1] = q(i+1, 0);
01588 }
01589
01590
01591 template
01592 <
01593 typename T1, bool REFCNT1,
01594 typename N,
01595 typename T2, bool REFCNT2
01596 >
01597 void col_table_extract_solution
01598 (
01599 const matrix<T1, REFCNT1>& t,
01600 const N& n,
01601 vector<T2, REFCNT2>& x
01602 )
01603 {
01604 x.resize(n);
01605 for(std::size_t i = 0; i < n; ++i)
01606 x[i] = t(i+1, 0);
01607 }
01608
01609
01611
01612 template
01613 <
01614 typename T1, bool REFCNT1,
01615 typename T2, bool REFCNT2,
01616 typename T3, bool REFCNT3,
01617 typename T4, bool REFCNT4
01618 >
01619 void row_table_create
01620 (
01621 const matrix<T1, REFCNT1>& a,
01622 const vector<T2, REFCNT2>& b,
01623 const vector<T3, REFCNT3>& c,
01624 matrix<T4, REFCNT4>& q
01625 )
01626 {
01627 ARAGELI_ASSERT_0(c.size() == a.ncols());
01628 row_table_create(a, b, q);
01629 row_table_place_c(c, q);
01630 }
01631
01632
01634
01635 template
01636 <
01637 typename T1, bool REFCNT1,
01638 typename T2, bool REFCNT2,
01639 typename T4, bool REFCNT4
01640 >
01641 void row_table_split
01642 (
01643 matrix<T1, REFCNT1>& a,
01644 vector<T2, REFCNT2>& b,
01645 const matrix<T4, REFCNT4>& q
01646 )
01647 {
01648 ARAGELI_ASSERT_0(!q.is_empty());
01649
01650 a.assign_fromsize(q.nrows() - 1, q.ncols() - 1);
01651 b.resize(a.nrows());
01652
01653 for(std::size_t i = 1; i < q.nrows(); ++i)
01654 {
01655 b[i-1] = q(i, 0);
01656 for(std::size_t j = 1; j < q.ncols(); ++j)
01657 a(i-1, j-1) = q(i, j);
01658 }
01659 }
01660
01661
01663
01664 template
01665 <
01666 typename T1, bool REFCNT1,
01667 typename T2, bool REFCNT2,
01668 typename T3, bool REFCNT3,
01669 typename T4, bool REFCNT4
01670 >
01671 void row_table_split
01672 (
01673 matrix<T1, REFCNT1>& a,
01674 vector<T2, REFCNT2>& b,
01675 const vector<T3, REFCNT3>& c,
01676 const matrix<T4, REFCNT4>& q
01677 )
01678 {
01679 ARAGELI_ASSERT_0(!q.is_empty());
01680
01681 row_table_split(a, b, q);
01682 c.resize(a.ncols());
01683
01684 }
01685
01686
01688
01690 template
01691 <
01692 typename T1, bool REFCNT1,
01693 typename T2, bool REFCNT2,
01694 typename T3, bool REFCNT3,
01695 typename T4, bool REFCNT4,
01696 typename T5, bool REFCNT5
01697 >
01698 void col_table_create_by_standard
01699 (
01700 const matrix<T1, REFCNT1>& a,
01701 const vector<T2, REFCNT2>& b,
01702 const vector<T3, REFCNT3>& c,
01703 matrix<T4, REFCNT4>& t,
01704 vector<T5, REFCNT5>& nonbasis
01705 )
01706 {
01707 t.assign_fromsize(a.ncols() + a.nrows() + 1, a.ncols() + 1);
01708 typedef typename matrix<T1, REFCNT1>::size_type size_type;
01709
01710 t(0, 0) = null(a(0, 0));
01711 const T4& tnull = t(0, 0);
01712
01713 nonbasis.resize(a.ncols());
01714 for(size_type i = 1; i <= a.ncols(); ++i)
01715 {
01716 t(i, 0) = tnull;
01717 nonbasis[i-1] = i;
01718 }
01719
01720 for(size_type i = a.ncols() + 1; i < t.nrows(); ++i)
01721 t(i, 0) = b[i - a.ncols() - 1];
01722
01723 for(size_type j = 0; j < a.ncols(); ++j)
01724 {
01725 t(0, j+1) = -c[j];
01726 t(j+1, j+1) = opposite_unit(tnull);
01727
01728 for(size_type i = a.ncols() + 1; i < t.nrows(); ++i)
01729 t(i, j+1) = a(i - a.ncols() - 1, j);
01730 }
01731 }
01732
01733
01735 template
01736 <
01737 typename Ta, bool REFCNTa,
01738 typename Tb, bool REFCNTb,
01739 typename Tc, bool REFCNTc,
01740 typename Tx, bool REFCNTx,
01741 typename Tbasis, bool REFCNTbasis,
01742 typename Tres,
01743 typename Rule_s, typename Rule_r,
01744 typename Ctrler
01745 >
01746 result_kind primal_row_with_artificial_basis
01747 (
01748 const matrix<Ta, REFCNTa>& a,
01749 const vector<Tb, REFCNTb>& b,
01750 const vector<Tc, REFCNTc>& c,
01751 vector<Tx, REFCNTx>& basis_x,
01752 vector<Tbasis, REFCNTbasis>& basis,
01753 Tres& res,
01754 Rule_s rule_s, Rule_r rule_r,
01755 Ctrler ctrler
01756 )
01757 {
01758 ARAGELI_ASSERT_0(a.nrows() == b.size());
01759 ARAGELI_ASSERT_0(a.ncols() == c.size());
01760 ARAGELI_ASSERT_0(!a.is_empty());
01761
01762 ctrler.preamble();
01763 ctrler.input_data(a, b, c);
01764
01765
01766
01767 matrix<Ta, false> table;
01768 row_table_create(a, b, table);
01769
01770 ctrler.table_for_artificial(table);
01771
01772
01773
01774 artificial_basis_create(table, basis);
01775
01776 ctrler.artificial_table(table, basis);
01777
01778 result_kind rk = primal_row_iters
01779 (table, basis, rule_s, rule_r, ctrler.ctrl_for_artificial());
01780
01781 ctrler.optimal_artificial_table(table, basis);
01782
01783 ARAGELI_ASSERT_1(rk == rk_found);
01784
01785 if(is_negative(table(0, 0)))
01786 {
01787 ctrler.result(rk_empty);
01788 ctrler.conclusion();
01789 return rk_empty;
01790 }
01791
01792 ARAGELI_ASSERT_1(is_null(table(0, 0)));
01793
01794
01795
01796 basis_create_by_artificial
01797 (table, basis, ctrler.ctrl_for_basis_create_by_artificial());
01798
01799
01800
01801 row_table_place_c(c, table);
01802 ctrler.pre_first_table(table);
01803 row_table_pivot_basis_c(table, basis);
01804
01805 rk = primal_row_iters
01806 (table, basis, rule_s, rule_r, ctrler.ctrl_for_main_row_iters());
01807
01808 if(rk == rk_found)
01809 {
01810 basis_x.resize(basis.size());
01811 for(std::size_t i = 0; i < basis.size(); ++i)
01812 basis_x[i] = table(i+1, 0);
01813 res = table(0, 0);
01814
01815 output_aligned(std::cout << "\n\nrk_found:\n", table);
01816
01817 }
01818
01819 ctrler.result(rk);
01820 ctrler.conclusion();
01821 return rk;
01822 }
01823
01824
01826
01827 template
01828 <
01829 typename Ta, bool REFCNTa,
01830 typename Tb, bool REFCNTb,
01831 typename Tc, bool REFCNTc,
01832 typename Tx, bool REFCNTx,
01833 typename Tbasis, bool REFCNTbasis,
01834 typename Tres
01835 >
01836 inline result_kind primal_row_with_artificial_basis
01837 (
01838 const matrix<Ta, REFCNTa>& a,
01839 const vector<Tb, REFCNTb>& b,
01840 const vector<Tc, REFCNTc>& c,
01841 vector<Tx, REFCNTx>& basis_x,
01842 vector<Tbasis, REFCNTbasis>& basis,
01843 Tres& res
01844 )
01845 {
01846 return primal_row_with_artificial_basis
01847 (
01848 a, b, c, basis_x, basis, res,
01849 rule_s_primal_first(), rule_r_primal_lex(),
01850 ::Arageli::ctrl::simplex_method::primal_row_with_artificial_basis_idler()
01851 );
01852 }
01853
01855
01856
01857
01859 template
01860 <
01861 typename T1, bool REFCNT1,
01862 typename T2, bool REFCNT2
01863 >
01864 void basis_to_nonbasis
01865 (
01866 const vector<T1, REFCNT1>& basis,
01867 vector<T2, REFCNT2>& nonbasis,
01868 std::size_t first_number,
01869 std::size_t n
01870 )
01871 {
01872 std::size_t m = basis.size();
01873
01874 vector<bool, false> basis_marks(n, false);
01875 for(std::size_t i = 0; i < m; ++i)
01876 basis_marks[basis[i]-first_number] = true;
01877
01878 nonbasis.resize(n - m);
01879 std::size_t ib = 0;
01880 for(std::size_t i = 0; i < n; ++i)
01881 if(!basis_marks[i])nonbasis[ib++] = i + first_number;
01882
01883 ARAGELI_ASSERT_1(ib == nonbasis.size());
01884 }
01885
01886
01888 template
01889 <
01890 typename T1, bool REFCNT1,
01891 typename T2, bool REFCNT2
01892 >
01893 inline void basis_to_nonbasis
01894 (
01895 const vector<T1, REFCNT1>& basis,
01896 vector<T2, REFCNT2>& nonbasis,
01897 std::size_t n
01898 )
01899 { basis_to_nonbasis(basis, nonbasis, std::size_t(1), n); }
01900
01901
01902
01904 template
01905 <
01906 typename T_Q, bool REFCNT_Q, typename T_basis, bool REFCNT_basis,
01907 typename T_T, bool REFCNT_T, typename T_nonbasis, bool REFCNT_nonbasis
01908 >
01909 void row_to_col_table
01910 (
01911 const matrix<T_Q, REFCNT_Q>& q,
01912 const vector<T_basis, REFCNT_basis>& basis,
01913 matrix<T_T, REFCNT_T>& t,
01914 vector<T_nonbasis, REFCNT_nonbasis>& nonbasis
01915 )
01916 {
01917 ARAGELI_ASSERT_0(!q.is_empty());
01918
01919 std::size_t m = q.nrows() - 1;
01920 std::size_t n = q.ncols() - 1;
01921
01922 ARAGELI_ASSERT_0(basis.size() == m);
01923 ARAGELI_ASSERT_0(n >= m);
01924 ARAGELI_ASSERT_0(m == basis.size());
01925
01926 t.assign_fromsize(q.ncols(), n - m + 1);
01927 ARAGELI_ASSERT_1(!t.is_empty());
01928
01929
01930 basis_to_nonbasis(basis, nonbasis, n);
01931
01932
01933 t(0, 0) = q(0, 0);
01934
01935
01936
01937 for(std::size_t i = 0; i < m; ++i)
01938 {
01939 std::size_t r = basis[i];
01940 ARAGELI_ASSERT_0(r >= 1 && r <= n);
01941 t(r, 0) = q(i+1, 0);
01942
01943 for(std::size_t j = 1; j < t.ncols(); ++j)
01944 t(r, j) = q(i+1, nonbasis[j-1]);
01945 }
01946
01947
01948
01949 for(std::size_t j = 0; j < nonbasis.size(); ++j)
01950 {
01951 t(0, j+1) = q(0, nonbasis[j]);
01952 t(nonbasis[j], j+1) = opposite_unit(t(0, 0));
01953 }
01954 }
01955
01956
01958
01959 template
01960 <
01961 typename T_QT, bool REFCNT_QT,
01962 typename T_basis_nonbasis, bool REFCNT_basis_nonbasis
01963 >
01964 void row_to_col_table
01965 (
01966 matrix<T_QT, REFCNT_QT>& qt,
01967 vector<T_basis_nonbasis, REFCNT_basis_nonbasis>& basis_nonbasis
01968 )
01969 {
01970 matrix<T_QT, REFCNT_QT> t;
01971 vector<T_basis_nonbasis, REFCNT_basis_nonbasis> nonbasis;
01972
01973 row_to_col_table(qt, basis_nonbasis, t, nonbasis);
01974
01975 swap(qt, t);
01976 swap(basis_nonbasis, nonbasis);
01977 }
01978
01979
01981
01987 template
01988 <
01989 typename T_Q, bool REFCNT_Q,
01990 typename T_basis, bool REFCNT_basis,
01991 typename T_DQ, bool REFCNT_DQ,
01992 typename T_Dbasis, bool REFCNT_Dbasis
01993 >
01994 void primal_row_to_dual_row_table
01995 (
01996 const matrix<T_Q, REFCNT_Q>& q,
01997 const vector<T_basis, REFCNT_basis>& basis,
01998 matrix<T_DQ, REFCNT_DQ>& dq,
01999 vector<T_Dbasis, REFCNT_Dbasis>& dbasis
02000 )
02001 {
02002 ARAGELI_ASSERT_0(!q.is_empty());
02003 ARAGELI_ASSERT_0(!basis.is_empty());
02004 ARAGELI_ASSERT_0(q.nrows() - 1 == basis.size());
02005 ARAGELI_ASSERT_0(q.nrows() <= q.ncols());
02006
02007 dq.assign_fromsize
02008 (
02009 q.ncols() - basis.size(),
02010 q.nrows() + q.ncols() - basis.size() - 1
02011 );
02012
02013 dq(0, 0) = -q(0, 0);
02014
02015 for(std::size_t j = 1; j < q.nrows(); ++j)
02016 dq(0, j) = q(j, 0);
02017
02018 vector<std::size_t, false> nonbasis;
02019 basis_to_nonbasis(basis, nonbasis, q.ncols() - 1);
02020 ARAGELI_ASSERT_1(nonbasis.size() == dq.nrows() - 1);
02021
02022 const T_Q& pattern = q(0, 0);
02023 dbasis.resize(nonbasis.size());
02024
02025 for(std::size_t i = 1; i <= nonbasis.size(); ++i)
02026 {
02027 std::size_t k = nonbasis[i-1];
02028 dq(i, 0) = q(0, k);
02029 for(std::size_t j = 1; j < q.nrows(); ++j)
02030 dq(i, j) = -q(j, k);
02031
02032 dq(i, q.nrows() + i - 1) = unit(pattern);
02033 dbasis[i-1] = q.nrows() + i - 1;
02034 }
02035 }
02036
02037
02039
02040
02042 template <typename T, bool REFCNT, typename Prow>
02043 result_kind gomory1_clip (matrix<T, REFCNT>& t, Prow& prow)
02044 {
02045 ARAGELI_ASSERT_0(!t.is_empty());
02046 ARAGELI_ASSERT_0(is_primal_allow(t));
02047 ARAGELI_ASSERT_0(is_dual_allow(t));
02048
02049 typedef typename matrix<T, REFCNT>::size_type size_type;
02050
02051 size_type r = 0;
02052 while(r < t.nrows() && is_integer(t(r, 0)))++r;
02053
02054 if(r == t.nrows())return rk_found;
02055 prow = r;
02056
02057 t.insert_row(t.nrows(), null(t(0, 0)));
02058 for(size_type j = 0; j < t.ncols(); ++j)
02059 t(t.nrows() - 1, j) = -frac(t(r, j));
02060
02061 ARAGELI_ASSERT_1(is_negative(t(t.nrows() - 1, 0)));
02062 ARAGELI_ASSERT_1(!is_integer(t(t.nrows() - 1, 0)));
02063
02064 return rk_nonoptimal;
02065 }
02066
02068
02069 template <typename T, bool REFCNT>
02070 result_kind gomory1_clip (matrix<T, REFCNT>& t)
02071 {
02072 typename matrix<T, REFCNT>::size_type prow;
02073 return gomory1_clip(t, prow);
02074 }
02075
02076 }
02077
02078 namespace ctrl
02079 {
02080 namespace simplex_method
02081 {
02082
02083 using namespace Arageli::simplex_method;
02084
02086 struct gomory1_iter_idler
02087 {
02088 class abort : public ctrl::abort {};
02089
02090 template <typename T, typename Nonbasis>
02091 void preamble (const T& t, const Nonbasis& nonbasis) const {}
02092
02093 template <typename T, typename Nonbasis>
02094 void conclusion (const T& t, const Nonbasis& nonbasis, result_kind rk) const {}
02095
02096 template <typename T, typename Prow>
02097 void after_gomory1_clip (const T& t, Prow prow, result_kind rk) const {}
02098
02099 dual_col_iters_idler ctrl_for_dual_col_iters () const
02100 { return dual_col_iters_idler(); }
02101 };
02102
02103
02105 struct gomory1_iters_idler
02106 {
02107 class abort : public ctrl::abort {};
02108
02109 template <typename T, typename Nonbasis>
02110 void preamble (const T& t, const Nonbasis& nonbasis) const {}
02111
02112 template <typename T, typename Nonbasis>
02113 void conclusion (const T& t, const Nonbasis& nonbasis, result_kind rk) const {}
02114
02115 template <typename T, typename Nonbasis>
02116 void before_iter (const T& t, const Nonbasis& nonbasis) const {}
02117
02118 template <typename T, typename Nonbasis>
02119 void after_iter
02120 (
02121 const T& t, const Nonbasis& nonbasis,
02122 result_kind rk
02123 ) const {}
02124
02125 gomory1_iter_idler ctrl_for_gomory1_iter () const
02126 { return gomory1_iter_idler(); }
02127 };
02128
02129 }}
02130
02131
02132 namespace simplex_method
02133 {
02134
02136 template
02137 <
02138 typename T1, bool REFCNT1,
02139 typename T2, bool REFCNT2,
02140 typename Ctrler
02141 >
02142 result_kind gomory1_iter
02143 (
02144 matrix<T1, REFCNT1>& t,
02145 vector<T2, REFCNT2>& nonbasis,
02146 Ctrler ctrler
02147 )
02148 {
02149 ARAGELI_ASSERT_0(!t.is_empty());
02150 ARAGELI_ASSERT_0(is_primal_allow(t));
02151 ARAGELI_ASSERT_0(is_dual_allow(t));
02152
02153 ctrler.preamble(t, nonbasis);
02154 typename matrix<T1, REFCNT1>::size_type prow;
02155 result_kind res = gomory1_clip(t, prow);
02156 ctrler.after_gomory1_clip(t, prow, res);
02157
02158 if(res == rk_nonoptimal)
02159 {
02160 res = dual_col_iters(t, nonbasis, ctrler.ctrl_for_dual_col_iters());
02161 if(res == rk_found)res = rk_nonoptimal;
02162 }
02163
02164 ctrler.conclusion(t, nonbasis, res);
02165 return res;
02166 }
02167
02168
02169
02170 template
02171 <
02172 typename T1, bool REFCNT1,
02173 typename T2, bool REFCNT2,
02174 typename Ctrler
02175 >
02176 result_kind gomory1_iters
02177 (
02178 matrix<T1, REFCNT1>& t,
02179 vector<T2, REFCNT2>& nonbasis,
02180 Ctrler ctrler
02181 )
02182 {
02183 ARAGELI_ASSERT_0(!t.is_empty());
02184 ARAGELI_ASSERT_0(is_primal_allow(t));
02185 ARAGELI_ASSERT_0(is_dual_allow(t));
02186
02187 ctrler.preamble(t, nonbasis);
02188 result_kind res = rk_nonoptimal;
02189
02190 while(res == rk_nonoptimal)
02191 {
02192 ctrler.before_iter(t, nonbasis);
02193 res = gomory1_iter(t, nonbasis, ctrler.ctrl_for_gomory1_iter());
02194 ctrler.after_iter(t, nonbasis, res);
02195 }
02196
02197 ctrler.conclusion(t, nonbasis, res);
02198 return res;
02199 }
02200
02201
02202 template
02203 <
02204 typename T1, bool REFCNT1,
02205 typename T2, bool REFCNT2
02206 >
02207 inline result_kind gomory1_iters
02208 (
02209 matrix<T1, REFCNT1>& t,
02210 vector<T2, REFCNT2>& nonbasis
02211 )
02212 { return gomory1_iters(t, nonbasis, ::Arageli::ctrl::simplex_method::gomory1_iters_idler()); }
02213
02214
02216
02217
02218
02220
02222 template
02223 <
02224 typename T_a, bool REFCNT_a,
02225 typename T_b, bool REFCNT_b,
02226 typename T_c, bool REFCNT_c,
02227 typename T_da, bool REFCNT_da,
02228 typename T_db, bool REFCNT_db,
02229 typename T_dc, bool REFCNT_dc,
02230 typename T_basis, bool REFCNT_basis
02231 >
02232 void primal_to_dual_canonical
02233 (
02234 const matrix<T_a, REFCNT_a>& a,
02235 const vector<T_b, REFCNT_b>& b,
02236 const vector<T_c, REFCNT_c>& c,
02237 matrix<T_da, REFCNT_da>& da,
02238 vector<T_db, REFCNT_db>& db,
02239 vector<T_dc, REFCNT_dc>& dc,
02240 vector<T_basis, REFCNT_basis>& basis
02241 )
02242 {
02243 ARAGELI_ASSERT_0(!a.is_empty());
02244 ARAGELI_ASSERT_0(a.ncols() == c.size());
02245 ARAGELI_ASSERT_0(a.nrows() == b.size());
02246
02247 db = -c;
02248
02249 da.assign_fromsize(a.ncols(), 2*a.nrows() + a.ncols());
02250 dc.resize(2*b.size() + a.ncols());
02251 basis.resize(da.nrows());
02252
02253 for(std::size_t j = 0; j < a.ncols(); ++j)
02254 {
02255 da(j, 2*a.nrows() + j) = unit(a(0, 0));
02256 basis[j] = 2*a.nrows() + j + 1;
02257
02258 for(std::size_t i = 0; i < a.nrows(); ++i)
02259 {
02260 da(j, 2*i) = -a(i, j);
02261 da(j, 2*i + 1) = a(i, j);
02262
02263 dc[2*i] = -b[i];
02264 dc[2*i + 1] = b[i];
02265 }
02266 }
02267 }
02268
02269
02271
02278 template
02279 <
02280 typename T_a, bool REFCNT_a,
02281 typename T_b, bool REFCNT_b,
02282 typename T_c, bool REFCNT_c,
02283 typename T_basis, bool REFCNT_basis,
02284 typename T_da, bool REFCNT_da,
02285 typename T_db, bool REFCNT_db,
02286 typename T_dc, bool REFCNT_dc,
02287 typename T_res,
02288 typename T_ab, bool REFCNT_ab,
02289 typename T_cb, bool REFCNT_cb
02290 >
02291 void primal_to_dual_standard_discr
02292 (
02293 const matrix<T_a, REFCNT_a>& a,
02294 const vector<T_b, REFCNT_b>& b,
02295 const vector<T_c, REFCNT_c>& c,
02296 const vector<T_basis, REFCNT_basis> basis,
02297 matrix<T_da, REFCNT_da>& da,
02298 vector<T_db, REFCNT_db>& db,
02299 vector<T_dc, REFCNT_dc>& dc,
02300 T_res& res_offset,
02301 matrix<T_ab, REFCNT_ab>& bsuba,
02302 vector<T_cb, REFCNT_cb>& bsubc
02303 )
02304 {
02305 ARAGELI_ASSERT_0(!a.is_empty());
02306 ARAGELI_ASSERT_0(a.ncols() == c.size());
02307 ARAGELI_ASSERT_0(a.nrows() == b.size());
02308 ARAGELI_ASSERT_0(!basis.is_empty());
02309
02310 vector<T_basis, false> basism1 = basis - unit(basis[0]);
02311 vector<T_basis, false> nonbasism1;
02312 basis_to_nonbasis(basis, nonbasism1, c.size());
02313 nonbasism1 -= unit(basis[0]);
02314
02315
02316
02317 fill_submatrix_col(a, basism1, bsuba);
02318 fill_subvector(c, basism1, bsubc);
02319 matrix<T_ab, false> inv_bsuba = inverse(bsuba);
02320 output_aligned(std::cout << "\n$$$$$$B^(-1) matrix\n", inv_bsuba);
02321
02322 matrix<T_ab, false> nonbsuba;
02323 fill_submatrix_col(a, nonbasism1, nonbsuba);
02324
02325 matrix<T_ab, false> bm1n = inv_bsuba*nonbsuba;
02326 output_aligned(std::cout << "\n$$$$$$B^(-1) * N\n", bm1n);
02327
02328 vector<T_cb, false> nonbsubc;
02329 fill_subvector(c, nonbasism1, nonbsubc);
02330
02331 da = -bm1n;
02332 da.transpose();
02333 db = (bsubc*bm1n - nonbsubc);
02334
02335
02336
02337
02338
02339
02340
02341 dc = -inv_bsuba*b;
02342 res_offset = -dotprod(bsubc*inv_bsuba, b);
02343 }
02344
02347
02348 struct linear_prog_task_base
02349 {
02350 enum constraint_type
02351 {
02352 ct_equal = 0x01,
02353 ct_greater_equal = 0x02,
02354 ct_less_equal = 0x04,
02355 ct_integer = 0x08
02356 };
02357
02358 enum optimum_type { ot_min, ot_max };
02359 };
02360
02361
02363
02365 template <typename T, bool REFCNT = true>
02366 class linear_prog_task : public linear_prog_task_base
02367 {
02368 public:
02369
02370 typedef vector<T, REFCNT> c_type;
02371 typedef matrix<T, REFCNT> a_type;
02372 typedef vector<T, REFCNT> b_type;
02373 typedef vector<constraint_type, REFCNT> relation_type;
02374 typedef vector<constraint_type, REFCNT> individual_type;
02375
02376 linear_prog_task () {}
02377
02378 linear_prog_task
02379 (
02380 const c_type& c_a,
02381 const a_type& a_a,
02382 const b_type& b_a,
02383 const relation_type& relation_a,
02384 const individual_type& individual_a,
02385 optimum_type optimum_a = ot_max
02386 )
02387 : c_m(c_a),
02388 a_m(a_a),
02389 b_m(b_a),
02390 relation_m(relation_a),
02391 individual_m(individual_a),
02392 optimum_m(optimum_a)
02393 {}
02394
02395
02396
02397 linear_prog_task
02398 (
02399 const c_type& c_a,
02400 const a_type& a_a,
02401 const b_type& b_a,
02402 optimum_type optimum_a = ot_max
02403 )
02404 : c_m(c_a),
02405 a_m(a_a),
02406 b_m(b_a),
02407 relation_m(b_m.size(), ct_equal),
02408
02409 optimum_m(optimum_a)
02410 {}
02411
02412
02413 optimum_type optimum () const { return optimum_m; }
02414 const c_type& c () const { return c_m; }
02415 const a_type& a () const { return a_m; }
02416 const b_type& b () const { return b_m; }
02417 const relation_type& relation () const { return relation_m; }
02418 const individual_type& individual () const { return individual_m; }
02419
02420 bool is_canonical () const;
02421 bool is_standard () const;
02422 bool is_integer () const;
02423 bool is_partial_integer () const;
02424
02425 bool is_normal () const;
02426
02427 void change_optimal (optimum_type);
02428
02429 void canonical ()
02430 {
02431
02432 }
02433
02434 void standard ();
02435
02436 void dual ();
02437
02438 private:
02439
02440 c_type c_m;
02441 a_type a_m;
02442 b_type b_m;
02443 relation_type relation_m;
02444 individual_type individual_m;
02445 optimum_type optimum_m;
02446
02447 };
02448
02449
02450 template <typename T, bool REFCNT, typename Ch, typename ChT>
02451 std::basic_ostream<Ch, ChT>& output_list
02452 (
02453 std::basic_ostream<Ch, ChT>& out,
02454 const linear_prog_task<T, REFCNT>& lpt
02455 )
02456 {
02457
02458
02459 out << "(";
02460 out << lpt.optimum() << ", ";
02461 output_list(out, lpt.c()); out << ", ";
02462 output_list(out, lpt.a()); out << ", ";
02463 output_list(out, lpt.b()); out << ", ";
02464 output_list(out, lpt.relation());
02465 output_list(out, lpt.individual());
02466 out << ")";
02467
02468 return out;
02469 }
02470
02471
02472 template <typename T, bool REFCNT, typename Ch, typename ChT>
02473 std::basic_istream<Ch, ChT>& input_list
02474 (
02475 std::basic_istream<Ch, ChT>& in,
02476 linear_prog_task<T, REFCNT>& lpt
02477 )
02478 {
02479 if(!_Internal::read_literal(in, "("))
02480 {
02481 in.clear(std::ios_base::failbit);
02482 return in;
02483 }
02484
02485 int ot;
02486 in >> ot;
02487
02488 if(!_Internal::read_literal(in, ","))
02489 {
02490 in.clear(std::ios_base::failbit);
02491 return in;
02492 }
02493
02494 typedef linear_prog_task<T, REFCNT> LPT;
02495 typename LPT::c_type c;
02496 in >> c;
02497
02498 if(!_Internal::read_literal(in, ","))
02499 {
02500 in.clear(std::ios_base::failbit);
02501 return in;
02502 }
02503
02504 typename LPT::a_type a;
02505 in >> a;
02506
02507 if(!_Internal::read_literal(in, ","))
02508 {
02509 in.clear(std::ios_base::failbit);
02510 return in;
02511 }
02512
02513 typename LPT::b_type b;
02514 in >> b;
02515
02516 if(!_Internal::read_literal(in, ","))
02517 {
02518 in.clear(std::ios_base::failbit);
02519 return in;
02520 }
02521
02522 typename LPT::relation_type relation;
02523 vector<int> relt;
02524 in >> relt;
02525
02526 if(!_Internal::read_literal(in, ","))
02527 {
02528 in.clear(std::ios_base::failbit);
02529 return in;
02530 }
02531
02532 relation.resize(relt.size());
02533 for(std::size_t i = 0; i < relt.size(); ++i)
02534 relation[i] = linear_prog_task_base::constraint_type(relt[i]);
02535
02536 typename LPT::individual_type individual;
02537 vector<int> indt;
02538 in >> indt;
02539
02540 individual.resize(indt.size());
02541 for(std::size_t i = 0; i < indt.size(); ++i)
02542 individual[i] = linear_prog_task_base::constraint_type(indt[i]);
02543
02544 if(!_Internal::read_literal(in, ")"))
02545 {
02546 in.clear(std::ios_base::failbit);
02547 return in;
02548 }
02549
02550 lpt = LPT
02551 (
02552 c, a, b, relation, individual,
02553 linear_prog_task_base::optimum_type(ot)
02554 );
02555
02556 return in;
02557 }
02558
02559
02560 template <typename T, bool REFCNT, typename Ch, typename ChT>
02561 std::basic_ostream<Ch, ChT>& output_aligned
02562 (
02563 std::basic_ostream<Ch, ChT>& out,
02564 const linear_prog_task<T, REFCNT>& lpt,
02565 const char* var = "x"
02566 )
02567 {
02568 if(lpt.optimum() == linear_prog_task_base::ot_max)
02569 out << "max";
02570 else out << "min";
02571
02572 out << "(";
02573 bool first = true;
02574 for(std::size_t i = 0; i < lpt.c().size(); ++i)
02575 if(!is_null(lpt.c().el(i)))
02576 {
02577 if(first)
02578 {
02579 first = false;
02580 output_polynom_first(out, lpt.c().el(i));
02581 }
02582 else
02583 {
02584 output_polynom_internal(out, lpt.c().el(i));
02585 }
02586
02587 out << "*" << var << i+1;
02588 }
02589
02590 if(first)out << "0";
02591 out << ")\n";
02592
02593 std::ostringstream buf;
02594
02595 matrix<std::string, false> bufmatrix
02596 (
02597 lpt.a().nrows(),
02598 2*lpt.a().ncols() + 1 + 1 ,
02599 std::string()
02600 );
02601
02602 for(std::size_t i = 0; i < bufmatrix.nrows(); ++i)
02603 {
02604 for(std::size_t j = 0; j < lpt.a().ncols(); ++j)
02605 {
02606 buf.str("");
02607 const T& el = lpt.a().el(i, j);
02608 if(is_negative(el))
02609 {
02610 bufmatrix(i, 2*j) = "-";
02611 buf << -el;
02612 }
02613 else if(is_positive(el))
02614 {
02615 buf << el;
02616 }
02617
02618 buf << "*" << var << j+1;
02619 bufmatrix(i, 2*j + 1) = buf.str();
02620 }
02621
02622 ARAGELI_ASSERT_1(lpt.relation().el(i) != linear_prog_task_base::ct_integer);
02623
02624 switch(lpt.relation().el(i))
02625 {
02626 case linear_prog_task_base::ct_equal:
02627 bufmatrix(i, bufmatrix.ncols() - 2) = "="; break;
02628 case linear_prog_task_base::ct_greater_equal:
02629 bufmatrix(i, bufmatrix.ncols() - 2) = ">="; break;
02630 case linear_prog_task_base::ct_less_equal:
02631 bufmatrix(i, bufmatrix.ncols() - 2) = "<="; break;
02632 }
02633
02634 buf.str("");
02635 buf << lpt.b().el(i);
02636 bufmatrix(i, bufmatrix.ncols() - 1) = buf.str();
02637 }
02638
02639 output_aligned(out, bufmatrix, "", "", " ");
02640
02641 for(std::size_t i = 0; i < lpt.individual().size(); ++i)
02642 {
02643 out << var << i+1;
02644 linear_prog_task_base::constraint_type ct =
02645 linear_prog_task_base::constraint_type
02646 (lpt.individual().el(i) & ~linear_prog_task_base::ct_integer);
02647
02648 switch(ct)
02649 {
02650 case 0: break;
02651 case linear_prog_task_base::ct_equal:
02652 out << " = "; break;
02653 case linear_prog_task_base::ct_greater_equal:
02654 out << " >= "; break;
02655 case linear_prog_task_base::ct_less_equal:
02656 out << " <= "; break;
02657 default: ARAGELI_ASSERT_1(!"It's impossible!");
02658 }
02659
02660 if(ct)out << "0";
02661 if(lpt.individual().el(i) & linear_prog_task_base::ct_integer)
02662 {
02663 if(ct)out << ",";
02664 out << " integer";
02665 }
02666
02667 out << "\n";
02668 }
02669
02670 return out;
02671 }
02672
02673
02674
02675
02676
02677 }
02678 }
02679
02680
02681 #ifdef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE
02682 #define ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_SIMPLEX_METHOD
02683
02684 #undef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_SIMPLEX_METHOD
02685 #endif
02686
02687
02688 #endif