BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/QP_solver/QP_basis_inverse_impl.h
Go to the documentation of this file.
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_basis_inverse_impl.h $
00015 // $Id: QP_basis_inverse_impl.h 38453 2007-04-27 00:34:44Z gaertner $
00016 // 
00017 //
00018 // Author(s)     : Sven Schoenherr 
00019 //                 Bernd Gaertner <gaertner@inf.ethz.ch>
00020 //                 Franz Wessendorp 
00021 //                 Kaspar Fischer 
00022 
00023 CGAL_BEGIN_NAMESPACE
00024 
00025 // =============================
00026 // class implementation (cont'd)
00027 // =============================
00028 
00029 // creation and initialization
00030 // ---------------------------
00031 // set-up
00032 template < class ET_, class Is_LP_ >
00033 void  QP_basis_inverse<ET_,Is_LP_>::
00034 set( int n, int m, int nr_equalities)
00035 {
00036     CGAL_qpe_assertion( n >= 0);
00037     CGAL_qpe_assertion( m >= 0);
00038     b = s = 0;
00039     // l is the maximum size of the basis in phase I
00040     l = (std::min)( n+nr_equalities+1, m);
00041     if ( ! M.empty()) M.clear();
00042     set( Is_LP());
00043     
00044     if ( ! x_l.empty()) x_l.clear();
00045     if ( ! x_x.empty()) x_x.clear();
00046        
00047     x_l.insert( x_l.end(), l, et0);
00048     x_x.insert( x_x.end(), l, et0); // has to grow later QP-case
00049     
00050     if ( ! tmp_l.empty()) tmp_l.clear();
00051     if ( ! tmp_x.empty()) tmp_x.clear();
00052 
00053     tmp_l.insert( tmp_l.end(), l, et0);
00054     tmp_x.insert( tmp_x.end(), l, et0); // has to grow later QP-case
00055 
00056 }
00057 
00058 // update functions
00059 // ----------------
00060 // leaving of original variable (update type U2)
00061 template < class ET_, class Is_LP_ >
00062 void  QP_basis_inverse<ET_,Is_LP_>::
00063 leave_original( )
00064 {
00065     // assert QP case
00066     Assert_compile_time_tag( Tag_false(), Is_LP());
00067 
00068     // determine new denominator (`z')
00069     --b;
00070     ET    z     = M[ l+b][ l+b];
00071     bool  z_neg = ( z < et0);
00072     CGAL_qpe_assertion( z != et0);
00073 
00074     // update matrix in place
00075     update_inplace_QP( M[ l+b].begin(), M[ l+b].begin()+l,
00076                        -z, ( z_neg ? d : -d));
00077                                                                  
00078     // store new denominator
00079     d = ( z_neg ? -z : z);
00080     CGAL_qpe_assertion( d > et0);
00081 
00082     CGAL_qpe_debug {
00083         if ( vout.verbose()) print();
00084     }
00085 }
00086 
00087 // entering of slack variable (update type U3)
00088 template < class ET_, class Is_LP_ >
00089 void  QP_basis_inverse<ET_,Is_LP_>::
00090 enter_slack( )
00091 {
00092     // assert QP case
00093     Assert_compile_time_tag( Tag_false(), Is_LP());
00094 
00095     // determine new denominator (`z')
00096     --s;
00097     ET    z     = M[ s][ s];
00098     bool  z_neg = ( z < et0);
00099     CGAL_qpe_assertion( z != et0);
00100 
00101     // update matrix in place
00102     typename Matrix::iterator  col_it;
00103     typename Row   ::iterator    x_it;
00104     unsigned int               col;
00105     for (   col = 0,   col_it = M.begin()+l,   x_it = x_x.begin();
00106             col < b;
00107           ++col,     ++col_it,               ++x_it              ) {
00108         *x_it = (*col_it)[ s];
00109     }
00110     update_inplace_QP( M[ s].begin(), x_x.begin(), -z, ( z_neg ? d : -d));
00111 
00112     // store new denominator
00113     d = ( z_neg ? -z : z);
00114     CGAL_qpe_assertion( d > et0);
00115 
00116     CGAL_qpe_debug {
00117         if ( vout.verbose()) print();
00118     }
00119 }
00120 
00121 // replacing of original by slack variable (update type U8)
00122 template < class ET_, class Is_LP_ >
00123 void  QP_basis_inverse<ET_,Is_LP_>::
00124 enter_slack_leave_original( )
00125 {
00126     // assert LP case or phase I
00127     CGAL_qpe_assertion( is_LP || is_phaseI);
00128 
00129     // update matrix in-place
00130     // ----------------------
00131     typename Matrix::iterator  matrix_it;
00132     typename Row   ::iterator       x_it;
00133     unsigned int                     row;
00134 
00135     // QP (in phase I)?
00136     matrix_it = M.begin();
00137     if ( is_QP) matrix_it += l;
00138 
00139     // get last column of basis inverse (store it in 'x_x')
00140     --s; --b;
00141     for (   row = 0,   x_it = x_x.begin();
00142             row < s;
00143           ++row,     ++x_it,               ++matrix_it) {
00144         *x_it = (*matrix_it)[ b];
00145     }
00146     ET    z     = (*matrix_it)[ b];
00147     bool  z_neg = ( z < et0);
00148     CGAL_qpe_assertion( z != et0);
00149 
00150     // update matrix
00151     update_inplace_LP( matrix_it->begin(), x_x.begin(), -z, ( z_neg ? d : -d));
00152 
00153     // store new denominator
00154     // ---------------------
00155     d = ( z_neg ? -z : z);
00156     CGAL_qpe_assertion( d > et0);
00157 
00158     CGAL_qpe_debug {
00159         if ( vout.verbose()) print();
00160     }
00161 }
00162 
00163 
00164 // replacing of original by original variable with precondition in QP-case
00165 // for phaseII                               (update type UZ_1)
00166 template < class ET_, class Is_LP_ >
00167 template < class ForwardIterator >
00168 void  QP_basis_inverse<ET_,Is_LP_>::
00169 z_replace_original_by_original(ForwardIterator y_l_it,
00170                                ForwardIterator y_x_it, const ET& s_delta,
00171                                const ET& s_nu, unsigned int k_i)
00172 {
00173 
00174     // assert QP case and phaseII
00175     CGAL_qpe_assertion(is_QP && is_phaseII);
00176 
00177 
00178     // prepare \hat{k}_{1} -scalar
00179     ET  hat_k_1 = *(y_x_it + k_i);
00180 
00181     // prepare \hat{\rho} -vector in x_l, x_x
00182     copy_row_in_B_O(x_l.begin(), x_x.begin(), k_i);
00183     
00184     // prepare \hat{v} -vector in tmp_l, tmp_x
00185     
00186     // tmp_l -part
00187     std::transform(y_l_it, (y_l_it+s), x_l.begin(), tmp_l.begin(),
00188         compose2_2(std::plus<ET>(), Identity<ET>(),
00189         std::bind1st(std::multiplies<ET>(), s_delta)));
00190     
00191     // tmp_x -part    
00192     std::transform(y_x_it, (y_x_it+b), x_x.begin(), tmp_x.begin(),
00193         compose2_2(std::plus<ET>(), Identity<ET>(),
00194         std::bind1st(std::multiplies<ET>(), s_delta)));
00195     tmp_x[k_i] -= d;
00196     
00197     // prepare \hat{k}_{2} -scalar
00198     ET  hat_k_2 = s_nu - (et2 * s_delta * hat_k_1);
00199     
00200     CGAL_qpe_assertion( d != et0);
00201         
00202     // update matrix in place
00203     z_update_inplace(x_l.begin(), x_x.begin(), tmp_l.begin(), tmp_x.begin(),
00204                       hat_k_1 * hat_k_1, -hat_k_2, -hat_k_1, d*d);
00205     
00206     // store new denominator
00207     d = CGAL::integral_division(hat_k_1 * hat_k_1, d);
00208 
00209     CGAL_qpe_assertion( d > et0);
00210 
00211     CGAL_qpe_debug {
00212         if ( vout.verbose()) print();
00213     }
00214     
00215 }
00216 
00217 
00218 // replacing of original by slack variable with precondition in QP-case
00219 // for phaseII                               (update type UZ_2)
00220 template < class ET_, class Is_LP_ >
00221 void  QP_basis_inverse<ET_,Is_LP_>::
00222 z_replace_original_by_slack( )
00223 {
00224 
00225     // assert QP case and phaseII
00226     CGAL_qpe_assertion(is_QP && is_phaseII);
00227 
00228     // adapt s and b
00229     --s; --b;
00230 
00231     // prepare \hat{\rho} -vector in x_l, x_x
00232     copy_row_in_B_O(x_l.begin(), x_x.begin(), b);
00233     
00234     // prepare \hat{\varrho} -vector in tmp_l, tmp_x
00235     copy_row_in_C(tmp_l.begin(), tmp_x.begin(), s);
00236     
00237     // prepare \hat{\kappa} -scalar
00238     ET  hat_kappa = M[l+b][s];
00239     
00240     // prepare \hat{\xi} -scalar
00241     ET hat_xi = M[s][s];
00242         
00243     CGAL_qpe_assertion( d != et0);
00244     
00245     // update matrix in place
00246     z_update_inplace(x_l.begin(), x_x.begin(), tmp_l.begin(), tmp_x.begin(),
00247                            hat_kappa * hat_kappa, hat_xi, -hat_kappa, d * d);
00248                      
00249     // store new denominator
00250     d = CGAL::integral_division(hat_kappa * hat_kappa, d);
00251 
00252     CGAL_qpe_assertion( d > et0);
00253 
00254     CGAL_qpe_debug {
00255         if ( vout.verbose()) print();
00256     }
00257 
00258 }
00259 
00260 
00261 // replacing of slack by original variable with precondition in QP-case
00262 // for phaseII                               (update type UZ_3)
00263 template < class ET_, class Is_LP_ >
00264 template < class ForwardIterator >
00265 void  QP_basis_inverse<ET_,Is_LP_>::
00266 z_replace_slack_by_original(ForwardIterator y_l_it,
00267                             ForwardIterator y_x_it,
00268                                         ForwardIterator u_x_it, const ET& hat_kappa,
00269                                     const ET& hat_nu)
00270 {
00271     // assert QP case and phaseII
00272     CGAL_qpe_assertion(is_QP && is_phaseII);
00273     
00274     // get copies of y_l_it and y_x_it for later use
00275     ForwardIterator y_l_it_copy = y_l_it;
00276     ForwardIterator y_x_it_copy = y_x_it;
00277 
00278     CGAL_qpe_assertion( d != et0);
00279     
00280     // prepare \hat{\phi}
00281      
00282     // prepare \hat{\varphi} -vector in x_l, x_x
00283     multiply(u_x_it, u_x_it, x_l.begin(), x_x.begin(), Tag_false(),
00284              Tag_false());
00285              
00286     // prepare \hat{\kappa} -scalar
00287     
00288     // prepare \hat{\nu} -scalar
00289    
00290     // update matrix in place
00291     z_update_inplace(x_l.begin(), x_x.begin(), y_l_it, y_x_it,
00292                      hat_kappa * hat_kappa, -hat_nu, hat_kappa, d * d);    
00293     
00294     // append new rows and columns
00295     // ---------------------------
00296     typename Row   ::iterator  row_it, x_l_it, x_x_it;
00297     typename Matrix::iterator  matrix_it;
00298     unsigned int               count;
00299     
00300     // insert new row and column at the end of block P
00301     CGAL_qpe_assertion(M.size()>=s+1);
00302     if (M[s].size()==0) {
00303         // row has to be filled first
00304         M[s].insert(M[s].end(), s+1, et0);
00305     }
00306      
00307     
00308     // P-block: left of diagonal (including element on diagonal)
00309     y_l_it = y_l_it_copy;
00310     for (  row_it = M[s].begin(), x_l_it = x_l.begin();
00311            row_it != M[s].end() - 1;
00312          ++row_it,  ++x_l_it,  ++y_l_it                ) {
00313         *row_it = 
00314           CGAL::integral_division((hat_nu * *x_l_it)-(hat_kappa * *y_l_it), d);  
00315     } 
00316     *row_it = -hat_nu;
00317      
00318     // Q-block
00319     y_x_it = y_x_it_copy;
00320     for (  matrix_it = M.begin()+l, count = 0, x_x_it = x_x.begin();
00321            count < b;
00322          ++matrix_it,  ++count, ++x_x_it, ++y_x_it                  ) {
00323         (*matrix_it)[s] = 
00324           CGAL::integral_division((hat_nu * *x_x_it) - (hat_kappa * *y_x_it), d);
00325     }
00326           
00327     // insert new row and column at the end of blocks Q and R
00328     ensure_physical_row(l+b);
00329     
00330     // Q-block
00331     for (  row_it = M[l+b].begin(), count = 0, x_l_it = x_l.begin();
00332            count < s;
00333          ++row_it,  ++count,  ++x_l_it                              ) {
00334         *row_it = CGAL::integral_division(-hat_kappa * *x_l_it, d);
00335     }
00336     *row_it = hat_kappa;
00337     
00338     // R-block
00339     for (  row_it = M[l+b].begin()+l, count = 0, x_x_it = x_x.begin();
00340            count < b;
00341          ++row_it,  ++count,  ++x_x_it                                ) {
00342         *row_it = CGAL::integral_division(-hat_kappa * *x_x_it, d);
00343     }
00344     *row_it = et0;
00345     
00346     //adapt s and b
00347     ++s; ++b; 
00348 
00349     // store new denominator
00350     d = CGAL::integral_division(hat_kappa * hat_kappa, d);
00351 
00352     CGAL_qpe_assertion( d > et0);
00353 
00354     CGAL_qpe_debug {
00355         if ( vout.verbose()) print();
00356     }
00357                      
00358 }
00359 
00360 
00361 // replacing of slack by slack variable with precondition in QP-case
00362 // for phaseII                               (update type UZ_4)
00363 template < class ET_, class Is_LP_ >
00364 template < class ForwardIterator >
00365 void  QP_basis_inverse<ET_,Is_LP_>::
00366 z_replace_slack_by_slack(ForwardIterator u_x_it, unsigned int k_j)
00367 {
00368 
00369     // assert QP case and phaseII
00370     CGAL_qpe_assertion(is_QP && is_phaseII);
00371 
00372     // prepare \hat{v} -vector in x_l, x_x
00373     multiply(u_x_it, u_x_it, x_l.begin(), x_x.begin(),Tag_false(),
00374              Tag_false());
00375     x_l[k_j] -= d;
00376     
00377     // prepare \hat{\varrho} -vector in tmp_l, tmp_x
00378     copy_row_in_C(tmp_l.begin(), tmp_x.begin(), k_j);
00379     
00380     // prepare \hat{k}_{1} -scalar
00381     ET  hat_k_1 = inner_product_x(tmp_x.begin(), u_x_it);
00382     
00383     // prepare \hat{k}_{3} -scalar
00384     ET  hat_k_3 = -M[k_j][k_j];
00385     
00386     CGAL_qpe_assertion( d != et0);    
00387     
00388     // update matrix in place
00389     z_update_inplace(x_l.begin(), x_x.begin(), tmp_l.begin(), tmp_x.begin(),
00390                      hat_k_1 * hat_k_1, -hat_k_3, -hat_k_1, d * d);
00391                      
00392     // store new denominator
00393     d = CGAL::integral_division(hat_k_1 * hat_k_1, d);
00394 
00395     CGAL_qpe_assertion( d > et0);
00396 
00397     CGAL_qpe_debug {
00398         if ( vout.verbose()) print();
00399     }
00400       
00401 }
00402 
00403 
00404 // copying of reduced basis inverse row in (upper) C-half
00405 template < class ET_, class Is_LP_ >
00406 template < class OutIt >
00407 void  QP_basis_inverse<ET_,Is_LP_>::
00408 copy_row_in_C(OutIt y_l_it, OutIt y_x_it, unsigned int r)
00409 {
00410     typename Matrix::const_iterator  matrix_it;
00411     typename Row   ::const_iterator     row_it;
00412     unsigned int  count;
00413     
00414     // P-block: left of diagonal (including element on diagonal)
00415     matrix_it = M.begin()+r;
00416     for (  row_it = matrix_it->begin();
00417            row_it != matrix_it->end(); 
00418          ++row_it, ++y_l_it            ) {
00419         *y_l_it = *row_it;    
00420     }
00421     
00422     // P-block: right of diagonal (excluding element on diagonal)
00423     for (  matrix_it = M.begin()+r+1, count = r+1;
00424            count < s; 
00425          ++matrix_it,  ++count,  ++y_l_it         ) {
00426         *y_l_it = (*matrix_it)[r];
00427     }
00428     
00429     // Q-block
00430     for (  matrix_it = M.begin()+l, count = 0;
00431            count < b;
00432          ++matrix_it,  ++count,  ++y_x_it     ) {
00433         *y_x_it = (*matrix_it)[r]; 
00434     } 
00435 }
00436 
00437 
00438 // copying of reduced basis inverse row in (lower) B_O-half
00439 template < class ET_, class Is_LP_ >
00440 template < class OutIt >
00441 void  QP_basis_inverse<ET_,Is_LP_>::
00442 copy_row_in_B_O(OutIt y_l_it, OutIt y_x_it, unsigned int r)
00443 {
00444     typename Matrix::const_iterator  matrix_it;
00445     typename Row   ::const_iterator     row_it;
00446     unsigned int  count;
00447     
00448     // Q-block
00449     matrix_it = M.begin()+l+r;
00450     for (  row_it = matrix_it->begin(), count = 0;
00451            count < s;
00452          ++row_it,  ++count,  ++y_l_it           ) {
00453         *y_l_it = *row_it;
00454     }
00455     
00456     // R-block: left of diagonal (including element on diagonal)
00457     for (  row_it = matrix_it->begin()+l; 
00458            row_it != matrix_it->end();
00459          ++row_it,  ++y_x_it            ) {
00460         *y_x_it = *row_it;
00461     }
00462     
00463     // R-block: right of diagonal (excluding element on diagonal)
00464     for (  matrix_it = M.begin()+l+r+1, count = r+1;
00465            count < b;
00466          ++matrix_it,  ++count,  ++y_x_it           ) {
00467         *y_x_it = (*matrix_it)[l+r];
00468     }
00469 
00470 }
00471 
00472 template < class ET_, class Is_LP_ >
00473 template < class ForIt >
00474 void  QP_basis_inverse<ET_,Is_LP_>::
00475 z_update_inplace( ForIt psi1_l_it, ForIt psi1_x_it,
00476                   ForIt psi2_l_it, ForIt psi2_x_it,
00477                      const ET& omega0, const ET& omega1,
00478                          const ET& omega2, const ET& omega3)
00479 {
00480     typename Matrix::      iterator  matrix_it;
00481     typename Row   ::      iterator     row_it;
00482     typename Row   ::const_iterator      y_it1_r, y_it1_c, y_it2_r, y_it2_c;
00483         
00484     unsigned int  row, col, k = l+b;
00485     ET           u_elem;
00486 
00487     // rows: 0..s-1  ( P )
00488     for (  row = 0, matrix_it = M.begin(),
00489            y_it1_r = psi1_l_it,  y_it2_r = psi2_l_it;
00490            row < s;
00491          ++row, ++matrix_it, ++y_it1_r, ++y_it2_r  ) {
00492               
00493         // columns: 0..row  ( P )
00494         for (   row_it =  matrix_it->begin(),
00495                 y_it1_c = psi1_l_it,  y_it2_c = psi2_l_it;
00496                 row_it != matrix_it->end();
00497               ++row_it,  ++y_it1_c,  ++y_it2_c            ) {
00498                 
00499             u_elem = (*y_it1_r * *y_it2_c) + (*y_it2_r * *y_it1_c);
00500             u_elem *= omega2;
00501             u_elem += omega1 * *y_it1_r * *y_it1_c;
00502             update_entry( *row_it, omega0, u_elem, omega3);
00503         } 
00504     }
00505         
00506     // rows: l..k-1  ( Q R )
00507     for (  row = l, matrix_it = M.begin()+l,
00508            y_it1_r = psi1_x_it,  y_it2_r = psi2_x_it;
00509            row != k;
00510          ++row,  ++matrix_it,  ++y_it1_r,  ++y_it2_r ) {
00511             
00512         // columns: 0..s-1  ( Q )
00513         for (   col = 0,   row_it =  matrix_it->begin(),
00514                 y_it1_c = psi1_l_it,  y_it2_c = psi2_l_it;
00515                 col < s;
00516               ++col, ++row_it,  ++y_it1_c,  ++y_it2_c     ){
00517     
00518             u_elem = (*y_it1_r * *y_it2_c) + (*y_it2_r * *y_it1_c);
00519                u_elem *= omega2;
00520                u_elem += omega1 * *y_it1_r * *y_it1_c; 
00521                update_entry( *row_it, omega0, u_elem, omega3);
00522         }
00523     
00524         // columns: l..k-1  ( R )
00525         for (  row_it = matrix_it->begin()+l,
00526                y_it1_c = psi1_x_it,  y_it2_c = psi2_x_it;
00527                row_it != matrix_it->end();
00528              ++row_it,  ++y_it1_c,  ++y_it2_c            ){
00529                  
00530             u_elem = (*y_it1_r * *y_it2_c) + (*y_it2_r * *y_it1_c);
00531             u_elem *= omega2;
00532                 u_elem += omega1 * *y_it1_r * *y_it1_c;     
00533             update_entry( *row_it, omega0, u_elem, omega3);
00534         }
00535             
00536     } 
00537         
00538 } 
00539 
00540 
00541 // swap functions
00542 // --------------
00543 // swap variable ``to the end'' of R
00544 template < class ET_, class Is_LP_ >                            // LP case
00545 void  QP_basis_inverse<ET_,Is_LP_>::
00546 swap_variable( unsigned int j, Tag_true)
00547 {
00548     unsigned int  k = b-1;
00549     if ( j == k) return;
00550 
00551     // swap rows
00552     // ---------
00553     typename Row::iterator   row_j_it = M[ j].begin();
00554     typename Row::iterator   row_k_it = M[ k].begin();
00555     unsigned int  count;
00556 
00557     // swap entries 0..b-1 (row <-> row) [in Q]
00558     for (   count = 0;
00559             count < b;
00560           ++count,     ++row_j_it, ++row_k_it) {
00561         std::iter_swap( row_j_it, row_k_it);
00562     }
00563 }
00564 
00565 template < class ET_, class Is_LP_ >                            // QP case
00566 void  QP_basis_inverse<ET_,Is_LP_>::
00567 swap_variable( unsigned int j, Tag_false)
00568 {
00569     unsigned int  i = l+j, k = l+b-1;
00570     if ( i == k) return;
00571 
00572     // swap rows and columns
00573     // ---------------------
00574     typename    Row::iterator   row_i_it = M[ i].begin();
00575     typename    Row::iterator   row_k_it = M[ k].begin();
00576     typename Matrix::iterator  matrix_it = M.begin()+(i+1);
00577     unsigned int  count;
00578 
00579     // swap entries 0..s-1 (row <-> row) [in Q]
00580     for (   count = 0;
00581             count < s;
00582           ++count,     ++row_i_it, ++row_k_it) {
00583         std::iter_swap( row_i_it, row_k_it);
00584     }
00585 
00586     if ( is_phaseII) {
00587 
00588         // swap entries l..i-1 (row <-> row) [in R]
00589         for (   count = l,   row_i_it += l-s,   row_k_it += l-s;
00590                 count < i;
00591               ++count,     ++row_i_it,        ++row_k_it       ) {
00592             std::iter_swap( row_i_it, row_k_it);
00593         }
00594 
00595         // swap entries i+1..k-1 (column <-> row) [in R]
00596         for ( ++count,                        ++row_k_it;
00597                 count < k;
00598               ++count,     ++matrix_it,       ++row_k_it) {
00599             std::swap( ( *matrix_it)[ i], *row_k_it);
00600         }
00601 
00602         // swap entries i,i with k,k (entry <-> entry) [in R]
00603         std::iter_swap( row_i_it, row_k_it);
00604     }
00605 }
00606 
00607 // swap constraint ``to the end'' of P
00608 template < class ET_, class Is_LP_ >                            // LP case
00609 void  QP_basis_inverse<ET_,Is_LP_>::
00610 swap_constraint( unsigned int i, Tag_true)
00611 {
00612     unsigned int  k = s-1;
00613     if ( i == k) return;
00614 
00615     // swap columns
00616     // ------------
00617     typename Matrix::iterator  matrix_it = M.begin();
00618     unsigned int  count;
00619 
00620     // swap entries 0..s-1 (column <-> column) [in Q]
00621     for (   count = 0;
00622             count < s;
00623           ++count,     ++matrix_it) {
00624         std::swap( ( *matrix_it)[ i], ( *matrix_it)[ k]);
00625     }
00626 }
00627 
00628 template < class ET_, class Is_LP_ >                            // QP case
00629 void  QP_basis_inverse<ET_,Is_LP_>::
00630 swap_constraint( unsigned int i, Tag_false)
00631 {
00632  
00633     if ( i == s-1) return;
00634 
00635     // swap rows and columns
00636     // ---------------------
00637     typename    Row::iterator   row_i_it = M[ i].begin();
00638     typename    Row::iterator   row_k_it = M[ s-1].begin();
00639     typename Matrix::iterator  matrix_it = M.begin()+i;
00640     unsigned int  count;
00641 
00642     if ( is_phaseI) {
00643 
00644         // skip empty P
00645         matrix_it =M.begin() + l;
00646 
00647     } else {
00648 
00649         // swap entries 0..i-1 (row <-> row) [in P]
00650         for (   count =  0;
00651                 count < i;
00652               ++count,      ++row_i_it, ++row_k_it) {
00653             std::iter_swap( row_i_it, row_k_it);
00654         }
00655 
00656         // swap entries i+1..s-2 (column <-> row) [in P]
00657         for ( count = i + 1, ++matrix_it, ++row_k_it;
00658                 count < s-1;
00659               ++count,     ++matrix_it, ++row_k_it) {
00660             std::swap( ( *matrix_it)[ i], *row_k_it);
00661         }
00662         // the remaining two entries to be swapped on the main diagonal
00663         std::swap(M[i][i], M[s-1][s-1]);
00664 
00665         // advance to Q
00666         matrix_it = M.begin() + l;
00667     }
00668 
00669     // swap entries l..l+b (column <-> column) [in Q]
00670     for (   count = 0;
00671             count < b;
00672           ++count,     ++matrix_it) {
00673         std::swap( ( *matrix_it)[ i], ( *matrix_it)[ s-1]);
00674     }
00675 }
00676 
00677 // diagnostic output
00678 // -----------------
00679 template < class ET_, class Is_LP_ >
00680 void  QP_basis_inverse<ET_,Is_LP_>::
00681 print( )
00682 {
00683     // P
00684     if ( is_LP || is_phaseII) {
00685         for ( unsigned int row = 0; row < s; ++row) {
00686             std::copy( M[ row].begin(),
00687                        M[ row].begin() + ( is_LP ? s : row+1),
00688                        std::ostream_iterator<ET>( vout.out(), " "));
00689             vout.out() << std::endl;
00690         }
00691         if ( is_QP) vout.out() << "= = = = = = = = = =" << std::endl;
00692     }
00693 
00694     // Q & R
00695     if ( is_QP) {
00696         for ( unsigned int row = l; row < l+b; ++row) {
00697             std::copy( M[ row].begin(), M[ row].begin()+s,
00698                        std::ostream_iterator<ET>( vout.out(), " "));
00699             if ( is_phaseII) {
00700                 vout.out() << "|| ";
00701                 std::copy( M[ row].begin()+l, M[ row].end(),
00702                            std::ostream_iterator<ET>( vout.out(), " "));
00703             }
00704             vout.out() << std::endl;
00705         }
00706     }
00707     vout.out() << "denominator = " << d << std::endl;
00708 }
00709 
00710 CGAL_END_NAMESPACE
00711 
00712 // ===== EOF ==================================================================
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines