BWAPI
|
00001 // Copyright (c) 1997-2007 ETH Zurich (Switzerland). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00005 // the terms of the Q Public License version 1.0. 00006 // See the file LICENSE.QPL distributed with CGAL. 00007 // 00008 // Licenseges holding a valid commercial license may use this file in 00009 // accordance with the commercial license agreement provided with the software. 00010 // 00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00013 // 00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/QP_solver/include/CGAL/QP_solver/QP_solver.h $ 00015 // $Id: QP_solver.h 46451 2008-10-23 14:31:10Z gaertner $ 00016 // 00017 // 00018 // Author(s) : Kaspar Fischer 00019 // : Bernd Gaertner <gaertner@inf.ethz.ch> 00020 // : Sven Schoenherr 00021 // : Franz Wessendorp 00022 00023 #ifndef CGAL_QP_SOLVER_H 00024 #define CGAL_QP_SOLVER_H 00025 00026 #include <CGAL/iterator.h> 00027 #include <CGAL/QP_solver/basic.h> 00028 #include <CGAL/QP_solver/functors.h> 00029 #include <CGAL/QP_options.h> 00030 #include <CGAL/QP_solution.h> 00031 #include <CGAL/QP_solver/QP_basis_inverse.h> 00032 #include <CGAL/QP_solver/QP_pricing_strategy.h> 00033 #include <CGAL/QP_solver/QP_full_exact_pricing.h> 00034 #include <CGAL/QP_solver/QP_partial_exact_pricing.h> 00035 #include <CGAL/QP_solver/QP_full_filtered_pricing.h> 00036 #include <CGAL/QP_solver/QP_partial_filtered_pricing.h> 00037 #include <CGAL/QP_solver/QP_exact_bland_pricing.h> 00038 00039 #include <CGAL/algorithm.h> 00040 00041 #include <CGAL/IO/Verbose_ostream.h> 00042 00043 #include <boost/bind.hpp> 00044 #include <boost/function.hpp> 00045 #include <boost/iterator/transform_iterator.hpp> 00046 00047 #include <vector> 00048 #include <numeric> 00049 #include <algorithm> 00050 00051 CGAL_BEGIN_NAMESPACE 00052 00053 // ================== 00054 // class declarations 00055 // ================== 00056 template < typename Q, typename ET, typename Tags > 00057 class QP_solver; 00058 00059 template <class ET> 00060 class QP_solution; 00061 00062 namespace QP_solver_impl { // namespace for implemenation details 00063 // -------------- 00064 // Tags generator 00065 // -------------- 00066 template < typename Linear, 00067 typename Nonnegative > 00068 struct QP_tags { 00069 typedef Linear Is_linear; 00070 typedef Nonnegative Is_nonnegative; 00071 }; 00072 00073 template < class Q, class Is_linear > 00074 struct D_selector {}; 00075 00076 template <class Q> 00077 struct D_selector<Q, Tag_false> // quadratic 00078 { 00079 typedef typename Q::D_iterator D_iterator; 00080 }; 00081 00082 template <class Q> 00083 struct D_selector<Q, Tag_true> // linear 00084 { 00085 // dummy type, not used 00086 typedef int** D_iterator; 00087 }; 00088 00089 template < class Q, class Is_nonnegative > 00090 struct Bd_selector {}; 00091 00092 template < class Q > 00093 struct Bd_selector<Q, Tag_false> // nonstandard form 00094 { 00095 typedef typename Q::FL_iterator FL_iterator; 00096 typedef typename Q::L_iterator L_iterator; 00097 typedef typename Q::FU_iterator FU_iterator; 00098 typedef typename Q::U_iterator U_iterator; 00099 }; 00100 00101 template < class Q > 00102 struct Bd_selector<Q, Tag_true> // standard form 00103 { 00104 // dummy types, not used 00105 typedef int* FL_iterator; 00106 typedef int* L_iterator; 00107 typedef int* FU_iterator; 00108 typedef int* U_iterator; 00109 }; 00110 00111 // only allow filtered pricing if NT = double 00112 template <typename Q, typename ET, typename Tags, typename NT> 00113 struct Filtered_pricing_strategy_selector 00114 { 00115 typedef QP_full_exact_pricing<Q, ET, Tags> FF; 00116 typedef QP_partial_exact_pricing<Q, ET, Tags> PF; 00117 }; 00118 00119 template <typename Q, typename ET, typename Tags> 00120 struct Filtered_pricing_strategy_selector<Q, ET, Tags, double> 00121 { 00122 typedef QP_full_filtered_pricing<Q, ET, Tags> FF; 00123 typedef QP_partial_filtered_pricing<Q, ET, Tags> PF; 00124 }; 00125 00126 } // end of namespace for implementation details 00127 00128 // ================ 00129 // class interfaces 00130 // ================ 00131 00132 00133 template < typename Q, typename ET, typename Tags > 00134 class QP_solver : public QP_solver_base<ET> { 00135 00136 public: // public types 00137 typedef QP_solver<Q, ET, Tags> Self; 00138 typedef QP_solver_base<ET> Base; 00139 00140 // types from the QP 00141 typedef typename Q::A_iterator A_iterator; 00142 typedef typename Q::B_iterator B_iterator; 00143 typedef typename Q::C_iterator C_iterator; 00144 typedef CGAL::Comparison_result Row_type; 00145 typedef typename Q::R_iterator Row_type_iterator; 00146 00147 // the remaining types might not be present in the qp, so the 00148 // following selectors generate dummy types for them 00149 typedef typename QP_solver_impl:: 00150 D_selector<Q, typename Tags::Is_linear>:: 00151 D_iterator D_iterator; 00152 typedef typename QP_solver_impl:: 00153 Bd_selector<Q, typename Tags::Is_nonnegative>:: 00154 L_iterator L_iterator; 00155 typedef typename QP_solver_impl:: 00156 Bd_selector<Q, typename Tags::Is_nonnegative>:: 00157 U_iterator U_iterator; 00158 typedef typename QP_solver_impl:: 00159 Bd_selector<Q, typename Tags::Is_nonnegative>:: 00160 FL_iterator FL_iterator; 00161 typedef typename QP_solver_impl:: 00162 Bd_selector<Q, typename Tags::Is_nonnegative>:: 00163 FU_iterator FU_iterator; 00164 00165 // types from the Tags 00166 typedef typename Tags::Is_linear Is_linear; 00167 typedef typename Tags::Is_nonnegative Is_nonnegative; 00168 00169 // friends 00170 template <class Q_, class ET_> 00171 friend bool has_linearly_independent_equations 00172 (const Q_& qp, const ET_& dummy); 00173 00174 private: // private types 00175 00176 // types of original problem: 00177 typedef typename std::iterator_traits<A_iterator>::value_type A_column; 00178 typedef typename std::iterator_traits<D_iterator>::value_type D_row; 00179 00180 typedef typename std::iterator_traits<A_column >::value_type A_entry; 00181 typedef typename std::iterator_traits<B_iterator>::value_type B_entry; 00182 typedef typename std::iterator_traits<C_iterator>::value_type C_entry; 00183 typedef typename std::iterator_traits<D_row >::value_type D_entry; 00184 typedef typename std::iterator_traits<L_iterator>::value_type L_entry; 00185 typedef typename std::iterator_traits<U_iterator>::value_type U_entry; 00186 00187 // slack columns: 00188 // 00189 // The following two types are used to (conceptually) add to the matrix A 00190 // additional columns that model the constraints "x_s>=0" for the slack 00191 // variables x_s. Of course, we do not store the column (which is just 00192 // plus/minus a unit vector), but maintain a pair (int,bool): the first 00193 // entry says in which column the +-1 is and the second entry of the pair 00194 // says whether it is +1 (false) or -1 (true). 00195 typedef std::pair<int,bool> Slack_column; 00196 typedef std::vector<Slack_column> A_slack; 00197 00198 // artificial columns 00199 // 00200 // Artificial columns that are (conceptually) added to the matrix A are 00201 // handled exactly like slack columns (see above). 00202 typedef std::pair<int,bool> Art_column; 00203 typedef std::vector<Art_column> A_art; 00204 00205 // special artificial column: 00206 // 00207 // Also for the special artificial variable we (conceptually) add a column 00208 // to A. This column contains only +-1's (but it may contain several nonzero 00209 // entries). 00210 typedef std::vector<A_entry> S_art; 00211 00212 // auxiliary objective vector (i.e., the objective vector for phase I): 00213 typedef std::vector<C_entry> C_aux; 00214 00215 public: // export some additional types: 00216 00217 typedef typename Base::Indices Indices; 00218 typedef typename Base::Index_mutable_iterator Index_iterator; 00219 typedef typename Base::Index_const_iterator Index_const_iterator; 00220 00221 // For problems in nonstandard form we also export the following type, which 00222 // for an original variable will say whether it sits at is lower, upper, at 00223 // its lower and upper (fixed) bound, or at zero, or whether the variable is 00224 // basic: 00225 enum Bound_index { LOWER, ZERO, UPPER, FIXED, BASIC }; 00226 00227 private: 00228 typedef std::vector<Bound_index> Bound_index_values; 00229 typedef typename Bound_index_values::iterator 00230 Bound_index_value_iterator; 00231 typedef typename Bound_index_values::const_iterator 00232 Bound_index_value_const_iterator; 00233 00234 // values (variables' numerators): 00235 typedef std::vector<ET> Values; 00236 typedef typename Values::iterator Value_iterator; 00237 typedef typename Values::const_iterator 00238 Value_const_iterator; 00239 00240 // access values by basic index functor: 00241 typedef CGAL::Value_by_basic_index<Value_const_iterator> 00242 Value_by_basic_index; 00243 00244 // access to original problem by basic variable/constraint index: 00245 typedef QP_vector_accessor<A_column, false, false > A_by_index_accessor; 00246 typedef boost::transform_iterator 00247 < A_by_index_accessor,Index_const_iterator > 00248 A_by_index_iterator; 00249 00250 // todo kf: following can be removed once we have all these (outdated) 00251 // accessors removed: 00252 typedef QP_vector_accessor< B_iterator, false, false > 00253 B_by_index_accessor; 00254 typedef boost::transform_iterator 00255 < B_by_index_accessor, Index_const_iterator > 00256 B_by_index_iterator; 00257 00258 typedef QP_vector_accessor< C_iterator, false, false > 00259 C_by_index_accessor; 00260 typedef boost::transform_iterator 00261 <C_by_index_accessor, Index_const_iterator > 00262 C_by_index_iterator; 00263 00264 typedef QP_matrix_accessor< A_iterator, false, true, false, false> 00265 A_accessor; 00266 typedef boost::function1<typename A_accessor::result_type, int> 00267 A_row_by_index_accessor; 00268 typedef boost::transform_iterator 00269 < A_row_by_index_accessor, Index_iterator > 00270 A_row_by_index_iterator; 00271 00272 // Access to the matrix D sometimes converts to ET, and 00273 // sometimes retruns the original input type 00274 typedef QP_matrix_pairwise_accessor< D_iterator, ET > 00275 D_pairwise_accessor; 00276 typedef boost::transform_iterator 00277 < D_pairwise_accessor, Index_const_iterator> 00278 D_pairwise_iterator; 00279 typedef QP_matrix_pairwise_accessor< D_iterator, D_entry > 00280 D_pairwise_accessor_input_type; 00281 typedef boost::transform_iterator 00282 < D_pairwise_accessor_input_type, Index_const_iterator > 00283 D_pairwise_iterator_input_type; 00284 00285 // access to special artificial column by basic constraint index: 00286 typedef QP_vector_accessor< typename S_art::const_iterator, false, false> 00287 S_by_index_accessor; 00288 typedef boost::transform_iterator 00289 < S_by_index_accessor, Index_iterator > 00290 S_by_index_iterator; 00291 00292 public: 00293 00294 typedef typename A_slack::const_iterator 00295 A_slack_iterator; 00296 00297 typedef typename A_art::const_iterator 00298 A_artificial_iterator; 00299 00300 typedef typename C_aux::const_iterator 00301 C_auxiliary_iterator; 00302 00303 typedef typename Base::Variable_numerator_iterator 00304 Variable_numerator_iterator; 00305 00306 typedef Index_const_iterator Basic_variable_index_iterator; 00307 typedef Value_const_iterator Basic_variable_numerator_iterator; 00308 typedef Index_const_iterator Basic_constraint_index_iterator; 00309 00310 typedef QP_pricing_strategy<Q, ET, Tags> Pricing_strategy; 00311 00312 private: 00313 // compile time tag for symbolic perturbation, should be moved into traits 00314 // class when symbolic perturbation is to be implemented 00315 Tag_false is_perturbed; 00316 00317 // some constants 00318 const ET et0, et1, et2; 00319 00320 // verbose output streams 00321 mutable Verbose_ostream vout; // used for any diagnostic output 00322 mutable Verbose_ostream vout1; // used for some diagnostic output 00323 mutable Verbose_ostream vout2; // used for more diagnostic output 00324 mutable Verbose_ostream vout3; // used for full diagnostic output 00325 mutable Verbose_ostream vout4; // used for output of basis inverse 00326 mutable Verbose_ostream vout5; // used for output of validity tests 00327 00328 // pricing strategy 00329 Pricing_strategy* strategyP; 00330 00331 // given QP 00332 int qp_n; // number of variables 00333 int qp_m; // number of constraints 00334 00335 // min x^T D x + c^T x + c0 00336 A_iterator qp_A; // constraint matrix 00337 B_iterator qp_b; // right-hand-side vector 00338 C_iterator qp_c; // objective vector 00339 C_entry qp_c0; // constant term in objective function 00340 // attention: qp_D represents *twice* the matrix D 00341 D_iterator qp_D; // objective matrix 00342 Row_type_iterator qp_r; // row-types of constraints 00343 FL_iterator qp_fl; // lower bound finiteness vector 00344 L_iterator qp_l; // lower bound vector 00345 FU_iterator qp_fu; // upper bound finiteness vector 00346 U_iterator qp_u; // upper bound vector 00347 00348 A_slack slack_A; // slack part of constraint matrix 00349 00350 // auxiliary problem 00351 A_art art_A; // artificial part of constraint matrix 00352 // Note: in phase I there is an 00353 // additional "fake" column attached 00354 // to this "matrix", see init_basis() 00355 00356 S_art art_s; // special artificial column for slacks 00357 int art_s_i; // art_s_i>=0 -> index of special 00358 // artificial column 00359 // art_s_i==-1 -> no sp. art. col 00360 // art_s_i==-2 -> sp. art. col removed 00361 // after it left basis 00362 int art_basic; // number of basic artificial variables 00363 C_aux aux_c; // objective function for phase I 00364 // initially has the same size as A_art 00365 00366 Indices B_O; // basis (original variables) 00367 // Note: the size of B_O is always 00368 // correct, i.e., equals the number of 00369 // basic original variables, plus (in 00370 // phase I) the number of basic 00371 // artificial variables. 00372 00373 Indices B_S; // basis ( slack variables) 00374 00375 Indices C; // basic constraints ( C = E+S_N ) 00376 // Note: the size of C is always 00377 // correct, i.e., corresponds to the 00378 // size of the (conceptual) set 00379 // $E\cup S_N$. 00380 00381 Indices S_B; // nonbasic constraints ( S_B '=' B_S) 00382 00383 QP_basis_inverse<ET,Is_linear> 00384 inv_M_B; // inverse of basis matrix 00385 00386 const ET& d; // reference to `inv_M_B.denominator()' 00387 00388 Values x_B_O; // basic variables (original) 00389 // Note: x_B_O is only enlarged, 00390 // so its size need not be |B|. 00391 00392 Values x_B_S; // basic variables (slack) 00393 Values lambda; // lambda (from KKT conditions) 00394 Bound_index_values x_O_v_i; // bounds value index vector 00395 // the following vectors are updated 00396 // with each update in order to avoid 00397 // evaluating a matrix vector 00398 // multiplication 00399 Values r_C; // r_C = A_{C,N_O}x_{N_O} 00400 // Note: r_C.size() == C.size(). 00401 00402 Values r_S_B; // r_S_B = A_{S_B,N_O}x_{N_O} 00403 00404 // The following to variables are initialized (if used at all) in 00405 // transition(). They are not used in case Is_linear or 00406 // Is_nonnegative is set to Tag_true. 00407 Values r_B_O; // r_B_O = 2D_{B_O,N_O}x_{N_O} 00408 Values w; // w = 2D_{O, N_O}x_{N_O} 00409 00410 int m_phase; // phase of the Simplex method 00411 Quadratic_program_status m_status; // status of last pivot step 00412 int m_pivots; // number of pivot steps 00413 00414 bool is_phaseI; // flag indicating phase I 00415 bool is_phaseII;// flag indicating phase II 00416 bool is_RTS_transition; // flag indicating transition 00417 // from Ratio Test Step1 to Ratio 00418 // Test Step2 00419 const bool is_LP; // flag indicating a linear program 00420 const bool is_QP; // flag indicating a quadratic program 00421 00422 // the following flag indicates whether the program is in equational form 00423 // AND still has all its equations; this is given in phase I for any 00424 // program in equational form, but it may change if redundant constraints 00425 // get removed from the basis. If no_ineq == true, the program is treated 00426 // in a more efficient manner, since in that case we need no bookkeeping 00427 // for basic constraints 00428 bool no_ineq; 00429 bool has_ineq; // !no_ineq 00430 00431 const bool is_nonnegative; // standard form, from Tag 00432 00433 // additional variables 00434 int l; // minimum of 'qp_n+e+1' and 'qp_m' 00435 // Note: this is an upper bound for 00436 // the size of the reduced basis in 00437 // phase I (in phase II, the reduced 00438 // basis size can be arbitrarily 00439 // large) 00440 00441 int e; // number of equality constraints 00442 00443 // Given a variable number i, in_B[i] is -1 iff x_i is not in the current 00444 // basis. If the number in_B[i] is >=0, it is the basis heading of x_i. 00445 Indices in_B; // variable in basis, -1 if non-basic 00446 00447 // Given a number i in {0,...,qp_m-1} of a constraint, 00448 Indices in_C; // constraint in basis, -1 if non-basic 00449 // Note: in_C is only maintained if 00450 // there are inequality constraints. 00451 00452 Values b_C; // exact version of `qp_b' 00453 // restricted to basic constraints C 00454 Values minus_c_B; // exact version of `-qp_c' 00455 // restricted to basic variables B_O 00456 // Note: minus_c_B is only enlarged, 00457 // so its size need not be |B|. 00458 00459 Values A_Cj; // exact version of j-th column of A 00460 // restricted to basic constraints C 00461 Values two_D_Bj; // exact version of twice the j-th 00462 // column of D restricted to B_O 00463 // Note: tmp_x_2 is only enlarged, 00464 // so its size need not be |B|. 00465 00466 int j; // index of entering variable `x_j' 00467 00468 int i; // index of leaving variable `x_i' 00469 ET x_i; // numerator of leaving variable `x_i' 00470 ET q_i; // corresponding `q_i' 00471 int direction; // indicates whether the current 00472 // entering variable x_j is increased 00473 // or decreased 00474 Bound_index ratio_test_bound_index; // indicates for leaving 00475 // original variables which bound 00476 // was hit with upper bounding 00477 00478 ET mu; // numerator of `t_j' 00479 ET nu; // denominator of `t_j' 00480 00481 Values q_lambda; // length dependent on C 00482 Values q_x_O; // used in the ratio test & update 00483 // Note: q_x_O is only enlarged, 00484 // so its size need not be |B|. 00485 00486 Values q_x_S; // 00487 00488 Values tmp_l; // temporary vector of size l 00489 Values tmp_x; // temporary vector of s. >= B_O.size() 00490 // Note: tmp_x is only enlarged, 00491 // so its size need not be |B|. 00492 00493 Values tmp_l_2; // temporary vector of size l 00494 Values tmp_x_2; // temporary vector of s. >= B_O.size() 00495 // Note: tmp_x_2 is only enlarged, 00496 // so its size need not be |B|. 00497 // Diagnostics 00498 struct Diagnostics { 00499 bool redundant_equations; 00500 }; 00501 00502 Diagnostics diagnostics; 00503 00504 public: 00505 00506 /* 00507 * Note: Some member functions below are suffixed with '_'. 00508 * They are member templates and their declaration is "hidden", 00509 * because they are also implemented in the class interface. 00510 * This is a workaround for M$-VC++, which otherwise fails to 00511 * instantiate them correctly. 00512 */ 00513 00514 // creation & initialization 00515 // ------------------------- 00516 // creation 00517 QP_solver(const Q& qp, 00518 const Quadratic_program_options& options = 00519 Quadratic_program_options()); 00520 00521 virtual ~QP_solver() 00522 { 00523 if (strategyP != static_cast<Pricing_strategy*>(0)) 00524 delete strategyP; 00525 } 00526 00527 00528 private: 00529 // set-up of QP 00530 void set( const Q& qp); 00531 void set_D (const Q& qp, Tag_true is_linear); 00532 void set_D (const Q& qp, Tag_false is_linear); 00533 00534 // set-up of explicit bounds 00535 void set_explicit_bounds(const Q& qp); 00536 void set_explicit_bounds(const Q& qp, Tag_true /*is_nonnegative*/); 00537 void set_explicit_bounds(const Q& qp, Tag_false /*is_nonnegative*/); 00538 00539 // initialization (of phase I) 00540 void init( ); 00541 00542 // initialization (of phase II) 00543 /* 00544 template < class InputIterator > 00545 void init( InputIterator basic_variables_first, 00546 InputIterator basic_variables_beyond); 00547 */ 00548 00549 // operations 00550 // ---------- 00551 // pivot step 00552 Quadratic_program_status pivot( ) 00553 { CGAL_qpe_assertion( phase() > 0); 00554 CGAL_qpe_assertion( phase() < 3); 00555 pivot_step(); 00556 return status(); } 00557 00558 // solve QP 00559 Quadratic_program_status solve( ) 00560 { CGAL_qpe_assertion( phase() > 0); 00561 while ( phase() < 3) { pivot_step(); } 00562 return status(); } 00563 00564 public: 00565 00566 // access 00567 // ------ 00568 // access to QP 00569 int number_of_variables ( ) const { return qp_n; } 00570 int number_of_constraints( ) const { return qp_m; } 00571 00572 A_iterator a_begin( ) const { return qp_A; } 00573 A_iterator a_end ( ) const { return qp_A+qp_n; } 00574 00575 B_iterator b_begin( ) const { return qp_b; } 00576 B_iterator b_end ( ) const { return qp_b+qp_m; } 00577 00578 C_iterator c_begin( ) const { return qp_c; } 00579 C_iterator c_end ( ) const { return qp_c+qp_n; } 00580 00581 C_entry c_0 ( ) const { return qp_c0;} 00582 00583 D_iterator d_begin( ) const { return qp_D; } 00584 D_iterator d_end ( ) const { return qp_D+qp_n; } 00585 00586 Row_type_iterator row_type_begin( ) const { return qp_r; } 00587 Row_type_iterator row_type_end ( ) const { return qp_r+qp_m; } 00588 00589 // access to current status 00590 int phase ( ) const { return m_phase; } 00591 Quadratic_program_status status ( ) const { return m_status; } 00592 int iterations( ) const { return m_pivots; } 00593 00594 // access to common denominator 00595 const ET& variables_common_denominator( ) const 00596 { 00597 CGAL_qpe_assertion (d > 0); 00598 return d; 00599 } 00600 00601 // access to current solution 00602 ET solution_numerator( ) const; 00603 00604 // access to current solution 00605 ET solution_denominator( ) const { return et2*d*d; } 00606 00607 // access to original variables 00608 int number_of_original_variables( ) const { return qp_n; } 00609 00610 // access to slack variables 00611 int number_of_slack_variables( ) const { return slack_A.size(); } 00612 00613 // access to artificial variables 00614 int number_of_artificial_variables( ) const { return art_A.size(); } 00615 00616 C_auxiliary_iterator 00617 c_auxiliary_value_iterator_begin( ) const { return aux_c.begin(); } 00618 C_auxiliary_iterator 00619 c_auxiliary_value_iterator_end( ) const {return aux_c.end(); } 00620 00621 // access to basic variables 00622 int number_of_basic_variables( ) const { return B_O.size()+B_S.size(); } 00623 int number_of_basic_original_variables( ) const { return B_O.size(); } 00624 int number_of_basic_slack_variables( ) const { return B_S.size(); } 00625 00626 Basic_variable_index_iterator 00627 basic_original_variable_indices_begin( ) const { return B_O.begin(); } 00628 Basic_variable_index_iterator 00629 basic_original_variable_indices_end ( ) const { return B_O.end(); } 00630 00631 Basic_variable_numerator_iterator 00632 basic_original_variables_numerator_begin( ) const { return x_B_O.begin(); } 00633 Basic_variable_numerator_iterator 00634 basic_original_variables_numerator_end ( ) const { return x_B_O.begin() 00635 + B_O.size(); } 00636 00637 public: // only the pricing strategies (including user-defined ones 00638 // need access to this) -- make them friends? 00639 00640 // access to working variables 00641 int number_of_working_variables( ) const { return in_B.size(); } 00642 00643 bool is_basic( int j) const 00644 { 00645 CGAL_qpe_assertion(j >= 0); 00646 CGAL_qpe_assertion(j < number_of_working_variables()); 00647 return (in_B[ j] >= 0); 00648 } 00649 00650 bool is_original(int j) const 00651 { 00652 CGAL_qpe_assertion(j >= 0); 00653 CGAL_qpe_assertion(j < number_of_working_variables()); 00654 return (j < qp_n); 00655 } 00656 00657 bool phaseI( ) const {return is_phaseI;} 00658 00659 bool is_artificial(int k) const; 00660 00661 int get_l() const; 00662 00663 // Returns w[j] for an original variable x_j. 00664 ET w_j_numerator(int j) const 00665 { 00666 CGAL_qpe_assertion((0 <= j) && (j < qp_n) && is_phaseII); 00667 return w[j]; 00668 } 00669 00670 Bound_index nonbasic_original_variable_bound_index(int i) const 00671 // Returns on which bound the nonbasic variable x_i is currently 00672 // sitting: 00673 // 00674 // - LOWER: the variable is sitting on its lower bound. 00675 // - UPPER: the variable is sitting on its upper bound. 00676 // - FIXED: the variable is sitting on its lower and upper bound. 00677 // - ZERO: the variable has value zero and is sitting on its lower 00678 // bound, its upper bound, or betweeen the two bounds. 00679 // 00680 // Note: in the latter case you can call state_of_zero_nonbasic_variable() 00681 // to find out which bound is active, if any. 00682 { 00683 CGAL_assertion(!check_tag(Is_nonnegative()) && 00684 !is_basic(i) && i < qp_n); 00685 if (x_O_v_i[i] == BASIC) { 00686 CGAL_qpe_assertion(false); 00687 } 00688 return x_O_v_i[i]; 00689 }; 00690 00691 int state_of_zero_nonbasic_variable(int i) const 00692 // Returns -1 if the original variable x_i equals its lower bound, 00693 // 0 if it lies strictly between its lower and upper bound, and 1 if 00694 // it coincides with its upper bound. 00695 // 00696 // See also the documentation of nonbasic_original_variable_bound_index() 00697 // above. 00698 { 00699 CGAL_assertion(!check_tag(Is_nonnegative()) && 00700 !is_basic(i) && i < qp_n && x_O_v_i[i] == ZERO); 00701 if (*(qp_fl+i) && CGAL::is_zero(*(qp_l+i))) 00702 return -1; 00703 if (*(qp_fu+i) && CGAL::is_zero(*(qp_u+i))) 00704 return 1; 00705 return 0; 00706 } 00707 00708 private: 00709 // miscellaneous 00710 // ------------- 00711 // setting the pricing strategy: 00712 void set_pricing_strategy ( Quadratic_program_pricing_strategy strategy); 00713 00714 // diagnostic output 00715 void set_verbosity( int verbose = 0, std::ostream& stream = std::cout); 00716 00717 00718 public: 00719 // access to indices of basic constraints 00720 int number_of_basic_constraints( ) const { return C.size(); } 00721 00722 Basic_constraint_index_iterator 00723 basic_constraint_indices_begin( ) const { return C.begin(); } 00724 Basic_constraint_index_iterator 00725 basic_constraint_indices_end ( ) const { return C.end(); } 00726 00727 // helper functions 00728 template < class RndAccIt1, class RndAccIt2, class NT > 00729 NT mu_j_( int j, RndAccIt1 lambda_it, RndAccIt2 x_it, const NT& dd) const; 00730 00731 ET dual_variable( int i) 00732 { 00733 for ( int j = 0; j < qp_m; ++j) { 00734 tmp_x[ j] = inv_M_B.entry( j, i); 00735 } 00736 return std::inner_product( tmp_x.begin(), tmp_x.begin()+qp_m, 00737 minus_c_B.begin(), et0); 00738 } 00739 00740 public: 00741 // public access to compressed lambda (used in filtered base) 00742 Value_const_iterator get_lambda_begin() const 00743 { 00744 return lambda.begin(); 00745 } 00746 Value_const_iterator get_lambda_end() const 00747 { 00748 return lambda.begin() + C.size(); 00749 } 00750 00751 00752 private: 00753 00754 // private member functions 00755 // ------------------------ 00756 // initialization 00757 void init_basis( ); 00758 void init_basis__slack_variables( int s_i, Tag_true has_no_inequalities); 00759 void init_basis__slack_variables( int s_i, Tag_false has_no_inequalities); 00760 void init_basis__slack_variables( int s_i, bool has_no_inequalities) { 00761 if (has_no_inequalities) 00762 init_basis__slack_variables (s_i, Tag_true()); 00763 else 00764 init_basis__slack_variables (s_i, Tag_false()); 00765 } 00766 00767 void init_basis__constraints ( int s_i, Tag_true has_no_inequalities); 00768 void init_basis__constraints ( int s_i, Tag_false has_no_inequalities); 00769 void init_basis__constraints ( int s_i, bool has_no_inequalities) { 00770 if (has_no_inequalities) 00771 init_basis__constraints (s_i, Tag_true()); 00772 else 00773 init_basis__constraints (s_i, Tag_false()); 00774 } 00775 00776 void init_x_O_v_i(); 00777 void init_r_C(Tag_true /*is_nonnegative*/); 00778 void init_r_C(Tag_false /*is_nonnegative*/); 00779 void init_r_S_B(Tag_true /*is_nonnegative*/); 00780 void init_r_S_B(Tag_false /*is_nonnegative*/); 00781 00782 void init_r_B_O(); 00783 void init_w(); 00784 00785 00786 void init_solution( ); 00787 void init_solution__b_C( Tag_true has_no_inequalities); 00788 void init_solution__b_C( Tag_false has_no_inequalities); 00789 void init_solution__b_C( bool has_no_inequalities) { 00790 if (has_no_inequalities) 00791 init_solution__b_C (Tag_true()); 00792 else 00793 init_solution__b_C (Tag_false()); 00794 } 00795 00796 void init_additional_data_members( ); 00797 00798 // function needed for set up of auxiliary problem for symbolic perturbation 00799 int signed_leading_exponent( int row); 00800 // This is a variant of set_up_auxiliary_problem for symbolic perturbation 00801 // for the perturbed case 00802 void set_up_auxiliary_problemI( Tag_true is_perturbed); 00803 00804 void set_up_auxiliary_problem(); 00805 00806 // transition (to phase II) 00807 void transition( ); 00808 void transition( Tag_true is_linear); 00809 void transition( Tag_false is_linear); 00810 00811 // pivot step 00812 void pivot_step( ); 00813 00814 // pricing 00815 void pricing( ); 00816 00817 template < class NT, class It > 00818 void mu_j__linear_part_( NT& mu_j, int j, It lambda_it, 00819 Tag_true has_no_inequalities) const; 00820 template < class NT, class It > 00821 void mu_j__linear_part_( NT& mu_j, int j, It lambda_it, 00822 Tag_false has_no_inequalities) const; 00823 template < class NT, class It > 00824 void mu_j__linear_part_( NT& mu_j, int j, It lambda_it, 00825 bool has_no_inequalities) const { 00826 if (has_no_inequalities) 00827 mu_j__linear_part_ (mu_j, j, lambda_it, Tag_true()); 00828 else 00829 mu_j__linear_part_ (mu_j, j, lambda_it, Tag_false()); 00830 } 00831 00832 00833 // template < class NT, class It > 00834 // void mu_j__quadratic_part_( NT& mu_j, int j, It x_it, 00835 // Tag_true is_linear) const; 00836 // template < class NT, class It > 00837 // void mu_j__quadratic_part_( NT& mu_j, int j, It x_it, 00838 // Tag_false is_linear) const; 00839 // template < class NT, class It > 00840 // void mu_j__quadratic_part_( NT& mu_j, int j, It x_it, 00841 // Tag_false is_linear, 00842 // Tag_true is_symmetric) const; 00843 // template < class NT, class It > 00844 // void mu_j__quadratic_part_( NT& mu_j, int j, It x_it, 00845 // Tag_false is_linear, 00846 // Tag_false is_symmetric) const; 00847 00848 template < class NT, class It > 00849 void mu_j__slack_or_artificial_( NT& mu_j, int j, It lambda_it, 00850 const NT& dd, 00851 Tag_true has_no_inequalities) const; 00852 template < class NT, class It > 00853 void mu_j__slack_or_artificial_( NT& mu_j, int j, It lambda_it, 00854 const NT& dd, 00855 Tag_false has_no_inequalities) const; 00856 00857 template < class NT, class It > 00858 void mu_j__slack_or_artificial_( NT& mu_j, int j, It lambda_it, 00859 const NT& dd, 00860 bool has_no_inequalities) const { 00861 if (has_no_inequalities) 00862 mu_j__slack_or_artificial_ (mu_j, j, lambda_it, dd, Tag_true()); 00863 else 00864 mu_j__slack_or_artificial_ (mu_j, j, lambda_it, dd, Tag_false()); 00865 } 00866 00867 // ratio test 00868 void ratio_test_init( ); 00869 void ratio_test_init__A_Cj( Value_iterator A_Cj_it, int j, 00870 Tag_true has_no_inequalities); 00871 void ratio_test_init__A_Cj( Value_iterator A_Cj_it, int j, 00872 Tag_false has_no_inequalities); 00873 void ratio_test_init__A_Cj( Value_iterator A_Cj_it, int j, 00874 bool has_no_inequalities) { 00875 if (has_no_inequalities) 00876 ratio_test_init__A_Cj (A_Cj_it, j, Tag_true()); 00877 else 00878 ratio_test_init__A_Cj (A_Cj_it, j, Tag_false()); 00879 } 00880 00881 void ratio_test_init__2_D_Bj( Value_iterator two_D_Bj_it, int j, 00882 Tag_true is_linear); 00883 void ratio_test_init__2_D_Bj( Value_iterator two_D_Bj_it, int j, 00884 Tag_false is_linear); 00885 void ratio_test_init__2_D_Bj( Value_iterator two_D_Bj_it, int j, 00886 Tag_false is_linear, 00887 Tag_true has_no_inequalities); 00888 void ratio_test_init__2_D_Bj( Value_iterator two_D_Bj_it, int j, 00889 Tag_false is_linear, 00890 Tag_false has_no_inequalities); 00891 void ratio_test_init__2_D_Bj( Value_iterator two_D_Bj_it, int j, 00892 Tag_false is_linear, 00893 bool has_no_inequalities) { 00894 if (has_no_inequalities) 00895 ratio_test_init__2_D_Bj( two_D_Bj_it, j, is_linear, Tag_true()); 00896 else 00897 ratio_test_init__2_D_Bj( two_D_Bj_it, j, is_linear, Tag_false()); 00898 } 00899 00900 00901 void ratio_test_1( ); 00902 void ratio_test_1__q_x_O( Tag_true is_linear); 00903 void ratio_test_1__q_x_O( Tag_false is_linear); 00904 void ratio_test_1__q_x_S( Tag_true has_no_inequalities); 00905 void ratio_test_1__q_x_S( Tag_false has_no_inequalities); 00906 void ratio_test_1__q_x_S( bool has_no_inequalities) { 00907 if (has_no_inequalities) 00908 ratio_test_1__q_x_S (Tag_true()); 00909 else 00910 ratio_test_1__q_x_S (Tag_false()); 00911 } 00912 00913 void ratio_test_1__t_min_j(Tag_true /*is_nonnegative*/); 00914 void ratio_test_1__t_min_j(Tag_false /*is_nonnegative*/); 00915 00916 void ratio_test_1__t_i( Index_iterator i_it, Index_iterator end_it, 00917 Value_iterator x_it, Value_iterator q_it, 00918 Tag_true no_check); 00919 void ratio_test_1__t_i( Index_iterator i_it, Index_iterator end_it, 00920 Value_iterator x_it, Value_iterator q_it, 00921 Tag_false no_check); 00922 00923 // replaces the above two functions 00924 void ratio_test_1__t_min_B(Tag_true has_no_inequalities ); 00925 void ratio_test_1__t_min_B(Tag_false has_no_inequalities ); 00926 void ratio_test_1__t_min_B(bool has_no_inequalities ) { 00927 if (has_no_inequalities) 00928 ratio_test_1__t_min_B (Tag_true()); 00929 else 00930 ratio_test_1__t_min_B (Tag_false()); 00931 } 00932 00933 void ratio_test_1_B_O__t_i(Index_iterator i_it, Index_iterator end_it, 00934 Value_iterator x_it, Value_iterator q_it, 00935 Tag_true /*is_nonnegative*/); 00936 void ratio_test_1_B_O__t_i(Index_iterator i_it, Index_iterator end_it, 00937 Value_iterator x_it, Value_iterator q_it, 00938 Tag_false /*is_nonnegative*/); 00939 void ratio_test_1_B_S__t_i(Index_iterator i_it, Index_iterator end_it, 00940 Value_iterator x_it, Value_iterator q_it, 00941 Tag_true /*is_nonnegative*/); 00942 void ratio_test_1_B_S__t_i(Index_iterator i_it, Index_iterator end_it, 00943 Value_iterator x_it, Value_iterator q_it, 00944 Tag_false /*is_nonnegative*/); 00945 00946 void test_implicit_bounds_dir_pos(int k, const ET& x_k, const ET& q_k, 00947 int& i_min, ET& d_min, ET& q_min); 00948 void test_implicit_bounds_dir_neg(int k, const ET& x_k, const ET& q_k, 00949 int& i_min, ET& d_min, ET& q_min); 00950 void test_explicit_bounds_dir_pos(int k, const ET& x_k, const ET& q_k, 00951 int& i_min, ET& d_min, ET& q_min); 00952 void test_explicit_bounds_dir_neg(int k, const ET& x_k, const ET& q_k, 00953 int& i_min, ET& d_min, ET& q_min); 00954 void test_mixed_bounds_dir_pos(int k, const ET& x_k, const ET& q_k, 00955 int& i_min, ET& d_min, ET& q_min); 00956 void test_mixed_bounds_dir_neg(int k, const ET& x_k, const ET& q_k, 00957 int& i_min, ET& d_min, ET& q_min); 00958 00959 void ratio_test_1__t_j( Tag_true is_linear); 00960 void ratio_test_1__t_j( Tag_false is_linear); 00961 00962 void ratio_test_2( Tag_true is_linear); 00963 void ratio_test_2( Tag_false is_linear); 00964 void ratio_test_2__p( Tag_true has_no_inequalities); 00965 void ratio_test_2__p( Tag_false has_no_inequalities); 00966 void ratio_test_2__p( bool has_no_inequalities) { 00967 if (has_no_inequalities) 00968 ratio_test_2__p (Tag_true()); 00969 else 00970 ratio_test_2__p (Tag_false()); 00971 } 00972 00973 // update 00974 void update_1( ); 00975 void update_1( Tag_true is_linear); 00976 void update_1( Tag_false is_linear); 00977 00978 void update_2( Tag_true is_linear); 00979 void update_2( Tag_false is_linear); 00980 00981 void replace_variable( ); 00982 void replace_variable( Tag_true has_no_inequalities); 00983 void replace_variable( Tag_false has_no_inequalities); 00984 void replace_variable( bool has_no_inequalities) { 00985 if (has_no_inequalities) 00986 replace_variable (Tag_true()); 00987 else 00988 replace_variable (Tag_false()); 00989 } 00990 00991 void replace_variable_original_original( ); 00992 // update of the vector r 00993 void replace_variable_original_original_upd_r(Tag_true 00994 /*is_nonnegative*/); 00995 void replace_variable_original_original_upd_r(Tag_false 00996 /*is_nonnegative*/); 00997 00998 void replace_variable_original_slack( ); 00999 // update of the vector r 01000 void replace_variable_original_slack_upd_r(Tag_true /*is_nonnegative*/); 01001 void replace_variable_original_slack_upd_r(Tag_false /*is_nonnegative*/); 01002 01003 void replace_variable_slack_original( ); 01004 // update of the vector r 01005 void replace_variable_slack_original_upd_r(Tag_true /*is_nonnegative*/); 01006 void replace_variable_slack_original_upd_r(Tag_false /*is_nonnegative*/); 01007 01008 void replace_variable_slack_slack( ); 01009 // update of the vector r 01010 void replace_variable_slack_slack_upd_r(Tag_true /*is_nonnegative*/); 01011 void replace_variable_slack_slack_upd_r(Tag_false /*is_nonnegative*/); 01012 01013 void remove_artificial_variable_and_constraint( ); 01014 // update of the vector r 01015 void remove_artificial_variable_and_constraint_upd_r(Tag_true 01016 /*is_nonnegative*/); 01017 void remove_artificial_variable_and_constraint_upd_r(Tag_false 01018 /*is_nonnegative*/); 01019 01020 void expel_artificial_variables_from_basis( ); 01021 01022 // update that occurs only with upper bounding in ratio test step 1 01023 void enter_and_leave_variable( ); 01024 01025 void enter_variable( ); 01026 // update of the vectors w and r 01027 void enter_variable_original_upd_w_r(Tag_true /*is_nonnegative*/); 01028 void enter_variable_original_upd_w_r(Tag_false /*is_nonnegative*/); 01029 void enter_variable_slack_upd_w_r(Tag_true /*is_nonnegative*/); 01030 void enter_variable_slack_upd_w_r(Tag_false /*is_nonnegative*/); 01031 01032 void leave_variable( ); 01033 // update of the vectors w and r 01034 void leave_variable_original_upd_w_r(Tag_true /*is_nonnegative*/); 01035 void leave_variable_original_upd_w_r(Tag_false /*is_nonnegative*/); 01036 void leave_variable_slack_upd_w_r(Tag_true /*is_nonnegative*/); 01037 void leave_variable_slack_upd_w_r(Tag_false /*is_nonnegative*/); 01038 01039 void z_replace_variable( ); 01040 void z_replace_variable( Tag_true has_no_inequalities); 01041 void z_replace_variable( Tag_false has_no_inequalities); 01042 void z_replace_variable( bool has_no_inequalities) { 01043 if (has_no_inequalities) 01044 z_replace_variable (Tag_true()); 01045 else 01046 z_replace_variable (Tag_false()); 01047 } 01048 01049 void z_replace_variable_original_by_original( ); 01050 // update of the vectors w and r 01051 void z_replace_variable_original_by_original_upd_w_r(Tag_true 01052 /*is_nonnegative*/); 01053 void z_replace_variable_original_by_original_upd_w_r(Tag_false 01054 /*is_nonnegative*/); 01055 01056 void z_replace_variable_original_by_slack( ); 01057 // update of the vectors w and r 01058 void z_replace_variable_original_by_slack_upd_w_r(Tag_true 01059 /*is_nonnegative*/); 01060 void z_replace_variable_original_by_slack_upd_w_r(Tag_false 01061 /*is_nonnegative*/); 01062 01063 void z_replace_variable_slack_by_original( ); 01064 // update of the vectors w and r 01065 void z_replace_variable_slack_by_original_upd_w_r(Tag_true 01066 /*is_nonnegative*/); 01067 void z_replace_variable_slack_by_original_upd_w_r(Tag_false 01068 /*is_nonnegative*/); 01069 01070 void z_replace_variable_slack_by_slack( ); 01071 // update of the vectors w and r 01072 void z_replace_variable_slack_by_slack_upd_w_r(Tag_true 01073 /*is_nonnegative*/); 01074 void z_replace_variable_slack_by_slack_upd_w_r(Tag_false 01075 /*is_nonnegative*/); 01076 01077 // update of the parts r_C and r_S_B 01078 void update_r_C_r_S_B__j(ET& x_j); 01079 void update_r_C_r_S_B__j_i(ET& x_j, ET& x_i); 01080 void update_r_C_r_S_B__i(ET& x_i); 01081 01082 // update of w and r_B_O 01083 void update_w_r_B_O__j(ET& x_j); 01084 void update_w_r_B_O__j_i(ET& x_j, ET& x_i); 01085 void update_w_r_B_O__i(ET& x_i); 01086 01087 01088 bool basis_matrix_stays_regular( ); 01089 01090 // current solution 01091 void compute_solution(Tag_true /*is_nonnegative*/); 01092 void compute_solution(Tag_false /*is_nonnegative*/); 01093 01094 void compute__x_B_S( Tag_false has_no_inequalities, 01095 Tag_false /*is_nonnegative*/); 01096 void compute__x_B_S( Tag_false has_no_inequalities, 01097 Tag_true /*is_nonnegative*/); 01098 void compute__x_B_S( Tag_true has_no_inequalities, 01099 Tag_false /*is_nonnegative*/); 01100 void compute__x_B_S( Tag_true has_no_inequalities, 01101 Tag_true /*is_nonnegative*/); 01102 void compute__x_B_S( bool has_no_inequalities, 01103 Tag_true is_nonnegative) { 01104 if (has_no_inequalities) 01105 compute__x_B_S (Tag_true(), is_nonnegative); 01106 else 01107 compute__x_B_S (Tag_false(), is_nonnegative); 01108 } 01109 01110 void compute__x_B_S( bool has_no_inequalities, 01111 Tag_false is_nonnegative) { 01112 if (has_no_inequalities) 01113 compute__x_B_S (Tag_true(), is_nonnegative); 01114 else 01115 compute__x_B_S (Tag_false(), is_nonnegative); 01116 } 01117 01118 void multiply__A_S_BxB_O( Value_iterator in, Value_iterator out) const; 01119 01120 ET multiply__A_ixO(int row) const; 01121 void multiply__A_CxN_O(Value_iterator out) const; 01122 bool check_r_C(Tag_true /*is_nonnegative*/) const; 01123 bool check_r_C(Tag_false /*is_nonnegative*/) const; 01124 01125 void multiply__A_S_BxN_O(Value_iterator out) const; 01126 bool check_r_S_B(Tag_true /*is_nonnegative*/) const; 01127 bool check_r_S_B(Tag_false /*is_nonnegative*/) const; 01128 01129 void multiply__2D_B_OxN_O(Value_iterator out) const; 01130 bool check_r_B_O(Tag_true /*is_nonnegative*/) const; 01131 bool check_r_B_O(Tag_false /*is_nonnegative*/) const; 01132 01133 void multiply__2D_OxN_O(Value_iterator out) const; 01134 bool check_w(Tag_true /*is_nonnegative*/) const; 01135 bool check_w(Tag_false /*is_nonnegative*/) const; 01136 01137 // utility routines for QP's in nonstandard form: 01138 ET original_variable_value_under_bounds(int i) const; 01139 ET nonbasic_original_variable_value (int i) const; 01140 01141 public: 01142 // for original variables 01143 ET variable_numerator_value(int i) const; 01144 ET unbounded_direction_value(int i) const; 01145 ET lambda_numerator(int i) const 01146 { 01147 // we use the vector lambda which conforms to C (basic constraints) 01148 CGAL_qpe_assertion (i >= 0); 01149 CGAL_qpe_assertion (i <= qp_m); 01150 if (no_ineq) 01151 return lambda[i]; 01152 else { 01153 int k = in_C[i]; // position of i in C 01154 if (k != -1) 01155 return lambda[k]; 01156 else 01157 return et0; 01158 } 01159 } 01160 01161 private: 01162 // check basis inverse 01163 bool check_basis_inverse( ); 01164 bool check_basis_inverse( Tag_true is_linear); 01165 bool check_basis_inverse( Tag_false is_linear); 01166 01167 // diagnostic output 01168 void print_program ( ) const; 01169 void print_basis ( ) const; 01170 void print_solution( ) const; 01171 void print_ratio_1_original(int k, const ET& x_k, const ET& q_k); 01172 void print_ratio_1_slack(int k, const ET& x_k, const ET& q_k); 01173 01174 const char* variable_type( int k) const; 01175 01176 // ensure container size 01177 template <class Container> 01178 void ensure_size(Container& c, typename Container::size_type desired_size) { 01179 typedef typename Container::value_type Value_type; 01180 for (typename Container::size_type i=c.size(); i < desired_size; ++i) { 01181 c.push_back(Value_type()); 01182 } 01183 } 01184 01185 private: 01186 01187 private: // (inefficient) access to bounds of variables: 01188 // Given an index of an original or slack variable, returns whether 01189 // or not the variable has a finite lower bound. 01190 bool has_finite_lower_bound(int i) const; 01191 01192 // Given an index of an original or slack variable, returns whether 01193 // or not the variable has a finite upper bound. 01194 bool has_finite_upper_bound(int i) const; 01195 01196 // Given an index of an original or slack variable, returns its 01197 // lower bound. 01198 ET lower_bound(int i) const; 01199 01200 // Given an index of an original variable, returns its upper bound. 01201 ET upper_bound(int i) const; 01202 01203 struct Bnd { // (inefficient) utility class representing a possibly 01204 // infinite bound 01205 enum Kind { MINUS_INF=-1, FINITE=0, PLUS_INF=1 }; 01206 const Kind kind; // whether the bound is finite or not 01207 const ET value; // bound's value in case it is finite 01208 01209 Bnd(bool is_upper, bool is_finite, const ET& value) 01210 : kind(is_upper? (is_finite? FINITE : PLUS_INF) : 01211 (is_finite? FINITE : MINUS_INF)), 01212 value(value) {} 01213 Bnd(Kind kind, const ET& value) : kind(kind), value(value) {} 01214 01215 bool operator==(const ET& v) const { return kind == FINITE && value == v; } 01216 bool operator==(const Bnd& b) const { 01217 return kind == b.kind && (kind != FINITE || value == b.value); 01218 } 01219 bool operator!=(const Bnd& b) const { return !(*this == b); } 01220 bool operator<(const ET& v) const { return kind == FINITE && value < v; } 01221 bool operator<(const Bnd& b) const { 01222 return kind < b.kind || 01223 (kind == b.kind && kind == FINITE && value < b.value); 01224 } 01225 bool operator<=(const Bnd& b) const { return *this < b || *this == b; } 01226 bool operator>(const ET& v) const { return kind == FINITE && value > v; } 01227 bool operator>(const Bnd& b) const { return !(*this <= b); } 01228 bool operator>=(const Bnd& b) const { return !(*this < b); } 01229 01230 Bnd operator*(const ET& f) const { return Bnd(kind, value*f); } 01231 }; 01232 01233 // Given an index of an original, slack, or artificial variable, 01234 // return its lower bound. 01235 Bnd lower_bnd(int i) const; 01236 01237 // Given an index of an original, slack, or artificial variable, 01238 // return its upper bound. 01239 Bnd upper_bnd(int i) const; 01240 01241 private: 01242 bool is_value_correct() const; 01243 // ---------------------------------------------------------------------------- 01244 01245 // =============================== 01246 // class implementation (template) 01247 // =============================== 01248 01249 public: 01250 01251 // pricing 01252 // ------- 01253 // The solver provides three methods to compute mu_j; the first 01254 // two below take additional information (which the pricing 01255 // strategy either provides in exact- or NT-form), and the third 01256 // simply does the exact computation. (Note: internally, we use 01257 // the third version, too, see ratio_test_1__t_j().) 01258 01259 // computation of mu_j with standard form 01260 template < class RndAccIt1, class RndAccIt2, class NT > 01261 NT 01262 mu_j( int j, RndAccIt1 lambda_it, RndAccIt2 x_it, const NT& dd) const 01263 { 01264 NT mu_j; 01265 01266 if ( j < qp_n) { // original variable 01267 01268 // [c_j +] A_Cj^T * lambda_C 01269 mu_j = ( is_phaseI ? NT( 0) : dd * NT(*(qp_c+ j))); 01270 mu_j__linear_part( mu_j, j, lambda_it, no_ineq); 01271 01272 // ... + 2 D_Bj^T * x_B 01273 mu_j__quadratic_part( mu_j, j, x_it, Is_linear()); 01274 01275 } else { // slack or artificial 01276 01277 mu_j__slack_or_artificial( mu_j, j, lambda_it, dd, 01278 no_ineq); 01279 01280 } 01281 01282 return mu_j; 01283 } 01284 01285 // computation of mu_j with upper bounding 01286 template < class RndAccIt1, class RndAccIt2, class NT > 01287 NT 01288 mu_j( int j, RndAccIt1 lambda_it, RndAccIt2 x_it, const NT& w_j, 01289 const NT& dd) const 01290 { 01291 NT mu_j; 01292 01293 if ( j < qp_n) { // original variable 01294 01295 // [c_j +] A_Cj^T * lambda_C 01296 mu_j = ( is_phaseI ? NT( 0) : dd * NT(*(qp_c+ j))); 01297 mu_j__linear_part( mu_j, j, lambda_it, no_ineq); 01298 01299 // ... + 2 D_Bj^T * x_B + 2 D_Nj x_N 01300 mu_j__quadratic_part( mu_j, j, x_it, w_j, dd, Is_linear()); 01301 01302 } else { // slack or artificial 01303 01304 mu_j__slack_or_artificial( mu_j, j, lambda_it, dd, 01305 no_ineq); 01306 01307 } 01308 01309 return mu_j; 01310 } 01311 01312 // computation of mu_j (exact, both for upper bounding and standard form) 01313 ET 01314 mu_j( int j) const 01315 { 01316 CGAL_qpe_assertion(!is_basic(j)); 01317 01318 if (!check_tag(Is_nonnegative()) && 01319 !check_tag(Is_linear()) && 01320 !is_phaseI && is_original(j)) { 01321 return mu_j(j, 01322 lambda.begin(), 01323 basic_original_variables_numerator_begin(), 01324 w_j_numerator(j), 01325 variables_common_denominator()); 01326 } else { 01327 return mu_j(j, 01328 lambda.begin(), 01329 basic_original_variables_numerator_begin(), 01330 variables_common_denominator()); 01331 } 01332 } 01333 01334 private: 01335 01336 // pricing (private helper functions) 01337 // ---------------------------------- 01338 template < class NT, class It > inline // no ineq. 01339 void 01340 mu_j__linear_part( NT& mu_j, int j, It lambda_it, Tag_true) const 01341 { 01342 mu_j += inv_M_B.inner_product_l( lambda_it, *(qp_A+ j)); 01343 } 01344 01345 template < class NT, class It > inline // has ineq. 01346 void 01347 mu_j__linear_part( NT& mu_j, int j, It lambda_it, Tag_false) const 01348 { 01349 mu_j += inv_M_B.inner_product_l 01350 ( lambda_it, 01351 A_by_index_iterator( C.begin(), 01352 A_by_index_accessor( *(qp_A + j)))); 01353 } 01354 01355 template < class NT, class It > inline 01356 void 01357 mu_j__linear_part( NT& mu_j, int j, It lambda_it, 01358 bool has_no_inequalities) const { 01359 if (has_no_inequalities) 01360 mu_j__linear_part (mu_j, j, lambda_it, Tag_true()); 01361 else 01362 mu_j__linear_part (mu_j, j, lambda_it, Tag_false()); 01363 } 01364 01365 template < class NT, class It > inline // LP case, standard form 01366 void 01367 mu_j__quadratic_part( NT&, int, It, Tag_true) const 01368 { 01369 // nop 01370 } 01371 01372 template < class NT, class It > inline // LP case, upper bounded 01373 void 01374 mu_j__quadratic_part( NT&, int, It, const NT& /*w_j*/, const NT& /*dd*/, 01375 Tag_true) const 01376 { 01377 // nop 01378 } 01379 01380 template < class NT, class It > inline // QP case, standard form 01381 void 01382 mu_j__quadratic_part( NT& mu_j, int j, It x_it, Tag_false) const 01383 { 01384 if ( is_phaseII) { 01385 // 2 D_Bj^T * x_B 01386 mu_j += inv_M_B.inner_product_x 01387 ( x_it, 01388 D_pairwise_iterator_input_type( B_O.begin(), 01389 D_pairwise_accessor_input_type(qp_D, j))); 01390 } 01391 } 01392 01393 template < class NT, class It > inline // QP case, upper bounded 01394 void 01395 mu_j__quadratic_part( NT& mu_j, int j, It x_it, const NT& w_j, 01396 const NT& dd, Tag_false) const 01397 { 01398 if ( is_phaseII) { 01399 mu_j += dd * w_j; 01400 // 2 D_Bj^T * x_B 01401 mu_j += inv_M_B.inner_product_x 01402 ( x_it, 01403 D_pairwise_iterator_input_type( B_O.begin(), 01404 D_pairwise_accessor_input_type(qp_D, j))); 01405 } 01406 } 01407 01408 01409 template < class NT, class It > inline // no ineq. 01410 void 01411 mu_j__slack_or_artificial( NT& mu_j, int j, It lambda_it, const NT& dd, Tag_true) const 01412 { 01413 j -= qp_n; 01414 // artificial variable 01415 // A_j^T * lambda 01416 mu_j = lambda_it[ j]; 01417 if ( art_A[ j].second) mu_j = -mu_j; 01418 01419 // c_j + ... 01420 mu_j += dd*NT(aux_c[ j]); 01421 01422 } 01423 01424 template < class NT, class It > inline // has ineq. 01425 void 01426 mu_j__slack_or_artificial( NT& mu_j, int j, It lambda_it, const NT& dd, Tag_false) const 01427 { 01428 j -= qp_n; 01429 01430 if ( j < (int)slack_A.size()) { // slack variable 01431 01432 // A_Cj^T * lambda_C 01433 mu_j = lambda_it[ in_C[ slack_A[ j].first]]; 01434 if ( slack_A[ j].second) mu_j = -mu_j; 01435 01436 } else { // artificial variable 01437 j -= slack_A.size(); 01438 01439 // A_Cj^T * lambda_C 01440 mu_j = lambda_it[ in_C[ art_A[ j].first]]; 01441 if ( art_A[ j].second) mu_j = -mu_j; 01442 01443 // c_j + ... 01444 mu_j += dd*NT(aux_c[ j]); 01445 } 01446 } 01447 01448 template < class NT, class It > inline 01449 void 01450 mu_j__slack_or_artificial( NT& mu_j, int j, It lambda_it, 01451 const NT& dd, bool has_no_inequalities) const { 01452 if (has_no_inequalities) 01453 mu_j__slack_or_artificial (mu_j, j, lambda_it, dd, Tag_true()); 01454 else 01455 mu_j__slack_or_artificial (mu_j, j, lambda_it, dd, Tag_false()); 01456 } 01457 }; 01458 01459 // ---------------------------------------------------------------------------- 01460 01461 // ============================= 01462 // class implementation (inline) 01463 // ============================= 01464 01465 // initialization 01466 // -------------- 01467 01468 // transition 01469 // ---------- 01470 template < class Q, typename ET, typename Tags > inline // QP case 01471 void QP_solver<Q, ET, Tags>:: 01472 transition( Tag_false) 01473 { 01474 typedef Creator_2< D_iterator, int, 01475 D_pairwise_accessor > D_transition_creator_accessor; 01476 01477 typedef Creator_2< Index_iterator, D_pairwise_accessor, 01478 D_pairwise_iterator > D_transition_creator_iterator; 01479 01480 // initialization of vector w and vector r_B_O: 01481 if (!check_tag(Is_nonnegative())) { 01482 init_w(); 01483 init_r_B_O(); 01484 } 01485 01486 // here is what we need in the transition: an iterator that steps through 01487 // the basic indices, where dereferencing 01488 // yields an iterator through the corresponding row of D, restricted 01489 // to the basic indices. This means that we select the principal minor of D 01490 // corresponding to the current basis. 01491 01492 // To realize this, we transform B_O.begin() via the function h where 01493 // h(i) = D_pairwise_iterator 01494 // (B_O.begin(), 01495 // D_pairwise_accessor(qp_D, i)) 01496 01497 01498 inv_M_B.transition 01499 (boost::make_transform_iterator 01500 (B_O.begin(), 01501 boost::bind 01502 (D_transition_creator_iterator(), B_O.begin(), 01503 boost::bind (D_transition_creator_accessor(), qp_D, _1)))); 01504 } 01505 01506 template < typename Q, typename ET, typename Tags > inline // LP case 01507 void QP_solver<Q, ET, Tags>:: 01508 transition( Tag_true) 01509 { 01510 inv_M_B.transition(); 01511 } 01512 01513 // ratio test 01514 // ---------- 01515 template < typename Q, typename ET, typename Tags > inline // LP case 01516 void QP_solver<Q, ET, Tags>:: 01517 ratio_test_init__2_D_Bj( Value_iterator, int, Tag_true) 01518 { 01519 // nop 01520 } 01521 01522 template < typename Q, typename ET, typename Tags > inline // QP case 01523 void QP_solver<Q, ET, Tags>:: 01524 ratio_test_init__2_D_Bj( Value_iterator two_D_Bj_it, int j_, Tag_false) 01525 { 01526 if ( is_phaseII) { 01527 ratio_test_init__2_D_Bj( two_D_Bj_it, j_, 01528 Tag_false(), no_ineq); 01529 } 01530 } 01531 01532 template < typename Q, typename ET, typename Tags > inline // QP, no ineq. 01533 void QP_solver<Q, ET, Tags>:: 01534 ratio_test_init__2_D_Bj( Value_iterator two_D_Bj_it, int j_, Tag_false, 01535 Tag_true ) 01536 { 01537 // store exact version of `2 D_{B_O,j}' 01538 D_pairwise_accessor d_accessor( qp_D, j_); 01539 std::copy( D_pairwise_iterator( B_O.begin(), d_accessor), 01540 D_pairwise_iterator( B_O.end (), d_accessor), 01541 two_D_Bj_it); 01542 } 01543 01544 template < typename Q, typename ET, typename Tags > inline // QP, has ineq 01545 void QP_solver<Q, ET, Tags>:: 01546 ratio_test_init__2_D_Bj( Value_iterator two_D_Bj_it, int j_, Tag_false, 01547 Tag_false) 01548 { 01549 // store exact version of `2 D_{B_O,j}' 01550 if ( j_ < qp_n) { // original variable 01551 ratio_test_init__2_D_Bj( two_D_Bj_it, j_, Tag_false(), Tag_true()); 01552 } else { // slack variable 01553 std::fill_n( two_D_Bj_it, B_O.size(), et0); 01554 } 01555 } 01556 01557 template < typename Q, typename ET, typename Tags > inline // LP case 01558 void QP_solver<Q, ET, Tags>:: 01559 ratio_test_1__q_x_O( Tag_true) 01560 { 01561 inv_M_B.multiply_x( A_Cj.begin(), q_x_O.begin()); 01562 } 01563 01564 template < typename Q, typename ET, typename Tags > inline // QP case 01565 void QP_solver<Q, ET, Tags>:: 01566 ratio_test_1__q_x_O( Tag_false) 01567 { 01568 if ( is_phaseI) { // phase I 01569 inv_M_B.multiply_x( A_Cj.begin(), q_x_O.begin()); 01570 } else { // phase II 01571 inv_M_B.multiply ( A_Cj.begin(), two_D_Bj.begin(), 01572 q_lambda.begin(), q_x_O.begin()); 01573 } 01574 } 01575 01576 template < typename Q, typename ET, typename Tags > inline // no ineq. 01577 void QP_solver<Q, ET, Tags>:: 01578 ratio_test_1__q_x_S( Tag_true) 01579 { 01580 // nop 01581 } 01582 01583 template < typename Q, typename ET, typename Tags > inline // has ineq. 01584 void QP_solver<Q, ET, Tags>:: 01585 ratio_test_1__q_x_S( Tag_false) 01586 { 01587 // A_S_BxB_O * q_x_O 01588 multiply__A_S_BxB_O( q_x_O.begin(), q_x_S.begin()); 01589 01590 // ( A_S_BxB_O * q_x_O) - A_S_Bxj 01591 if ( j < qp_n) { 01592 std::transform( q_x_S.begin(), 01593 q_x_S.begin()+S_B.size(), 01594 A_by_index_iterator( S_B.begin(), 01595 A_by_index_accessor( *(qp_A + j))), 01596 q_x_S.begin(), 01597 compose2_2( std::minus<ET>(), 01598 Identity<ET>(), 01599 std::bind1st( std::multiplies<ET>(), d))); 01600 } 01601 01602 // q_x_S = -+ ( A_S_BxB_O * q_x_O - A_S_Bxj) 01603 Value_iterator q_it = q_x_S.begin(); 01604 Index_iterator i_it; 01605 for ( i_it = B_S.begin(); i_it != B_S.end(); ++i_it, ++q_it) { 01606 if ( ! slack_A[ *i_it - qp_n].second) *q_it = -(*q_it); 01607 } 01608 } 01609 01610 template < typename Q, typename ET, typename Tags > inline // no check 01611 void QP_solver<Q, ET, Tags>:: 01612 ratio_test_1__t_i( Index_iterator, Index_iterator, 01613 Value_iterator, Value_iterator, Tag_true) 01614 { 01615 // nop 01616 } 01617 01618 template < typename Q, typename ET, typename Tags > inline // check 01619 void QP_solver<Q, ET, Tags>:: 01620 ratio_test_1__t_i( Index_iterator i_it, Index_iterator end_it, 01621 Value_iterator x_it, Value_iterator q_it, Tag_false) 01622 { 01623 // check `t_i's 01624 for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it) { 01625 if ( ( *q_it > et0) && ( ( *x_it * q_i) < ( x_i * *q_it))) { 01626 i = *i_it; x_i = *x_it; q_i = *q_it; 01627 } 01628 } 01629 } 01630 01631 template < typename Q, typename ET, typename Tags > inline // LP case 01632 void QP_solver<Q, ET, Tags>:: 01633 ratio_test_1__t_j( Tag_true) 01634 { 01635 // nop 01636 } 01637 01638 template < typename Q, typename ET, typename Tags > inline // QP case 01639 void QP_solver<Q, ET, Tags>:: 01640 ratio_test_1__t_j( Tag_false) 01641 { 01642 if ( is_phaseII) { 01643 01644 // compute `nu' and `mu_j' 01645 mu = mu_j(j); 01646 nu = inv_M_B.inner_product( A_Cj.begin(), two_D_Bj.begin(), 01647 q_lambda.begin(), q_x_O.begin()); 01648 if ( j < qp_n) { // original variable 01649 nu -= d*ET( (*(qp_D + j))[ j]); 01650 } 01651 CGAL_qpe_assertion_msg(nu <= et0, 01652 "nu <= et0 violated -- is your D matrix positive semidefinite?"); 01653 01654 // check `t_j' 01655 CGAL_qpe_assertion(mu != et0); 01656 // bg: formula below compares abs values, assuming mu < 0 01657 if ( ( nu < et0) && ( ( (mu < et0 ? mu : -mu) * q_i) > ( x_i * nu))) { 01658 i = -1; q_i = et1; 01659 } 01660 } 01661 } 01662 01663 template < typename Q, typename ET, typename Tags > inline // LP case 01664 void QP_solver<Q, ET, Tags>:: 01665 ratio_test_2( Tag_true) 01666 { 01667 // nop 01668 } 01669 01670 template < typename Q, typename ET, typename Tags > inline // no ineq. 01671 void QP_solver<Q, ET, Tags>:: 01672 ratio_test_2__p( Tag_true) 01673 { 01674 // get column index of entering variable in basis 01675 int col = in_B[ j]; 01676 01677 CGAL_qpe_assertion( col >= 0); 01678 col += l; 01679 01680 // get (last) column of `M_B^{-1}' (Note: `p_...' is stored in `q_...') 01681 Value_iterator it; 01682 int row; 01683 unsigned int k; 01684 for ( k = 0, row = 0, it = q_lambda.begin(); 01685 k < C.size(); 01686 ++k, ++row, ++it ) { 01687 *it = inv_M_B.entry( row, col); 01688 } 01689 for ( k = 0, row = l, it = q_x_O.begin(); 01690 k < B_O.size(); 01691 ++k, ++row, ++it ) { 01692 *it = inv_M_B.entry( row, col); 01693 } 01694 } 01695 01696 template < typename Q, typename ET, typename Tags > inline // has ineq. 01697 void QP_solver<Q, ET, Tags>:: 01698 ratio_test_2__p( Tag_false) 01699 { 01700 Value_iterator v_it; 01701 Index_iterator i_it; 01702 01703 // compute 'p_lambda' and 'p_x_O' (Note: `p_...' is stored in `q_...') 01704 // ------------------------------------------------------------------- 01705 01706 // type of entering variable 01707 if ( j < qp_n) { // original 01708 01709 // use 'no_ineq' variant 01710 ratio_test_2__p( Tag_true()); 01711 01712 } else { // slack 01713 01714 j -= qp_n; 01715 01716 // get column A_{S_j,B_O}^T (i.e. row of A_{S_B,B_O}) 01717 int row = slack_A[ j].first; 01718 bool sign = slack_A[ j].second; 01719 01720 for ( i_it = B_O.begin(), v_it = tmp_x.begin(); 01721 i_it != B_O.end(); 01722 ++i_it, ++v_it ) { 01723 *v_it = ( sign ? 01724 *((*(qp_A+ *i_it))+ row) : - (*((*(qp_A + *i_it))+ row))); 01725 } 01726 01727 // compute ( p_l | p_x_O )^T = M_B^{-1} * ( 0 | A_{S_j,B_O} )^T 01728 std::fill_n( tmp_l.begin(), C.size(), et0); 01729 inv_M_B.multiply( tmp_l .begin(), tmp_x .begin(), 01730 q_lambda.begin(), q_x_O.begin()); 01731 01732 j += qp_n; 01733 } 01734 01735 // compute 'p_x_S' 01736 // --------------- 01737 // A_S_BxB_O * p_x_O 01738 multiply__A_S_BxB_O( q_x_O.begin(), q_x_S.begin()); 01739 01740 // p_x_S = +- ( A_S_BxB_O * p_x_O) 01741 for ( i_it = B_S.begin(), v_it = q_x_S.begin(); 01742 i_it != B_S.end(); 01743 ++i_it, ++v_it ) { 01744 if ( ! slack_A[ *i_it - qp_n].second) *v_it = -(*v_it); 01745 } 01746 } 01747 01748 // update 01749 // ------ 01750 template < typename Q, typename ET, typename Tags > inline // LP case 01751 void QP_solver<Q, ET, Tags>:: 01752 update_1( Tag_true) 01753 { 01754 // replace leaving with entering variable 01755 if ((i == j) && (i >= 0)) { 01756 enter_and_leave_variable(); 01757 } else { 01758 replace_variable(); 01759 } 01760 } 01761 01762 template < typename Q, typename ET, typename Tags > inline // QP case 01763 void QP_solver<Q, ET, Tags>:: 01764 update_1( Tag_false) 01765 { 01766 if ( is_phaseI) { // phase I 01767 01768 // replace leaving with entering variable 01769 if ((i == j) && (i >= 0)) { 01770 enter_and_leave_variable(); 01771 } else { 01772 replace_variable(); 01773 } 01774 01775 } else { // phase II 01776 01777 if ((i == j) && (i >= 0)) { 01778 enter_and_leave_variable(); 01779 } else { 01780 01781 if ( ( i >= 0) && basis_matrix_stays_regular()) { 01782 01783 // leave variable from basis, if 01784 // - some leaving variable was found and 01785 // - basis matrix stays regular 01786 leave_variable(); 01787 01788 } else { 01789 01790 // enter variable into basis, if 01791 // - no leaving variable was found or 01792 // - basis matrix would become singular when variable i leaves 01793 01794 if ( i < 0 ) { 01795 enter_variable(); 01796 } else { 01797 z_replace_variable(); 01798 } 01799 } 01800 } 01801 } 01802 } 01803 01804 template < typename Q, typename ET, typename Tags > inline // LP case 01805 void QP_solver<Q, ET, Tags>:: 01806 update_2( Tag_true) 01807 { 01808 // nop 01809 } 01810 01811 template < typename Q, typename ET, typename Tags > inline // no ineq. 01812 void QP_solver<Q, ET, Tags>:: 01813 replace_variable( Tag_true) 01814 { 01815 replace_variable_original_original(); 01816 strategyP->leaving_basis( i); 01817 } 01818 01819 template < typename Q, typename ET, typename Tags > inline // has ineq. 01820 void QP_solver<Q, ET, Tags>:: 01821 replace_variable( Tag_false) 01822 { 01823 // determine type of variables 01824 bool enter_original = ( (j < qp_n) || (j >= (int)( qp_n+slack_A.size()))); 01825 bool leave_original = ( (i < qp_n) || (i >= (int)( qp_n+slack_A.size()))); 01826 01827 // update basis & basis inverse 01828 if ( leave_original) { 01829 if ( enter_original) { // orig <--> orig 01830 replace_variable_original_original(); 01831 } else { // slack <--> orig 01832 replace_variable_slack_original(); 01833 } 01834 01835 // special artificial variable removed? 01836 if ( is_phaseI && ( i == art_s_i)) { 01837 // remove the fake column - it corresponds 01838 // to the special artificial variable which is 01839 // (like all artificial variables) not needed 01840 // anymore once it leaves the basis. Note: 01841 // regular artificial variables are only removed 01842 // from the problem after phase I 01843 // art_s_i == -1 -> there is no special artificial variable 01844 // art_s_i == -2 -> there was a special artificial variable, 01845 // but has been removed 01846 art_s_i = -2; 01847 art_A.pop_back(); 01848 CGAL_qpe_assertion(in_B[in_B.size()-1] == -1); // really removed? 01849 in_B.pop_back(); 01850 // BG: shouldn't the pricing strategy be notfied also here? 01851 } else { 01852 strategyP->leaving_basis( i); 01853 } 01854 } else { 01855 if ( enter_original) { // orig <--> slack 01856 replace_variable_original_slack(); 01857 } else { // slack <--> slack 01858 replace_variable_slack_slack(); 01859 } 01860 strategyP->leaving_basis( i); 01861 } 01862 } 01863 01864 template < typename Q, typename ET, typename Tags > inline 01865 bool QP_solver<Q, ET, Tags>:: 01866 basis_matrix_stays_regular() 01867 { 01868 CGAL_qpe_assertion( is_phaseII); 01869 int new_row, k; 01870 01871 if ( has_ineq && (i >= qp_n)) { // slack variable 01872 new_row = slack_A[ i-qp_n].first; 01873 A_row_by_index_accessor a_accessor = 01874 boost::bind (A_accessor( qp_A, 0, qp_n), _1, new_row); 01875 std::copy( A_row_by_index_iterator( B_O.begin(), a_accessor), 01876 A_row_by_index_iterator( B_O.end (), a_accessor), 01877 tmp_x.begin()); 01878 inv_M_B.multiply( tmp_x.begin(), // dummy (not used) 01879 tmp_x.begin(), tmp_l_2.begin(), tmp_x_2.begin(), 01880 Tag_false(), // QP 01881 Tag_false()); // ignore 1st argument 01882 return ( -inv_M_B.inner_product_x( tmp_x_2.begin(), tmp_x.begin()) != et0); 01883 01884 01885 } else { // check original variable 01886 k = l+in_B[ i]; 01887 return ( inv_M_B.entry( k, k) != et0); 01888 } 01889 01890 /* ToDo: check, if really not needed in 'update_1': 01891 - basis has already minimal size or 01892 || ( B_O.size()==C.size()) 01893 */ 01894 } 01895 01896 // current solution 01897 // ---------------- 01898 template < typename Q, typename ET, typename Tags > inline // no inequalities, upper bounded 01899 void QP_solver<Q, ET, Tags>:: 01900 compute__x_B_S( Tag_true /*has_equalities_only_and_full_rank*/, 01901 Tag_false /*is_nonnegative*/) 01902 { 01903 // nop 01904 } 01905 01906 template < typename Q, typename ET, typename Tags > inline // no inequalities, standard form 01907 void QP_solver<Q, ET, Tags>:: 01908 compute__x_B_S( Tag_true /*has_equalities_only_and_full_rank*/, 01909 Tag_true /*is_nonnegative*/) 01910 { 01911 // nop 01912 } 01913 01914 01915 template < typename Q, typename ET, typename Tags > inline // has inequalities, upper bounded 01916 void QP_solver<Q, ET, Tags>:: 01917 compute__x_B_S( Tag_false /*has_equalities_only_and_full_rank*/, 01918 Tag_false /*is_nonnegative*/) 01919 { 01920 // A_S_BxB_O * x_B_O 01921 multiply__A_S_BxB_O( x_B_O.begin(), x_B_S.begin()); 01922 01923 // b_S_B - ( A_S_BxB_O * x_B_O) 01924 B_by_index_accessor b_accessor( qp_b); 01925 std::transform( B_by_index_iterator( S_B.begin(), b_accessor), 01926 B_by_index_iterator( S_B.end (), b_accessor), 01927 x_B_S.begin(), 01928 x_B_S.begin(), 01929 compose2_2( std::minus<ET>(), 01930 std::bind1st( std::multiplies<ET>(), d), 01931 Identity<ET>())); 01932 01933 // b_S_B - ( A_S_BxB_O * x_B_O) - r_S_B 01934 std::transform(x_B_S.begin(), x_B_S.begin()+S_B.size(), 01935 r_S_B.begin(), x_B_S.begin(), 01936 compose2_2(std::minus<ET>(), 01937 Identity<ET>(), 01938 std::bind1st( std::multiplies<ET>(), d))); 01939 01940 01941 // x_B_S = +- ( b_S_B - A_S_BxB_O * x_B_O) 01942 Value_iterator x_it = x_B_S.begin(); 01943 Index_iterator i_it; 01944 for ( i_it = B_S.begin(); i_it != B_S.end(); ++i_it, ++x_it) { 01945 if ( slack_A[ *i_it - qp_n].second) *x_it = -(*x_it); 01946 } 01947 01948 } 01949 01950 01951 01952 template < typename Q, typename ET, typename Tags > inline // has inequalities, standard form 01953 void QP_solver<Q, ET, Tags>:: 01954 compute__x_B_S( Tag_false /*has_equalities_only_and_full_rank*/, 01955 Tag_true /*is_nonnegative*/) 01956 { 01957 // A_S_BxB_O * x_B_O 01958 multiply__A_S_BxB_O( x_B_O.begin(), x_B_S.begin()); 01959 01960 // b_S_B - ( A_S_BxB_O * x_B_O) 01961 B_by_index_accessor b_accessor( qp_b); 01962 std::transform( B_by_index_iterator( S_B.begin(), b_accessor), 01963 B_by_index_iterator( S_B.end (), b_accessor), 01964 x_B_S.begin(), 01965 x_B_S.begin(), 01966 compose2_2( std::minus<ET>(), 01967 std::bind1st( std::multiplies<ET>(), d), 01968 Identity<ET>())); 01969 01970 // x_B_S = +- ( b_S_B - A_S_BxB_O * x_B_O) 01971 Value_iterator x_it = x_B_S.begin(); 01972 Index_iterator i_it; 01973 for ( i_it = B_S.begin(); i_it != B_S.end(); ++i_it, ++x_it) { 01974 if ( slack_A[ *i_it - qp_n].second) *x_it = -(*x_it); 01975 } 01976 01977 } 01978 01979 CGAL_END_NAMESPACE 01980 01981 #include <CGAL/QP_solver/Unbounded_direction.h> 01982 #include <CGAL/QP_solver/QP_solver_nonstandardform_impl.h> 01983 #include <CGAL/QP_solver/QP_solver_bounds_impl.h> 01984 #include <CGAL/QP_solver/QP_solver_impl.h> 01985 01986 #endif // CGAL_QP_SOLVER_H 01987 01988 // ===== EOF ==================================================================