BWAPI
|
00001 // Copyright (c) 1997-2007 ETH Zurich (Switzerland). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00005 // the terms of the Q Public License version 1.0. 00006 // See the file LICENSE.QPL distributed with CGAL. 00007 // 00008 // Licenseges holding a valid commercial license may use this file in 00009 // accordance with the commercial license agreement provided with the software. 00010 // 00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00013 // 00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/QP_solver/include/CGAL/QP_solution.h $ 00015 // $Id: QP_solution.h 46451 2008-10-23 14:31:10Z gaertner $ 00016 // 00017 // 00018 // Author(s) : Kaspar Fischer 00019 // : Bernd Gaertner <gaertner@inf.ethz.ch> 00020 // : Sven Schoenherr 00021 // : Franz Wessendorp 00022 00023 #ifndef CGAL_QP_SOLUTION_H 00024 #define CGAL_QP_SOLUTION_H 00025 00026 #include <iostream> 00027 #include <vector> 00028 #include <CGAL/basic.h> 00029 #include <CGAL/Handle_for.h> 00030 #include <CGAL/function_objects.h> 00031 #include <CGAL/Algebraic_structure_traits.h> 00032 #include <boost/bind.hpp> 00033 #include <boost/function.hpp> 00034 #include <boost/iterator/counting_iterator.hpp> 00035 #include <boost/iterator/transform_iterator.hpp> 00036 00037 CGAL_BEGIN_NAMESPACE 00038 00039 // forward references 00040 template <typename Q, typename ET, typename Tags> 00041 class QP_solver; 00042 00043 namespace QP_solution_detail { 00044 template <typename ET> 00045 class Quotient_normalizer; 00046 00047 template <typename ET> 00048 class Value_by_index; 00049 00050 template <typename ET> 00051 class Unbounded_direction_by_index; 00052 00053 template <typename ET> 00054 class Lambda_by_index; 00055 } 00056 00057 // global status type 00058 enum Quadratic_program_status 00059 { 00060 QP_UPDATE, 00061 QP_INFEASIBLE, 00062 QP_UNBOUNDED, 00063 QP_OPTIMAL 00064 }; 00065 00066 // abstract base class of all QP-solvers 00067 // ------------------------------------- 00068 template <class ET> 00069 class QP_solver_base 00070 { 00071 public: 00072 // types 00073 typedef CGAL::Creator_2< ET, ET, Quotient<ET> > 00074 U_Quotient_creator; // unnormalized quotient creator ET x ET -> (ET, ET) 00075 00076 typedef QP_solution_detail::Quotient_normalizer<ET> 00077 Quotient_normalizer; // normalizer (ET, ET) -> (ET, ET) 00078 00079 typedef boost::function1< Quotient<ET>, ET > 00080 Quotient_maker; 00081 00082 typedef std::vector<int> 00083 Indices; 00084 00085 typedef Indices::iterator 00086 Index_mutable_iterator; 00087 00088 typedef Indices::const_iterator 00089 Index_const_iterator; 00090 00091 typedef typename QP_solution_detail::Value_by_index<ET> Value_by_index; 00092 00093 typedef typename boost::transform_iterator 00094 <Value_by_index, boost::counting_iterator<int> > 00095 Variable_numerator_iterator; 00096 00097 typedef boost::transform_iterator 00098 <Quotient_maker, Variable_numerator_iterator> 00099 Variable_value_iterator; 00100 00101 typedef typename QP_solution_detail::Unbounded_direction_by_index<ET> 00102 Unbounded_direction_by_index; 00103 00104 typedef boost::transform_iterator 00105 <Unbounded_direction_by_index, boost::counting_iterator<int> > 00106 Unbounded_direction_iterator; 00107 00108 typedef typename QP_solution_detail::Lambda_by_index<ET> 00109 Lambda_by_index; 00110 00111 typedef boost::transform_iterator 00112 <Lambda_by_index, boost::counting_iterator<int> > 00113 Lambda_numerator_iterator; 00114 00115 typedef boost::transform_iterator 00116 <Quotient_maker,Lambda_numerator_iterator> 00117 Lambda_iterator; 00118 00119 public: 00120 00121 // virtual access functions to solution that will 00122 // be overridden by QP_solver below 00123 00124 // Solution 00125 // -------- 00126 virtual ET solution_numerator() const = 0; 00127 virtual ET solution_denominator() const = 0; 00128 Quotient<ET> solution( ) const 00129 { 00130 // workaround to please Boost 1.33.1: 00131 ET n = solution_numerator(); 00132 ET d = solution_denominator(); 00133 return 00134 boost::bind 00135 (Quotient_normalizer(), boost::bind 00136 (U_Quotient_creator(), _1, _2)) 00137 (n, d); 00138 // (solution_numerator(), solution_denominator()); 00139 } 00140 virtual Quadratic_program_status status() const = 0; 00141 virtual int iterations() const = 0; 00142 00143 // Variable values 00144 // --------------- 00145 virtual ET variable_numerator_value (int i) const = 0; 00146 virtual const ET& variables_common_denominator( ) const = 0; 00147 virtual int number_of_variables() const = 0; 00148 00149 // value type ET 00150 Variable_numerator_iterator 00151 original_variables_numerator_begin( ) const 00152 { return Variable_numerator_iterator 00153 (boost::counting_iterator<int>(0), 00154 Value_by_index(this));} 00155 00156 00157 Variable_numerator_iterator 00158 original_variables_numerator_end ( ) const 00159 { return Variable_numerator_iterator 00160 (boost::counting_iterator<int>(number_of_variables()) , 00161 Value_by_index(this));} 00162 00163 // value type Quotient<ET> 00164 Variable_value_iterator 00165 original_variable_values_begin( ) const 00166 { return Variable_value_iterator 00167 (original_variables_numerator_begin(), 00168 boost::bind 00169 (boost::bind 00170 (Quotient_normalizer(), boost::bind 00171 (U_Quotient_creator(), _1, _2)), _1, variables_common_denominator())); 00172 } 00173 00174 Variable_value_iterator 00175 original_variable_values_end ( ) const 00176 { return Variable_value_iterator 00177 (original_variables_numerator_end(), 00178 boost::bind 00179 (boost::bind 00180 (Quotient_normalizer(), boost::bind 00181 (U_Quotient_creator(), _1, _2)), _1, variables_common_denominator())); 00182 } 00183 00184 // Basic variables and constraints 00185 // ------------------------------- 00186 virtual Index_const_iterator 00187 basic_original_variable_indices_begin() const = 0; 00188 virtual Index_const_iterator 00189 basic_original_variable_indices_end() const = 0; 00190 virtual int number_of_basic_original_variables() const = 0; 00191 virtual Index_const_iterator 00192 basic_constraint_indices_begin() const = 0; 00193 virtual Index_const_iterator 00194 basic_constraint_indices_end() const = 0; 00195 virtual int number_of_basic_constraints() const = 0; 00196 00197 // Unboundedness 00198 // ------------- 00199 virtual ET unbounded_direction_value(int i) const = 0; 00200 00201 Unbounded_direction_iterator unbounded_direction_begin() const 00202 { return Unbounded_direction_iterator 00203 (boost::counting_iterator<int>(0), 00204 Unbounded_direction_by_index(this));} 00205 00206 // Returns the past-the-end iterator corresponding to 00207 // unbounded_direction_begin(). 00208 Unbounded_direction_iterator unbounded_direction_end() const 00209 { return Unbounded_direction_iterator 00210 (boost::counting_iterator<int>(number_of_variables()), 00211 Unbounded_direction_by_index(this));} 00212 00213 00214 // Optimality 00215 // ---------- 00216 virtual ET lambda_numerator(int i) const = 0; 00217 virtual int number_of_constraints() const = 0; 00218 00219 // value type ET 00220 Lambda_numerator_iterator 00221 lambda_numerator_begin() const 00222 { return Lambda_numerator_iterator 00223 (boost::counting_iterator<int>(0), 00224 Lambda_by_index(this));} 00225 00226 Lambda_numerator_iterator 00227 lambda_numerator_end() const 00228 { return Lambda_numerator_iterator 00229 (boost::counting_iterator<int>(number_of_constraints()), 00230 Lambda_by_index(this));} 00231 00232 // value type Quotient<ET> 00233 Lambda_iterator 00234 lambda_begin() const 00235 { 00236 return Lambda_iterator 00237 (lambda_numerator_begin(), 00238 boost::bind 00239 (boost::bind 00240 (Quotient_normalizer(), boost::bind 00241 (U_Quotient_creator(), _1, _2)), _1, variables_common_denominator())); 00242 } 00243 00244 Lambda_iterator 00245 lambda_end() const 00246 { 00247 return Lambda_iterator 00248 (lambda_numerator_end(), 00249 boost::bind 00250 (boost::bind 00251 (Quotient_normalizer(), boost::bind 00252 (U_Quotient_creator(), _1, _2)), _1, variables_common_denominator())); 00253 } 00254 00255 // destruction 00256 // ----------- 00257 virtual ~QP_solver_base() {} 00258 }; 00259 00260 00261 // Quadratic_program_solution class: a handle for QP_solver_base<ET> 00262 // ----------------------------------------------------------------- 00263 template <class ET_> 00264 class Quadratic_program_solution: Handle_for<const QP_solver_base<ET_>*> 00265 { 00266 public: 00267 typedef ET_ ET; 00268 // interface types 00269 // =============== 00270 00271 // variable values / indices 00272 // ------------------------- 00273 typedef typename QP_solver_base<ET>::Variable_value_iterator 00274 Variable_value_iterator; 00275 00276 typedef typename QP_solver_base<ET>::Variable_numerator_iterator 00277 Variable_numerator_iterator; 00278 00279 typedef typename QP_solver_base<ET>::Index_const_iterator 00280 Index_iterator; 00281 00282 // certificates 00283 // ------------ 00284 typedef typename QP_solver_base<ET>::Unbounded_direction_iterator 00285 Unboundedness_certificate_iterator; 00286 00287 typedef 00288 typename QP_solver_base<ET>::Lambda_numerator_iterator 00289 Optimality_certificate_numerator_iterator; 00290 00291 typedef typename QP_solver_base<ET>::Lambda_iterator 00292 Optimality_certificate_iterator; 00293 00294 typedef typename QP_solver_base<ET>::Lambda_numerator_iterator 00295 Infeasibility_certificate_iterator; 00296 00297 // methods 00298 // ------- 00299 Quadratic_program_solution () 00300 : Handle_for<const QP_solver_base<ET>*>(), et0(0) 00301 { 00302 *(this->ptr()) = 0; // unitialized solution 00303 } 00304 00305 Quadratic_program_solution (const QP_solver_base<ET>* s) 00306 : Handle_for<const QP_solver_base<ET>*>(s), et0(0) 00307 {} 00308 00309 Quadratic_program_solution& 00310 operator= (const Quadratic_program_solution& sol) 00311 { 00312 if (this != &sol) { 00313 // delete the old solver if necessary 00314 if (!this->is_shared()) delete *(this->ptr()); 00315 this->Handle_for<const QP_solver_base<ET>*>::operator=(sol); 00316 } 00317 return *this; 00318 } 00319 00320 ~Quadratic_program_solution() 00321 { 00322 if (!this->is_shared()) delete *(this->ptr()); 00323 } 00324 00325 private: 00326 const QP_solver_base<ET>* solver() const 00327 { 00328 return *(this->Ptr()); 00329 } 00330 00331 public: 00332 bool is_void() const 00333 { 00334 return solver() == 0; 00335 } 00336 00337 Quotient<ET> objective_value() const 00338 { 00339 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00340 return solver()->solution(); 00341 } 00342 00343 ET objective_value_numerator() const 00344 { 00345 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00346 return solver()->solution_numerator(); 00347 } 00348 00349 ET objective_value_denominator() const 00350 { 00351 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00352 return solver()->solution_denominator(); 00353 } 00354 00355 Quadratic_program_status status() const 00356 { 00357 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00358 return solver()->status(); 00359 } 00360 00361 bool is_optimal() const 00362 { 00363 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00364 return status() == QP_OPTIMAL; 00365 } 00366 00367 bool is_infeasible() const 00368 { 00369 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00370 return status() == QP_INFEASIBLE; 00371 } 00372 00373 bool is_unbounded() const 00374 { 00375 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00376 return status() == QP_UNBOUNDED; 00377 } 00378 00379 int number_of_iterations() const 00380 { 00381 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00382 return solver()->iterations(); 00383 } 00384 00385 Variable_value_iterator variable_values_begin() const 00386 { 00387 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00388 return solver()->original_variable_values_begin(); 00389 } 00390 00391 Variable_value_iterator variable_values_end() const 00392 { 00393 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00394 return solver()->original_variable_values_end(); 00395 } 00396 00397 Variable_numerator_iterator variable_numerators_begin() const 00398 { 00399 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00400 return solver()->original_variables_numerator_begin(); 00401 } 00402 00403 Variable_numerator_iterator variable_numerators_end() const 00404 { 00405 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00406 return solver()->original_variables_numerator_end(); 00407 } 00408 00409 const ET& variables_common_denominator() const 00410 { 00411 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00412 return solver()->variables_common_denominator(); 00413 } 00414 00415 Index_iterator basic_variable_indices_begin() const 00416 { 00417 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00418 return solver()->basic_original_variable_indices_begin(); 00419 } 00420 00421 Index_iterator basic_variable_indices_end() const 00422 { 00423 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00424 return solver()->basic_original_variable_indices_end(); 00425 } 00426 00427 int number_of_basic_variables() const 00428 { 00429 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00430 return solver()->number_of_basic_original_variables(); 00431 } 00432 00433 Index_iterator basic_constraint_indices_begin() const 00434 { 00435 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00436 return solver()->basic_constraint_indices_begin(); 00437 } 00438 00439 Index_iterator basic_constraint_indices_end() const 00440 { 00441 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00442 return solver()->basic_constraint_indices_end(); 00443 } 00444 00445 int number_of_basic_constraints() const 00446 { 00447 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00448 return solver()->number_of_basic_constraints(); 00449 } 00450 00451 Optimality_certificate_numerator_iterator 00452 optimality_certificate_numerators_begin() const 00453 { 00454 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00455 CGAL_qpe_assertion(status() == QP_OPTIMAL); 00456 return solver()->lambda_numerator_begin(); 00457 } 00458 00459 Optimality_certificate_numerator_iterator 00460 optimality_certificate_numerators_end() const 00461 { 00462 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00463 CGAL_qpe_assertion(status() == QP_OPTIMAL); 00464 return solver()->lambda_numerator_end(); 00465 } 00466 00467 Optimality_certificate_iterator 00468 optimality_certificate_begin() const 00469 { 00470 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00471 CGAL_qpe_assertion(status() == QP_OPTIMAL); 00472 return solver()->lambda_begin(); 00473 } 00474 00475 Optimality_certificate_iterator 00476 optimality_certificate_end() const 00477 { 00478 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00479 CGAL_qpe_assertion(status() == QP_OPTIMAL); 00480 return solver()->lambda_end(); 00481 } 00482 00483 // infeasibility 00484 // ------------- 00485 Infeasibility_certificate_iterator 00486 infeasibility_certificate_begin() const 00487 { 00488 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00489 CGAL_qpe_assertion(status() == QP_INFEASIBLE); 00490 return solver()->lambda_numerator_begin(); 00491 } 00492 00493 Infeasibility_certificate_iterator 00494 infeasibility_certificate_end() const 00495 { 00496 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00497 CGAL_qpe_assertion(status() == QP_INFEASIBLE); 00498 return solver()->lambda_numerator_end(); 00499 } 00500 00501 // unboundedness 00502 // ------------- 00503 Unboundedness_certificate_iterator unboundedness_certificate_begin() const 00504 { 00505 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00506 CGAL_qpe_assertion(status() == QP_UNBOUNDED); 00507 return solver()->unbounded_direction_begin(); 00508 } 00509 00510 Unboundedness_certificate_iterator unboundedness_certificate_end() const 00511 { 00512 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00513 CGAL_qpe_assertion(status() == QP_UNBOUNDED); 00514 return solver()->unbounded_direction_end(); 00515 } 00516 00517 private: 00518 ET et0; // 0 00519 00520 // validity 00521 // -------- 00522 00523 // error message returned by failing validation 00524 std::string err_msg; 00525 00526 // the error message is set by the following function 00527 bool error (const std::string& message) 00528 { 00529 err_msg = message; 00530 return false; 00531 } 00532 00533 public: 00534 bool is_valid() const 00535 { 00536 return err_msg.empty(); 00537 } 00538 00539 const std::string& get_error() const 00540 { 00541 return err_msg; 00542 } 00543 00544 // these four methods use the certificates to validate the solution 00545 // of all four program types; in case this fails, the solution becomes 00546 // invalid (and this explains why the methods are non-const) 00547 template <class QuadraticProgram> 00548 bool solves_quadratic_program 00549 (const QuadraticProgram& qp) 00550 { return solves_program(qp, Tag_false(), Tag_false()); } 00551 00552 template <class LinearProgram> 00553 bool solves_linear_program 00554 (const LinearProgram& lp) 00555 { return solves_program(lp, Tag_true(), Tag_false()); } 00556 00557 template <class NonnegativeQuadraticProgram> 00558 bool solves_nonnegative_quadratic_program 00559 (const NonnegativeQuadraticProgram& qp) 00560 { return solves_program(qp, Tag_false(), Tag_true()); } 00561 00562 template <class NonnegativeLinearProgram> 00563 bool solves_nonnegative_linear_program 00564 (const NonnegativeLinearProgram& lp) 00565 { return solves_program(lp, Tag_true(), Tag_true()); } 00566 00567 // helper used by all four validation methods above; see 00568 // QP_solver/QP_solution_impl.h for its implementation 00569 template <class Program, typename Is_linear, typename Is_nonnegative> 00570 bool solves_program (const Program& p, 00571 Is_linear is_linear, Is_nonnegative is_nonnegative); 00572 00573 private: 00574 // helpers used by the previous method 00575 template <typename Program> 00576 bool is_feasible (const Program& p, 00577 typename std::vector<ET>& ax_minus_b, 00578 Tag_true /*is_nonnegative*/); 00579 template <typename Program> 00580 bool is_feasible (const Program& p, 00581 typename std::vector<ET>& ax_minus_b, 00582 Tag_false /*is_nonnegative*/); 00583 00584 template <typename Program> 00585 bool is_optimal_1 (const Program& p); 00586 00587 template <typename Program> 00588 bool is_optimal_2 (const Program& p, 00589 const typename std::vector<ET>& ax_minus_b); 00590 00591 template <typename Program> 00592 bool is_optimal_3 (const Program& p, typename std::vector<ET>& two_Dx, 00593 Tag_true /*is_linear*/, Tag_true /*is_nonnegative*/); 00594 template <typename Program> 00595 bool is_optimal_3 (const Program& p, typename std::vector<ET>& two_Dx, 00596 Tag_false /*is_linear*/, Tag_true /*is_nonnegative*/); 00597 template <typename Program> 00598 bool is_optimal_3 (const Program& p, typename std::vector<ET>& two_Dx, 00599 Tag_true /*is_linear*/, Tag_false /*is_nonnegative*/); 00600 template <typename Program> 00601 bool is_optimal_3 (const Program& p, typename std::vector<ET>& two_Dx, 00602 Tag_false /*is_linear*/, Tag_false /*is_nonnegative*/); 00603 00604 template <typename Program> 00605 bool is_infeasible_1 (const Program& p); 00606 00607 template <typename Program> 00608 bool is_infeasible_2 (const Program& p, 00609 typename std::vector<ET>& lambda_a, 00610 Tag_true /*is_nonnegative*/); 00611 template <typename Program> 00612 bool is_infeasible_2 (const Program& p, 00613 typename std::vector<ET>& lambda_a, 00614 Tag_false /*is_nonnegative*/); 00615 00616 template <typename Program> 00617 bool is_infeasible_3 (const Program& p, 00618 const typename std::vector<ET>& /*lambda_a*/, 00619 Tag_true /*is_nonnegative*/); 00620 template <typename Program> 00621 bool is_infeasible_3 (const Program& p, 00622 const typename std::vector<ET>& lambda_a, 00623 Tag_false /*is_nonnegative*/); 00624 00625 template <typename Program> 00626 bool is_unbounded_1 (const Program& p); 00627 00628 template <typename Program> 00629 bool is_unbounded_2 (const Program& p, Tag_true /*is_nonnegative*/); 00630 template <typename Program> 00631 bool is_unbounded_2 (const Program& p, Tag_false /*is_nonnegative*/); 00632 00633 template <typename Program> 00634 bool is_unbounded_3 (const Program& p, Tag_true /*is_linear*/); 00635 template <typename Program> 00636 bool is_unbounded_3 (const Program& p, Tag_false /*is_linear*/); 00637 00638 template <typename Program> 00639 bool is_value_correct 00640 (const Program& p, typename std::vector<ET>& /*two_Dx*/, 00641 Tag_true /*is_linear*/); 00642 00643 template <typename Program> 00644 bool is_value_correct 00645 (const Program& p, typename std::vector<ET>& two_Dx, 00646 Tag_false /*is_linear*/); 00647 00648 template <typename Program> 00649 bool are_constraints_feasible 00650 (const Program& p, typename std::vector<ET>& ax); 00651 00652 template <typename Program> 00653 bool are_bounds_feasible (const Program& p, Tag_true /*is_nonnegative*/); 00654 template <typename Program> 00655 bool are_bounds_feasible (const Program& p, Tag_false /*is_nonnegative*/); 00656 00657 template <typename Program, typename Z_iterator > 00658 void add_Az 00659 (const Program& p, Z_iterator z, typename std::vector<ET>& v); 00660 00661 template <typename Program, typename Z_iterator > 00662 void add_two_Dz 00663 (const Program& p, Z_iterator z, typename std::vector<ET>& v); 00664 00665 template <typename Program, typename Z_iterator > 00666 void add_zA 00667 (const Program& p, Z_iterator z, typename std::vector<ET>& v); 00668 00669 template <typename Program> 00670 void add_c 00671 (const Program& p, typename std::vector<ET>& v); 00672 00673 }; 00674 00675 // output 00676 template <typename ET> 00677 std::ostream& operator<< 00678 (std::ostream& o, const Quadratic_program_solution<ET>& s) 00679 { 00680 o << "status: "; 00681 switch (s.status()) { 00682 case QP_INFEASIBLE: 00683 return o << "INFEASIBLE\n"; 00684 case QP_UNBOUNDED: 00685 return o << "UNBOUNDED\n"; 00686 case QP_OPTIMAL: 00687 o << "OPTIMAL\n"; 00688 break; 00689 default: 00690 CGAL_qpe_assertion(false); 00691 } 00692 o << "objective value: " << s.objective_value() << "\n"; 00693 o << "variable values:\n"; 00694 int j=0; 00695 for ( typename Quadratic_program_solution<ET>::Variable_value_iterator 00696 it = s.variable_values_begin(); 00697 it < s.variable_values_end(); ++it, ++j) 00698 o << " " << j << ": " << *it << "\n"; 00699 return o; 00700 } 00701 00702 // Details 00703 namespace QP_solution_detail { 00704 // Quotient_normalizer 00705 // ------------------- 00706 template < typename ET> 00707 class Quotient_normalizer { 00708 public: 00709 typedef CGAL::Quotient<ET> result_type; 00710 00711 private: 00712 typedef CGAL::Algebraic_structure_traits<ET> AST; 00713 typedef typename AST::Algebraic_category Category; 00714 00715 public: 00716 typedef CGAL::Boolean_tag< 00717 CGAL::is_same_or_derived<CGAL::Unique_factorization_domain_tag,Category>::value> 00718 Has_gcd; 00719 00720 typedef CGAL::Boolean_tag< 00721 CGAL::is_same_or_derived<CGAL::Integral_domain_tag,Category>::value> 00722 Has_exact_division; 00723 00724 CGAL::Quotient<ET> normalize 00725 (const CGAL::Quotient<ET>& q, 00726 Tag_true /*has_gcd*/, 00727 Tag_true /*has_exact_division*/) const 00728 { 00729 if (CGAL::is_zero (q.numerator())) 00730 return CGAL::Quotient<ET>(ET(0), ET(1)); 00731 ET gcd = CGAL::gcd (q.numerator(), q.denominator()); 00732 return CGAL::Quotient<ET> 00733 (CGAL::integral_division (q.numerator(), gcd), 00734 CGAL::integral_division (q.denominator(), gcd)); 00735 } 00736 00737 CGAL::Quotient<ET> normalize 00738 (const CGAL::Quotient<ET>& q, 00739 Tag_true /*has_gcd*/, 00740 Tag_false /*has_exact_division*/) const 00741 { 00742 return q; 00743 } 00744 00745 CGAL::Quotient<ET> normalize 00746 (const CGAL::Quotient<ET>& q, 00747 Tag_false /*has_gcd*/, 00748 Tag_true /*has_exact_division*/) const 00749 { 00750 return q; 00751 } 00752 00753 CGAL::Quotient<ET> normalize 00754 (const CGAL::Quotient<ET>& q, 00755 Tag_false /*has_gcd*/, 00756 Tag_false /*has_exact_division*/) const 00757 { 00758 return q; 00759 } 00760 00761 CGAL::Quotient<ET> operator() (const CGAL::Quotient<ET>& q) const 00762 { 00763 return normalize (q, Has_gcd(), Has_exact_division()); 00764 } 00765 }; 00766 00767 // Value_by_index 00768 // -------------- 00769 template < typename ET> 00770 class Value_by_index : public std::unary_function< int, ET> 00771 { 00772 public: 00773 typedef QP_solver_base<ET> QP; 00774 typedef ET result_type; 00775 00776 Value_by_index(const QP* solver) 00777 : s (solver) 00778 {} 00779 00780 // returns value * denominator 00781 result_type operator () ( int i) const 00782 { 00783 return s->variable_numerator_value(i); 00784 } 00785 00786 const QP* s; 00787 }; 00788 00789 // Unbounded_direction_by_index 00790 // ---------------------------- 00791 template < typename ET> 00792 class Unbounded_direction_by_index : public std::unary_function< int, ET> 00793 { 00794 public: 00795 typedef QP_solver_base<ET> QP; 00796 typedef ET result_type; 00797 00798 Unbounded_direction_by_index(const QP* solver) 00799 : s (solver) 00800 {} 00801 00802 result_type operator () ( int i) const 00803 { 00804 return s->unbounded_direction_value(i); 00805 } 00806 00807 const QP* s; 00808 }; 00809 00810 // Lambda_by_index 00811 // --------------- 00812 template < typename ET> 00813 class Lambda_by_index : public std::unary_function< int, ET> 00814 { 00815 public: 00816 typedef QP_solver_base<ET> QP; 00817 typedef ET result_type; 00818 00819 Lambda_by_index(const QP* solver) 00820 : s (solver) 00821 {} 00822 00823 result_type operator () ( int i) const 00824 { 00825 return s->lambda_numerator(i); 00826 } 00827 00828 const QP* s; 00829 }; 00830 } 00831 CGAL_END_NAMESPACE 00832 00833 #include <CGAL/QP_solver/QP_solution_impl.h> 00834 00835 #endif// CGAL_QP_SOLUTION_H