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__partial_base.h $ 00015 // $Id: QP__partial_base.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 #ifndef CGAL_QP__PARTIAL_BASE_H 00024 #define CGAL_QP__PARTIAL_BASE_H 00025 00026 // includes 00027 #include <CGAL/QP_solver/QP_pricing_strategy.h> 00028 #include <CGAL/Random.h> 00029 #include <algorithm> 00030 #include <vector> 00031 #include <cmath> 00032 00033 CGAL_BEGIN_NAMESPACE 00034 00035 // ================== 00036 // class declarations 00037 // ================== 00038 template < typename Q, typename ET, typename Tags > 00039 class QP__partial_base; 00040 00041 template < class Solver > 00042 struct transition_sync_functor { 00043 00044 // Note that we rely here on working_vars being the number of 00045 // variables without artificials and the solvers in_B variable 00046 // being up to date. Furthermore the operator() below relies on short 00047 // circuit evaluation 00048 00049 transition_sync_functor( const Solver& s, int w) : amb_solver(s), 00050 working_vars(w) { } 00051 00052 bool operator() (int i) { 00053 return (i < working_vars) && !amb_solver.is_basic(i); 00054 } 00055 00056 private: 00057 const Solver& amb_solver; 00058 int working_vars; 00059 }; 00060 00061 00062 // =============== 00063 // class interface 00064 // =============== 00065 template < typename Q, typename ET, typename Tags > 00066 class QP__partial_base : virtual public QP_pricing_strategy<Q,ET,Tags> { 00067 00068 // self 00069 typedef QP__partial_base<Q,ET,Tags> Self; 00070 typedef QP_pricing_strategy<Q,ET,Tags> Base; 00071 00072 typedef typename Base::QP_solver QP_solver; 00073 protected: 00074 00075 // types 00076 typedef typename QP_solver::Indices Indices; 00077 typedef typename QP_solver::Index_iterator Index_iterator; 00078 typedef typename QP_solver::Index_const_iterator Index_const_iterator; 00079 00080 // construction 00081 QP__partial_base( bool randomize, Random& random); 00082 00083 // initialization 00084 virtual void init( ); 00085 00086 // access 00087 Index_const_iterator active_set_begin( ) const { return N.begin(); } 00088 Index_const_iterator active_set_end ( ) const { return N.begin()+s; } 00089 00090 Index_const_iterator inactive_set_begin( ) const { return N.begin()+s; } 00091 Index_const_iterator inactive_set_end ( ) const { return N.end (); } 00092 00093 // operations 00094 void entering_basis( Index_const_iterator it); 00095 void activating ( Index_const_iterator& it); 00096 00097 virtual void leaving_basis( int i); 00098 virtual void transition( ); 00099 00100 private: 00101 00102 // data members 00103 Indices N; // non-basis; 00104 int s; // size of active set 00105 00106 bool permute; // flag: permute initial non-basis 00107 Random& rand_src; // random source 00108 00109 //basic_functor<QP_solver> is_non_basic; 00110 }; 00111 00112 // ---------------------------------------------------------------------------- 00113 00114 // =============================== 00115 // class implementation (template) 00116 // =============================== 00117 00118 // construction 00119 template < typename Q, typename ET, typename Tags > inline 00120 QP__partial_base<Q,ET,Tags>:: 00121 QP__partial_base( bool randomize, Random& random) 00122 : permute( randomize), rand_src( random) 00123 { } 00124 00125 // initialization 00126 template < typename Q, typename ET, typename Tags > 00127 void 00128 QP__partial_base<Q,ET,Tags>:: 00129 init( ) 00130 { 00131 // initialize indices of non-basic variables 00132 int w = this->solver().number_of_working_variables(); 00133 int b = this->solver().number_of_basic_variables(); 00134 00135 if ( ! N.empty()) N.clear(); 00136 N.reserve( w-b); // use 'w' ??? 00137 for ( int i = 0; i < w; ++i) { 00138 if ( ! this->solver().is_basic( i)) N.push_back( i); 00139 } 00140 if ( permute) std::random_shuffle( N.begin(), N.end(), rand_src); 00141 00142 // initialize size of active set 00143 int n = this->solver().number_of_variables(); 00144 int m = this->solver().number_of_constraints(); 00145 // we also want to cover the high constraints/variable ratio 00146 if (n < m) (std::swap)(n,m); 00147 00148 s = (std::min)( static_cast< unsigned int>( m*std::sqrt( n/2.0)), 00149 static_cast< unsigned int>(N.size())); 00150 00151 //is_non_basic.init(this->solver()); 00152 } 00153 00154 // operations 00155 template < typename Q, typename ET, typename Tags > inline 00156 void 00157 QP__partial_base<Q,ET,Tags>:: 00158 entering_basis( Index_const_iterator it) 00159 { 00160 CGAL_qpe_precondition( it >= active_set_begin() && it < active_set_end()); 00161 00162 // remove from active set 00163 --s; 00164 const_cast< typename Indices::value_type&>( *it) = N[ s]; 00165 N[ s] = N.back(); 00166 N.pop_back(); 00167 } 00168 00169 template < typename Q, typename ET, typename Tags > inline 00170 void 00171 QP__partial_base<Q,ET,Tags>:: 00172 activating( Index_const_iterator& it) 00173 { 00174 CGAL_qpe_precondition( 00175 it >= inactive_set_begin() && it < inactive_set_end()); 00176 00177 // 'append' to active set 00178 std::swap( const_cast< typename Indices::value_type&>( *it), N[ s]); 00179 it = N.begin()+s; 00180 ++s; 00181 } 00182 00183 template < typename Q, typename ET, typename Tags > 00184 void 00185 QP__partial_base<Q,ET,Tags>:: 00186 leaving_basis( int i) 00187 { 00188 // all non-basic variables active? 00189 if ( s == static_cast< int>( N.size())) { 00190 00191 // append at the end of all non-basic variables 00192 N.push_back( i); 00193 00194 } else { 00195 00196 // insert at the end of the current active subset 00197 N.push_back( N[ s]); 00198 N[ s] = i; 00199 } 00200 ++s; 00201 } 00202 00203 00204 template < typename Q, typename ET, typename Tags > 00205 void 00206 QP__partial_base<Q,ET,Tags>:: 00207 transition( ) 00208 { 00209 // Remove from N nonbasic slack and original variables that have become 00210 // basic during the expelling of artificial variables out of the basis 00211 // (between phaseI and phaseII), since these formerly nonbasic variables 00212 // have not entered the basis through pricing the set N has not accordingly 00213 // been updated. 00214 // Remove from N the artificial variables as well. 00215 // Note that we rely on the number of working variables including only 00216 // original and slack variables, the solvers in_B variable must be 00217 // up to date. 00218 // Furthermore we rely on std::partition not destroying the randomness 00219 // of the order of the nonbasic variables in N. 00220 00221 int w = this->solver().number_of_working_variables(); 00222 transition_sync_functor<QP_solver> is_non_basic(this->solver(), w); 00223 N.erase( std::partition( N.begin(), N.end(), 00224 is_non_basic), N.end()); 00225 00226 // initialize size of active set 00227 int n = this->solver().number_of_variables(); 00228 int m = this->solver().number_of_constraints(); 00229 00230 s = (std::min)( static_cast< unsigned int>( m*std::sqrt( n/2.0)), 00231 static_cast< unsigned int>(N.size())); 00232 } 00233 00234 CGAL_END_NAMESPACE 00235 00236 #endif // CGAL_QP__PARTIAL_BASE_H 00237 00238 // ===== EOF ==================================================================