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 // Licensees 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_impl.h $ 00015 // $Id: QP_solver_impl.h 46194 2008-10-09 13:07:49Z gaertner $ 00016 // 00017 // 00018 // Author(s) : Sven Schoenherr 00019 // Bernd Gaertner <gaertner@inf.ethz.ch> 00020 // Franz Wessendorp 00021 // Kaspar Fischer 00022 00023 #include <CGAL/QP_solver/Initialization.h> 00024 00025 CGAL_BEGIN_NAMESPACE 00026 00027 // ============================= 00028 // class implementation (cont'd) 00029 // ============================= 00030 00031 // transition (to phase II) 00032 // ------------------------ 00033 template < typename Q, typename ET, typename Tags > 00034 void 00035 QP_solver<Q, ET, Tags>:: 00036 transition( ) 00037 { 00038 CGAL_qpe_debug { 00039 if ( vout.verbose()) { 00040 vout2 << std::endl 00041 << "----------------------" << std::endl 00042 << 'T'; 00043 vout1 << "[ t"; vout << "ransition to phase II"; vout1 << " ]"; 00044 vout << std::endl; 00045 vout2 << "----------------------"; 00046 } 00047 } 00048 00049 // update status 00050 m_phase = 2; 00051 is_phaseI = false; 00052 is_phaseII = true; 00053 00054 // remove artificial variables 00055 in_B.erase( in_B.begin()+qp_n+slack_A.size(), in_B.end()); 00056 //ensure_size(tmp_x_2, tmp_x.size()); 00057 // update basis inverse 00058 CGAL_qpe_debug { 00059 vout4 << std::endl << "basis-inverse:" << std::endl; 00060 } 00061 transition( Is_linear()); 00062 CGAL_qpe_debug { 00063 check_basis_inverse(); 00064 } 00065 00066 // initialize exact version of `-qp_c' (implicit conversion to ET) 00067 C_by_index_accessor c_accessor( qp_c); 00068 std::transform( C_by_index_iterator( B_O.begin(), c_accessor), 00069 C_by_index_iterator( B_O.end (), c_accessor), 00070 minus_c_B.begin(), std::negate<ET>()); 00071 00072 // compute initial solution of phase II 00073 compute_solution(Is_nonnegative()); 00074 00075 // diagnostic output 00076 CGAL_qpe_debug { 00077 if ( vout.verbose()) print_solution(); 00078 } 00079 00080 // notify pricing strategy 00081 strategyP->transition(); 00082 } 00083 00084 // access 00085 // ------ 00086 // numerator of current solution; the denominator is 2*d*d, so we should 00087 // compute here d*d*(x^T2Dx + x^T2c + 2c0) 00088 template < typename Q, typename ET, typename Tags > 00089 ET QP_solver<Q, ET, Tags>:: 00090 solution_numerator( ) const 00091 { 00092 ET s, z = et0; 00093 int i, j; 00094 00095 if (check_tag(Is_nonnegative()) || is_phaseI) { 00096 // standard form or phase I; it suffices to go 00097 // through the basic variables; all D- and c-entries 00098 // are obtained through the appropriate iterators 00099 Index_const_iterator i_it; 00100 Value_const_iterator x_i_it, c_it; 00101 00102 // foreach i 00103 x_i_it = x_B_O.begin(); 00104 c_it = minus_c_B .begin(); 00105 for ( i_it = B_O.begin(); i_it != B_O.end(); ++i_it, ++x_i_it, ++c_it){ 00106 i = *i_it; 00107 00108 // compute quadratic part: 2D_i x 00109 s = et0; 00110 if ( is_QP && is_phaseII) { 00111 // half the off-diagonal contribution 00112 s += std::inner_product(x_B_O.begin(), x_i_it, 00113 D_pairwise_iterator( 00114 B_O.begin(), 00115 D_pairwise_accessor( qp_D, i)), 00116 et0); 00117 // the other half 00118 s *= et2; 00119 // diagonal contribution 00120 s += ET( (*(qp_D + i))[ i]) * *x_i_it; 00121 } 00122 // add linear part: 2c_i 00123 s -= d * et2 * ET( *c_it); 00124 00125 // add x_i(2D_i x + 2c_i) 00126 z += s * *x_i_it; // endowed with a factor of d*d now 00127 } 00128 } else { 00129 // nonstandard form and phase II, 00130 // take all original variables into account; all D- and c-entries 00131 // are obtained from the input data directly 00132 // order in i_it and j_it matches original variable order 00133 if (is_QP) { 00134 // quadratic part 00135 i=0; 00136 for (Variable_numerator_iterator 00137 i_it = this->original_variables_numerator_begin(); 00138 i_it < this->original_variables_numerator_end(); ++i_it, ++i) { 00139 // do something only if *i_it != 0 00140 if (*i_it == et0) continue; 00141 s = et0; // contribution of i-th row 00142 Variable_numerator_iterator j_it = 00143 this->original_variables_numerator_begin(); 00144 // half the off-diagonal contribution 00145 j=0; 00146 for (; j<i; ++j_it, ++j) 00147 s += ET(*((*(qp_D+i))+j)) * *j_it; 00148 // the other half 00149 s *= et2; 00150 // the diagonal entry 00151 s += ET(*((*(qp_D+i))+j)) * *j_it; 00152 // accumulate 00153 z += s * *i_it; 00154 } 00155 } 00156 // linear part 00157 j=0; s = et0; 00158 for (Variable_numerator_iterator 00159 j_it = this->original_variables_numerator_begin(); 00160 j_it < this->original_variables_numerator_end(); ++j_it, ++j) 00161 s += et2 * ET(*(qp_c+j)) * *j_it; 00162 z += d * s; 00163 } 00164 // finally, add the constant term (phase II only) 00165 if (is_phaseII) z += et2 * ET(qp_c0) * d * d; 00166 return z; 00167 } 00168 00169 // pivot step 00170 // ---------- 00171 template < typename Q, typename ET, typename Tags > 00172 void 00173 QP_solver<Q, ET, Tags>:: 00174 pivot_step( ) 00175 { 00176 ++m_pivots; 00177 00178 // diagnostic output 00179 CGAL_qpe_debug { 00180 vout2 << std::endl 00181 << "==========" << std::endl 00182 << "Pivot Step" << std::endl 00183 << "==========" << std::endl; 00184 } 00185 vout << "[ phase " << ( is_phaseI ? "I" : "II") 00186 << ", iteration " << m_pivots << " ]" << std::endl; 00187 00188 00189 // pricing 00190 // ------- 00191 pricing(); 00192 00193 00194 // check for optimality 00195 if ( j < 0) { 00196 00197 if ( is_phaseI) { // phase I 00198 // since we no longer assume full row rank and subsys assumption 00199 // we have to strengthen the precondition for infeasibility 00200 if (this->solution_numerator() > et0) { 00201 // problem is infeasible 00202 m_phase = 3; 00203 m_status = QP_INFEASIBLE; 00204 00205 vout << " "; 00206 vout << "problem is INFEASIBLE" << std::endl; 00207 00208 } else { // Drive/remove artificials out of basis 00209 expel_artificial_variables_from_basis(); 00210 transition(); 00211 } 00212 } else { // phase II 00213 00214 // optimal solution found 00215 m_phase = 3; 00216 m_status = QP_OPTIMAL; 00217 00218 vout << " "; 00219 vout << "solution is OPTIMAL" << std::endl; 00220 00221 } 00222 return; 00223 } 00224 00225 00226 // ratio test & update (step 1) 00227 // ---------------------------- 00228 // initialize ratio test 00229 ratio_test_init(); 00230 00231 00232 // diagnostic output 00233 CGAL_qpe_debug { 00234 if ( vout2.verbose() && is_QP && is_phaseII) { 00235 vout2.out() << std::endl 00236 << "----------------------------" << std::endl 00237 << "Ratio Test & Update (Step 1)" << std::endl 00238 << "----------------------------" << std::endl; 00239 } 00240 } 00241 00242 // loop (step 1) 00243 do { 00244 00245 // ratio test 00246 ratio_test_1(); 00247 00248 // check for unboundedness 00249 if ( q_i == et0) { 00250 m_phase = 3; 00251 m_status = QP_UNBOUNDED; 00252 00253 vout << " "; 00254 vout << "problem is UNBOUNDED" << std::endl; 00255 00256 CGAL_qpe_debug { 00257 //nu should be zero in this case 00258 // note: (-1)/hat{\nu} is stored instead of \hat{\nu} 00259 // todo kf: as this is just used for an assertion check, 00260 // all the following lines should only be executed if 00261 // assertions are enabled... 00262 nu = inv_M_B.inner_product( A_Cj.begin(), two_D_Bj.begin(), 00263 q_lambda.begin(), q_x_O.begin()); 00264 if (is_QP) { 00265 if (j < qp_n) { 00266 nu -= d*ET(*((*(qp_D+j))+j)); 00267 } 00268 } 00269 CGAL_qpe_assertion(nu == et0); 00270 } 00271 return; 00272 } 00273 00274 // update 00275 update_1(); 00276 00277 } while ( j >= 0); 00278 00279 // ratio test & update (step 2) 00280 // ---------------------------- 00281 /* 00282 if ( i >= 0) { 00283 00284 // diagnostic output 00285 CGAL_qpe_debug { 00286 vout2 << std::endl 00287 << "----------------------------" << std::endl 00288 << "Ratio Test & Update (Step 2)" << std::endl 00289 << "----------------------------" << std::endl; 00290 } 00291 00292 // compute index of entering variable 00293 j += in_B.size(); 00294 00295 // loop (step 2) 00296 while ( ( i >= 0) && basis_matrix_stays_regular()) { 00297 00298 // update 00299 update_2( Is_linear()); 00300 00301 // ratio test 00302 ratio_test_2( Is_linear()); 00303 } 00304 } 00305 */ 00306 // instead of the above piece of code we now have 00307 // diagnostic output 00308 if (is_RTS_transition) { 00309 is_RTS_transition = false; 00310 00311 CGAL_qpe_debug { 00312 vout2 << std::endl 00313 << "----------------------------" << std::endl 00314 << "Ratio Test & Update (Step 2)" << std::endl 00315 << "----------------------------" << std::endl; 00316 } 00317 00318 // compute index of entering variable 00319 j += in_B.size(); 00320 00321 ratio_test_2( Is_linear()); 00322 00323 while ((i >= 0) && basis_matrix_stays_regular()) { 00324 00325 update_2(Is_linear()); 00326 00327 ratio_test_2(Is_linear()); 00328 00329 } 00330 } 00331 00332 00333 00334 // ratio test & update (step 3) 00335 // ---------------------------- 00336 CGAL_qpe_assertion_msg( i < 0, "Step 3 should never be reached!"); 00337 00338 // diagnostic output 00339 00340 if ( vout.verbose()) print_basis(); 00341 if ( vout.verbose()) print_solution(); 00342 00343 // transition to phase II (if possible) 00344 // ------------------------------------ 00345 if ( is_phaseI && ( art_basic == 0)) { 00346 CGAL_qpe_debug { 00347 if ( vout2.verbose()) { 00348 vout2.out() << std::endl 00349 << "all artificial variables are nonbasic" 00350 << std::endl; 00351 } 00352 } 00353 transition(); 00354 } 00355 } 00356 00357 // pricing 00358 template < typename Q, typename ET, typename Tags > 00359 void 00360 QP_solver<Q, ET, Tags>:: 00361 pricing( ) 00362 { 00363 // diagnostic output 00364 CGAL_qpe_debug { 00365 if ( vout2.verbose()) { 00366 vout2 << std::endl 00367 << "-------" << std::endl 00368 << "Pricing" << std::endl 00369 << "-------" << std::endl; 00370 } 00371 } 00372 00373 // call pricing strategy 00374 j = strategyP->pricing(direction); 00375 00376 // diagnostic output 00377 00378 if ( vout.verbose()) { 00379 if ( j < 0) { 00380 CGAL_qpe_debug { 00381 vout2 << "entering variable: none" << std::endl; 00382 } 00383 } else { 00384 vout << " "; 00385 vout << "entering: "; 00386 vout << j; 00387 CGAL_qpe_debug { 00388 vout2 << " (" << variable_type( j) << ')' << std::endl; 00389 vout2 << "direction: " 00390 << ((direction == 1) ? "positive" : "negative") << std::endl; 00391 } 00392 } 00393 } 00394 } 00395 00396 // initialization of ratio-test 00397 template < typename Q, typename ET, typename Tags > 00398 void 00399 QP_solver<Q, ET, Tags>:: 00400 ratio_test_init( ) 00401 { 00402 // store exact version of `A_Cj' (implicit conversion) 00403 ratio_test_init__A_Cj( A_Cj.begin(), j, no_ineq); 00404 00405 // store exact version of `2 D_{B_O,j}' 00406 ratio_test_init__2_D_Bj( two_D_Bj.begin(), j, Is_linear()); 00407 } 00408 00409 template < typename Q, typename ET, typename Tags > // no ineq. 00410 void QP_solver<Q, ET, Tags>:: 00411 ratio_test_init__A_Cj( Value_iterator A_Cj_it, int j_, Tag_true) 00412 { 00413 // store exact version of `A_Cj' (implicit conversion) 00414 if ( j_ < qp_n) { // original variable 00415 00416 CGAL::copy_n( *(qp_A + j_), qp_m, A_Cj_it); 00417 00418 } else { // artificial variable 00419 00420 unsigned int k = j_; 00421 k -= qp_n; 00422 std::fill_n( A_Cj_it, qp_m, et0); 00423 A_Cj_it[ k] = ( art_A[ k].second ? -et1 : et1); 00424 } 00425 } 00426 00427 template < typename Q, typename ET, typename Tags > // has ineq. 00428 void QP_solver<Q, ET, Tags>:: 00429 ratio_test_init__A_Cj( Value_iterator A_Cj_it, int j_, Tag_false) 00430 { 00431 // store exact version of `A_Cj' (implicit conversion) 00432 if ( j_ < qp_n) { // original variable 00433 A_by_index_accessor a_accessor( *(qp_A + j_)); 00434 std::copy( A_by_index_iterator( C.begin(), a_accessor), 00435 A_by_index_iterator( C.end (), a_accessor), 00436 A_Cj_it); 00437 00438 } else { 00439 unsigned int k = j_; 00440 k -= qp_n; 00441 std::fill_n( A_Cj_it, C.size(), et0); 00442 00443 if ( k < slack_A.size()) { // slack variable 00444 00445 A_Cj_it[ in_C[ slack_A[ k].first]] = ( slack_A[ k].second ? -et1 00446 : et1); 00447 00448 } else { // artificial variable 00449 k -= slack_A.size(); 00450 00451 if ( j_ != art_s_i) { // normal art. 00452 00453 A_Cj_it[ in_C[ art_A[ k].first]] = ( art_A[ k].second ? -et1 00454 : et1); 00455 00456 } else { // special art. 00457 S_by_index_accessor s_accessor( art_s.begin()); 00458 std::copy( S_by_index_iterator( C.begin(), s_accessor), 00459 S_by_index_iterator( C.end (), s_accessor), 00460 A_Cj_it); 00461 } 00462 } 00463 } 00464 } 00465 00466 // ratio test (step 1) 00467 template < typename Q, typename ET, typename Tags > 00468 void 00469 QP_solver<Q, ET, Tags>:: 00470 ratio_test_1( ) 00471 { 00472 00473 // diagnostic output 00474 CGAL_qpe_debug { 00475 if ( vout2.verbose()) { 00476 vout2.out() << std::endl; 00477 if ( is_LP || is_phaseI) { 00478 vout2.out() << "----------" << std::endl 00479 << "Ratio Test" << std::endl 00480 << "----------" << std::endl; 00481 } else { 00482 vout2.out() << "Ratio Test (Step 1)" << std::endl 00483 << "-------------------" << std::endl; 00484 } 00485 if ( vout3.verbose()) { 00486 vout3.out() << " A_Cj: "; 00487 std::copy( A_Cj.begin(), A_Cj.begin()+C.size(), 00488 std::ostream_iterator<ET>( vout3.out()," ")); 00489 vout3.out() << std::endl; 00490 if ( is_QP && is_phaseII) { 00491 vout3.out() << " 2 D_Bj: "; 00492 std::copy( two_D_Bj.begin(), two_D_Bj.begin()+B_O.size(), 00493 std::ostream_iterator<ET>( vout3.out()," ")); 00494 vout3.out() << std::endl; 00495 } 00496 vout3.out() << std::endl; 00497 } 00498 } 00499 } 00500 00501 // compute `q_lambda' and `q_x' 00502 ratio_test_1__q_x_O( Is_linear()); 00503 ratio_test_1__q_x_S( no_ineq); 00504 00505 // diagnostic output 00506 CGAL_qpe_debug { 00507 if ( vout3.verbose()) { 00508 if ( is_QP && is_phaseII) { 00509 vout3.out() << "q_lambda: "; 00510 std::copy( q_lambda.begin(), q_lambda.begin()+C.size(), 00511 std::ostream_iterator<ET>( vout3.out()," ")); 00512 vout3.out() << std::endl; 00513 } 00514 vout3.out() << " q_x_O: "; 00515 std::copy( q_x_O.begin(), q_x_O.begin()+B_O.size(), 00516 std::ostream_iterator<ET>( vout3.out()," ")); 00517 vout3.out() << std::endl; 00518 00519 if ( has_ineq) { 00520 vout3.out() << " q_x_S: "; 00521 std::copy( q_x_S.begin(), q_x_S.begin()+B_S.size(), 00522 std::ostream_iterator<ET>( vout3.out()," ")); 00523 vout3.out() << std::endl; 00524 } 00525 vout3.out() << std::endl; 00526 } 00527 } 00528 00529 // check `t_i's 00530 x_i = et1; // trick: initialize 00531 q_i = et0; // minimum with +oo 00532 00533 // computation of t_{min}^{j} 00534 ratio_test_1__t_min_j(Is_nonnegative()); 00535 CGAL_qpe_debug { // todo kf: at first sight, this debug message should 00536 // only be output for problems in nonstandard form... 00537 if (vout2.verbose()) { 00538 vout2.out() << "t_min_j: " << x_i << '/' << q_i << std::endl; 00539 vout2.out() << std::endl; 00540 } 00541 } 00542 00543 // what happens, if all original variables are nonbasic? 00544 /* 00545 ratio_test_1__t_i( B_O.begin(), B_O.end(), 00546 x_B_O.begin(), q_x_O.begin(), Tag_false()); 00547 ratio_test_1__t_i( B_S.begin(), B_S.end(), 00548 x_B_S.begin(), q_x_S.begin(), no_ineq); 00549 */ 00550 ratio_test_1__t_min_B(no_ineq); 00551 00552 // check `t_j' 00553 ratio_test_1__t_j( Is_linear()); 00554 00555 // diagnostic output 00556 CGAL_qpe_debug { 00557 if ( vout2.verbose()) { 00558 for ( unsigned int k = 0; k < B_O.size(); ++k) { 00559 print_ratio_1_original(k, x_B_O[k], q_x_O[k]); 00560 } 00561 if ( has_ineq) { 00562 for ( unsigned int k = 0; k < B_S.size(); ++k) { 00563 /* 00564 vout2.out() << "t_S_" << k << ": " 00565 << x_B_S[ k] << '/' << q_x_S[ k] 00566 << ( ( q_i > et0) && ( i == B_S[ k]) ? " *":"") 00567 << std::endl; 00568 */ 00569 print_ratio_1_slack(k, x_B_S[k], q_x_S[k]); 00570 } 00571 } 00572 if ( is_QP && is_phaseII) { 00573 vout2.out() << std::endl 00574 << " t_j: " << mu << '/' << nu 00575 << ( ( q_i > et0) && ( i < 0) ? " *" : "") 00576 << std::endl; 00577 } 00578 vout2.out() << std::endl; 00579 } 00580 } 00581 if ( q_i > et0) { 00582 if ( i < 0) { 00583 vout2 << "leaving variable: none" << std::endl; 00584 } else { 00585 vout << ", "; 00586 vout << "leaving: "; 00587 vout << i; 00588 CGAL_qpe_debug { 00589 if ( vout2.verbose()) { 00590 if ( ( i < qp_n) || ( i >= (int)( qp_n+slack_A.size()))) { 00591 vout2.out() << " (= B_O[ " << in_B[ i] << "]: " 00592 << variable_type( i) << ')'; 00593 } else { 00594 vout2.out() << " (= B_S[ " << in_B[ i] << "]: slack)"; 00595 } 00596 } 00597 vout2 << std::endl; 00598 } 00599 00600 } 00601 } 00602 00603 } 00604 00605 00606 template < typename Q, typename ET, typename Tags > // Standard form 00607 void QP_solver<Q, ET, Tags>:: 00608 ratio_test_1__t_min_j(Tag_true /*is_nonnegative*/) 00609 { 00610 } 00611 00612 // By the pricing step we have the following precondition 00613 // direction == +1 => x_O_v_i[j] == (LOWER v ZERO) 00614 // direction == -1 => x_O_v_i[j] == (UPPER v ZERO) 00615 template < typename Q, typename ET, typename Tags > // Upper bounded 00616 void QP_solver<Q, ET, Tags>:: 00617 ratio_test_1__t_min_j(Tag_false /*is_nonnegative*/) 00618 { 00619 if (j < qp_n) { // original variable 00620 if (direction == 1) { 00621 if (x_O_v_i[j] == LOWER) { // has lower bound value 00622 if (*(qp_fu+j)) { // has finite upper bound 00623 x_i = (*(qp_u+j) - *(qp_l+j)); 00624 q_i = et1; 00625 i = j; 00626 ratio_test_bound_index = UPPER; 00627 } else { // has infinite upper bound 00628 x_i = et1; 00629 q_i = et0; 00630 } 00631 } else { // has value zero 00632 if (*(qp_fu+j)) { // has finite upper bound 00633 x_i = *(qp_u+j); 00634 q_i = et1; 00635 i = j; 00636 ratio_test_bound_index = UPPER; 00637 } else { // has infinite upper bound 00638 x_i = et1; 00639 q_i = et0; 00640 } 00641 } 00642 } else { // direction == -1 00643 if (x_O_v_i[j] == UPPER) { // has upper bound value 00644 if (*(qp_fl+j)) { // has finite lower bound 00645 x_i = (*(qp_u+j) - *(qp_l+j)); 00646 q_i = et1; 00647 i = j; 00648 ratio_test_bound_index = LOWER; 00649 } else { // has infinite lower bound 00650 x_i = et1; 00651 q_i = et0; 00652 } 00653 } else { // has value zero 00654 if (*(qp_fl+j)) { // has finite lower bound 00655 x_i = -(*(qp_l+j)); 00656 q_i = et1; 00657 i = j; 00658 ratio_test_bound_index = LOWER; 00659 } else { // has infinite lower bound 00660 x_i = et1; 00661 q_i = et0; 00662 } 00663 } 00664 } 00665 } else { // slack or artificial var 00666 x_i = et1; 00667 q_i = et0; 00668 } 00669 } 00670 00671 template < typename Q, typename ET, typename Tags > 00672 void QP_solver<Q, ET, Tags>:: 00673 ratio_test_1__t_min_B(Tag_true /*has_equalities_only_and_full_rank*/) 00674 { 00675 ratio_test_1_B_O__t_i(B_O.begin(), B_O.end(), x_B_O.begin(), 00676 q_x_O.begin(), Is_nonnegative()); 00677 } 00678 00679 template < typename Q, typename ET, typename Tags > 00680 void QP_solver<Q, ET, Tags>:: 00681 ratio_test_1__t_min_B(Tag_false /*has_equalities_only_and_full_rank*/) 00682 { 00683 ratio_test_1_B_O__t_i(B_O.begin(), B_O.end(), x_B_O.begin(), 00684 q_x_O.begin(), Is_nonnegative()); 00685 ratio_test_1_B_S__t_i(B_S.begin(), B_S.end(), x_B_S.begin(), 00686 q_x_S.begin(), Is_nonnegative()); 00687 } 00688 00689 // ratio test for the basic original variables 00690 template < typename Q, typename ET, typename Tags > // Standard form 00691 void QP_solver<Q, ET, Tags>:: 00692 ratio_test_1_B_O__t_i(Index_iterator i_it, Index_iterator end_it, 00693 Value_iterator x_it, Value_iterator q_it, 00694 Tag_true /*is_nonnegative*/) 00695 { 00696 for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) { 00697 test_implicit_bounds_dir_pos(*i_it, *x_it, *q_it, i, x_i, q_i); 00698 } 00699 } 00700 00701 // ratio test for the basic original variables 00702 template < typename Q, typename ET, typename Tags > // Upper bounded 00703 void QP_solver<Q, ET, Tags>:: 00704 ratio_test_1_B_O__t_i(Index_iterator i_it, Index_iterator end_it, 00705 Value_iterator x_it, Value_iterator q_it, 00706 Tag_false /*is_nonnegative*/) 00707 { 00708 if (is_phaseI) { 00709 if (direction == 1) { 00710 for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) { 00711 test_mixed_bounds_dir_pos(*i_it, *x_it, *q_it, i, x_i, q_i); 00712 } 00713 } else { 00714 for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) { 00715 test_mixed_bounds_dir_neg(*i_it, *x_it, *q_it, i, x_i, q_i); 00716 } 00717 } 00718 } else { 00719 if (direction == 1) { 00720 for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) { 00721 test_explicit_bounds_dir_pos(*i_it, *x_it, *q_it, i, x_i, q_i); 00722 } 00723 } else { 00724 for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) { 00725 test_explicit_bounds_dir_neg(*i_it, *x_it, *q_it, i, x_i, q_i); 00726 } 00727 } 00728 } 00729 } 00730 00731 // ratio test for the basic slack variables 00732 template < typename Q, typename ET, typename Tags > // Standard form 00733 void QP_solver<Q, ET, Tags>:: 00734 ratio_test_1_B_S__t_i(Index_iterator i_it, Index_iterator end_it, 00735 Value_iterator x_it, Value_iterator q_it, 00736 Tag_true /*is_nonnegative*/) 00737 { 00738 for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) { 00739 test_implicit_bounds_dir_pos(*i_it, *x_it, *q_it, i, x_i, q_i); 00740 } 00741 } 00742 00743 // ratio test for the basic slack variables 00744 template < typename Q, typename ET, typename Tags > // Upper bounded 00745 void QP_solver<Q, ET, Tags>:: 00746 ratio_test_1_B_S__t_i(Index_iterator i_it, Index_iterator end_it, 00747 Value_iterator x_it, Value_iterator q_it, 00748 Tag_false /*is_nonnegative*/) 00749 { 00750 if (direction == 1) { 00751 for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) { 00752 test_implicit_bounds_dir_pos(*i_it, *x_it, *q_it, i, x_i, q_i); 00753 } 00754 } else { 00755 for ( ; i_it != end_it; ++i_it, ++x_it, ++q_it ) { 00756 test_implicit_bounds_dir_neg(*i_it, *x_it, *q_it, i, x_i, q_i); 00757 } 00758 } 00759 } 00760 00761 // test for one basic variable with implicit bounds only, 00762 // note that this function writes the member variables i, x_i, q_i 00763 template < typename Q, typename ET, typename Tags > 00764 void QP_solver<Q, ET, Tags>:: 00765 test_implicit_bounds_dir_pos(int k, const ET& x_k, const ET& q_k, 00766 int& i_min, ET& d_min, ET& q_min) 00767 { 00768 if ((q_k > et0) && (x_k * q_min < d_min * q_k)) { 00769 i_min = k; 00770 d_min = x_k; 00771 q_min = q_k; 00772 } 00773 } 00774 00775 // test for one basic variable with implicit bounds only, 00776 // note that this function writes the member variables i, x_i, q_i 00777 template < typename Q, typename ET, typename Tags > 00778 void QP_solver<Q, ET, Tags>:: 00779 test_implicit_bounds_dir_neg(int k, const ET& x_k, const ET& q_k, 00780 int& i_min, ET& d_min, ET& q_min) 00781 { 00782 if ((q_k < et0) && (x_k * q_min < -(d_min * q_k))) { 00783 i_min = k; 00784 d_min = x_k; 00785 q_min = -q_k; 00786 } 00787 } 00788 00789 // test for one basic variable with explicit bounds only, 00790 // note that this function writes the member variables i, x_i, q_i and 00791 // ratio_test_bound_index, although the second and third variable name 00792 // are in the context of upper bounding misnomers 00793 template < typename Q, typename ET, typename Tags > 00794 void QP_solver<Q, ET, Tags>:: 00795 test_explicit_bounds_dir_pos(int k, const ET& x_k, const ET& q_k, 00796 int& i_min, ET& d_min, ET& q_min) 00797 { 00798 if (q_k > et0) { // check for lower bound 00799 if (*(qp_fl+k)) { 00800 ET diff = x_k - (d * ET(*(qp_l+k))); 00801 if (diff * q_min < d_min * q_k) { 00802 i_min = k; 00803 d_min = diff; 00804 q_min = q_k; 00805 ratio_test_bound_index = LOWER; 00806 } 00807 } 00808 } else { // check for upper bound 00809 if ((q_k < et0) && (*(qp_fu+k))) { 00810 ET diff = (d * ET(*(qp_u+k))) - x_k; 00811 if (diff * q_min < -(d_min * q_k)) { 00812 i_min = k; 00813 d_min = diff; 00814 q_min = -q_k; 00815 ratio_test_bound_index = UPPER; 00816 } 00817 } 00818 } 00819 } 00820 00821 // test for one basic variable with explicit bounds only, 00822 // note that this function writes the member variables i, x_i, q_i and 00823 // ratio_test_bound_index, although the second and third variable name 00824 // are in the context of upper bounding misnomers 00825 template < typename Q, typename ET, typename Tags > 00826 void QP_solver<Q, ET, Tags>:: 00827 test_explicit_bounds_dir_neg(int k, const ET& x_k, const ET& q_k, 00828 int& i_min, ET& d_min, ET& q_min) 00829 { 00830 if (q_k < et0) { // check for lower bound 00831 if (*(qp_fl+k)) { 00832 ET diff = x_k - (d * ET(*(qp_l+k))); 00833 if (diff * q_min < -(d_min * q_k)) { 00834 i_min = k; 00835 d_min = diff; 00836 q_min = -q_k; 00837 ratio_test_bound_index = LOWER; 00838 } 00839 } 00840 } else { // check for upper bound 00841 if ((q_k > et0) && (*(qp_fu+k))) { 00842 ET diff = (d * ET(*(qp_u+k))) - x_k; 00843 if (diff * q_min < d_min * q_k) { 00844 i_min = k; 00845 d_min = diff; 00846 q_min = q_k; 00847 ratio_test_bound_index = UPPER; 00848 } 00849 } 00850 } 00851 } 00852 00853 // test for one basic variable with mixed bounds, 00854 // note that this function writes the member variables i, x_i, q_i and 00855 // ratio_test_bound_index, although the second and third variable name 00856 // are in the context of upper bounding misnomers 00857 template < typename Q, typename ET, typename Tags > 00858 void QP_solver<Q, ET, Tags>:: 00859 test_mixed_bounds_dir_pos(int k, const ET& x_k, const ET& q_k, 00860 int& i_min, ET& d_min, ET& q_min) 00861 { 00862 if (q_k > et0) { // check for lower bound 00863 if (k < qp_n) { // original variable 00864 if (*(qp_fl+k)) { 00865 ET diff = x_k - (d * ET(*(qp_l+k))); 00866 if (diff * q_min < d_min * q_k) { 00867 i_min = k; 00868 d_min = diff; 00869 q_min = q_k; 00870 ratio_test_bound_index = LOWER; 00871 } 00872 } 00873 } else { // artificial variable 00874 if (x_k * q_min < d_min * q_k) { 00875 i_min = k; 00876 d_min = x_k; 00877 q_min = q_k; 00878 } 00879 } 00880 } else { // check for upper bound 00881 if ((q_k < et0) && (k < qp_n) && *(qp_fu+k)) { 00882 ET diff = (d * ET(*(qp_u+k))) - x_k; 00883 if (diff * q_min < -(d_min * q_k)) { 00884 i_min = k; 00885 d_min = diff; 00886 q_min = -q_k; 00887 ratio_test_bound_index = UPPER; 00888 } 00889 } 00890 } 00891 } 00892 00893 // test for one basic variable with mixed bounds, 00894 // note that this function writes the member variables i, x_i, q_i and 00895 // ratio_test_bound_index, although the second and third variable name 00896 // are in the context of upper bounding misnomers 00897 template < typename Q, typename ET, typename Tags > 00898 void QP_solver<Q, ET, Tags>:: 00899 test_mixed_bounds_dir_neg(int k, const ET& x_k, const ET& q_k, 00900 int& i_min, ET& d_min, ET& q_min) 00901 { 00902 if (q_k < et0) { // check for lower bound 00903 if (k < qp_n) { // original variable 00904 if (*(qp_fl+k)) { 00905 ET diff = x_k - (d * ET(*(qp_l+k))); 00906 if (diff * q_min < -(d_min * q_k)) { 00907 i_min = k; 00908 d_min = diff; 00909 q_min = -q_k; 00910 ratio_test_bound_index = LOWER; 00911 } 00912 } 00913 } else { // artificial variable 00914 if (x_k * q_min < -(d_min * q_k)) { 00915 i_min = k; 00916 d_min = x_k; 00917 q_min = -q_k; 00918 } 00919 } 00920 } else { // check for upper bound 00921 if ((q_k > et0) && (k < qp_n) && *(qp_fu+k)) { 00922 ET diff = (d * ET(*(qp_u+k))) - x_k; 00923 if (diff * q_min < d_min * q_k) { 00924 i_min = k; 00925 d_min = diff; 00926 q_min = q_k; 00927 ratio_test_bound_index = UPPER; 00928 } 00929 } 00930 } 00931 } 00932 00933 00934 template < typename Q, typename ET, typename Tags > // QP case 00935 void 00936 QP_solver<Q, ET, Tags>:: 00937 ratio_test_2( Tag_false) 00938 { 00939 // diagnostic output 00940 CGAL_qpe_debug { 00941 if ( vout2.verbose()) { 00942 vout2.out() << std::endl 00943 << "Ratio Test (Step 2)" << std::endl 00944 << "-------------------" << std::endl; 00945 } 00946 } 00947 00948 // compute `p_lambda' and `p_x' (Note: `p_...' is stored in `q_...') 00949 ratio_test_2__p( no_ineq); 00950 00951 // diagnostic output 00952 CGAL_qpe_debug { 00953 if ( vout3.verbose()) { 00954 vout3.out() << "p_lambda: "; 00955 std::copy( q_lambda.begin(), q_lambda.begin()+C.size(), 00956 std::ostream_iterator<ET>( vout3.out()," ")); 00957 vout3.out() << std::endl; 00958 vout3.out() << " p_x_O: "; 00959 std::copy( q_x_O.begin(), q_x_O.begin()+B_O.size(), 00960 std::ostream_iterator<ET>( vout3.out()," ")); 00961 vout3.out() << std::endl; 00962 if ( has_ineq) { 00963 vout3.out() << " p_x_S: "; 00964 std::copy( q_x_S.begin(), q_x_S.begin()+B_S.size(), 00965 std::ostream_iterator<ET>( vout3.out()," ")); 00966 vout3.out() << std::endl; 00967 } 00968 vout3.out() << std::endl; 00969 } 00970 } 00971 00972 // Idea here: At this point, the goal is to increase \mu_j until either we 00973 // become optimal (\mu_j=0), or one of the variables in x^*_\hat{B} drops 00974 // down to zero. 00975 // 00976 // Let us see first how this is done in the standard-form case (where 00977 // Sven's thesis applies). Eq. (2.11) in Sven's thesis holds, and by 00978 // multlying it by $M_\hat{B}^{-1}$ we obtain an equation for \lambda and 00979 // x^*_\hat{B}. The interesting equation (the one for x^*_\hat{B}) looks 00980 // more or less as follows: 00981 // 00982 // x(mu_j) = x(0) + mu_j q_it (1) 00983 // 00984 // where q_it is the vector from (2.12). In paritcular, for 00985 // mu_j=mu_j(t_1) (i.e., if we plug the value of mu_j at the beginning of 00986 // this ratio step 2 into (1)) we have 00987 // 00988 // x(mu_j(t_1)) = x(0) + mu_j(t_1) q_it (2) 00989 // 00990 // where x(mu_j(t_1)) is the current solution of the solver at this point 00991 // (i.e., at the beginning of ratio step 2). 00992 // 00993 // By subtracting (2) from (1) we can thus eliminate the "unkown" x(0) 00994 // (which is cheaper than computing it): 00995 // 00996 // x(mu_j) = x(mu_j(t_1)) + (mu_j-mu_j(t_1)) q_it 00997 // ---------------- 00998 // := delta 00999 // 01000 // In order to compute for each variable x_k in \hat{B} the value of mu_j 01001 // for which x_k(mu_j) = 0, we thus evaluate 01002 // 01003 // x(mu_j(t_1))_k 01004 // delta_k:= - -------------- 01005 // q_it_k 01006 // 01007 // The first variable in \hat{B} that hits zero "in the future" is then 01008 // the one whose delta_k equals 01009 // 01010 // delta_min:= min {delta_k | k in \hat{B} and (q_it)_k < 0 } 01011 // 01012 // So in order to handle the standard-form case, we would compute this 01013 // minimum. Once we have delta_min, we need to check whether we get 01014 // optimal BEFORE a variable drops to zero. As delta = mu_j - mu_j(t_1), 01015 // the latter is precisely the case if delta_min >= -mu_j(t_1). 01016 // 01017 // (Note: please forget the crap identitiy between (2.11) and (2.12); the 01018 // notation is misleading.) 01019 // 01020 // Now to the nonstandard-form case. 01021 01022 // fw: By definition delta_min >= 0, such that initializing 01023 // delta_min with -mu_j(t_1) has the desired effect that a basic variable 01024 // is leaving only if 0 <= delta_min < -mu_j(t_1). 01025 // 01026 // The only initialization of delta_min as fraction x_i/q_i that works is 01027 // x_i=mu_j(t_1); q_i=-1; (see below). 01028 // 01029 // Since mu_j(t_1) has been computed in ratio test step 1 we can 01030 // reuse it. 01031 01032 x_i = mu; // initialize minimum 01033 q_i = -et1; // with -mu_j(t_1) 01034 01035 Value_iterator x_it = x_B_O.begin(); 01036 Value_iterator q_it = q_x_O.begin(); 01037 Index_iterator i_it; 01038 for ( i_it = B_O.begin(); i_it != B_O.end(); ++i_it, ++x_it, ++q_it) { 01039 if ( ( *q_it < et0) && ( ( *x_it * q_i) < ( x_i * *q_it))) { 01040 i = *i_it; x_i = *x_it; q_i = *q_it; 01041 } 01042 } 01043 x_it = x_B_S.begin(); 01044 q_it = q_x_S.begin(); 01045 for ( i_it = B_S.begin(); i_it != B_S.end(); ++i_it, ++x_it, ++q_it) { 01046 if ( ( *q_it < et0) && ( ( *x_it * q_i) < ( x_i * *q_it))) { 01047 i = *i_it; x_i = *x_it; q_i = *q_it; 01048 } 01049 } 01050 01051 CGAL_qpe_debug { 01052 if ( vout2.verbose()) { 01053 for ( unsigned int k = 0; k < B_O.size(); ++k) { 01054 vout2.out() << "mu_j_O_" << k << ": - " 01055 << x_B_O[ k] << '/' << q_x_O[ k] 01056 << ( ( q_i < et0) && ( i == B_O[ k]) ? " *" : "") 01057 << std::endl; 01058 } 01059 for ( unsigned int k = 0; k < B_S.size(); ++k) { 01060 vout2.out() << "mu_j_S_" << k << ": - " 01061 << x_B_S[ k] << '/' << q_x_S[ k] 01062 << ( ( q_i < et0) && ( i == B_S[ k]) ? " *" : "") 01063 << std::endl; 01064 } 01065 vout2.out() << std::endl; 01066 } 01067 } 01068 if ( i < 0) { 01069 vout2 << "leaving variable: none" << std::endl; 01070 } else { 01071 vout1 << ", "; 01072 vout << "leaving"; vout2 << " variable"; vout << ": "; 01073 vout << i; 01074 if ( vout2.verbose()) { 01075 if ( i < qp_n) { 01076 vout2.out() << " (= B_O[ " << in_B[ i] << "]: original)" 01077 << std::endl; 01078 } else { 01079 vout2.out() << " (= B_S[ " << in_B[ i] << "]: slack)" 01080 << std::endl; 01081 } 01082 } 01083 } 01084 01085 } 01086 01087 // update (step 1) 01088 template < typename Q, typename ET, typename Tags > 01089 void 01090 QP_solver<Q, ET, Tags>:: 01091 update_1( ) 01092 { 01093 CGAL_qpe_debug { 01094 if ( vout2.verbose()) { 01095 vout2.out() << std::endl; 01096 if ( is_LP || is_phaseI) { 01097 vout2.out() << "------" << std::endl 01098 << "Update" << std::endl 01099 << "------" << std::endl; 01100 } else { 01101 vout2.out() << "Update (Step 1)" << std::endl 01102 << "---------------" << std::endl; 01103 } 01104 } 01105 } 01106 01107 // update basis & basis inverse 01108 update_1( Is_linear()); 01109 CGAL_qpe_assertion(check_basis_inverse()); 01110 01111 // check the updated vectors r_C and r_S_B 01112 CGAL_expensive_assertion(check_r_C(Is_nonnegative())); 01113 CGAL_expensive_assertion(check_r_S_B(Is_nonnegative())); 01114 01115 // check the vectors r_B_O and w in phaseII for QPs 01116 CGAL_qpe_debug { 01117 if (is_phaseII && is_QP) { 01118 CGAL_expensive_assertion(check_r_B_O(Is_nonnegative())); 01119 CGAL_expensive_assertion(check_w(Is_nonnegative())); 01120 } 01121 } 01122 01123 // compute current solution 01124 compute_solution(Is_nonnegative()); 01125 01126 // check feasibility 01127 CGAL_qpe_debug { 01128 if (j < 0 && !is_RTS_transition) // todo kf: is this too conservative? 01129 // Note: the above condition is necessary because of the 01130 // following. In theory, it is true that the current 01131 // solution is at this point in the solver always 01132 // feasible. However, the solution has its x_j-entry equal to 01133 // the current t from the pricing, and is not zero (in the 01134 // standard-form case) or the current lower/upper bound 01135 // of the variable (in the non-standard-form case), resp., as 01136 // the routines is_solution_feasible() and 01137 // is_solution_feasible_for_auxiliary_problem() assume. 01138 if (is_phaseI) { 01139 CGAL_expensive_assertion( 01140 is_solution_feasible_for_auxiliary_problem()); 01141 } else { 01142 CGAL_expensive_assertion(is_solution_feasible()); 01143 } 01144 else 01145 vout2 << "(feasibility not checked in intermediate step)" << std::endl; 01146 CGAL_expensive_assertion(check_tag(Is_nonnegative()) || 01147 r_C.size() == C.size()); 01148 } 01149 01150 } 01151 01152 // update (step 2) 01153 template < typename Q, typename ET, typename Tags > // QP case 01154 void 01155 QP_solver<Q, ET, Tags>:: 01156 update_2( Tag_false) 01157 { 01158 CGAL_qpe_debug { 01159 vout2 << std::endl 01160 << "Update (Step 2)" << std::endl 01161 << "---------------" << std::endl; 01162 } 01163 01164 // leave variable from basis 01165 leave_variable(); 01166 CGAL_qpe_debug { 01167 check_basis_inverse(); 01168 } 01169 01170 // check the updated vectors r_C, r_S_B, r_B_O and w 01171 CGAL_expensive_assertion(check_r_C(Is_nonnegative())); 01172 CGAL_expensive_assertion(check_r_S_B(Is_nonnegative())); 01173 CGAL_expensive_assertion(check_r_B_O(Is_nonnegative())); 01174 CGAL_expensive_assertion(check_w(Is_nonnegative())); 01175 01176 // compute current solution 01177 compute_solution(Is_nonnegative()); 01178 } 01179 01180 template < typename Q, typename ET, typename Tags > 01181 void 01182 QP_solver<Q, ET, Tags>:: 01183 expel_artificial_variables_from_basis( ) 01184 { 01185 int row_ind; 01186 ET r_A_Cj; 01187 01188 CGAL_qpe_debug { 01189 vout2 << std::endl 01190 << "---------------------------------------------" << std::endl 01191 << "Expelling artificial variables from the basis" << std::endl 01192 << "---------------------------------------------" << std::endl; 01193 } 01194 01195 // try to pivot the artificials out of the basis 01196 // Note that we do not notify the pricing strategy about variables 01197 // leaving the basis, furthermore the pricing strategy does not 01198 // know about variables entering the basis. 01199 // The partial pricing strategies that keep the set of nonbasic vars 01200 // explicitly are synchronized during transition from phaseI to phaseII 01201 for (unsigned int i_ = qp_n + slack_A.size(); i_ < in_B.size(); ++i_) { 01202 if (is_basic(i_)) { // is basic 01203 if (has_ineq) { 01204 row_ind = in_C[ art_A[i_ - qp_n - slack_A.size()].first]; 01205 } else { 01206 row_ind = art_A[i_ - qp_n].first; 01207 } 01208 01209 // determine first possible entering variable, 01210 // if there is any 01211 for (unsigned int j_ = 0; j_ < qp_n + slack_A.size(); ++j_) { 01212 if (!is_basic(j_)) { // is nonbasic 01213 ratio_test_init__A_Cj( A_Cj.begin(), j_, no_ineq); 01214 r_A_Cj = inv_M_B.inv_M_B_row_dot_col(row_ind, A_Cj.begin()); 01215 if (r_A_Cj != et0) { 01216 ratio_test_1__q_x_O(Is_linear()); 01217 i = i_; 01218 j = j_; 01219 update_1(Is_linear()); 01220 break; 01221 } 01222 } 01223 } 01224 } 01225 } 01226 if ((art_basic != 0) && no_ineq) { 01227 // the vector in_C was not used in phase I, but now we remove redundant 01228 // constraints and switch to has_ineq treatment, hence we need it to 01229 // be correct at this stage 01230 for (int i=0; i<qp_m; ++i) 01231 in_C.push_back(i); 01232 } 01233 diagnostics.redundant_equations = (art_basic != 0); 01234 01235 // now reset the no_ineq and has_ineq flags to match the situation 01236 no_ineq = no_ineq && !diagnostics.redundant_equations; 01237 has_ineq = !no_ineq; 01238 01239 // remove the remaining ones with their corresponding equality constraints 01240 // Note: the special artificial variable can always be driven out of the 01241 // basis 01242 for (unsigned int i_ = qp_n + slack_A.size(); i_ < in_B.size(); ++i_) { 01243 if (in_B[i_] >= 0) { 01244 i = i_; 01245 CGAL_qpe_debug { 01246 vout2 << std::endl 01247 << "~~> removing artificial variable " << i 01248 << " and its equality constraint" << std::endl 01249 << std::endl; 01250 } 01251 remove_artificial_variable_and_constraint(); 01252 } 01253 } 01254 } 01255 01256 01257 // replace variable in basis 01258 template < typename Q, typename ET, typename Tags > 01259 void 01260 QP_solver<Q, ET, Tags>:: 01261 replace_variable( ) 01262 { 01263 CGAL_qpe_debug { 01264 vout2 << "<--> nonbasic (" << variable_type( j) << ") variable " << j 01265 << " replaces basic (" << variable_type( i) << ") variable " << i 01266 << std::endl << std::endl; 01267 } 01268 01269 // replace variable 01270 replace_variable( no_ineq); 01271 01272 // pivot step done 01273 i = j = -1; 01274 } 01275 01276 template < typename Q, typename ET, typename Tags > 01277 void QP_solver<Q, ET, Tags>:: 01278 replace_variable_original_original( ) 01279 { 01280 // updates for the upper bounded case 01281 replace_variable_original_original_upd_r(Is_nonnegative()); 01282 01283 int k = in_B[ i]; 01284 01285 // replace original variable [ in: j | out: i ] 01286 in_B [ i] = -1; 01287 in_B [ j] = k; 01288 B_O[ k] = j; 01289 01290 minus_c_B[ k] = 01291 ( is_phaseI ? 01292 ( j < qp_n ? et0 : -aux_c[j-qp_n-slack_A.size()]) : -ET( *(qp_c+ j))); 01293 01294 if ( is_phaseI) { 01295 if ( j >= qp_n) ++art_basic; 01296 if ( i >= qp_n) --art_basic; 01297 } 01298 01299 // diagnostic output 01300 CGAL_qpe_debug { 01301 if ( vout2.verbose()) print_basis(); 01302 } 01303 01304 // update basis inverse 01305 inv_M_B.enter_original_leave_original( q_x_O.begin(), k); 01306 } 01307 01308 // update of the vector r for U_5 with upper bounding, note that we 01309 // need the headings C, and S_{B} before they are updated 01310 template < typename Q, typename ET, typename Tags > // Standard form 01311 void QP_solver<Q, ET, Tags>:: 01312 replace_variable_original_original_upd_r(Tag_true ) 01313 { 01314 } 01315 01316 // update of the vector r for U_5 with upper bounding, note that we 01317 // need the headings C, and S_{B} before they are updated 01318 template < typename Q, typename ET, typename Tags > // Upper bounded 01319 void QP_solver<Q, ET, Tags>:: 01320 replace_variable_original_original_upd_r(Tag_false ) 01321 { 01322 ET x_j, x_i; 01323 01324 if (is_artificial(j)) { 01325 if (!is_artificial(i)) { 01326 x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i); 01327 update_r_C_r_S_B__i(x_i); 01328 // update x_O_v_i 01329 x_O_v_i[i] = ratio_test_bound_index; 01330 } 01331 } else { 01332 x_j = nonbasic_original_variable_value(j); 01333 if (is_artificial(i)) { 01334 update_r_C_r_S_B__j(x_j); 01335 } else { 01336 x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i); 01337 update_r_C_r_S_B__j_i(x_j, x_i); 01338 // update x_O_v_i 01339 x_O_v_i[i] = ratio_test_bound_index; 01340 } 01341 // update x_O_v_i 01342 x_O_v_i[j] = BASIC; 01343 } 01344 } 01345 01346 01347 template < typename Q, typename ET, typename Tags > 01348 void QP_solver<Q, ET, Tags>:: 01349 replace_variable_slack_slack( ) 01350 { 01351 01352 // updates for the upper bounded case 01353 replace_variable_slack_slack_upd_r(Is_nonnegative()); 01354 01355 int k = in_B[ i]; 01356 01357 // replace slack variable [ in: j | out: i ] 01358 in_B [ i] = -1; 01359 in_B [ j] = k; 01360 B_S[ k] = j; 01361 S_B[ k] = slack_A[ j-qp_n].first; 01362 01363 // replace inequality constraint [ in: i | out: j ] 01364 int old_row = S_B[ k]; 01365 int new_row = slack_A[ i-qp_n].first; 01366 k = in_C[ old_row]; 01367 01368 in_C[ old_row] = -1; 01369 in_C[ new_row] = k; 01370 C[ k ] = new_row; 01371 01372 b_C[ k] = ET( *(qp_b+ new_row)); 01373 01374 // diagnostic output 01375 CGAL_qpe_debug { 01376 if ( vout2.verbose()) print_basis(); 01377 } 01378 01379 // update basis inverse 01380 A_row_by_index_accessor a_accessor = 01381 boost::bind( A_accessor( qp_A, 0, qp_n), _1, new_row); 01382 std::copy( A_row_by_index_iterator( B_O.begin(), a_accessor), 01383 A_row_by_index_iterator( B_O.end (), a_accessor), 01384 tmp_x.begin()); 01385 if ( art_s_i > 0) { // special artificial 01386 tmp_x[ in_B[ art_s_i]] = ET( art_s[ new_row]); 01387 } 01388 inv_M_B.enter_slack_leave_slack( tmp_x.begin(), k); 01389 } 01390 01391 // update of the vector r for U_6 with upper bounding, note that we 01392 // need the headings C, and S_{B} before they are updated 01393 template < typename Q, typename ET, typename Tags > // Standard form 01394 void QP_solver<Q, ET, Tags>:: 01395 replace_variable_slack_slack_upd_r(Tag_true ) 01396 { 01397 } 01398 01399 // update of the vector r for U_6 with upper bounding, note that we 01400 // need the headings C, and S_{B} before they are updated 01401 template < typename Q, typename ET, typename Tags > // Upper bounded 01402 void QP_solver<Q, ET, Tags>:: 01403 replace_variable_slack_slack_upd_r(Tag_false ) 01404 { 01405 int sigma_j = slack_A[ j-qp_n].first; 01406 01407 // swap r_gamma_C(sigma_j) in r_C with r_gamma_S_B(sigma_i) in r_S_B 01408 std::swap(r_C[in_C[sigma_j]], r_S_B[in_B[i]]); 01409 } 01410 01411 01412 template < typename Q, typename ET, typename Tags > 01413 void QP_solver<Q, ET, Tags>:: 01414 replace_variable_slack_original( ) 01415 { 01416 // updates for the upper bounded case 01417 replace_variable_slack_original_upd_r(Is_nonnegative()); 01418 01419 int k = in_B[ i]; 01420 01421 // leave original variable [ out: i ] 01422 in_B [ B_O.back()] = k; 01423 B_O[ k] = B_O.back(); 01424 in_B [ i ] = -1; 01425 B_O.pop_back(); 01426 01427 minus_c_B[ k] = minus_c_B[ B_O.size()]; 01428 01429 if ( is_phaseI && ( i >= qp_n)) --art_basic; 01430 01431 // enter slack variable [ in: j ] 01432 int old_row = slack_A[ j-qp_n].first; 01433 in_B [ j] = B_S.size(); 01434 B_S.push_back( j); 01435 S_B.push_back( old_row); 01436 01437 // leave inequality constraint [ out: j ] 01438 int l = in_C[ old_row]; 01439 b_C[ l ] = b_C[ C.size()-1]; 01440 C[ l ] = C.back(); 01441 in_C[ C.back()] = l; 01442 in_C[ old_row ] = -1; 01443 C.pop_back(); 01444 // diagnostic output 01445 CGAL_qpe_debug { 01446 if ( vout2.verbose()) print_basis(); 01447 } 01448 01449 // update basis inverse 01450 inv_M_B.swap_variable( k); 01451 inv_M_B.swap_constraint( l); 01452 inv_M_B.enter_slack_leave_original(); 01453 } 01454 01455 // update of the vector r for U_8 with upper bounding, note that we 01456 // need the headings C, and S_{B} before they are updated 01457 template < typename Q, typename ET, typename Tags > // Standard form 01458 void QP_solver<Q, ET, Tags>:: 01459 replace_variable_slack_original_upd_r(Tag_true ) 01460 { 01461 } 01462 01463 // update of the vector r for U_8 with upper bounding, note that we 01464 // need the headings C, and S_{B} before they are updated 01465 template < typename Q, typename ET, typename Tags > // Upper bounded 01466 void QP_solver<Q, ET, Tags>:: 01467 replace_variable_slack_original_upd_r(Tag_false ) 01468 { 01469 if (!is_artificial(i)) { 01470 ET x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i); 01471 update_r_C_r_S_B__i(x_i); 01472 } 01473 01474 int sigma_j = slack_A[ j-qp_n].first; 01475 01476 // append r_gamma_C(sigma_j) from r_C to r_S_B: 01477 r_S_B.push_back(r_C[in_C[sigma_j]]); 01478 01479 // remove r_gamma_C(sigma_j) from r_C: 01480 r_C[in_C[sigma_j]] = r_C.back(); 01481 r_C.pop_back(); 01482 01483 // update x_O_v_i 01484 if (!is_artificial(i)) // original and not artificial? 01485 x_O_v_i[i] = ratio_test_bound_index; 01486 } 01487 01488 01489 template < typename Q, typename ET, typename Tags > 01490 void QP_solver<Q, ET, Tags>:: 01491 replace_variable_original_slack( ) 01492 { 01493 // updates for the upper bounded case 01494 replace_variable_original_slack_upd_r(Is_nonnegative()); 01495 01496 int k = in_B[ i]; 01497 01498 // enter original variable [ in: j ] 01499 01500 minus_c_B[ B_O.size()] 01501 = ( is_phaseI ? 01502 ( j < qp_n ? et0 : -aux_c[j-qp_n-slack_A.size()]) 01503 : -ET( *(qp_c+ j))); 01504 01505 01506 in_B [ j] = B_O.size(); 01507 B_O.push_back( j); 01508 01509 if ( is_phaseI && ( j >= qp_n)) ++art_basic; 01510 01511 // leave slack variable [ out: i ] 01512 B_S[ k ] = B_S.back(); 01513 S_B[ k ] = S_B.back(); 01514 in_B [ B_S.back()] = k; 01515 in_B [ i ] = -1; 01516 B_S.pop_back(); 01517 S_B.pop_back(); 01518 01519 // enter inequality constraint [ in: i ] 01520 int new_row = slack_A[ i-qp_n].first; 01521 01522 b_C[ C.size()] = ET( *(qp_b+ new_row)); 01523 in_C[ new_row ] = C.size(); 01524 C.push_back( new_row); 01525 // diagnostic output 01526 CGAL_qpe_debug { 01527 if ( vout2.verbose()) print_basis(); 01528 } 01529 01530 // update basis inverse 01531 A_row_by_index_accessor a_accessor = 01532 boost::bind (A_accessor( qp_A, 0, qp_n), _1, new_row); 01533 std::copy( A_row_by_index_iterator( B_O.begin(), a_accessor), 01534 A_row_by_index_iterator( B_O.end (), a_accessor), 01535 tmp_x.begin()); 01536 if ( art_s_i > 0) { // special art. 01537 tmp_x[ in_B[ art_s_i]] = ET( art_s[ new_row]); 01538 } 01539 inv_M_B.enter_original_leave_slack( q_x_O.begin(), tmp_x.begin()); 01540 01541 } 01542 01543 // update of the vector r for U_7 with upper bounding, note that we 01544 // need the headings C, and S_{B} before they are updated 01545 template < typename Q, typename ET, typename Tags > // Standard form 01546 void QP_solver<Q, ET, Tags>:: 01547 replace_variable_original_slack_upd_r(Tag_true ) 01548 { 01549 } 01550 01551 // update of the vector r for U_7 with upper bounding, note that we 01552 // need the headings C, and S_{B} before they are updated 01553 template < typename Q, typename ET, typename Tags > // Upper bounded 01554 void QP_solver<Q, ET, Tags>:: 01555 replace_variable_original_slack_upd_r(Tag_false ) 01556 { 01557 if (!is_artificial(j)) { 01558 ET x_j = nonbasic_original_variable_value(j); 01559 update_r_C_r_S_B__j(x_j); 01560 } 01561 01562 // append r_gamma_S_B(sigma_i) from r_S_B to r_C 01563 r_C.push_back(r_S_B[in_B[i]]); 01564 01565 // remove r_gamma_S_B(sigma_i) from r_S_B 01566 r_S_B[in_B[i]] = r_S_B.back(); 01567 r_S_B.pop_back(); 01568 01569 // update x_O_v_i 01570 if (!is_artificial(j)) { 01571 x_O_v_i[j] = BASIC; 01572 } 01573 } 01574 01575 01576 template < typename Q, typename ET, typename Tags > 01577 void QP_solver<Q, ET, Tags>:: 01578 remove_artificial_variable_and_constraint( ) 01579 { 01580 // updates for the upper bounded case 01581 remove_artificial_variable_and_constraint_upd_r(Is_nonnegative()); 01582 01583 int k = in_B[ i]; 01584 01585 // leave artificial (original) variable [ out: i ] 01586 in_B [ B_O.back()] = k; 01587 B_O[ k] = B_O.back(); 01588 in_B [ i ] = -1; 01589 B_O.pop_back(); 01590 01591 minus_c_B[ k] = minus_c_B[ B_O.size()]; 01592 01593 if ( is_phaseI && ( i >= qp_n)) --art_basic; 01594 01595 int old_row = art_A[i - qp_n - slack_A.size()].first; 01596 01597 // leave its equality constraint 01598 int l = in_C[ old_row]; 01599 b_C[ l ] = b_C[ C.size()-1]; 01600 C[ l ] = C.back(); 01601 in_C[ C.back()] = l; 01602 in_C[ old_row ] = -1; 01603 C.pop_back(); 01604 // diagnostic output 01605 CGAL_qpe_debug { 01606 if ( vout2.verbose()) print_basis(); 01607 } 01608 01609 // update basis inverse 01610 inv_M_B.swap_variable( k); 01611 inv_M_B.swap_constraint( l); 01612 inv_M_B.enter_slack_leave_original(); 01613 } 01614 01615 // update of the vector r with upper bounding for the removal of an 01616 // artificial variable with its equality constraint, note that we 01617 // need the headings C before it is updated 01618 template < typename Q, typename ET, typename Tags > // Standard form 01619 void QP_solver<Q, ET, Tags>:: 01620 remove_artificial_variable_and_constraint_upd_r(Tag_true ) 01621 { 01622 } 01623 01624 // update of the vector r with upper bounding for the removal of an 01625 // artificial variable with its equality constraint, note that we 01626 // need the headings C before it is updated 01627 template < typename Q, typename ET, typename Tags > // Upper bounded 01628 void QP_solver<Q, ET, Tags>:: 01629 remove_artificial_variable_and_constraint_upd_r(Tag_false ) 01630 { 01631 int sigma_i = art_A[i - qp_n - slack_A.size()].first; 01632 01633 // remove r_gamma_C(sigma_i) from r_C 01634 r_C[in_C[sigma_i]] = r_C.back(); 01635 r_C.pop_back(); 01636 } 01637 01638 // update that occurs only with upper bounding in ratio test step 1 01639 template < typename Q, typename ET, typename Tags > 01640 void QP_solver<Q, ET, Tags>:: 01641 enter_and_leave_variable( ) 01642 { 01643 01644 CGAL_qpe_assertion((i == j) && (i >= 0)); 01645 01646 CGAL_qpe_debug { 01647 vout2 << "<--> nonbasic (" << variable_type( j) << ") variable " << j 01648 << " enters and leaves basis" << std::endl << std::endl; 01649 } 01650 01651 01652 ET diff; 01653 ET x_j = nonbasic_original_variable_value(j); 01654 01655 if (ratio_test_bound_index == LOWER) { 01656 diff = x_j - ET(*(qp_l+j)); 01657 } else { 01658 diff = x_j - ET(*(qp_u+j)); 01659 } 01660 01661 if (is_phaseI) { 01662 update_r_C_r_S_B__j(diff); 01663 } else { 01664 update_w_r_B_O__j(diff); 01665 update_r_C_r_S_B__j(diff); 01666 } 01667 01668 x_O_v_i[j] = ratio_test_bound_index; 01669 01670 // notify pricing strategy (it has called enter_basis on i before) 01671 strategyP->leaving_basis (i); 01672 01673 // variable entered and left basis 01674 i = -1; j = -1; 01675 } 01676 01677 01678 01679 // enter variable into basis 01680 template < typename Q, typename ET, typename Tags > 01681 void 01682 QP_solver<Q, ET, Tags>:: 01683 enter_variable( ) 01684 { 01685 CGAL_qpe_assertion (is_phaseII); 01686 CGAL_qpe_debug { 01687 vout2 << "--> nonbasic (" << variable_type( j) << ") variable " 01688 << j << " enters basis" << std::endl << std::endl; 01689 } 01690 01691 // update basis & basis inverse: 01692 if (no_ineq || (j < qp_n)) { // original variable 01693 01694 // updates for the upper bounded case: 01695 enter_variable_original_upd_w_r(Is_nonnegative()); 01696 01697 // enter original variable [ in: j ]: 01698 if (minus_c_B.size() <= B_O.size()) { // Note: minus_c_B and the 01699 // containers resized in this 01700 // if-block are only enlarged 01701 // and never made smaller 01702 // (while B_O always has the 01703 // correct size). We check here 01704 // whether we need to enlarge 01705 // them. 01706 CGAL_qpe_assertion(minus_c_B.size() == B_O.size()); 01707 minus_c_B.push_back(et0); 01708 q_x_O.push_back(et0); 01709 tmp_x .push_back(et0); 01710 tmp_x_2.push_back(et0); 01711 two_D_Bj.push_back(et0); 01712 x_B_O.push_back(et0); 01713 } 01714 minus_c_B[B_O.size()] = -ET(*(qp_c+ j)); // Note: B_O has always the 01715 // correct size. 01716 01717 in_B[j] = B_O.size(); 01718 B_O.push_back(j); 01719 01720 // diagnostic output 01721 CGAL_qpe_debug { 01722 if (vout2.verbose()) 01723 print_basis(); 01724 } 01725 01726 // update basis inverse 01727 // note: (-1)\hat{\nu} is stored instead of \hat{\nu} 01728 inv_M_B.enter_original(q_lambda.begin(), q_x_O.begin(), -nu); 01729 01730 } else { // slack variable 01731 01732 // updates for the upper bounded case: 01733 enter_variable_slack_upd_w_r(Is_nonnegative()); 01734 01735 // enter slack variable [ in: j ]: 01736 in_B [ j] = B_S.size(); 01737 B_S.push_back( j); 01738 S_B.push_back( slack_A[ j-qp_n].first); 01739 01740 // leave inequality constraint [ out: j ]: 01741 int old_row = slack_A[ j-qp_n].first; 01742 int k = in_C[old_row]; 01743 01744 // reflect change of active constraints heading C in b_C: 01745 b_C[ k] = b_C[C.size()-1]; 01746 01747 C[ k] = C.back(); 01748 in_C[ C.back() ] = k; 01749 in_C[ old_row ] = -1; 01750 C.pop_back(); 01751 01752 // diagnostic output: 01753 CGAL_qpe_debug { 01754 if (vout2.verbose()) 01755 print_basis(); 01756 } 01757 01758 // update basis inverse: 01759 inv_M_B.swap_constraint(k); // swap to back 01760 inv_M_B.enter_slack(); // drop drop 01761 } 01762 01763 // variable entered: 01764 j -= in_B.size(); 01765 } 01766 01767 // update of the vectors w and r for U_1 with upper bounding, note that we 01768 // need the headings C, S_{B}, B_{O} before they are updated 01769 template < typename Q, typename ET, typename Tags > // Standard form 01770 void QP_solver<Q, ET, Tags>:: 01771 enter_variable_original_upd_w_r(Tag_true ) 01772 { 01773 } 01774 01775 // update of the vectors w and r for U_1 with upper bounding, note that we 01776 // need the headings C, S_{B}, B_{O} before they are updated 01777 template < typename Q, typename ET, typename Tags > // Upper bounded 01778 void QP_solver<Q, ET, Tags>:: 01779 enter_variable_original_upd_w_r(Tag_false ) 01780 { 01781 01782 ET x_j = nonbasic_original_variable_value(j); 01783 01784 // Note: w needs to be updated before r_C, r_S_B 01785 update_w_r_B_O__j(x_j); 01786 update_r_C_r_S_B__j(x_j); 01787 01788 // append w_j to r_B_O 01789 if (!check_tag(Is_linear())) // (kf.) 01790 r_B_O.push_back(w[j]); 01791 01792 // update x_O_v_i 01793 x_O_v_i[j] = BASIC; 01794 } 01795 01796 // update of the vectors w and r for U_3 with upper bounding, note that we 01797 // need the headings C, S_{B}, B_{O} before they are updated 01798 template < typename Q, typename ET, typename Tags > // Standard form 01799 void QP_solver<Q, ET, Tags>:: 01800 enter_variable_slack_upd_w_r(Tag_true ) 01801 { 01802 } 01803 01804 // update of the vectors w and r for U_3 with upper bounding, note that we 01805 // need the headings C, S_{B}, B_{O} before they are updated 01806 template < typename Q, typename ET, typename Tags > // Upper bounded 01807 void QP_solver<Q, ET, Tags>:: 01808 enter_variable_slack_upd_w_r(Tag_false ) 01809 { 01810 01811 int sigma_j = slack_A[ j-qp_n].first; 01812 01813 // append r_gamma_C(sigma_j) to r_S_B 01814 r_S_B.push_back(r_C[in_C[sigma_j]]); 01815 01816 // remove r_gamma_C(sigma_j) from r_C 01817 r_C[in_C[sigma_j]] = r_C.back(); 01818 r_C.pop_back(); 01819 } 01820 01821 // leave variable from basis 01822 template < typename Q, typename ET, typename Tags > 01823 void 01824 QP_solver<Q, ET, Tags>:: 01825 leave_variable( ) 01826 { 01827 CGAL_qpe_debug { 01828 vout2 << "<-- basic (" << variable_type( i) << ") variable " 01829 << i << " leaves basis" << std::endl << std::endl; 01830 } 01831 01832 // update basis & basis inverse 01833 int k = in_B[ i]; 01834 if ( no_ineq || ( i < qp_n)) { // original variable 01835 01836 // updates for the upper bounded case 01837 leave_variable_original_upd_w_r(Is_nonnegative()); 01838 01839 // leave original variable [ out: i ] 01840 in_B [ B_O.back()] = k; 01841 in_B [ i ] = -1; 01842 //in_B [ B_O.back()] = k; 01843 B_O[ k] = B_O.back(); B_O.pop_back(); 01844 01845 minus_c_B [ k] = minus_c_B [ B_O.size()]; 01846 two_D_Bj[ k] = two_D_Bj[ B_O.size()]; 01847 01848 01849 // diagnostic output 01850 CGAL_qpe_debug { 01851 if ( vout2.verbose()) print_basis(); 01852 } 01853 01854 // update basis inverse 01855 inv_M_B.swap_variable( k); 01856 inv_M_B.leave_original(); 01857 01858 } else { // slack variable 01859 01860 // updates for the upper bounded case 01861 leave_variable_slack_upd_w_r(Is_nonnegative()); 01862 01863 // leave slack variable [ out: i ] 01864 in_B [ B_S.back()] = k; // former last var moves to position k 01865 in_B [ i ] = -1; // i gets deleted 01866 B_S[ k] = B_S.back(); B_S.pop_back(); 01867 S_B[ k] = S_B.back(); S_B.pop_back(); 01868 01869 // enter inequality constraint [ in: i ] 01870 int new_row = slack_A[ i-qp_n].first; 01871 01872 A_Cj[ C.size()] = ( j < qp_n ? ET( *((*(qp_A + j))+ new_row)) : et0); 01873 01874 b_C[ C.size()] = ET( *(qp_b+ new_row)); 01875 in_C[ new_row ] = C.size(); 01876 C.push_back( new_row); 01877 01878 // diagnostic output 01879 CGAL_qpe_debug { 01880 if ( vout2.verbose()) print_basis(); 01881 } 01882 01883 // update basis inverse 01884 A_row_by_index_accessor a_accessor = 01885 boost::bind (A_accessor( qp_A, 0, qp_n), _1, new_row); 01886 std::copy( A_row_by_index_iterator( B_O.begin(), a_accessor), 01887 A_row_by_index_iterator( B_O.end (), a_accessor), 01888 tmp_x.begin()); 01889 inv_M_B.leave_slack( tmp_x.begin()); 01890 } 01891 01892 // notify pricing strategy 01893 strategyP->leaving_basis( i); 01894 01895 // variable left 01896 i = -1; 01897 } 01898 01899 // update of the vectors w and r for U_2 with upper bounding, note that we 01900 // need the headings C, S_{B}, B_{O} before they are updated 01901 template < typename Q, typename ET, typename Tags > // Standard form 01902 void QP_solver<Q, ET, Tags>:: 01903 leave_variable_original_upd_w_r(Tag_true ) 01904 { 01905 } 01906 01907 // update of the vectors w and r for U_2 with upper bounding, note that we 01908 // need the headings C, S_{B}, B_{O} before they are updated 01909 template < typename Q, typename ET, typename Tags > // Upper bounded 01910 void QP_solver<Q, ET, Tags>:: 01911 leave_variable_original_upd_w_r(Tag_false ) 01912 { 01913 01914 ET x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i); 01915 01916 // Note: w needs to be updated before r_C, r_S_B 01917 update_w_r_B_O__i(x_i); 01918 update_r_C_r_S_B__i(x_i); 01919 01920 // remove r_beta_O(i) from r_B_O 01921 if (!check_tag(Is_linear())) { // (kf.) 01922 r_B_O[in_B[i]] = r_B_O.back(); 01923 r_B_O.pop_back(); 01924 } 01925 01926 // update x_O_v_i 01927 x_O_v_i[i] = ratio_test_bound_index; 01928 } 01929 01930 // update of the vectors w and r for U_4 with upper bounding, note that we 01931 // need the headings C, S_{B}, B_{O} before they are updated 01932 template < typename Q, typename ET, typename Tags > // Standard form 01933 void QP_solver<Q, ET, Tags>:: 01934 leave_variable_slack_upd_w_r(Tag_true ) 01935 { 01936 } 01937 01938 // update of the vectors w and r for U_4 with upper bounding, note that we 01939 // need the headings C, S_{B}, B_{O} before they are updated 01940 template < typename Q, typename ET, typename Tags > // Upper bounded 01941 void QP_solver<Q, ET, Tags>:: 01942 leave_variable_slack_upd_w_r(Tag_false ) 01943 { 01944 01945 // append r_gamma_S_B(sigma_i) to r_C 01946 r_C.push_back(r_S_B[in_B[i]]); 01947 01948 // remove r_gamma_S_B(sigma_i) from r_S_B 01949 r_S_B[in_B[i]] = r_S_B.back(); 01950 r_S_B.pop_back(); 01951 } 01952 01953 01954 // replace variable in basis QP-case, transition to Ratio Test Step 2 01955 template < typename Q, typename ET, typename Tags > 01956 void QP_solver<Q, ET, Tags>:: 01957 z_replace_variable( ) 01958 { 01959 CGAL_qpe_debug { 01960 vout2 << "<--> nonbasic (" << variable_type( j) << ") variable " << j 01961 << " z_replaces basic (" << variable_type( i) << ") variable " << i 01962 << std::endl << std::endl; 01963 } 01964 01965 // replace variable 01966 z_replace_variable( no_ineq); 01967 01968 // pivot step not yet completely done 01969 i = -1; 01970 j -= in_B.size(); 01971 is_RTS_transition = true; 01972 } 01973 01974 01975 template < typename Q, typename ET, typename Tags > inline // no inequalities 01976 void QP_solver<Q, ET, Tags>:: 01977 z_replace_variable( Tag_true) 01978 { 01979 z_replace_variable_original_by_original(); 01980 strategyP->leaving_basis(i); 01981 01982 } 01983 01984 01985 template < typename Q, typename ET, typename Tags > inline // has inequalities 01986 void QP_solver<Q, ET, Tags>:: 01987 z_replace_variable( Tag_false) 01988 { 01989 // determine type of variables 01990 bool enter_original = ( (j < qp_n) || (j >= (int)( qp_n+slack_A.size()))); 01991 bool leave_original = ( (i < qp_n) || (i >= (int)( qp_n+slack_A.size()))); 01992 01993 // update basis and basis inverse 01994 if ( leave_original) { 01995 if ( enter_original) { 01996 z_replace_variable_original_by_original(); 01997 } else { 01998 z_replace_variable_original_by_slack(); 01999 } 02000 } else { 02001 if ( enter_original) { 02002 z_replace_variable_slack_by_original(); 02003 } else { 02004 z_replace_variable_slack_by_slack(); 02005 } 02006 } 02007 strategyP->leaving_basis( i); 02008 } 02009 02010 02011 // replacement with precond det(M_{B \setminus \{i\}})=0 02012 template < typename Q, typename ET, typename Tags > 02013 void QP_solver<Q, ET, Tags>:: 02014 z_replace_variable_original_by_original( ) 02015 { 02016 // updates for the upper bounded case 02017 z_replace_variable_original_by_original_upd_w_r(Is_nonnegative()); 02018 02019 int k = in_B[ i]; 02020 02021 // replace original variable [ in: j | out: i ] 02022 in_B [ i] = -1; 02023 in_B [ j] = k; 02024 B_O[ k] = j; 02025 02026 minus_c_B[ k] = -ET( *(qp_c+ j)); 02027 02028 // diagnostic output 02029 CGAL_qpe_debug { 02030 if ( vout2.verbose()) print_basis(); 02031 } 02032 02033 // compute s_delta 02034 D_pairwise_accessor d_accessor( qp_D, j); 02035 ET s_delta =d_accessor(j)-d_accessor(i); 02036 02037 // update basis inverse 02038 // note: (-1)\hat{\nu} is stored instead of \hat{\nu} 02039 inv_M_B.z_replace_original_by_original( q_lambda.begin(), q_x_O.begin(), 02040 s_delta, -nu, k); 02041 02042 } 02043 02044 // update of the vectors w and r for U_Z_1 with upper bounding, note that we 02045 // need the headings C, S_{B}, B_{O} before they are updated 02046 template < typename Q, typename ET, typename Tags > // Standard form 02047 void QP_solver<Q, ET, Tags>:: 02048 z_replace_variable_original_by_original_upd_w_r(Tag_true ) 02049 { 02050 } 02051 02052 // update of the vectors w and r for U_Z_1 with upper bounding, note that we 02053 // need the headings C, S_{B}, B_{O} before they are updated 02054 template < typename Q, typename ET, typename Tags > 02055 // Upper bounded 02056 void QP_solver<Q, ET, Tags>:: 02057 z_replace_variable_original_by_original_upd_w_r(Tag_false ) 02058 { 02059 02060 ET x_j = nonbasic_original_variable_value(j); 02061 ET x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i); 02062 02063 // Note: w needs to be updated before r_C, r_S_B 02064 update_w_r_B_O__j_i(x_j, x_i); 02065 update_r_C_r_S_B__j_i(x_j, x_i); 02066 02067 // replace r_beta_O(i) with w_j 02068 r_B_O[in_B[i]] = w[j]; 02069 02070 // update x_O_v_i 02071 x_O_v_i[j] = BASIC; 02072 x_O_v_i[i] = ratio_test_bound_index; 02073 } 02074 02075 02076 // replacement with precond det(M_{B \setminus \{i\}})=0 02077 template < typename Q, typename ET, typename Tags > 02078 void QP_solver<Q, ET, Tags>:: 02079 z_replace_variable_original_by_slack( ) 02080 { 02081 // updates for the upper bounded case 02082 z_replace_variable_original_by_slack_upd_w_r(Is_nonnegative()); 02083 02084 int k = in_B[ i]; 02085 02086 // leave original variable [ out: i ] 02087 in_B [ B_O.back()] = k; 02088 B_O[ k] = B_O.back(); 02089 in_B [ i ] = -1; 02090 B_O.pop_back(); 02091 02092 minus_c_B[ k] = minus_c_B[ B_O.size()]; 02093 02094 // enter slack variable [ in: j ] 02095 int old_row = slack_A[ j-qp_n].first; 02096 in_B [ j] = B_S.size(); 02097 B_S.push_back( j); 02098 S_B.push_back( old_row); 02099 02100 // leave inequality constraint [ out: j ] 02101 int l = in_C[ old_row]; 02102 b_C[ l ] = b_C[ C.size()-1]; 02103 C[ l ] = C.back(); 02104 in_C[ C.back()] = l; 02105 in_C[ old_row ] = -1; 02106 C.pop_back(); 02107 02108 // diagnostic output 02109 CGAL_qpe_debug { 02110 if ( vout2.verbose()) print_basis(); 02111 } 02112 02113 // update basis inverse 02114 inv_M_B.swap_variable( k); 02115 inv_M_B.swap_constraint( l); 02116 inv_M_B.z_replace_original_by_slack( ); 02117 02118 } 02119 02120 // update of the vectors w and r for U_Z_2 with upper bounding, note that we 02121 // need the headings C, S_{B}, B_{O} before they are updated 02122 template < typename Q, typename ET, typename Tags > // Standard form 02123 void QP_solver<Q, ET, Tags>:: 02124 z_replace_variable_original_by_slack_upd_w_r(Tag_true ) 02125 { 02126 } 02127 02128 02129 // update of the vectors w and r for U_Z_2 with upper bounding, note that we 02130 // need the headings C, S_{B}, B_{O} before they are updated 02131 template < typename Q, typename ET, typename Tags > // Upper bounded 02132 void QP_solver<Q, ET, Tags>:: 02133 z_replace_variable_original_by_slack_upd_w_r(Tag_false ) 02134 { 02135 02136 ET x_i = (ratio_test_bound_index == LOWER) ? *(qp_l+i) : *(qp_u+i); 02137 02138 // Note: w needs to be updated before r_C, r_S_B 02139 update_w_r_B_O__i(x_i); 02140 update_r_C_r_S_B__i(x_i); 02141 02142 int sigma_j = slack_A[ j-qp_n].first; 02143 02144 // append r_gamma_C(sigma_j) to r_S_B 02145 r_S_B.push_back(r_C[in_C[sigma_j]]); 02146 02147 // remove r_gamma_C(sigma_j) from r_C 02148 r_C[in_C[sigma_j]] = r_C.back(); 02149 r_C.pop_back(); 02150 02151 // remove r_beta_O(i) from r_B_O 02152 if (!check_tag(Is_linear())) { // (kf.) 02153 r_B_O[in_B[i]] = r_B_O.back(); 02154 r_B_O.pop_back(); 02155 } 02156 02157 // update x_O_v_i 02158 x_O_v_i[i] = ratio_test_bound_index; 02159 } 02160 02161 02162 // replacement with precond det(M_{B \setminus \{i\}})=0 02163 template < typename Q, typename ET, typename Tags > 02164 void QP_solver<Q, ET, Tags>:: 02165 z_replace_variable_slack_by_original( ) 02166 { 02167 // updates for the upper bounded case 02168 z_replace_variable_slack_by_original_upd_w_r(Is_nonnegative()); 02169 02170 int k = in_B[ i]; 02171 if (minus_c_B.size() <= B_O.size()) { // Note: minus_c_B and the 02172 // containers resized in this 02173 // if-block are only enlarged 02174 // and never made smaller 02175 // (while B_O always has the 02176 // correct size). We check here 02177 // whether we need to enlarge 02178 // them. 02179 CGAL_qpe_assertion(minus_c_B.size() == B_O.size()); 02180 minus_c_B.push_back(et0); 02181 q_x_O.push_back(et0); 02182 tmp_x .push_back(et0); 02183 tmp_x_2.push_back(et0); 02184 two_D_Bj.push_back(et0); 02185 x_B_O.push_back(et0); 02186 } 02187 02188 // enter original variable [ in: j ] 02189 02190 minus_c_B[ B_O.size()] = -ET( *(qp_c+ j)); 02191 02192 02193 in_B [ j] = B_O.size(); 02194 B_O.push_back( j); 02195 02196 02197 // leave slack variable [ out: i ] 02198 B_S[ k ] = B_S.back(); 02199 S_B[ k ] = S_B.back(); 02200 in_B [ B_S.back()] = k; 02201 in_B [ i ] = -1; 02202 B_S.pop_back(); 02203 S_B.pop_back(); 02204 02205 // enter inequality constraint [ in: i ] 02206 int new_row = slack_A[ i-qp_n].first; 02207 02208 b_C[ C.size()] = ET( *(qp_b+ new_row)); 02209 in_C[ new_row ] = C.size(); 02210 C.push_back( new_row); 02211 02212 // diagnostic output 02213 CGAL_qpe_debug { 02214 if ( vout2.verbose()) print_basis(); 02215 } 02216 02217 // update basis inverse 02218 // -------------------- 02219 02220 // prepare u 02221 A_row_by_index_accessor a_accessor = 02222 boost::bind (A_accessor( qp_A, 0, qp_n), _1, new_row); 02223 std::copy( A_row_by_index_iterator( B_O.begin(), a_accessor), 02224 A_row_by_index_iterator( B_O.end (), a_accessor), 02225 tmp_x.begin()); 02226 02227 02228 // prepare kappa 02229 ET kappa = d * ET(*((*(qp_A + j))+new_row)) 02230 - inv_M_B.inner_product_x( tmp_x.begin(), q_x_O.begin()); 02231 02232 // note: (-1)/hat{\nu} is stored instead of \hat{\nu} 02233 inv_M_B.z_replace_slack_by_original( q_lambda.begin(), q_x_O.begin(), 02234 tmp_x.begin(), kappa, -nu); 02235 } 02236 02237 // update of the vectors w and r for U_Z_3 with upper bounding, note that we 02238 // need the headings C, S_{B}, B_{O} before they are updated 02239 template < typename Q, typename ET, typename Tags > // Standard form 02240 void QP_solver<Q, ET, Tags>:: 02241 z_replace_variable_slack_by_original_upd_w_r(Tag_true ) 02242 { 02243 } 02244 02245 // update of the vectors w and r for U_Z_3 with upper bounding, note that we 02246 // need the headings C, S_{B}, B_{O} before they are updated 02247 template < typename Q, typename ET, typename Tags > // Upper bounded 02248 void QP_solver<Q, ET, Tags>:: 02249 z_replace_variable_slack_by_original_upd_w_r(Tag_false ) 02250 { 02251 02252 ET x_j = nonbasic_original_variable_value(j); 02253 02254 // Note: w needs to be updated before r_C, r_S_B 02255 update_w_r_B_O__j(x_j); 02256 update_r_C_r_S_B__j(x_j); 02257 02258 // append r_gamma_S_B(sigma_i) to r_C 02259 r_C.push_back(r_S_B[in_B[i]]); 02260 02261 // remove r_gamma_S_B(sigma_i) from r_S_B 02262 r_S_B[in_B[i]] = r_S_B.back(); 02263 r_S_B.pop_back(); 02264 02265 // append w_j to r_B_O 02266 if (!check_tag(Is_linear())) // (kf.) 02267 r_B_O.push_back(w[j]); 02268 02269 // update x_O_v_i 02270 x_O_v_i[j] = BASIC; 02271 } 02272 02273 02274 // replacement with precond det(M_{B \setminus \{i\}})=0 02275 template < typename Q, typename ET, typename Tags > 02276 void QP_solver<Q, ET, Tags>:: 02277 z_replace_variable_slack_by_slack( ) 02278 { 02279 // updates for the upper bounded case 02280 z_replace_variable_slack_by_slack_upd_w_r(Is_nonnegative()); 02281 02282 int k = in_B[ i]; 02283 02284 // replace slack variable [ in: j | out: i ] 02285 in_B [ i] = -1; 02286 in_B [ j] = k; 02287 B_S[ k] = j; 02288 S_B[ k] = slack_A[ j-qp_n].first; 02289 02290 // replace inequality constraint [ in: i | out: j ] 02291 int old_row = S_B[ k]; 02292 int new_row = slack_A[ i-qp_n].first; 02293 k = in_C[ old_row]; 02294 02295 in_C[ old_row] = -1; 02296 in_C[ new_row] = k; 02297 C[ k ] = new_row; 02298 02299 b_C[ k] = ET( *(qp_b+ new_row)); 02300 02301 // diagnostic output 02302 CGAL_qpe_debug { 02303 if ( vout2.verbose()) print_basis(); 02304 } 02305 02306 // update basis inverse 02307 // -------------------- 02308 A_row_by_index_accessor a_accessor = 02309 boost::bind ( A_accessor( qp_A, 0, qp_n), _1, new_row); 02310 std::copy( A_row_by_index_iterator( B_O.begin(), a_accessor), 02311 A_row_by_index_iterator( B_O.end (), a_accessor), 02312 tmp_x.begin()); 02313 02314 02315 inv_M_B.z_replace_slack_by_slack( tmp_x.begin(), k); 02316 } 02317 02318 // update of the vectors w and r for U_Z_4 with upper bounding, note that we 02319 // need the headings C, S_{B}, B_{O} before they are updated 02320 template < typename Q, typename ET, typename Tags > // Standard form 02321 void QP_solver<Q, ET, Tags>:: 02322 z_replace_variable_slack_by_slack_upd_w_r(Tag_true ) 02323 { 02324 } 02325 02326 02327 // update of the vectors w and r for U_Z_4 with upper bounding, note that we 02328 // need the headings C, S_{B}, B_{O} before they are updated 02329 template < typename Q, typename ET, typename Tags > // Upper bounded 02330 void QP_solver<Q, ET, Tags>:: 02331 z_replace_variable_slack_by_slack_upd_w_r(Tag_false ) 02332 { 02333 02334 int sigma_j = slack_A[ j-qp_n].first; 02335 02336 // swap r_sigma_j in r_C with r_sigma_i in r_S_B 02337 std::swap(r_C[in_C[sigma_j]], r_S_B[in_B[i]]); 02338 } 02339 02340 // update of the vectors r_C and r_S_B with "x_j" column 02341 template < typename Q, typename ET, typename Tags > 02342 void QP_solver<Q, ET, Tags>:: 02343 update_r_C_r_S_B__j(ET& x_j) 02344 { 02345 // update of vector r_{C} 02346 A_by_index_accessor a_accessor_j(*(qp_A + j)); 02347 02348 A_by_index_iterator A_C_j_it(C.begin(), a_accessor_j); 02349 02350 for (Value_iterator r_C_it = r_C.begin(); r_C_it != r_C.end(); 02351 ++r_C_it, ++A_C_j_it) { 02352 *r_C_it -= x_j * ET(*A_C_j_it); 02353 } 02354 02355 // update of r_{S_{B}} 02356 A_by_index_iterator A_S_B_j_it(S_B.begin(), a_accessor_j); 02357 02358 for (Value_iterator r_S_B_it = r_S_B.begin(); r_S_B_it != r_S_B.end(); 02359 ++r_S_B_it, ++A_S_B_j_it) { 02360 *r_S_B_it -= x_j * ET(*A_S_B_j_it); 02361 } 02362 } 02363 02364 // update of the vectors r_C and r_S_B with "x_j" and "x_i" column 02365 template < typename Q, typename ET, typename Tags > 02366 void QP_solver<Q, ET, Tags>:: 02367 update_r_C_r_S_B__j_i(ET& x_j, ET& x_i) 02368 { 02369 // update of vector r_{C} 02370 A_by_index_accessor a_accessor_j(*(qp_A+j)); 02371 A_by_index_accessor a_accessor_i(*(qp_A+i)); 02372 02373 A_by_index_iterator A_C_j_it(C.begin(), a_accessor_j); 02374 A_by_index_iterator A_C_i_it(C.begin(), a_accessor_i); 02375 02376 for (Value_iterator r_C_it = r_C.begin(); r_C_it != r_C.end(); 02377 ++r_C_it, ++A_C_j_it, ++A_C_i_it) { 02378 *r_C_it += (x_i * ET(*A_C_i_it)) - (x_j * ET(*A_C_j_it)); 02379 } 02380 02381 // update of vector r_{S_{B}} 02382 A_by_index_iterator A_S_B_j_it(S_B.begin(), a_accessor_j); 02383 A_by_index_iterator A_S_B_i_it(S_B.begin(), a_accessor_i); 02384 02385 for (Value_iterator r_S_B_it = r_S_B.begin(); r_S_B_it != r_S_B.end(); 02386 ++r_S_B_it, ++A_S_B_j_it, ++A_S_B_i_it) { 02387 *r_S_B_it += (x_i * ET(*A_S_B_i_it)) - (x_j * ET(*A_S_B_j_it)); 02388 } 02389 } 02390 02391 // update of the vectors r_C and r_S_B with "x_i'" column 02392 template < typename Q, typename ET, typename Tags > 02393 void QP_solver<Q, ET, Tags>:: 02394 update_r_C_r_S_B__i(ET& x_i) 02395 { 02396 // update of vector r_{C} 02397 A_by_index_accessor a_accessor_i(*(qp_A+i)); 02398 A_by_index_iterator A_C_i_it(C.begin(), a_accessor_i); 02399 02400 for (Value_iterator r_C_it = r_C.begin(); r_C_it != r_C.end(); 02401 ++r_C_it, ++A_C_i_it) { 02402 *r_C_it += x_i * ET(*A_C_i_it); 02403 } 02404 02405 // update of r_{S_{B}} 02406 A_by_index_iterator A_S_B_i_it(S_B.begin(), a_accessor_i); 02407 02408 for (Value_iterator r_S_B_it = r_S_B.begin(); r_S_B_it != r_S_B.end(); 02409 ++r_S_B_it, ++A_S_B_i_it) { 02410 *r_S_B_it += x_i * ET(*A_S_B_i_it); 02411 } 02412 } 02413 02414 02415 // Update of w and r_B_O with "x_j" column. 02416 // 02417 // todo: could be optimized slightly by factoring out the factor 2 02418 // (which is implicitly contained in the pairwise accessor for D). 02419 template < typename Q, typename ET, typename Tags > 02420 void QP_solver<Q, ET, Tags>:: 02421 update_w_r_B_O__j(ET& x_j) 02422 { 02423 // assertion checking: 02424 CGAL_expensive_assertion(!check_tag(Is_nonnegative())); 02425 02426 // Note: we only do anything it we are dealing with a QP. 02427 if (!check_tag(Is_linear())) { 02428 D_pairwise_accessor d_accessor_j(qp_D, j); 02429 02430 // update of vector w: 02431 for (int it = 0; it < qp_n; ++it) 02432 w[it] -= d_accessor_j(it) * x_j; 02433 02434 // update of r_B_O: 02435 D_pairwise_iterator D_B_O_j_it(B_O.begin(), d_accessor_j); 02436 for (Value_iterator r_B_O_it = r_B_O.begin(); 02437 r_B_O_it != r_B_O.end(); 02438 ++r_B_O_it, ++D_B_O_j_it) 02439 *r_B_O_it -= *D_B_O_j_it * x_j; 02440 } 02441 } 02442 02443 // update of w and r_B_O with "x_j" and "x_i" column 02444 template < typename Q, typename ET, typename Tags > 02445 void QP_solver<Q, ET, Tags>:: 02446 update_w_r_B_O__j_i(ET& x_j, ET& x_i) 02447 { 02448 // assertion checking: 02449 CGAL_expensive_assertion(!check_tag(Is_nonnegative())); 02450 02451 // Note: we only do anything it we are dealing with a QP. 02452 if (!check_tag(Is_linear())) { 02453 D_pairwise_accessor d_accessor_i(qp_D, i); 02454 D_pairwise_accessor d_accessor_j(qp_D, j); 02455 02456 // update of vector w 02457 for (int it = 0; it < qp_n; ++it) 02458 w[it] += (d_accessor_i(it) * x_i) - (d_accessor_j(it) * x_j); 02459 02460 // update of r_B_O 02461 D_pairwise_iterator D_B_O_j_it(B_O.begin(), d_accessor_j); 02462 D_pairwise_iterator D_B_O_i_it(B_O.begin(), d_accessor_i); 02463 for (Value_iterator r_B_O_it = r_B_O.begin(); 02464 r_B_O_it != r_B_O.end(); 02465 ++r_B_O_it, ++D_B_O_j_it, ++D_B_O_i_it) 02466 *r_B_O_it += (*D_B_O_i_it * x_i) - (*D_B_O_j_it * x_j); 02467 } 02468 } 02469 02470 // update of w and r_B_O with "x_i" column 02471 template < typename Q, typename ET, typename Tags > 02472 void QP_solver<Q, ET, Tags>:: 02473 update_w_r_B_O__i(ET& x_i) 02474 { 02475 CGAL_expensive_assertion(!check_tag(Is_nonnegative())); 02476 02477 // Note: we only do anything it we are dealing with a QP. 02478 if (!check_tag(Is_linear())) { 02479 02480 // update of vector w: 02481 D_pairwise_accessor d_accessor_i(qp_D, i); 02482 02483 for (int it = 0; it < qp_n; ++it) 02484 w[it] += d_accessor_i(it) * x_i; 02485 02486 // update of r_B_O: 02487 D_pairwise_iterator D_B_O_i_it(B_O.begin(), d_accessor_i); 02488 for (Value_iterator r_B_O_it = r_B_O.begin(); 02489 r_B_O_it != r_B_O.end(); 02490 ++r_B_O_it, ++D_B_O_i_it) 02491 *r_B_O_it += *D_B_O_i_it * x_i; 02492 } 02493 } 02494 02495 // Compute solution, meaning compute the solution vector x and the KKT 02496 // coefficients lambda. 02497 template < typename Q, typename ET, typename Tags > // Standard form 02498 void QP_solver<Q, ET, Tags>:: 02499 compute_solution(Tag_true) 02500 { 02501 // compute current solution, original variables and lambdas 02502 inv_M_B.multiply( b_C.begin(), minus_c_B.begin(), 02503 lambda.begin(), x_B_O.begin()); 02504 02505 // compute current solution, slack variables 02506 compute__x_B_S(no_ineq, Is_nonnegative()); 02507 } 02508 02509 // Compute solution, meaning compute the solution vector x and the KKT 02510 // coefficients lambda. 02511 template < typename Q, typename ET, typename Tags > // Upper bounded 02512 void QP_solver<Q, ET, Tags>:: 02513 compute_solution(Tag_false) 02514 { 02515 // compute the difference b_C - r_C 02516 std::transform(b_C.begin(), b_C.begin()+C.size(), // Note: r_C.size() == 02517 // C.size() always holds, 02518 // whereas b_C.size() >= 02519 // C.size() in general. 02520 r_C.begin(), tmp_l.begin(), std::minus<ET>()); 02521 02522 // compute the difference minus_c_B - r_B_O: 02523 if (is_phaseII && is_QP) { 02524 std::transform(minus_c_B.begin(), minus_c_B.begin() + B_O.size(), 02525 r_B_O.begin(), tmp_x.begin(), std::minus<ET>()); 02526 02527 // compute current solution, original variables and lambdas: 02528 inv_M_B.multiply( tmp_l.begin(), tmp_x.begin(), 02529 lambda.begin(), x_B_O.begin()); 02530 } else { // r_B_O == 0 02531 02532 // compute current solution, original variables and lambdas 02533 inv_M_B.multiply( tmp_l.begin(), minus_c_B.begin(), 02534 lambda.begin(), x_B_O.begin()); 02535 } 02536 02537 // compute current solution, slack variables 02538 compute__x_B_S( no_ineq, Is_nonnegative()); 02539 } 02540 02541 template < typename Q, typename ET, typename Tags > 02542 void QP_solver<Q, ET, Tags>:: 02543 multiply__A_S_BxB_O(Value_iterator in, Value_iterator out) const 02544 { 02545 // initialize with zero vector 02546 std::fill_n( out, B_S.size(), et0); 02547 02548 // foreach original column of A in B_O (artificial columns are zero in S_B 02549 A_column a_col; // except special) 02550 Index_const_iterator row_it, col_it; 02551 Value_iterator out_it; 02552 //ET in_value; 02553 for ( col_it = B_O.begin(); col_it != B_O.end(); ++col_it, ++in) { 02554 const ET in_value = *in; 02555 out_it = out; 02556 02557 if ( *col_it < qp_n) { // original variable 02558 a_col = *(qp_A+ *col_it); 02559 02560 // foreach row of A in S_B 02561 for ( row_it = S_B.begin(); row_it != S_B.end(); ++row_it, 02562 ++out_it) { 02563 *out_it += ET( a_col[ *row_it]) * in_value; 02564 } 02565 } else { 02566 if ( *col_it == art_s_i) { // special artificial 02567 02568 // foreach row of 'art_s' 02569 for ( row_it = S_B.begin(); row_it != S_B.end(); ++row_it, 02570 ++out_it) { 02571 *out_it += ET( art_s[ *row_it]) * in_value; 02572 } 02573 } 02574 } 02575 } 02576 } 02577 02578 // compare the updated vector r_{C} with t_r_C=A_{C, N_O}x_{N_O} 02579 template < typename Q, typename ET, typename Tags > // Standard form 02580 bool QP_solver<Q, ET, Tags>:: 02581 check_r_C(Tag_true) const 02582 { 02583 return true; 02584 } 02585 02586 // compare the updated vector r_{C} with t_r_C=A_{C, N_O}x_{N_O} 02587 template < typename Q, typename ET, typename Tags > // Upper bounded 02588 bool QP_solver<Q, ET, Tags>:: 02589 check_r_C(Tag_false) const 02590 { 02591 Values t_r_C; 02592 // compute t_r_C from scratch 02593 t_r_C.resize(C.size(), et0); 02594 multiply__A_CxN_O(t_r_C.begin()); 02595 02596 // compare r_C and the from scratch computed t_r_C 02597 bool failed = false; 02598 int count = 0; 02599 Value_const_iterator t_r_C_it = r_C.begin(); 02600 for (Value_const_iterator r_C_it = r_C.begin(); r_C_it != r_C.end(); 02601 ++r_C_it, ++t_r_C_it, ++count) { 02602 if (*r_C_it != *t_r_C_it) { 02603 failed = true; 02604 } 02605 } 02606 return (!failed); 02607 } 02608 02609 // compare the updated vector r_{S_B} with t_r_S_B=A_{S_B, N_O}x_{N_O} 02610 template < typename Q, typename ET, typename Tags > // Standard form 02611 bool QP_solver<Q, ET, Tags>:: 02612 check_r_S_B(Tag_true) const 02613 { 02614 return true; 02615 } 02616 02617 // compare the updated vector r_{S_B} with t_r_S_B=A_{S_B, N_O}x_{N_O} 02618 template < typename Q, typename ET, typename Tags > // Upper bounded 02619 bool QP_solver<Q, ET, Tags>:: 02620 check_r_S_B(Tag_false) const 02621 { 02622 Values t_r_S_B; 02623 // compute t_r_S_B from scratch 02624 t_r_S_B.resize(S_B.size(), et0); 02625 multiply__A_S_BxN_O(t_r_S_B.begin()); 02626 02627 // compare r_S_B and the from scratch computed t_r_S_B 02628 bool failed = false; 02629 int count = 0; 02630 Value_const_iterator t_r_S_B_it = t_r_S_B.begin(); 02631 for (Value_const_iterator r_S_B_it = r_S_B.begin(); r_S_B_it != r_S_B.end(); 02632 ++r_S_B_it, ++t_r_S_B_it, ++count) { 02633 if (*r_S_B_it != *t_r_S_B_it) { 02634 failed = true; 02635 } 02636 } 02637 return (!failed); 02638 } 02639 02640 02641 // computes r_{B_{O}}:=2D_{B_O, N_O}x_{N_O} with upper bounding 02642 // OPTIMIZATION: If D is symmetric we can multiply by two at the end of the 02643 // computation of entry of r_B_O instead of each access to D 02644 template < typename Q, typename ET, typename Tags > 02645 void QP_solver<Q, ET, Tags>:: 02646 multiply__2D_B_OxN_O(Value_iterator out) const 02647 { 02648 //initialize 02649 std::fill_n( out, B_O.size(), et0); 02650 02651 Value_iterator out_it; 02652 ET value; 02653 02654 // foreach entry in r_B_O 02655 out_it = out; 02656 for (Index_const_iterator row_it = B_O.begin(); row_it != B_O.end(); 02657 ++row_it, ++out_it) { 02658 D_pairwise_accessor d_accessor_i(qp_D, *row_it); 02659 for (int i = 0; i < qp_n; ++i) { 02660 if (!is_basic(i)) { 02661 value = nonbasic_original_variable_value(i); 02662 *out_it += d_accessor_i(i) * value; 02663 } 02664 } 02665 } 02666 } 02667 02668 // compares the updated vector r_{B_O} with t_r_B_O=2D_{B_O, N_O}x_{N_O} 02669 template < typename Q, typename ET, typename Tags > // Standard form 02670 bool QP_solver<Q, ET, Tags>:: 02671 check_r_B_O(Tag_true) const 02672 { 02673 return true; 02674 } 02675 02676 // compares the updated vector r_{B_O} with t_r_B_O=2D_{B_O, N_O}x_{N_O} 02677 template < typename Q, typename ET, typename Tags > // Upper bounded 02678 bool QP_solver<Q, ET, Tags>:: 02679 check_r_B_O(Tag_false) const 02680 { 02681 Values t_r_B_O; 02682 // compute t_r_B_O from scratch 02683 t_r_B_O.resize(B_O.size(), et0); 02684 multiply__2D_B_OxN_O(t_r_B_O.begin()); 02685 02686 // compare r_B_O and the from scratch computed t_r_B_O 02687 bool failed = false; 02688 int count = 0; 02689 Value_const_iterator t_r_B_O_it = t_r_B_O.begin(); 02690 for (Value_const_iterator r_B_O_it = r_B_O.begin(); r_B_O_it != r_B_O.end(); 02691 ++r_B_O_it, ++t_r_B_O_it, ++count) { 02692 if (*r_B_O_it != *t_r_B_O_it) { 02693 failed = true; 02694 } 02695 } 02696 return (!failed); 02697 } 02698 02699 // compares the updated vector w with t_w=2D_{O,N_O}*x_N_O 02700 template < typename Q, typename ET, typename Tags > // Standard form 02701 bool QP_solver<Q, ET, Tags>:: 02702 check_w(Tag_true) const 02703 { 02704 return true; 02705 } 02706 02707 // compares the updated vector w with t_w=2D_O_N_O*x_N_O 02708 template < typename Q, typename ET, typename Tags > // Upper bounded 02709 bool QP_solver<Q, ET, Tags>:: 02710 check_w(Tag_false) const 02711 { 02712 Values t_w; 02713 // compute t_w from scratch 02714 t_w.resize( qp_n, et0); 02715 multiply__2D_OxN_O(t_w.begin()); 02716 02717 // compare w and the from scratch computed t_w 02718 bool failed = false; 02719 Value_const_iterator t_w_it = t_w.begin(); 02720 for (int i = 0; i < qp_n; ++i, ++t_w_it) { 02721 if (w[i] != *t_w_it) { 02722 failed = true; 02723 } 02724 } 02725 return (!failed); 02726 } 02727 02728 // check basis inverse 02729 template < typename Q, typename ET, typename Tags > 02730 bool 02731 QP_solver<Q, ET, Tags>:: 02732 check_basis_inverse() 02733 { 02734 // diagnostic output 02735 CGAL_qpe_debug { 02736 vout4 << "check: " << std::flush; 02737 } 02738 bool ok; 02739 if (is_phaseI) { 02740 ok = check_basis_inverse(Tag_true()); 02741 } else { 02742 ok = check_basis_inverse( Is_linear()); 02743 } 02744 02745 // diagnostic output 02746 CGAL_qpe_debug { 02747 if ( ok) { 02748 vout4 << "check ok"; 02749 } else { 02750 vout4 << "check failed"; 02751 } 02752 vout4 << std::endl; 02753 } 02754 02755 return ok; 02756 } 02757 02758 template < typename Q, typename ET, typename Tags > // LP case 02759 bool QP_solver<Q, ET, Tags>:: 02760 check_basis_inverse( Tag_true) 02761 { 02762 CGAL_qpe_debug { 02763 vout4 << std::endl; 02764 } 02765 bool res = true; 02766 unsigned int row, rows = C.size(); 02767 unsigned int col, cols = B_O.size(); 02768 Index_iterator i_it = B_O.begin(); 02769 Value_iterator q_it; 02770 02771 02772 // BG: is this a real check?? How does the special artifical 02773 // variable come in, e.g.? OK: it comes in through 02774 // ratio_test_init__A_Cj 02775 for ( col = 0; col < cols; ++col, ++i_it) { 02776 ratio_test_init__A_Cj( tmp_l.begin(), *i_it, 02777 no_ineq); 02778 inv_M_B.multiply_x( tmp_l.begin(), q_x_O.begin()); 02779 02780 CGAL_qpe_debug { 02781 if ( vout4.verbose()) { 02782 std::copy( tmp_l.begin(), tmp_l.begin()+rows, 02783 std::ostream_iterator<ET>( vout4.out(), " ")); 02784 vout4.out() << " || "; 02785 std::copy( q_x_O.begin(), q_x_O.begin()+cols, 02786 std::ostream_iterator<ET>( vout4.out(), " ")); 02787 vout4.out() << std::endl; 02788 } 02789 } 02790 02791 q_it = q_x_O.begin(); 02792 for ( row = 0; row < rows; ++row, ++q_it) { 02793 if ( *q_it != ( row == col ? d : et0)) { 02794 if ( ! vout4.verbose()) { 02795 std::cerr << std::endl << "basis-inverse check: "; 02796 } 02797 std::cerr << "failed ( row=" << row << " | col=" << col << " )" 02798 << std::endl; 02799 res = false; 02800 } 02801 } 02802 } 02803 02804 return res; 02805 } 02806 02807 template < typename Q, typename ET, typename Tags > // QP case 02808 bool QP_solver<Q, ET, Tags>:: 02809 check_basis_inverse( Tag_false) 02810 { 02811 bool res = true; 02812 unsigned int row, rows = C.size(); 02813 unsigned int col, cols = B_O.size(); 02814 Value_iterator v_it; 02815 Index_iterator i_it; 02816 02817 CGAL_qpe_debug { 02818 vout4 << std::endl; 02819 } 02820 // left part of M_B 02821 std::fill_n( tmp_l.begin(), rows, et0); 02822 for ( col = 0; col < rows; ++col) { 02823 02824 // get column of A_B^T (i.e. row of A_B) 02825 row = ( has_ineq ? C[ col] : col); 02826 v_it = tmp_x.begin(); 02827 for ( i_it = B_O.begin(); i_it != B_O.end(); ++i_it, ++v_it) { 02828 *v_it = ( *i_it < qp_n ? *((*(qp_A+ *i_it))+ row) : // original 02829 art_A[ *i_it - qp_n].first != (int)row ? et0 :// artific. 02830 ( art_A[ *i_it - qp_n].second ? -et1 : et1)); 02831 } 02832 // if ( art_s_i >= 0) { // special artificial variable? 02833 // CGAL_qpe_assertion ((int)in_B.size() == art_s_i+1); 02834 // // the special artificial variable has never been 02835 // // removed from the basis, consider it 02836 // tmp_x[ in_B[ art_s_i]] = art_s[ row]; 02837 // } 02838 // BG: currently, this check only runs in phase II, where we have no 02839 // articficials 02840 CGAL_qpe_assertion (art_s_i < 0); 02841 02842 inv_M_B.multiply( tmp_l.begin(), tmp_x.begin(), 02843 q_lambda.begin(), q_x_O.begin()); 02844 02845 CGAL_qpe_debug { 02846 if ( vout4.verbose()) { 02847 std::copy( tmp_l.begin(), tmp_l.begin()+rows, 02848 std::ostream_iterator<ET>( vout4.out(), " ")); 02849 vout4.out() << "| "; 02850 std::copy( tmp_x.begin(), tmp_x.begin()+cols, 02851 std::ostream_iterator<ET>( vout4.out(), " ")); 02852 vout4.out() << " || "; 02853 std::copy( q_lambda.begin(), q_lambda.begin()+rows, 02854 std::ostream_iterator<ET>( vout4.out(), " ")); 02855 vout4.out() << " | "; 02856 std::copy( q_x_O.begin(), q_x_O.begin()+cols, 02857 std::ostream_iterator<ET>( vout4.out(), " ")); 02858 vout4.out() << std::endl; 02859 } 02860 } 02861 02862 v_it = q_lambda.begin(); 02863 for ( row = 0; row < rows; ++row, ++v_it) { 02864 if ( *v_it != ( row == col ? d : et0)) { 02865 if ( ! vout4.verbose()) { 02866 std::cerr << std::endl << "basis-inverse check: "; 02867 } 02868 std::cerr << "failed ( row=" << row << " | col=" << col << " )" 02869 << std::endl; 02870 // return false; 02871 res = false; 02872 } 02873 } 02874 v_it = std::find_if( q_x_O.begin(), q_x_O.begin()+cols, 02875 std::bind2nd( std::not_equal_to<ET>(), et0)); 02876 if ( v_it != q_x_O.begin()+cols) { 02877 if ( ! vout4.verbose()) { 02878 std::cerr << std::endl << "basis-inverse check: "; 02879 } 02880 std::cerr << "failed ( row=" << rows+(v_it-q_x_O.begin()) 02881 << " | col=" << col << " )" << std::endl; 02882 // ToDo: return false; 02883 res = false; 02884 } 02885 } 02886 vout4 << "= = = = = = = = = =" << std::endl; 02887 02888 // right part of M_B 02889 if ( is_phaseI) std::fill_n( tmp_x.begin(), B_O.size(), et0); 02890 i_it = B_O.begin(); 02891 for ( col = 0; col < cols; ++col, ++i_it) { 02892 ratio_test_init__A_Cj ( tmp_l.begin(), *i_it, 02893 no_ineq); 02894 ratio_test_init__2_D_Bj( tmp_x.begin(), *i_it, Tag_false()); 02895 inv_M_B.multiply( tmp_l.begin(), tmp_x.begin(), 02896 q_lambda.begin(), q_x_O.begin()); 02897 02898 CGAL_qpe_debug { 02899 if ( vout4.verbose()) { 02900 std::copy( tmp_l.begin(), tmp_l.begin()+rows, 02901 std::ostream_iterator<ET>( vout4.out(), " ")); 02902 vout4.out() << "| "; 02903 std::copy( tmp_x.begin(), tmp_x.begin()+cols, 02904 std::ostream_iterator<ET>( vout4.out(), " ")); 02905 vout4.out() << " || "; 02906 std::copy( q_lambda.begin(), q_lambda.begin()+rows, 02907 std::ostream_iterator<ET>( vout4.out(), " ")); 02908 vout4.out() << " | "; 02909 std::copy( q_x_O.begin(), q_x_O.begin()+cols, 02910 std::ostream_iterator<ET>( vout4.out(), " ")); 02911 vout4.out() << std::endl; 02912 } 02913 } 02914 02915 v_it = std::find_if( q_lambda.begin(), q_lambda.begin()+rows, 02916 std::bind2nd( std::not_equal_to<ET>(), et0)); 02917 if ( v_it != q_lambda.begin()+rows) { 02918 if ( ! vout4.verbose()) { 02919 std::cerr << std::endl << "basis-inverse check: "; 02920 } 02921 std::cerr << "failed ( row=" << v_it-q_lambda.begin() 02922 << " | col=" << col << " )" << std::endl; 02923 // return false; 02924 res = false; 02925 } 02926 v_it = q_x_O.begin(); 02927 for ( row = 0; row < cols; ++row, ++v_it) { 02928 if ( *v_it != ( row == col ? d : et0)) { 02929 if ( ! vout4.verbose()) { 02930 std::cerr << std::endl << "basis-inverse check: "; 02931 } 02932 std::cerr << "failed ( row=" << row+rows << " | col=" 02933 << col << " )" << std::endl; 02934 // return false; 02935 res = false; 02936 } 02937 } 02938 } 02939 return res; 02940 } 02941 02942 // filtered strategies are only allowed if the input type as 02943 // indicated by C_entry is double; this may still fail if the 02944 // types of some other program entries are not double, but 02945 // since the filtered stuff is internal anyway, we can probably 02946 // live with this simple check 02947 template < typename Q, typename ET, typename Tags > 02948 void QP_solver<Q, ET, Tags>:: 02949 set_pricing_strategy 02950 ( Quadratic_program_pricing_strategy strategy) 02951 { 02952 CGAL_qpe_assertion( phase() != 1); 02953 CGAL_qpe_assertion( phase() != 2); 02954 02955 if (strategy == QP_DANTZIG) 02956 strategyP = new QP_full_exact_pricing<Q, ET, Tags>; 02957 else if (strategy == QP_FILTERED_DANTZIG) 02958 // choose between FF (double) and FE (anything else) 02959 strategyP = 02960 new typename QP_solver_impl::Filtered_pricing_strategy_selector 02961 <Q, ET, Tags, C_entry>::FF; 02962 else if (strategy == QP_PARTIAL_DANTZIG) 02963 strategyP = new QP_partial_exact_pricing<Q, ET, Tags>; 02964 else if (strategy == QP_PARTIAL_FILTERED_DANTZIG 02965 || strategy == QP_CHOOSE_DEFAULT) 02966 // choose between PF (double) and PE (anything else) 02967 strategyP = 02968 new typename QP_solver_impl::Filtered_pricing_strategy_selector 02969 <Q, ET, Tags, C_entry>::PF; 02970 else if (strategy == QP_BLAND) 02971 strategyP = new QP_exact_bland_pricing<Q, ET, Tags>; 02972 CGAL_qpe_assertion(strategyP != static_cast<Pricing_strategy*>(0)); 02973 02974 if ( phase() != -1) strategyP->set( *this, vout2); 02975 } 02976 02977 // diagnostic output 02978 // ----------------- 02979 template < typename Q, typename ET, typename Tags > 02980 void QP_solver<Q, ET, Tags>:: 02981 set_verbosity( int verbose, std::ostream& stream) 02982 { 02983 vout = Verbose_ostream( verbose > 0, stream); 02984 vout1 = Verbose_ostream( verbose == 1, stream); 02985 vout2 = Verbose_ostream( verbose >= 2, stream); 02986 vout3 = Verbose_ostream( verbose >= 3, stream); 02987 vout4 = Verbose_ostream( verbose == 4, stream); 02988 vout5 = Verbose_ostream( verbose == 5, stream); 02989 } 02990 02991 template < typename Q, typename ET, typename Tags > 02992 void QP_solver<Q, ET, Tags>:: 02993 print_program( ) const 02994 { 02995 int row, i; 02996 02997 // objective function 02998 vout4.out() << std::endl << "objective function:" << std::endl; 02999 if ( is_QP) { 03000 vout4.out() << "--> output of MATRIX must go here <--"; 03001 vout4.out() << std::endl; 03002 } 03003 std::copy( qp_c, qp_c+qp_n, 03004 std::ostream_iterator<C_entry>( vout4.out(), " ")); 03005 vout4.out() << "(+ " << qp_c0 << ") "; 03006 vout4.out() << std::endl; 03007 vout4.out() << std::endl; 03008 03009 // constraints 03010 vout4.out() << "constraints:" << std::endl; 03011 for ( row = 0; row < qp_m; ++row) { 03012 03013 // original variables 03014 for (i = 0; i < qp_n; ++i) 03015 vout4.out() << *((*(qp_A+ i))+row) << ' '; 03016 03017 // slack variables 03018 if ( ! slack_A.empty()) { 03019 vout4.out() << " | "; 03020 for ( i = 0; i < (int)slack_A.size(); ++i) { 03021 vout4.out() << ( slack_A[ i].first != row ? " 0" : 03022 ( slack_A[ i].second ? "-1" : "+1")) << ' '; 03023 } 03024 } 03025 03026 // artificial variables 03027 if ( ! art_A.empty()) { 03028 vout4.out() << " | "; 03029 for ( i = 0; i < (int)art_A.size(); ++i) { 03030 if (art_s_i == i+qp_n+(int)slack_A.size()) 03031 vout4.out() << " * "; // for special artificial column 03032 vout4.out() << ( art_A[ i].first != row ? " 0" : 03033 ( art_A[ i].second ? "-1" : "+1")) << ' '; 03034 } 03035 } 03036 if ( ! art_s.empty()) vout4.out() << " | " << art_s[ row] << ' '; 03037 03038 // rhs 03039 vout4.out() << " | " 03040 << ( *(qp_r+ row) == CGAL::EQUAL ? ' ' : 03041 ( *(qp_r+ row) == CGAL::SMALLER ? '<' : '>')) << "= " 03042 << *(qp_b+ row); 03043 if (!is_nonnegative) { 03044 vout4.out() << " - " << multiply__A_ixO(row); 03045 } 03046 vout4.out() << std::endl; 03047 } 03048 vout4.out() << std::endl; 03049 03050 // explicit bounds 03051 if (!is_nonnegative) { 03052 vout4.out() << "explicit bounds:" << std::endl; 03053 for (int i = 0; i < qp_n; ++i) { 03054 if (*(qp_fl+i)) { // finite lower bound 03055 vout4.out() << *(qp_l+i); 03056 } else { // infinite lower bound 03057 vout4.out() << "-inf"; 03058 } 03059 vout4.out() << " <= x_" << i << " <= "; 03060 if (*(qp_fu+i)) { 03061 vout4.out() << *(qp_u+i); 03062 } else { 03063 vout4.out() << "inf"; 03064 } 03065 vout4.out() << std::endl; 03066 } 03067 } 03068 } 03069 03070 template < typename Q, typename ET, typename Tags > 03071 void QP_solver<Q, ET, Tags>:: 03072 print_basis( ) const 03073 { 03074 char label; 03075 vout << " basis: "; 03076 CGAL_qpe_debug { 03077 vout2 << "basic variables" << ( has_ineq ? " " : "") << ": "; 03078 } 03079 std::copy( B_O.begin(), B_O.end (), 03080 std::ostream_iterator<int>( vout.out(), " ")); 03081 CGAL_qpe_debug { 03082 if ( vout2.verbose()) { 03083 if ( has_ineq && ( ! slack_A.empty())) { 03084 vout2.out() << " | "; 03085 std::copy( B_S.begin(), B_S.end(), 03086 std::ostream_iterator<int>( vout2.out(), " ")); 03087 } 03088 if ( is_phaseI) { 03089 vout2.out() << " (# of artificials: " << art_basic << ')'; 03090 } 03091 if ( has_ineq) { 03092 vout2.out() << std::endl 03093 << "basic constraints: "; 03094 for (Index_const_iterator i_it = 03095 C.begin(); i_it != C.end(); ++i_it) { 03096 label = (*(qp_r+ *i_it) == CGAL::EQUAL) ? 'e' : 'i'; 03097 vout2.out() << *i_it << ":" << label << " "; 03098 } 03099 /* 03100 std::copy( C.begin(), C.begin()+(C.size()-slack_A.size()), 03101 std::ostream_iterator<int>( vout2.out(), " ")); 03102 if ( ! slack_A.empty()) { 03103 vout2.out() << " | "; 03104 std::copy( C.end() - slack_A.size(), C.end(), 03105 std::ostream_iterator<int>( vout2.out(), " ")); 03106 } 03107 */ 03108 } 03109 if ( vout3.verbose()) { 03110 vout3.out() << std::endl 03111 << std::endl 03112 << " in_B: "; 03113 std::copy( in_B.begin(), in_B.end(), 03114 std::ostream_iterator<int>( vout3.out(), " ")); 03115 if ( has_ineq) { 03116 vout3.out() << std::endl 03117 << " in_C: "; 03118 std::copy( in_C.begin(), in_C.end(), 03119 std::ostream_iterator<int>( vout3.out(), " ")); 03120 } 03121 } 03122 } 03123 } 03124 vout.out() << std::endl; 03125 CGAL_qpe_debug { 03126 vout4 << std::endl << "basis-inverse:" << std::endl; 03127 } 03128 } 03129 03130 template < typename Q, typename ET, typename Tags > 03131 void QP_solver<Q, ET, Tags>:: 03132 print_solution( ) const 03133 { 03134 CGAL_qpe_debug { 03135 if ( vout3.verbose()) { 03136 vout3.out() << std::endl 03137 << " b_C: "; 03138 std::copy( b_C.begin(), b_C.begin()+C.size(), 03139 std::ostream_iterator<ET>( vout3.out()," ")); 03140 vout3.out() << std::endl 03141 << " -c_B_O: "; 03142 std::copy( minus_c_B.begin(), minus_c_B.begin()+B_O.size(), 03143 std::ostream_iterator<ET>( vout3.out()," ")); 03144 if (!is_nonnegative) { 03145 vout3.out() << std::endl 03146 << " r_C: "; 03147 std::copy( r_C.begin(), r_C.begin()+r_C.size(), 03148 std::ostream_iterator<ET>( vout3.out(), " ")); 03149 vout3.out() << std::endl 03150 << " r_B_O: "; 03151 std::copy( r_B_O.begin(), r_B_O.begin()+r_B_O.size(), 03152 std::ostream_iterator<ET>( vout3.out(), " ")); 03153 if (r_B_O.size() == 0) 03154 vout3.out() << "< will only be allocated in phase II>"; 03155 03156 } 03157 vout3.out() << std::endl; 03158 } 03159 if ( vout2.verbose()) { 03160 vout2.out() << std::endl << " lambda: "; 03161 std::copy( lambda.begin(), lambda.begin()+C.size(), 03162 std::ostream_iterator<ET>( vout2.out(), " ")); 03163 vout2.out() << std::endl << " x_B_O: "; 03164 std::copy( x_B_O.begin(), x_B_O.begin()+B_O.size(), 03165 std::ostream_iterator<ET>( vout2.out(), " ")); 03166 vout2.out() << std::endl; 03167 if (!is_nonnegative) { 03168 vout2.out() << " x_N_O: "; 03169 for (int i = 0; i < qp_n; ++i) { 03170 if (!is_basic(i)) { 03171 vout2.out() << d * 03172 nonbasic_original_variable_value(i); 03173 vout2.out() << " "; 03174 } 03175 } 03176 vout2.out() << std::endl; 03177 } 03178 if ( has_ineq) { 03179 vout2.out() << " x_B_S: "; 03180 std::copy( x_B_S.begin(), x_B_S.begin()+B_S.size(), 03181 std::ostream_iterator<ET>( vout2.out()," ")); 03182 vout2.out() << std::endl; 03183 } 03184 const ET denom = inv_M_B.denominator(); 03185 vout2.out() << " denominator: " << denom << std::endl; 03186 vout2.out() << std::endl; 03187 } 03188 } 03189 vout << " "; 03190 vout.out() 03191 << "solution: " 03192 << solution_numerator() << " / " << solution_denominator() 03193 << " ~= " 03194 << to_double 03195 (CGAL::Quotient<ET>(solution_numerator(), solution_denominator())) 03196 << std::endl; 03197 CGAL_qpe_debug { 03198 vout2 << std::endl; 03199 } 03200 } 03201 03202 template < typename Q, typename ET, typename Tags > 03203 void QP_solver<Q, ET, Tags>:: 03204 print_ratio_1_original(int k, const ET& x_k, const ET& q_k) 03205 { 03206 if (is_nonnegative) { // => direction== 1 03207 if (q_k > et0) { // check for lower bound 03208 vout2.out() << "t_O_" << k << ": " 03209 << x_k << '/' << q_k 03210 << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "") 03211 << std::endl; 03212 } else if (q_k < et0) { // check for upper bound 03213 vout2.out() << "t_O_" << k << ": " 03214 << "inf" << '/' << q_k 03215 << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "") 03216 << std::endl; 03217 } else { // q_k == 0 03218 vout2.out() << "t_O_" << k << ": " 03219 << "inf" 03220 << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "") 03221 << std::endl; 03222 } 03223 } else { // upper bounded 03224 if (q_k * ET(direction) > et0) { // check for lower bound 03225 if (B_O[k] < qp_n) { // original variable 03226 if (*(qp_fl+B_O[k])) { // finite lower bound 03227 vout2.out() << "t_O_" << k << ": " 03228 << x_k - (d * ET(*(qp_l+B_O[k]))) << '/' << q_k 03229 << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "") 03230 << std::endl; 03231 } else { // lower bound -infinity 03232 vout2.out() << "t_O_" << k << ": " 03233 << "-inf" << '/' << q_k 03234 << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "") 03235 << std::endl; 03236 } 03237 } else { // artificial variable 03238 vout2.out() << "t_O_" << k << ": " 03239 << x_k << '/' << q_k 03240 << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "") 03241 << std::endl; 03242 } 03243 } else if (q_k * ET(direction) < et0) { // check for upper bound 03244 if (B_O[k] < qp_n) { // original variable 03245 if (*(qp_fu+B_O[k])) { // finite upper bound 03246 vout2.out() << "t_O_" << k << ": " 03247 << (d * ET(*(qp_l+B_O[k]))) - x_k << '/' << q_k 03248 << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "") 03249 << std::endl; 03250 } else { // upper bound infinity 03251 vout2.out() << "t_O_" << k << ": " 03252 << "inf" << '/' << q_k 03253 << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "") 03254 << std::endl; 03255 } 03256 } else { // artificial variable 03257 vout2.out() << "t_O_" << k << ": " 03258 << "inf" << '/' << q_k 03259 << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "") 03260 << std::endl; 03261 } 03262 } else { // q_k == 0 03263 vout2.out() << "t_O_" << k << ": " 03264 << "inf" 03265 << ( ( q_i != et0) && ( i == B_O[ k]) ? " *" : "") 03266 << std::endl; 03267 } 03268 } 03269 } 03270 03271 template < typename Q, typename ET, typename Tags > 03272 void QP_solver<Q, ET, Tags>:: 03273 print_ratio_1_slack(int k, const ET& x_k, const ET& q_k) 03274 { 03275 if (is_nonnegative) { // => direction == 1 03276 if (q_k > et0) { // check for lower bound 03277 vout2.out() << "t_S_" << k << ": " 03278 << x_k << '/' << q_k 03279 << ( ( q_i != et0) && ( i == B_S[ k]) ? " *" : "") 03280 << std::endl; 03281 } else { // check for upper bound 03282 vout2.out() << "t_S_" << k << ": " 03283 << "inf" << '/' << q_k 03284 << ( ( q_i != et0) && ( i == B_S[ k]) ? " *" : "") 03285 << std::endl; 03286 } 03287 } else { // upper bounded 03288 if (q_k * ET(direction) > et0) { // check for lower bound 03289 vout2.out() << "t_S_" << k << ": " 03290 << x_k << '/' << q_k 03291 << ( ( q_i != et0) && ( i == B_S[ k]) ? " *" : "") 03292 << std::endl; 03293 } else if (q_k * ET(direction) < et0) { // check for upper bound 03294 vout2.out() << "t_S_" << k << ": " 03295 << "inf" << '/' << q_k 03296 << ( ( q_i != et0) && ( i == B_S[ k]) ? " *" : "") 03297 << std::endl; 03298 } else { // q_k == 0 03299 vout2.out() << "t_S_" << k << ": " 03300 << "inf" 03301 << ( ( q_i != et0) && ( i == B_S[ k]) ? " *" : "") 03302 << std::endl; 03303 } 03304 } 03305 } 03306 03307 03308 template < typename Q, typename ET, typename Tags > 03309 const char* QP_solver<Q, ET, Tags>:: 03310 variable_type( int k) const 03311 { 03312 return ( k < qp_n ? "original" : 03313 ( k < (int)( qp_n+slack_A.size()) ? "slack" : 03314 "artificial")); 03315 } 03316 03317 template < typename Q, typename ET, typename Tags > 03318 bool QP_solver<Q, ET, Tags>:: 03319 is_artificial(int k) const 03320 { 03321 return (k >= (int)(qp_n+slack_A.size())); 03322 } 03323 03324 template < typename Q, typename ET, typename Tags > 03325 int QP_solver<Q, ET, Tags>:: 03326 get_l() const 03327 { 03328 return l; 03329 } 03330 03331 CGAL_END_NAMESPACE 03332 03333 // ===== EOF ==================================================================