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_models.h $ 00015 // $Id: QP_models.h 46451 2008-10-23 14:31:10Z gaertner $ 00016 // 00017 // 00018 // Author(s) : Bernd Gaertner <gaertner@inf.ethz.ch>, Kaspar Fischer 00019 00020 #ifndef CGAL_QP_MODELS_H 00021 #define CGAL_QP_MODELS_H 00022 00023 #include <CGAL/basic.h> 00024 #include <CGAL/iterator.h> 00025 #include <CGAL/algorithm.h> 00026 #include <CGAL/QP_solver/basic.h> 00027 #include <CGAL/QP_solver/functors.h> 00028 #include <vector> 00029 #include <map> 00030 #include <iomanip> 00031 #include <istream> 00032 #include <sstream> 00033 #include <boost/iterator/counting_iterator.hpp> 00034 #include <boost/iterator/transform_iterator.hpp> 00035 00036 // this file defines the following models: 00037 // - Quadratic_program_from_iterators 00038 // - Quadratic_program 00039 // - Quadratic_program_from_mps 00040 // - Nonngative_quadratic_program_from_iterators 00041 // - Linear_program_from_iterators 00042 // - Nonngative_linear_program_from_iterators 00043 00044 // for convenience, every model is actually a model of the 00045 // concept QuadraticProgramInterface: 00046 #define QP_MODEL_ITERATOR_TYPES \ 00047 typedef typename Base::A_iterator A_iterator;\ 00048 typedef typename Base::B_iterator B_iterator;\ 00049 typedef typename Base::R_iterator R_iterator;\ 00050 typedef typename Base::FL_iterator FL_iterator;\ 00051 typedef typename Base::L_iterator L_iterator;\ 00052 typedef typename Base::FU_iterator FU_iterator;\ 00053 typedef typename Base::U_iterator U_iterator;\ 00054 typedef typename Base::D_iterator D_iterator;\ 00055 typedef typename Base::C_iterator C_iterator;\ 00056 typedef typename Base::C_entry C_entry 00057 CGAL_BEGIN_NAMESPACE 00058 00059 // default iterator types to used to make linear / nonnegative models 00060 // conform to QuadraticProgramInterface 00061 template <class Iterator> 00062 class QP_model_default_iterators { 00063 private: 00064 typedef typename std::iterator_traits<Iterator>::value_type value_type; 00065 public: 00066 typedef Const_oneset_iterator<value_type> 00067 It_1d; // 1-dimensional random access iterator for a constant value 00068 typedef Const_oneset_iterator<Const_oneset_iterator<value_type> > 00069 It_2d; // 2-dimensional random access iterator for a constant value 00070 }; 00071 00072 // Quadratic_program_from_iterators 00073 // -------------------------------- 00074 // this is the base class for all non-mps models 00075 template < 00076 typename A_it, // for constraint matrix A (columnwise) 00077 typename B_it, // for right-hand side b 00078 typename R_it, // for relations (value type Comparison) 00079 typename FL_it, // for finiteness of lower bounds (value type bool) 00080 typename L_it, // for lower bounds 00081 typename FU_it, // for finiteness of upper bounds (value type bool) 00082 typename U_it, // for upper bounds 00083 typename D_it, // for quadratic matrix D (rowwise) 00084 typename C_it > // for objective function c 00085 class Quadratic_program_from_iterators 00086 { 00087 public: 00088 // types 00089 typedef A_it A_iterator; 00090 typedef B_it B_iterator; 00091 typedef R_it R_iterator; 00092 typedef FL_it FL_iterator; 00093 typedef L_it L_iterator; 00094 typedef FU_it FU_iterator; 00095 typedef U_it U_iterator; 00096 typedef D_it D_iterator; 00097 typedef C_it C_iterator; 00098 typedef typename std::iterator_traits<C_it>::value_type C_entry; 00099 protected: 00100 // data 00101 int n_; 00102 int m_; 00103 A_iterator a_it; 00104 B_iterator b_it; 00105 R_iterator r_it; 00106 FL_iterator fl_it; 00107 L_iterator l_it; 00108 FU_iterator fu_it; 00109 U_iterator u_it; 00110 D_iterator d_it; 00111 C_iterator c_it; 00112 C_entry c_0; // constant term 00113 public: 00114 // construction 00115 Quadratic_program_from_iterators ( 00116 int n, int m, // number of variables / constraints 00117 const A_iterator& a, 00118 const B_iterator& b, 00119 const R_iterator& r, 00120 const FL_iterator& fl, 00121 const L_iterator& l, 00122 const FU_iterator& fu, 00123 const U_iterator& u, 00124 const D_iterator& d, 00125 const C_iterator& c, 00126 const C_entry& c0 = C_entry(0)) 00127 : n_ (n), m_ (m), a_it (a), b_it (b), r_it (r), fl_it (fl), l_it (l), 00128 fu_it (fu), u_it (u), d_it (d), c_it (c), c_0 (c0) 00129 {} 00130 00131 // access 00132 int get_n() const {return n_;} 00133 int get_m() const {return m_;} 00134 A_iterator get_a() const {return a_it;} 00135 B_iterator get_b() const {return b_it;} 00136 R_iterator get_r() const {return r_it;} 00137 FL_iterator get_fl() const {return fl_it;} 00138 L_iterator get_l() const {return l_it;} 00139 FU_iterator get_fu() const {return fu_it;} 00140 U_iterator get_u() const {return u_it;} 00141 D_iterator get_d() const {return d_it;} 00142 C_iterator get_c() const {return c_it;} 00143 C_entry get_c0() const {return c_0;} 00144 }; 00145 00146 // corresponding global function make_quadratic_program_from_iterators 00147 // ------------------------------------------------------------------- 00148 template < 00149 typename A_it, // for constraint matrix A (columnwise) 00150 typename B_it, // for right-hand side b 00151 typename R_it, // for relations (value type Comparison) 00152 typename FL_it, // for finiteness of lower bounds (value type bool) 00153 typename L_it, // for lower bounds 00154 typename FU_it, // for finiteness of upper bounds (value type bool) 00155 typename U_it, // for upper bounds 00156 typename D_it, // for quadratic matrix D (rowwise) 00157 typename C_it > // for objective function c 00158 Quadratic_program_from_iterators<A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, D_it, C_it> 00159 make_quadratic_program_from_iterators ( 00160 int n, int m, 00161 const A_it& a, 00162 const B_it& b, 00163 const R_it& r, 00164 const FL_it& fl, 00165 const L_it& l, 00166 const FU_it& fu, 00167 const U_it& u, 00168 const D_it& d, 00169 const C_it& c, 00170 typename std::iterator_traits<C_it>::value_type c0 = 00171 typename std::iterator_traits<C_it>::value_type(0)) 00172 { 00173 return Quadratic_program_from_iterators 00174 <A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, D_it, C_it> 00175 (n, m, a, b, r, fl, l, fu, u, d, c, c0); 00176 } 00177 00178 00179 // Linear_program_from_iterators 00180 // ----------------------------- 00181 template < 00182 typename A_it, // for constraint matrix A (columnwise) 00183 typename B_it, // for right-hand side b 00184 typename R_it, // for relations (value type Comparison) 00185 typename FL_it, // for finiteness of lower bounds (value type bool) 00186 typename L_it, // for lower bounds 00187 typename FU_it, // for finiteness of upper bounds (value type bool) 00188 typename U_it, // for upper bounds 00189 typename C_it > // for objective function c 00190 class Linear_program_from_iterators : 00191 public Quadratic_program_from_iterators 00192 <A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, 00193 typename QP_model_default_iterators<C_it>::It_2d, C_it> 00194 { 00195 private: 00196 typedef Quadratic_program_from_iterators 00197 <A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, 00198 typename QP_model_default_iterators<C_it>::It_2d, C_it> Base; 00199 typedef typename QP_model_default_iterators<C_it>::It_2d Const_D_iterator; 00200 public: 00201 QP_MODEL_ITERATOR_TYPES; 00202 Linear_program_from_iterators ( 00203 int n, int m, // number of variables / constraints 00204 const A_iterator& a, 00205 const B_iterator& b, 00206 const R_iterator& r, 00207 const FL_iterator& fl, 00208 const L_iterator& l, 00209 const FU_iterator& fu, 00210 const U_iterator& u, 00211 const C_iterator& c, 00212 const C_entry& c0 = C_entry(0) 00213 ) 00214 : Base (n, m, a, b, r, fl, l, fu, u, 00215 Const_D_iterator(C_entry(0)), c, c0) 00216 {} 00217 }; 00218 00219 // corresponding global function make_linear_program_from_iterators 00220 // ---------------------------------------------------------------- 00221 template < 00222 typename A_it, // for constraint matrix A (columnwise) 00223 typename B_it, // for right-hand side b 00224 typename R_it, // for relations (value type Comparison) 00225 typename FL_it, // for finiteness of lower bounds (value type bool) 00226 typename L_it, // for lower bounds 00227 typename FU_it, // for finiteness of upper bounds (value type bool) 00228 typename U_it, // for upper bounds 00229 typename C_it > // for objective function c 00230 Linear_program_from_iterators<A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, C_it> 00231 make_linear_program_from_iterators ( 00232 int n, int m, 00233 const A_it& a, 00234 const B_it& b, 00235 const R_it& r, 00236 const FL_it& fl, 00237 const L_it& l, 00238 const FU_it& fu, 00239 const U_it& u, 00240 const C_it& c, 00241 typename std::iterator_traits<C_it>::value_type c0 = 00242 typename std::iterator_traits<C_it>::value_type(0)) 00243 { 00244 return Linear_program_from_iterators 00245 <A_it, B_it, R_it, FL_it, L_it, FU_it, U_it, C_it> 00246 (n, m, a, b, r, fl, l, fu, u, c, c0); 00247 } 00248 00249 00250 // Nonnegative_quadratic_program_from_iterators 00251 // -------------------------------------------- 00252 template < 00253 typename A_it, // for constraint matrix A (columnwise) 00254 typename B_it, // for right-hand side b 00255 typename R_it, // for relations (value type Comparison) 00256 typename D_it, // for quadratic matrix D (rowwise) 00257 typename C_it > // for objective function c 00258 class Nonnegative_quadratic_program_from_iterators : 00259 public Quadratic_program_from_iterators <A_it, B_it, R_it, 00260 typename QP_model_default_iterators<bool*>::It_1d, 00261 typename QP_model_default_iterators<C_it>::It_1d, 00262 typename QP_model_default_iterators<bool*>::It_1d, 00263 typename QP_model_default_iterators<C_it>::It_1d, 00264 D_it, C_it> 00265 { 00266 private: 00267 typedef Quadratic_program_from_iterators <A_it, B_it, R_it, 00268 typename QP_model_default_iterators<bool*>::It_1d, 00269 typename QP_model_default_iterators<C_it>::It_1d, 00270 typename QP_model_default_iterators<bool*>::It_1d, 00271 typename QP_model_default_iterators<C_it>::It_1d, 00272 D_it, C_it> Base; 00273 typedef typename QP_model_default_iterators<bool*>::It_1d Const_FLU_iterator; 00274 typedef typename QP_model_default_iterators<C_it>::It_1d Const_LU_iterator; 00275 public: 00276 QP_MODEL_ITERATOR_TYPES; 00277 Nonnegative_quadratic_program_from_iterators ( 00278 int n, int m, // number of variables / constraints 00279 const A_iterator& a, 00280 const B_iterator& b, 00281 const R_iterator& r, 00282 const D_iterator& d, 00283 const C_iterator& c, 00284 const C_entry& c0 = C_entry(0) 00285 ) 00286 : Base (n, m, a, b, r, 00287 Const_FLU_iterator(true), Const_LU_iterator(C_entry(0)), 00288 Const_FLU_iterator(false), Const_LU_iterator(C_entry(0)), 00289 d, c, c0) 00290 {} 00291 }; 00292 00293 // corresponding global function 00294 // make_nonnegative_quadratic_program_from_iterators 00295 // ------------------------------------------------- 00296 template < 00297 typename A_it, // for constraint matrix A (columnwise) 00298 typename B_it, // for right-hand side b 00299 typename R_it, // for relations (value type Comparison) 00300 typename D_it, // for quadratic matrix D (rowwise) 00301 typename C_it > // for objective function c 00302 Nonnegative_quadratic_program_from_iterators 00303 <A_it, B_it, R_it, D_it, C_it> 00304 make_nonnegative_quadratic_program_from_iterators ( 00305 int n, int m, 00306 const A_it& a, 00307 const B_it& b, 00308 const R_it& r, 00309 const D_it& d, 00310 const C_it& c, 00311 typename std::iterator_traits<C_it>::value_type c0 = 00312 typename std::iterator_traits<C_it>::value_type(0)) 00313 { 00314 return Nonnegative_quadratic_program_from_iterators 00315 <A_it, B_it, R_it, D_it, C_it> 00316 (n, m, a, b, r, d, c, c0); 00317 } 00318 00319 00320 // Nonnegative_linear_program_from_iterators 00321 // ----------------------------------------- 00322 template < 00323 typename A_it, // for constraint matrix A (columnwise) 00324 typename B_it, // for right-hand side b 00325 typename R_it, // for relations (value type Comparison) 00326 typename C_it > // for objective function c 00327 class Nonnegative_linear_program_from_iterators : 00328 public Quadratic_program_from_iterators <A_it, B_it, R_it, 00329 typename QP_model_default_iterators<bool*>::It_1d, 00330 typename QP_model_default_iterators<C_it>::It_1d, 00331 typename QP_model_default_iterators<bool*>::It_1d, 00332 typename QP_model_default_iterators<C_it>::It_1d, 00333 typename QP_model_default_iterators<C_it>::It_2d, C_it> 00334 { 00335 private: 00336 typedef Quadratic_program_from_iterators <A_it, B_it, R_it, 00337 typename QP_model_default_iterators<bool*>::It_1d, 00338 typename QP_model_default_iterators<C_it>::It_1d, 00339 typename QP_model_default_iterators<bool*>::It_1d, 00340 typename QP_model_default_iterators<C_it>::It_1d, 00341 typename QP_model_default_iterators<C_it>::It_2d, C_it> Base; 00342 typedef typename QP_model_default_iterators<bool*>::It_1d Const_FLU_iterator; 00343 typedef typename QP_model_default_iterators<C_it>::It_1d Const_LU_iterator; 00344 typedef typename QP_model_default_iterators<C_it>::It_2d Const_D_iterator; 00345 public: 00346 QP_MODEL_ITERATOR_TYPES; 00347 Nonnegative_linear_program_from_iterators ( 00348 int n, int m, // number of variables / constraints 00349 const A_iterator& a, 00350 const B_iterator& b, 00351 const R_iterator& r, 00352 const C_iterator& c, 00353 const C_entry& c0 = C_entry(0) 00354 ) 00355 : Base (n, m, a, b, r, 00356 Const_FLU_iterator(true), Const_LU_iterator(C_entry(0)), 00357 Const_FLU_iterator(false), Const_LU_iterator(C_entry(0)), 00358 Const_D_iterator(C_entry(0)), c, c0) 00359 {} 00360 }; 00361 00362 // corresponding global function 00363 // make_nonnegative_linear_program_from_iterators 00364 // ---------------------------------------------- 00365 template < 00366 typename A_it, // for constraint matrix A (columnwise) 00367 typename B_it, // for right-hand side b 00368 typename R_it, // for relations (value type Comparison) 00369 typename C_it > // for objective function c 00370 Nonnegative_linear_program_from_iterators 00371 <A_it, B_it, R_it, C_it> 00372 make_nonnegative_linear_program_from_iterators ( 00373 int n, int m, 00374 const A_it& a, 00375 const B_it& b, 00376 const R_it& r, 00377 const C_it& c, 00378 typename std::iterator_traits<C_it>::value_type c0 = 00379 typename std::iterator_traits<C_it>::value_type(0)) 00380 { 00381 return Nonnegative_linear_program_from_iterators 00382 <A_it, B_it, R_it, C_it> 00383 (n, m, a, b, r, c, c0); 00384 } 00385 00386 00387 namespace QP_model_detail { 00388 // maps a container to its begin-iterator, as specified by HowToBegin 00389 template<typename Container, typename Iterator, typename HowToBegin> 00390 struct Begin 00391 : public std::unary_function< Container, Iterator > 00392 { 00393 typedef Iterator result_type; 00394 result_type operator () ( const Container& v) const 00395 { 00396 return HowToBegin()(v); 00397 } 00398 }; 00399 } 00400 00401 // Quadratic_program 00402 // ----------------- 00403 // sparse representation, entries can be set one by one, overriding 00404 // defaults; 00405 template <typename NT_> 00406 class Quadratic_program 00407 { 00408 public: 00409 typedef NT_ NT; 00410 private: 00411 // Sparse_vectors 00412 typedef std::map<int, NT> 00413 Sparse_vector; 00414 typedef std::map<int, CGAL::Comparison_result> 00415 Sparse_r_vector; 00416 typedef std::map<int, bool> 00417 Sparse_f_vector; 00418 00419 // Sparse_matrix 00420 typedef std::vector<Sparse_vector> 00421 Sparse_matrix; 00422 00423 // Sparse_vector_iterators 00424 //typedef CGAL::Fake_random_access_const_iterator<Sparse_vector> 00425 typedef boost::transform_iterator<CGAL::Map_with_default<Sparse_vector>, 00426 boost::counting_iterator<int> > 00427 Sparse_vector_iterator; 00428 typedef boost::transform_iterator<CGAL::Map_with_default<Sparse_r_vector>, 00429 boost::counting_iterator<int> > 00430 Sparse_r_vector_iterator; 00431 typedef boost::transform_iterator<CGAL::Map_with_default<Sparse_f_vector>, 00432 boost::counting_iterator<int> > 00433 Sparse_f_vector_iterator; 00434 00435 // Sparse_matrix_iterator 00436 struct HowToBegin 00437 { 00438 Sparse_vector_iterator operator() (const Sparse_vector& v) const 00439 { return Sparse_vector_iterator 00440 (boost::counting_iterator<int>(0), 00441 CGAL::Map_with_default<Sparse_vector>(&v, NT(0)));} 00442 }; 00443 00444 typedef QP_model_detail::Begin 00445 <Sparse_vector, Sparse_vector_iterator, HowToBegin> Beginner; 00446 typedef boost::transform_iterator 00447 <Beginner, typename Sparse_matrix::const_iterator> 00448 Sparse_matrix_iterator; 00449 00450 // program data; we maintain the invariant that only the 00451 // non-default elements are stored; this means that entries 00452 // may get removed again, and n_, m_ might be larger than 00453 // absolutely needed; we also maintain the invariants that 00454 // a_matrix and d_matrix always have n_ elements 00455 00456 int n_; 00457 int m_; 00458 Sparse_matrix a_matrix; 00459 Sparse_vector b_vector; 00460 Sparse_r_vector r_vector; 00461 Sparse_f_vector fl_vector; 00462 Sparse_vector l_vector; 00463 Sparse_f_vector fu_vector; 00464 Sparse_vector u_vector; 00465 Sparse_vector c_vector; 00466 Sparse_matrix d_matrix; 00467 NT c0_; 00468 00469 // default settings 00470 CGAL::Comparison_result default_r; // from constructor 00471 bool default_fl; // from constructor 00472 NT default_l; // from constructor 00473 bool default_fu; // from constructor 00474 NT default_u; // from constructor 00475 protected: 00476 bool is_valid_; 00477 private: 00478 std::string error_msg; 00479 00480 // methods 00481 // enlarges a_matrix, d_matrix to size s, under the 00482 // precondition that the previous sizes were smaller 00483 void grow_a_d (int s) 00484 { 00485 CGAL_qpe_assertion( a_matrix.size() == d_matrix.size() ); 00486 CGAL_qpe_assertion( a_matrix.size() < (unsigned int)s); 00487 for (int k = a_matrix.size(); k < s; ++k) { 00488 a_matrix.push_back(Sparse_vector()); 00489 d_matrix.push_back(Sparse_vector()); 00490 } 00491 } 00492 00493 public: 00494 // interface types 00495 typedef Sparse_matrix_iterator A_iterator; 00496 typedef Sparse_vector_iterator B_iterator; 00497 typedef Sparse_r_vector_iterator R_iterator; 00498 typedef Sparse_f_vector_iterator FL_iterator; 00499 typedef Sparse_vector_iterator L_iterator; 00500 typedef Sparse_f_vector_iterator FU_iterator; 00501 typedef Sparse_vector_iterator U_iterator; 00502 typedef Sparse_vector_iterator C_iterator; 00503 typedef Sparse_matrix_iterator D_iterator; 00504 typedef NT C_entry; 00505 00506 // concept methods 00507 int get_n() const 00508 { 00509 CGAL_qpe_assertion(is_valid()); 00510 return n_; 00511 } 00512 int get_m() const 00513 { 00514 CGAL_qpe_assertion(is_valid()); 00515 return m_; 00516 } 00517 A_iterator get_a() const 00518 { 00519 CGAL_qpe_assertion(is_valid()); 00520 return A_iterator (a_matrix.begin(), Beginner()); 00521 } 00522 B_iterator get_b() const 00523 { 00524 CGAL_qpe_assertion(is_valid()); 00525 return B_iterator (boost::counting_iterator<int>(0), 00526 CGAL::Map_with_default<Sparse_vector> 00527 (&b_vector, NT(0))); 00528 } 00529 R_iterator get_r() const 00530 { 00531 CGAL_qpe_assertion(is_valid()); 00532 return R_iterator (boost::counting_iterator<int>(0), 00533 CGAL::Map_with_default<Sparse_r_vector> 00534 (&r_vector, default_r)); 00535 } 00536 FL_iterator get_fl() const 00537 { 00538 CGAL_qpe_assertion(is_valid()); 00539 return FL_iterator (boost::counting_iterator<int>(0), 00540 CGAL::Map_with_default<Sparse_f_vector> 00541 (&fl_vector, default_fl)); 00542 } 00543 L_iterator get_l() const 00544 { 00545 CGAL_qpe_assertion(is_valid()); 00546 return L_iterator (boost::counting_iterator<int>(0), 00547 CGAL::Map_with_default<Sparse_vector> 00548 (&l_vector, default_l)); 00549 } 00550 FU_iterator get_fu() const 00551 { 00552 CGAL_qpe_assertion(is_valid()); 00553 return FU_iterator (boost::counting_iterator<int>(0), 00554 CGAL::Map_with_default<Sparse_f_vector> 00555 (&fu_vector, default_fu)); 00556 } 00557 U_iterator get_u() const 00558 { 00559 CGAL_qpe_assertion(is_valid()); 00560 return U_iterator (boost::counting_iterator<int>(0), 00561 CGAL::Map_with_default<Sparse_vector> 00562 (&u_vector, default_u)); 00563 } 00564 C_iterator get_c() const 00565 { 00566 CGAL_qpe_assertion(is_valid()); 00567 return C_iterator (boost::counting_iterator<int>(0), 00568 CGAL::Map_with_default<Sparse_vector> 00569 (&c_vector, NT(0))); 00570 } 00571 D_iterator get_d() const 00572 { 00573 CGAL_qpe_assertion(is_valid()); 00574 return D_iterator (d_matrix.begin(), Beginner()); 00575 } 00576 C_entry get_c0() const 00577 { 00578 CGAL_qpe_assertion(is_valid()); 00579 return c0_; 00580 } 00581 00582 bool is_valid() const 00583 { 00584 return is_valid_; 00585 } 00586 00587 const std::string& get_error() const 00588 { 00589 CGAL_qpe_assertion(!is_valid()); 00590 return error_msg; 00591 } 00592 00593 // default constructor 00594 Quadratic_program 00595 (CGAL::Comparison_result relation = CGAL::EQUAL, 00596 bool finite_lower = true, 00597 NT lower = 0, 00598 bool finite_upper = false, 00599 NT upper = 0) 00600 : n_(0), m_(0), c0_(0), 00601 default_r(relation), default_fl(finite_lower), 00602 default_l(lower), default_fu(finite_upper), 00603 default_u(upper), is_valid_(true) 00604 { 00605 CGAL_qpe_assertion(!finite_lower || !finite_upper || lower <= upper); 00606 } 00607 00608 00609 // constructor from iterators 00610 template <typename A_it, typename B_it, typename R_it, typename FL_it, 00611 typename L_it, typename FU_it, typename U_it, typename D_it, 00612 typename C_it> 00613 Quadratic_program 00614 ( 00615 int n, int m, // number of variables / constraints 00616 const A_it& a, 00617 const B_it& b, 00618 const R_it& r, 00619 const FL_it& fl, 00620 const L_it& l, 00621 const FU_it& fu, 00622 const U_it& u, 00623 const D_it& d, 00624 const C_it& c, 00625 const typename std::iterator_traits<C_it>::value_type& c0 = 0) 00626 : n_(0), m_(0), c0_(0), 00627 default_r(CGAL::EQUAL), default_fl(true), 00628 default_l(0), default_fu(false), default_u(0), is_valid_(true) 00629 { 00630 // now copy, using the set methods 00631 for (int j=0; j<n; ++j) { 00632 for (int i=0; i<m; ++i) 00633 set_a (j, i, (*(a+j))[i]); 00634 set_l (j, *(fl+j), *(l+j)); 00635 set_u (j, *(fu+j), *(u+j)); 00636 set_c (j, *(c+j)); 00637 } 00638 for (int i=0; i<m; ++i) { 00639 set_b (i, *(b+i)); 00640 set_r (i, *(r+i)); 00641 } 00642 for (int i=0; i<n; ++i) 00643 for (int j=0; j<=i; ++j) 00644 set_d (i, j, (*(d+i))[j]); 00645 set_c0 (c0); 00646 } 00647 00648 // type of problem 00649 bool is_linear() const 00650 { 00651 CGAL_qpe_assertion(d_matrix.size() == (unsigned int)(n_)); 00652 for (int i=0; i<n_; ++i) 00653 if (!d_matrix[i].empty()) return false; 00654 return true; 00655 } 00656 00657 private: 00658 // helpers to determine bound status 00659 // checks whether all bounds in flu are as given by the parameter "finite" 00660 // default_flu is the default-value of the underlying map that is not 00661 // stored 00662 bool all_bounds_are 00663 (bool finite, const Sparse_f_vector& flu, bool default_flu) const 00664 { 00665 if (finite == default_flu) 00666 return flu.empty(); 00667 else 00668 // are there exactly n non-default values "finite"? 00669 return flu.size() == (unsigned int)(n_); 00670 } 00671 00672 bool all_bounds_are_zero 00673 // checks whether all bounds in lu are 0. default_lu is the default-value 00674 // of the underlying map that is not stored 00675 (const Sparse_vector& lu, const NT& default_lu) const 00676 { 00677 if (CGAL::is_zero(default_lu)) 00678 return lu.empty(); 00679 else { 00680 // are there exactly n non-default values? 00681 if (lu.size() != (unsigned int)(n_)) return false; 00682 // ok, we have to test each of the non-default values against zero 00683 for (typename Sparse_vector::const_iterator 00684 j = lu.begin(); j != lu.end(); ++j) 00685 if (!CGAL::is_zero(j->second)) return false; 00686 return true; 00687 } 00688 } 00689 00690 public: 00691 00692 bool is_nonnegative() const 00693 { 00694 return 00695 all_bounds_are (true, fl_vector, default_fl) && 00696 all_bounds_are_zero (l_vector, default_l) && 00697 all_bounds_are (false, fu_vector, default_fu); 00698 } 00699 00700 bool is_nonpositive() const 00701 { 00702 return 00703 all_bounds_are (false, fl_vector, default_fl) && 00704 all_bounds_are_zero (u_vector, default_u) && 00705 all_bounds_are (true, fu_vector, default_fu); 00706 } 00707 00708 bool is_free() const 00709 { 00710 return 00711 all_bounds_are (false, fl_vector, default_fl) && 00712 all_bounds_are (false, fu_vector, default_fu); 00713 } 00714 00715 // set methods 00716 void set_a (int j, int i, const NT& val) 00717 { 00718 CGAL_qpe_assertion (j >= 0); 00719 CGAL_qpe_assertion (i >= 0); 00720 if (j >= n_) { 00721 n_ = j+1; 00722 grow_a_d(n_); 00723 } 00724 if (i >= m_) m_ = i+1; 00725 if (CGAL::is_zero(val)) 00726 a_matrix[j].erase(i); 00727 else 00728 a_matrix[j][i] = val; 00729 } 00730 00731 void set_b (int i, const NT& val) 00732 { 00733 CGAL_qpe_assertion (i >= 0); 00734 if (i >= m_) m_ = i+1; 00735 if (CGAL::is_zero(val)) 00736 b_vector.erase(i); 00737 else 00738 b_vector[i] = val; 00739 } 00740 00741 void set_r (int i, CGAL::Comparison_result val) 00742 { 00743 CGAL_qpe_assertion (i >= 0); 00744 if (i >= m_) m_ = i+1; 00745 if (val == default_r) 00746 r_vector.erase(i); 00747 else 00748 r_vector[i] = val; 00749 } 00750 00751 void set_l (int j, bool is_finite, const NT& val = NT(0)) 00752 { 00753 CGAL_qpe_assertion (j >= 0); 00754 if (j >= n_) { 00755 n_ = j+1; 00756 grow_a_d(n_); 00757 } 00758 if (is_finite == default_fl) 00759 fl_vector.erase(j); 00760 else 00761 fl_vector[j] = is_finite; 00762 if (val == default_l) 00763 l_vector.erase(j); 00764 else 00765 l_vector[j] = val; 00766 } 00767 00768 void set_u (int j, bool is_finite, const NT& val = NT(0)) 00769 { 00770 CGAL_qpe_assertion (j >= 0); 00771 if (j >= n_) { 00772 n_ = j+1; 00773 grow_a_d(n_); 00774 } 00775 if (is_finite == default_fu) 00776 fu_vector.erase(j); 00777 else 00778 fu_vector[j] = is_finite; 00779 if (val == default_u) 00780 u_vector.erase(j); 00781 else 00782 u_vector[j] = val; 00783 } 00784 00785 void set_c (int j, const NT& val) 00786 { 00787 CGAL_qpe_assertion (j >= 0); 00788 if (j >= n_) { 00789 n_ = j+1; 00790 grow_a_d(n_); 00791 } 00792 if (CGAL::is_zero(val)) 00793 c_vector.erase(j); 00794 else 00795 c_vector[j] = val; 00796 } 00797 00798 void set_c0 (const NT& val) 00799 { 00800 c0_ = val; 00801 } 00802 00803 void set_d (int i, int j, const NT& val) 00804 { 00805 CGAL_qpe_assertion (i >= 0); 00806 CGAL_qpe_assertion (j >= 0); 00807 CGAL_qpe_assertion (j <= i); // lower-diagonal entry 00808 if (i >= n_) { 00809 n_ = i+1; 00810 grow_a_d(n_); 00811 } 00812 if (CGAL::is_zero(val)) 00813 d_matrix[i].erase(j); 00814 else 00815 d_matrix[i][j] = val; 00816 } 00817 00818 protected: 00819 // helpers for errors/warnings 00820 std::string replace1 00821 (const std::string& msg,const std::string& replacement) const 00822 { 00823 std::string result(msg); 00824 const std::string::size_type pos = result.find('%'); 00825 CGAL_qpe_assertion(pos < result.size()); 00826 result.replace(pos,1,replacement); 00827 return result; 00828 } 00829 00830 bool err(const char* msg) { 00831 error_msg = msg; 00832 is_valid_ = false; 00833 return false; 00834 } 00835 00836 bool err1(const char* msg, 00837 const std::string& parameter1) { 00838 error_msg = replace1(msg,parameter1); 00839 is_valid_ = false; 00840 return false; 00841 } 00842 00843 bool err2(const char* msg, 00844 const std::string& parameter1, 00845 const std::string& parameter2) { 00846 error_msg = replace1(replace1(msg,parameter1),parameter2); 00847 is_valid_ = false; 00848 return false; 00849 } 00850 00851 bool err3(const char* msg, 00852 const std::string& parameter1, 00853 const std::string& parameter2, 00854 const std::string& parameter3) { 00855 error_msg = 00856 replace1(replace1(replace1(msg,parameter1),parameter2),parameter3); 00857 is_valid_ = false; 00858 return false; 00859 } 00860 00861 void warn(const std::string& msg) const { 00862 std::cerr << "Warning: " << msg << '.' << std::endl; 00863 } 00864 00865 void warn1(const std::string& msg,const std::string& parameter1) const { 00866 warn(replace1(msg,parameter1)); 00867 } 00868 00869 00870 }; 00871 00872 // Quadratic_program_from_mps 00873 // -------------------------- 00874 // for reading a QP from a stream in MPS format 00875 00876 template <typename NT_> 00877 class Quadratic_program_from_mps : 00878 public Quadratic_program<NT_> 00879 { 00880 public: 00881 typedef NT_ NT; 00882 private: 00883 typedef Quadratic_program<NT> Base; 00884 public: 00885 QP_MODEL_ITERATOR_TYPES; 00886 private: 00887 // types 00888 typedef std::map<std::string,unsigned int> Index_map; 00889 typedef std::pair<std::string,unsigned int> String_int_pair; 00890 public: 00891 // constructor 00892 Quadratic_program_from_mps 00893 (std::istream& in) 00894 : Base(), from(in), nt0(0), use_put_back_token(false) 00895 { 00896 // read NAME section: 00897 if (!name_section()) 00898 return; 00899 00900 // read ROWS section: 00901 if (!rows_section()) 00902 return; 00903 00904 // read COLUMNS section: 00905 if (!columns_section()) 00906 return; 00907 00908 // read RHS section: 00909 if (!rhs_section()) 00910 return; 00911 00912 // check for (optional) RANGES section: 00913 if (!ranges_section()) 00914 return; 00915 00916 // read optional BOUNDS section: 00917 if (!bounds_section()) 00918 return; 00919 00920 // read optional QMATRIX section: 00921 if (!qmatrix_section()) 00922 return; 00923 00924 // check for ENDATA: 00925 const std::string end = token(); 00926 if (end != "ENDATA") { 00927 this->err1("ENDDATA expected but found '%'",end); 00928 return; 00929 } 00930 00931 // remember the number of variables/constraint that we have now 00932 n_after_construction = this->get_n(); 00933 m_after_construction = this->get_m(); 00934 } 00935 00936 // returns the first comment that was read from the MPS stream 00937 const std::string& get_comment() const 00938 { 00939 return comment_; 00940 } 00941 00942 // returns name of the problem 00943 const std::string& get_problem_name() const 00944 { 00945 return name; 00946 } 00947 00948 const std::string& variable_name_by_index(int j) const 00949 { 00950 CGAL_qpe_assertion(this->is_valid()); 00951 CGAL_qpe_assertion(0<=j && j<n_after_construction); 00952 return var_by_index[j]; 00953 } 00954 00955 int variable_index_by_name (const std::string& name) const 00956 { 00957 const Index_map::const_iterator var_name = var_names.find(name); 00958 if (var_name == var_names.end()) // unknown variable 00959 return -1; 00960 else 00961 return var_name->second; 00962 } 00963 00964 const std::string& constraint_name_by_index(int i) const 00965 { 00966 CGAL_qpe_assertion(this->is_valid()); 00967 CGAL_qpe_assertion(0<=i && i<m_after_construction); 00968 return row_by_index[i]; 00969 } 00970 00971 int constraint_index_by_name (const std::string& name) const 00972 { 00973 const Index_map::const_iterator row_name = row_names.find(name); 00974 if (row_name == row_names.end()) // unknown constraint 00975 return -1; 00976 else 00977 return row_name->second; 00978 } 00979 00980 private: 00981 // data 00982 // ---- 00983 std::istream& from; // input stream 00984 NT nt0; 00985 00986 std::string D_section; // name of the section from which D was read 00987 std::string name; // name of the problem 00988 std::string comment_; // first comment in the input, if any 00989 std::string obj; // name of the objective "constraint" 00990 int n_after_construction; 00991 int m_after_construction; 00992 00993 Index_map row_names; 00994 Index_map duplicated_row_names; // to handle RANGES section 00995 Index_map var_names; 00996 std::vector<std::string> var_by_index; // name of i-th column 00997 std::vector<std::string> row_by_index; // name of i-th row 00998 00999 // variables used in token() (see below): 01000 bool use_put_back_token; 01001 std::string put_back_token; 01002 01003 // parsing routines 01004 // (Note: returns true iff a line-break was eaten.) 01005 bool whitespace() 01006 { 01007 // support for put_token_back(): 01008 if (use_put_back_token) 01009 return false; 01010 bool lineBreakFound = false; 01011 01012 char c; 01013 bool in_comment = false; // true iff we are within a comment 01014 const bool remember_comment = comment_.size() == 0; 01015 while (from.get(c)) 01016 if (in_comment) { 01017 if (c!='\r' && c!='\n') { 01018 if (remember_comment) 01019 comment_.push_back(c); 01020 } else 01021 in_comment = false; 01022 } else { // not in comment? 01023 if (!isspace(c)) { 01024 if (c!='$' && c!='*') { 01025 from.putback(c); 01026 break; 01027 } 01028 in_comment = true; 01029 lineBreakFound = true; 01030 } else { 01031 if (c=='\r' || c=='\n') 01032 lineBreakFound = true; 01033 } 01034 } 01035 return lineBreakFound; 01036 } 01037 01038 std::string token() { 01039 if (use_put_back_token) { 01040 use_put_back_token = false; 01041 return put_back_token; 01042 } 01043 whitespace(); 01044 std::string token; 01045 char c; 01046 while (from.get(c)) { 01047 if (isspace(c)) { 01048 from.putback(c); 01049 break; 01050 } 01051 token.push_back(c); 01052 } 01053 return token; 01054 } 01055 01056 void put_token_back(const std::string& token) { 01057 CGAL_qpe_assertion(!use_put_back_token); 01058 use_put_back_token = true; 01059 put_back_token = token; 01060 } 01061 01062 template<typename NumberType> 01063 bool number(NumberType& entry) { 01064 // whitespace(); the following >> should care for this 01065 from >> entry; 01066 return from.good(); 01067 } 01068 01069 bool name_section() 01070 { 01071 const std::string t = token(); 01072 if (t != "NAME") 01073 return this->err("expected 'NAME'"); 01074 // NAME: everything found until line break; whitespaces are allowed 01075 char c; 01076 std::string token; 01077 std::string whitespaces; 01078 if (whitespace()) 01079 // line break eaten, name is empty 01080 return true; 01081 do { 01082 from.get(c); 01083 if (c == '\r' || c == '\n') break; 01084 if (isspace(c)) 01085 whitespaces.push_back(c); // save whitespace 01086 else { 01087 // new actual character found: previous whitespaces belong to name 01088 name += whitespaces; 01089 whitespaces.clear(); 01090 name.push_back(c); 01091 } 01092 } while (true); 01093 return true; 01094 } 01095 01096 bool rows_section() 01097 { 01098 std::string t = token(); 01099 if (t != "ROWS") 01100 return this->err1("expected 'ROWS' but found '%'",t); 01101 01102 // read 'N', 'G', 'L', or 'E', and the name of the constraint: 01103 t = token(); 01104 int i = 0; // row index 01105 while (t != "COLUMNS") { 01106 const char type = t[0]; 01107 const std::string symbol(t); // for error message below 01108 t = token(); 01109 switch (type) { 01110 case 'N': 01111 // register name of objective row: 01112 if (obj.size() == 0) // remember first (and ignore others) 01113 obj = t; 01114 break; 01115 case 'G': 01116 case 'L': 01117 case 'E': 01118 { 01119 // register name of >=, <=, or = constraint: 01120 this->set_r (i, 01121 type == 'G'? CGAL::LARGER : 01122 (type == 'E'? CGAL::EQUAL : CGAL::SMALLER)); 01123 if (row_names.find(t) != row_names.end()) 01124 return this->err1("duplicate row name '%' in section ROWS",t); 01125 row_names.insert(String_int_pair(t,i)); 01126 row_by_index.push_back(t); 01127 ++i; 01128 } 01129 break; 01130 default: 01131 return 01132 this->err1 01133 ("expected 'N', 'L', 'E', or 'G' in ROWS section but found '%'", 01134 symbol); 01135 } 01136 t = token(); 01137 } 01138 put_token_back(t); 01139 01140 return true; 01141 } 01142 01143 bool columns_section() 01144 { 01145 std::string t = token(); 01146 if (t != "COLUMNS") 01147 return this->err1("expected 'COLUMNS' but found '%'",t); 01148 01149 t = token(); 01150 while (t != "RHS") { 01151 // find variable name: 01152 unsigned int var_index; 01153 std::string col_name; 01154 const Index_map::const_iterator var_name = var_names.find(t); 01155 if (var_name == var_names.end()) { // new variable? 01156 var_index = var_names.size(); 01157 col_name = t; 01158 var_names.insert(String_int_pair(t,var_index)); 01159 var_by_index.push_back(t); 01160 } else { // variable that is already known? 01161 var_index = var_name->second; 01162 col_name = var_name->first; 01163 } 01164 01165 bool doItAgain = true; 01166 for (int i=0; doItAgain; ++i) { 01167 // read row identifier: 01168 t = token(); 01169 01170 // read number: 01171 NT val; 01172 if (!number(val)) 01173 return this->err2 01174 ("number expected after row identifier '%' in '%' COLUMNS record", 01175 t,col_name); 01176 01177 // store number: 01178 if (t == obj) { // objective row? 01179 this->set_c(var_index, val); 01180 } else { // not objective row? 01181 const Index_map::const_iterator row_name = row_names.find(t); 01182 if (row_name == row_names.end()) 01183 return this->err1 01184 ("unknown row identifier '%' in section COLUMNS",t); 01185 this->set_a (var_index, row_name->second, val); 01186 } 01187 01188 // determine if we need to read another number: 01189 doItAgain = i==0 && !whitespace(); 01190 } 01191 01192 // read next token: 01193 t = token(); 01194 } 01195 put_token_back(t); 01196 01197 return true; 01198 } 01199 01200 bool rhs_section() 01201 { 01202 this->set_c0 (nt0); // no constant term yet 01203 std::string t = token(); 01204 if (t != "RHS") 01205 return this->err1("expected 'RHS' but found '%'",t); 01206 01207 t = token(); 01208 std::string rhs_id; 01209 while (t != "RANGES" && t != "BOUNDS" && 01210 t != "DMATRIX" && t != "QMATRIX" && t != "QUADOBJ" && 01211 t != "ENDATA") { 01212 // read rhs identifier and if it is different from the one 01213 // from the previous iteration, ignore the whole row: 01214 bool ignore = false; 01215 std::string ignored; 01216 if (rhs_id.size() == 0) { // first time we enter the loop? 01217 rhs_id = t; 01218 } else { // rhs_id already set 01219 if (t != rhs_id) { 01220 ignore = true; // ignore other rhs identifiers 01221 ignored = t; 01222 } 01223 } 01224 01225 bool doItAgain = true; 01226 for (int i=0; doItAgain; ++i) { 01227 // read row identifier: 01228 t = token(); 01229 01230 // read number: 01231 NT val; 01232 if (!number(val)) 01233 return this->err1("number expected after '%' in this RHS record",t); 01234 01235 // store number: 01236 const Index_map::const_iterator row_name = row_names.find(t); 01237 if (row_name == row_names.end()) { 01238 // no corresponding constraint; is it the constant term? 01239 if (t == obj) 01240 this->set_c0(-val); 01241 else 01242 return this->err1("unknown row identifier '%' in section RHS",t); 01243 } else { 01244 // we have an actual constraint 01245 if (!ignore) { 01246 this->set_b(row_name->second, val); 01247 } else { 01248 this->warn1("rhs with identifier '%' ignored", ignored); 01249 } 01250 } 01251 01252 // determine if we need to read another number: 01253 doItAgain = i==0 && !whitespace(); 01254 } 01255 01256 // read next token: 01257 t = token(); 01258 } 01259 put_token_back(t); 01260 01261 return true; 01262 } 01263 01264 bool ranges_section() 01265 { 01266 std::string t = token(); 01267 if (t != "RANGES") { // (Note: RANGES section is optional.) 01268 put_token_back(t); 01269 return true; 01270 } 01271 01272 t = token(); 01273 std::string range_id; 01274 while ((t != "BOUNDS" && t != "QMATRIX" && 01275 t != "DMATRIX" && t != "QUADOBJ" && t != "ENDATA")) { 01276 // read rhs identifier and if it is different from the one 01277 // from the previous iteration, ignore the whole row: 01278 bool ignore = false; 01279 std::string ignored; 01280 if (range_id.size() == 0) { // first time we enter the loop? 01281 range_id = t; 01282 } else { // range_id already set 01283 if (t != range_id) { 01284 ignore = true; // ignore other range identifiers 01285 ignored = t; 01286 } 01287 } 01288 bool doItAgain = true; 01289 for (int i=0; doItAgain; ++i) { 01290 // read row identifier: 01291 t = token(); 01292 01293 // read number: 01294 NT val; 01295 if (!number(val)) 01296 return this->err1 01297 ("number expected after '%' in this RANGES record",t); 01298 01299 // duplicate the constraint, depending on sign of val and type 01300 // of constraint 01301 const Index_map::const_iterator row_name = row_names.find(t); 01302 if (row_name == row_names.end()) { 01303 return this->err1("unknown row identifier '%' in section RANGES",t); 01304 } else { 01305 if (!ignore) { 01306 int index = row_name->second; 01307 CGAL::Comparison_result type = *(this->get_r()+index); 01308 // duplicate the row, unless it has already been duplicated 01309 const Index_map::const_iterator duplicated_row_name = 01310 duplicated_row_names.find(t); 01311 if (duplicated_row_name != duplicated_row_names.end()) 01312 return this->err1 01313 ("duplicate row identifier '%' in section RANGES",t); 01314 duplicated_row_names.insert(*row_name); 01315 std::string dup_name = row_name->first+std::string("_DUPLICATED"); 01316 int new_index = this->get_m(); 01317 row_names.insert(String_int_pair (dup_name, new_index)); 01318 row_by_index.push_back (dup_name); 01319 for (unsigned int j=0; j<var_names.size(); ++j) { 01320 NT val = (*(this->get_a()+j))[index]; 01321 this->set_a (j, new_index, val); 01322 } 01323 // determine rhs for this new row. Here are the rules: 01324 // if r is the ranges value and b is the old right-hand 01325 // side, then we have h <= constraint <= u according to 01326 // this table: 01327 // 01328 // row type sign of r h u 01329 // ---------------------------------------------- 01330 // G + or - b b + |r| 01331 // L + or - b - |r| b 01332 // E + b b + |r| 01333 // E - b - |r| b 01334 01335 switch (type) { 01336 case CGAL::LARGER: // introduce "<= b+|r|" 01337 this->set_r(new_index, CGAL::SMALLER); 01338 this->set_b(new_index, *(this->get_b()+index) + CGAL::abs(val)); 01339 break; 01340 case CGAL::SMALLER: // introduce ">= b-|r|" 01341 this->set_r(new_index, CGAL::LARGER); 01342 this->set_b(new_index, *(this->get_b()+index) - CGAL::abs(val)); 01343 break; 01344 case CGAL::EQUAL: 01345 if (CGAL_NTS is_positive (val)) { 01346 // introduce "<= b+|r|" 01347 this->set_r(new_index, CGAL::SMALLER); 01348 } else { 01349 // introduce ">= b-|r|" 01350 this->set_r(new_index, CGAL::LARGER); 01351 } 01352 this->set_b(new_index, *(this->get_b()+index) + val); 01353 break; 01354 default: 01355 CGAL_qpe_assertion(false); 01356 } 01357 } else { 01358 this->warn1("range with identifier '%' ignored", ignored); 01359 } 01360 } 01361 01362 // determine if we need to read another number: 01363 doItAgain = i==0 && !whitespace(); 01364 } 01365 01366 // read next token: 01367 t = token(); 01368 } 01369 put_token_back(t); 01370 01371 return true; 01372 } 01373 01374 bool bounds_section() 01375 { 01376 std::string t = token(); 01377 if (t != "BOUNDS") { // (Note: BOUNDS section is optional.) 01378 put_token_back(t); 01379 return true; 01380 } 01381 01382 t = token(); 01383 std::string bound_id; 01384 while (t != "QMATRIX" && t != "DMATRIX" && t != "QUADOBJ" && t != "ENDATA") { 01385 // process type of bound: 01386 enum Bound_type { LO, UP, FX, FR, MI, PL}; 01387 Bound_type type; 01388 if (t=="LO") 01389 type = LO; 01390 else if (t=="UP") 01391 type = UP; 01392 else if (t=="FX") 01393 type = FX; 01394 else if (t=="FR") 01395 type = FR; 01396 else if (t=="MI") 01397 type = MI; 01398 else if (t=="PL") 01399 type = PL; 01400 else 01401 return 01402 this->err1 01403 ("expected 'LO', 'UP', 'FX', 'FR', 'MI', or 'PL' here but found '%'", 01404 t); 01405 01406 // remember bound: 01407 const std::string bound = t; 01408 01409 // find bound label; there may be several, but we only process 01410 // the bounds having the first bound label that occurs. This 01411 // label may be empty, though 01412 t = token(); // bound label or variable name (case of empty bound label) 01413 if (bound_id.size() == 0) { // first time we see a bound label / variable? 01414 const Index_map::const_iterator var_name = var_names.find(t); 01415 if (var_name != var_names.end()) { // is the token a variable? 01416 bound_id = " "; // there is no bound label 01417 put_token_back(t); // the variable name is processed below 01418 } else 01419 bound_id = t; // we found a bound label 01420 } else { 01421 // now we already know the bound label 01422 if (bound_id == " ") // empty bound label? 01423 put_token_back(t); // the variable name is processed below 01424 else 01425 if (t != bound_id) { 01426 this->warn1("ignoring all bounds for bound label '%'",t); 01427 this->warn1("(only bounds for bound label '%' are accepted)", 01428 bound_id); 01429 } 01430 } 01431 01432 // find variable name; 01433 t = token(); 01434 const Index_map::const_iterator var_name = var_names.find(t); 01435 if (var_name == var_names.end()) // unknown variable? 01436 return this->err1("unknown variable '%' in BOUNDS section",t); 01437 const unsigned int var_index = var_name->second;; 01438 01439 // read value of bound, if appropriate: 01440 NT val; 01441 if (type==LO || type==UP || type==FX) 01442 if (!number(val)) 01443 return this->err2("expected number after '%' in % bound",t,bound); 01444 01445 // store bound: 01446 switch (type) { 01447 case FX: 01448 this->set_u (var_index, true, val); 01449 // no break here!! 01450 case LO: 01451 this->set_l (var_index, true, val); 01452 break; 01453 case UP: 01454 this->set_u (var_index, true, val); 01455 if (val <= 0 && *(this->get_fl()+var_index) 01456 && *(this->get_l()+var_index) == 0) 01457 if (val < 0) 01458 this->set_l(var_index, false); 01459 break; 01460 case FR: 01461 this->set_u(var_index, false); 01462 this->set_l(var_index, false); 01463 break; 01464 case MI: 01465 this->set_l(var_index, false); 01466 break; 01467 case PL: 01468 this->set_u(var_index, false); 01469 break; 01470 default: 01471 CGAL_qpe_assertion(false); 01472 } 01473 01474 // read next token: 01475 t = token(); 01476 } 01477 put_token_back(t); 01478 01479 return true; 01480 } 01481 01482 bool qmatrix_section() 01483 { 01484 std::string t = token(); 01485 if (t!="QMATRIX" && t!="DMATRIX" && t!="QUADOBJ") { // optional 01486 put_token_back(t); 01487 return true; 01488 } 01489 01490 // remember section name: 01491 D_section = t; 01492 const bool multiply_by_two = t=="DMATRIX"; 01493 01494 t = token(); 01495 std::string bound_id; 01496 while (t != "ENDATA") { 01497 // find first variable name; 01498 const Index_map::const_iterator var1_name = var_names.find(t); 01499 if (var1_name == var_names.end()) // unknown variable? 01500 return this->err2("unknown first variable '%' in '%' section", 01501 t, D_section); 01502 const unsigned int var1_index = var1_name->second; 01503 01504 // find second variable name; 01505 t = token(); 01506 const Index_map::const_iterator var2_name = var_names.find(t); 01507 if (var2_name == var_names.end()) // unknown variable? 01508 return this->err2("unknown second variable '%' in '%' section", 01509 t, D_section); 01510 const unsigned int var2_index = var2_name->second;; 01511 01512 // read value: 01513 NT val; 01514 if (!number(val)) 01515 return this->err2("expected number after '%' in section '%'", 01516 t, D_section); 01517 01518 // multiply by two if approriate: 01519 if (multiply_by_two) 01520 val *= NT(2); 01521 01522 // set entry in D: 01523 int i, j; 01524 if (var2_index <= var1_index) { 01525 i = var1_index; j = var2_index; 01526 } else { 01527 i = var2_index; j = var1_index; 01528 } 01529 // rule out that we previously put a different (nonzero) value at (i,j) 01530 NT old_val = (*(this->get_d()+i))[j]; 01531 if (!CGAL::is_zero(old_val) && old_val != val) 01532 return this->err3("nonsymmetric '%' section at variables '%' and '%'", 01533 D_section, var1_name->first, var2_name->first); 01534 this->set_d(i, j, val); 01535 01536 // read next token: 01537 t = token(); 01538 } 01539 put_token_back(t); 01540 01541 return true; 01542 } 01543 01544 }; 01545 01546 CGAL_END_NAMESPACE 01547 01548 #endif // CGAL_QP_MODELS_H