simplex_method.hpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002     
00003     simplex_method.hpp -- Simplex method and other.
00004 
00005     This file is part of Arageli library.
00006 
00007     Copyright (C) Nikolai Yu. Zolotykh, 1999--2006
00008     Copyright (C) Sergey S. Lyalin, 2005
00009     University of Nizhni Novgorod, Russia
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     //rk_nonint     ///< an optimal vector is not integer yet
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                         // Little inefficiency: every time it recomputes
00281                         // the result of division; maybe cache for those
00282                         // values is better way.
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     // for the circularity controll
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 } // namespace simplex_method
00605 
00606 
00607 namespace ctrl
00608 {
00609 namespace simplex_method
00610 {
00611 
00613 
00614 
00615 // WARNING!!! The following two controllers are to remove!
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 }} // namespace simplex_method, ctrl
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     // WARNING. Replace it to the special form of insert when it will have been written.
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 } // namespace simlex_table
01168 
01169 namespace ctrl
01170 {
01171 namespace simplex_method
01172 {
01173 
01174 //using namespace Arageli::simplex_method;
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                 // we found negligible row
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 } // namespace simplex_method
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 // @name Direct row simplex method with artificial basis method as a zeroth step.
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     // building the first simplex table
01766     
01767     matrix<Ta, false> table;
01768     row_table_create(a, b, table);
01769 
01770     ctrler.table_for_artificial(table);
01771 
01772     // the artificial basis method
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     // building the first allowable simplex table
01795 
01796     basis_create_by_artificial
01797         (table, basis, ctrler.ctrl_for_basis_create_by_artificial());
01798     
01799     //ctrler.first_table(table);
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     // nonbasis building
01930     basis_to_nonbasis(basis, nonbasis, n);
01931 
01932     // target function value moving
01933     t(0, 0) = q(0, 0);
01934 
01935     // basis rows filling
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     // zeroth row filling and nonbasis rows filling (minus ones placing)
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 } // namespace simplex_method
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     //std::sort(basism1);
02315     //std::sort(nonbasism1);
02316 
02317     fill_submatrix_col(a, basism1, bsuba);
02318     fill_subvector(c, basism1, bsubc);  // c_B
02319     matrix<T_ab, false> inv_bsuba = inverse(bsuba); // B^(-1) matrix
02320     output_aligned(std::cout << "\n$$$$$$B^(-1) matrix\n", inv_bsuba);
02321     
02322     matrix<T_ab, false> nonbsuba;   // N matrix
02323     fill_submatrix_col(a, nonbasism1, nonbsuba);
02324 
02325     matrix<T_ab, false> bm1n = inv_bsuba*nonbsuba;  // B^(-1) * N
02326     output_aligned(std::cout << "\n$$$$$$B^(-1) * N\n", bm1n);
02327 
02328     vector<T_cb, false> nonbsubc;   // c_N
02329     fill_subvector(c, nonbasism1, nonbsubc);
02330 
02331     da = -bm1n;
02332     da.transpose();
02333     db = (bsubc*bm1n - nonbsubc);
02334 
02335     //std::cout
02336     //  << "\n$$$$$$bsubc:\n" << bsubc
02337     //  << "\n$$$$$$bsubc*bm1n:\n" << bsubc*bm1n
02338     //  << "\n$$$$$$nonbsubc:\n" << nonbsubc
02339     //  << "\n$$$$$$db:\n" << db;
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     // Creates a canonical task.
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         //individual_m(individual_a, ct_greater_equal),     // WARNING! This line isn't compilable.
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     // WARNING! Restricted implementation.
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 /*relation*/ + 1 /*right part*/,
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     //#include "simplex_method.cpp"
02684     #undef  ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_SIMPLEX_METHOD
02685 #endif
02686 
02687 
02688 #endif

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