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_functions_impl.h $ 00015 // $Id: QP_functions_impl.h 46451 2008-10-23 14:31:10Z gaertner $ 00016 // 00017 // 00018 // Author(s) : Bernd Gaertner <gaertner@inf.ethz.ch> 00019 #ifndef CGAL_QP_FUNCTIONS_IMPL_H 00020 #define CGAL_QP_FUNCTIONS_IMPL_H 00021 00022 #include <iostream> 00023 #include <fstream> 00024 #include <CGAL/iterator.h> 00025 #include <CGAL/QP_solver/QP_solver.h> 00026 #include <CGAL/QP_models.h> 00027 #include <CGAL/QP_solution.h> 00028 00029 CGAL_BEGIN_NAMESPACE 00030 00031 namespace QP_functions_detail { 00032 // test whether the system is of the form A x == b (equations only) 00033 template <typename R> 00034 bool is_in_equational_form (const R& r) 00035 { 00036 typename R::R_iterator it = r.get_r(); 00037 typename R::R_iterator end = it + r.get_m(); 00038 for (; it < end; ++it) 00039 if (*it != CGAL::EQUAL) return false; 00040 return true; 00041 } 00042 00043 // test whether the row vectors of A that correpsond to equations 00044 // are linearly independent; this is done using type ET. The value 00045 // type of LinearInequalitySystem must be convertible to ET 00046 template <class Ar, class ET> 00047 bool has_linearly_independent_equations 00048 (const Ar& ar, const ET& dummy) { 00049 // we solve the following auxiliary LP, using exact type ET: 00050 // -------- 00051 // min 0 00052 // A x r 0 00053 // x >= 0 00054 // -------- 00055 // Then A has linearly independent equations if and only if all 00056 // artificials have left the basis after phase I; the QP_solver 00057 // diagnostics tells us this 00058 // 00059 // auxiliary LP type 00060 typedef typename 00061 std::iterator_traits<typename Ar::C_iterator>::value_type C_value; 00062 typedef typename 00063 std::iterator_traits<typename Ar::B_iterator>::value_type B_value; 00064 typedef Const_oneset_iterator <C_value> C_iterator; 00065 typedef Const_oneset_iterator <B_value> B_iterator; 00066 typedef Nonnegative_linear_program_from_iterators 00067 <typename Ar::A_iterator, B_iterator, 00068 typename Ar::R_iterator, C_iterator> LP; 00069 00070 // auxiliary LP 00071 LP lp (ar.get_n(), ar.get_m(), ar.get_a(), B_iterator(0), ar.get_r(), C_iterator(0)); 00072 00073 // solver Tags 00074 typedef QP_solver_impl::QP_tags< 00075 Tag_true, // Is_linear 00076 Tag_true> // Is_nonnegative 00077 Tags; 00078 00079 // solver type 00080 typedef QP_solver<LP, ET, Tags> Solver; 00081 00082 // now solve auxiliary LP and compute predicate value 00083 Solver solver (lp); 00084 return !solver.diagnostics.redundant_equations; 00085 } 00086 00087 // helper for MPS output: BOUNDS 00088 template <typename P> 00089 void print_bounds 00090 (std::ostream& , const P& , 00091 CGAL::Tag_true /*is_nonnegative*/) 00092 { 00093 // nop (default bounds are nonnegative) 00094 } 00095 00096 // helper for MPS output: BOUNDS 00097 template <typename P> 00098 void print_bounds 00099 (std::ostream& out, const P& p, 00100 CGAL::Tag_false /*is_nonnegative*/) 00101 { 00102 typename P::FL_iterator fl = p.get_fl(); 00103 typename P::FU_iterator fu = p.get_fu(); 00104 typename P::L_iterator l = p.get_l(); 00105 typename P::U_iterator u = p.get_u(); 00106 int n = p.get_n(); 00107 out << "BOUNDS\n"; 00108 for (int j=0; j<n; ++j, ++fl, ++l, ++fu, ++u) { 00109 if (!*fl || !CGAL::is_zero(*l)) { 00110 if (*fl) 00111 out << " LO BND x" << j << " " << *l << "\n"; 00112 else 00113 out << " MI BND x" << j << "\n"; 00114 } 00115 if (*fu) 00116 out << " UP BND x" << j << " " << *u << "\n"; 00117 } 00118 } 00119 00120 // helper for MPS output: DMATRIX/QMATRIX 00121 template <typename P> 00122 void print_qmatrix 00123 (std::ostream& , const P& , 00124 CGAL::Tag_true /*is_linear*/) 00125 { 00126 // nop 00127 } 00128 00129 // helper for MPS output: DMATRIX/QMATRIX 00130 template <typename P> 00131 void print_qmatrix 00132 (std::ostream& out, const P& p, 00133 CGAL::Tag_false /*is_linear*/) 00134 { 00135 typename P::D_iterator it = p.get_d(); 00136 int n = p.get_n(); 00137 bool empty_D = true; 00138 for (int i=0; i<n; ++i, ++it) { 00139 // handle only entries on/below diagonal 00140 for (int j=0; j<i+1; ++j) 00141 if (!CGAL::is_zero(*(*it + j))) { 00142 if (empty_D) { 00143 // first time we see a nonzero entry 00144 out << "QMATRIX\n"; 00145 empty_D = false; 00146 } 00147 out << " x" << i << " x" << j << " " << *(*it + j) << "\n"; 00148 // QMATRIX format prescribes symmetric matrix 00149 if (i != j) 00150 out << " x" << j << " x" << i << " " << *(*it + j) << "\n"; 00151 } 00152 } 00153 } 00154 00155 // check whether the two qp's have the same data; this is the case iff 00156 // they agree in n, m, a, b, r, fl, l, fu, u, d, c, c0 00157 // PRE: qp1, qp2 have the same internal number type 00158 template <typename Quadratic_program1, typename Quadratic_program2> 00159 bool are_equal_qp 00160 (const Quadratic_program1 &qp1, const Quadratic_program2 &qp2) 00161 { 00162 bool return_val = true; 00163 // check n 00164 if (qp1.get_n() != qp2.get_n()) { 00165 std::cerr << "Equality test fails with n: " 00166 << qp1.get_n() << " vs. " << qp2.get_n() << std::endl; 00167 return false; // wildly wrong, abort now 00168 } 00169 // check m 00170 if (qp1.get_m() != qp2.get_m()) { 00171 std::cerr << "Equality test fails with m: " 00172 << qp1.get_m() << " vs. " << qp2.get_m() << std::endl; 00173 return false; // wildly wrong, abort now 00174 } 00175 int n = qp1.get_n(); 00176 int m = qp1.get_m(); 00177 // check A 00178 typename Quadratic_program1::A_iterator a1 = qp1.get_a(); 00179 typename Quadratic_program2::A_iterator a2 = qp2.get_a(); 00180 for (int j=0; j<n; ++j, ++a1, ++a2) 00181 for (int i=0; i<m; ++i) 00182 if (*((*a1)+i) != *((*a2)+i)) { 00183 std::cerr << "Equality test fails with A[" 00184 << j << "][" << i << "]: " 00185 << *((*a1)+i) << " vs. " << *((*a2)+i) << std::endl; 00186 return_val = false; 00187 } 00188 // check b 00189 typename Quadratic_program1::B_iterator b1 = qp1.get_b(); 00190 typename Quadratic_program2::B_iterator b2 = qp2.get_b(); 00191 for (int i=0; i<m; ++i, ++b1, ++b2) 00192 if (*b1 != *b2) { 00193 std::cerr << "Equality test fails with b[" << i << "]: " 00194 << *b1 << " vs. " << *b2 << std::endl; 00195 return_val = false; 00196 } 00197 // check r 00198 typename Quadratic_program1::R_iterator r1 = qp1.get_r(); 00199 typename Quadratic_program2::R_iterator r2 = qp2.get_r(); 00200 for (int i=0; i<m; ++i, ++r1, ++r2) 00201 if (*r1 != *r2) { 00202 std::cerr << "Equality test fails with r[" << i << "]: " 00203 << *r1 << " vs. " << *r2 << std::endl; 00204 return_val = false; 00205 } 00206 // check fl, l 00207 typename Quadratic_program1::FL_iterator fl1 = qp1.get_fl(); 00208 typename Quadratic_program2::FL_iterator fl2 = qp2.get_fl(); 00209 typename Quadratic_program1::L_iterator l1 = qp1.get_l(); 00210 typename Quadratic_program2::L_iterator l2 = qp2.get_l(); 00211 for (int j=0; j<n; ++j, ++fl1, ++fl2, ++l1, ++l2) { 00212 if (*fl1 != *fl2) { 00213 std::cerr << "Equality test fails with fl[" << j << "]: " 00214 << *fl1 << " vs. " << *fl2 << std::endl; 00215 return_val = false; 00216 } 00217 if ((*fl1 == true) && (*l1 != *l2)) { 00218 std::cerr << "Equality test fails with l[" << j << "]: " 00219 << *l1 << " vs. " << *l2 << std::endl; 00220 return_val = false; 00221 } 00222 } 00223 00224 // check fu, u 00225 typename Quadratic_program1::FU_iterator fu1 = qp1.get_fu(); 00226 typename Quadratic_program2::FU_iterator fu2 = qp2.get_fu(); 00227 typename Quadratic_program1::U_iterator u1 = qp1.get_u(); 00228 typename Quadratic_program2::U_iterator u2 = qp2.get_u(); 00229 for (int j=0; j<n; ++j, ++fu1, ++fu2, ++u1, ++u2) { 00230 if (*fu1 != *fu2) { 00231 std::cerr << "Equality test fails with fu[" << j << "]: " 00232 << *fu1 << " vs. " << *fu2 << std::endl; 00233 return_val = false; 00234 } 00235 if ((*fu1 == true) && (*u1 != *u2)) { 00236 std::cerr << "Equality test fails with u[" << j << "]: " 00237 << *u1 << " vs. " << *u2 << std::endl; 00238 return_val = false; 00239 } 00240 } 00241 // check d 00242 typename Quadratic_program1::D_iterator d1 = qp1.get_d(); 00243 typename Quadratic_program2::D_iterator d2 = qp2.get_d(); 00244 for (int i=0; i<n; ++i, ++d1, ++d2) 00245 for (int j=0; j<i+1; ++j) // only access entries on/below diagonal 00246 if (*((*d1)+j) != *((*d2)+j)) { 00247 std::cerr << "Equality test fails with D[" 00248 << i << "][" << j << "]: " 00249 << *((*d1)+j) << " vs. " << *((*d2)+j) << std::endl; 00250 return_val = false; 00251 } 00252 // check c 00253 typename Quadratic_program1::C_iterator c1 = qp1.get_c(); 00254 typename Quadratic_program2::C_iterator c2 = qp2.get_c(); 00255 for (int j=0; j<n; ++j, ++c1, ++c2) 00256 if (*c1 != *c2) { 00257 std::cerr << "Equality test fails with c[" << j << "]: " 00258 << *c1 << " vs. " << *c2 << std::endl; 00259 return_val = false; 00260 } 00261 // check c0 00262 typename Quadratic_program1::C_entry c01 = qp1.get_c0(); 00263 typename Quadratic_program2::C_entry c02 = qp2.get_c0(); 00264 if (c01 != c02) { 00265 std::cerr << "Equality test fails with c0: " 00266 << c01 << " vs. " << c02 << std::endl; 00267 return_val = false; 00268 } 00269 return return_val; 00270 } 00271 00272 template <typename P, typename Is_linear, typename Is_nonnegative> 00273 void print_program 00274 (std::ostream& out, const P& p, 00275 const std::string& problem_name, 00276 Is_linear is_linear, 00277 Is_nonnegative is_nonnegative) 00278 { 00279 // NAME: 00280 out << "NAME " << problem_name << "\n"; 00281 00282 int n = p.get_n(); 00283 int m = p.get_m(); 00284 00285 // ROWS section: 00286 typename P::R_iterator r = p.get_r(); 00287 out << "ROWS\n" 00288 << " N obj\n"; // for the objective function 00289 for (int i=0; i<m; ++i, ++r) { 00290 if (*r == CGAL::SMALLER) 00291 out << " L"; 00292 else if (*r == CGAL::EQUAL) 00293 out << " E"; 00294 else if (*r == CGAL::LARGER) 00295 out << " G"; 00296 else 00297 CGAL_qpe_assertion_msg(false, "incorrect row-type"); 00298 out << " c" << i << "\n"; // row name is CI 00299 } 00300 00301 // COLUMNS section: 00302 typename P::A_iterator a = p.get_a(); 00303 typename P::C_iterator c = p.get_c(); 00304 typedef 00305 typename std::iterator_traits<typename P::C_iterator>::value_type IT; 00306 out << "COLUMNS\n"; 00307 for (int j=0; j<n; ++j, ++c, ++a) { 00308 // make sure that variable appears here even if it has only 00309 // zero coefficients 00310 bool written = false; 00311 if (!CGAL_NTS is_zero (*c)) { 00312 out << " x" << j << " obj " << *c << "\n"; 00313 written = true; 00314 } 00315 for (int i=0; i<m; ++i) { 00316 if (!CGAL_NTS is_zero (*((*a)+i))) { 00317 out << " x" << j << " c" << i << " " << *((*a)+i) << "\n"; 00318 written = true; 00319 } 00320 } 00321 if (!written) 00322 out << " x" << j << " obj " << IT(0) << "\n"; 00323 } 00324 00325 // RHS section: 00326 typename P::B_iterator b = p.get_b(); 00327 out << "RHS\n"; 00328 if (!CGAL_NTS is_zero (p.get_c0())) 00329 out << " rhs obj " << -p.get_c0() << "\n"; 00330 for (int i=0; i<m; ++i, ++b) 00331 if (!CGAL_NTS is_zero (*b)) 00332 out << " rhs c" << i << " " << *b << "\n"; 00333 00334 // BOUNDS section: 00335 QP_functions_detail::print_bounds (out, p, is_nonnegative); 00336 00337 // QMATRIX section: 00338 QP_functions_detail::print_qmatrix (out, p, is_linear); 00339 00340 // output end: 00341 out << "ENDATA\n"; 00342 } 00343 00344 template <typename Program, typename ET, 00345 typename Is_linear,typename Is_nonnegative > 00346 Quadratic_program_solution<ET> solve_program 00347 (const Program &p, const ET&, 00348 Is_linear, 00349 Is_nonnegative, 00350 const Quadratic_program_options& options) 00351 { 00352 typedef QP_solver< 00353 Program, ET, 00354 QP_solver_impl::QP_tags<Is_linear, Is_nonnegative> > 00355 Solver; 00356 const Solver* s = new Solver(p, options); 00357 Quadratic_program_solution<ET> solution(s); 00358 if (options.get_auto_validation()) { 00359 // validate solution 00360 if (options.get_verbosity() > 0) 00361 std::cout << "Validating solution...\n"; 00362 if (!solution.solves_program(p, Is_linear(), Is_nonnegative())) { 00363 // write log file 00364 std::ofstream out("QP_solver.log"); 00365 out << "Error: Program solution is invalid\n" 00366 << " (error message: " << solution.get_error() << ")\n" 00367 << "------------------\n" 00368 << "Solution function:\n" 00369 << "------------------\n"; 00370 print_solution_function (out, Is_linear(), Is_nonnegative()); 00371 out << "\n" 00372 << "--------\n" 00373 << "Program:\n" 00374 << "--------\n"; 00375 print_program (out, p, "unsolved", Is_linear(), Is_nonnegative()); 00376 out << "--------\n" 00377 << "Options:\n" 00378 << "--------\n" 00379 << options << std::endl; 00380 // print warning 00381 std::cerr 00382 << "Error: Program solution is invalid " 00383 << "(see QP_solver.log for details)" << std::endl; 00384 } 00385 } 00386 return solution; 00387 00388 } 00389 } 00390 00391 template <typename QuadraticProgram, typename ET> 00392 Quadratic_program_solution<ET> solve_quadratic_program 00393 (const QuadraticProgram &qp, const ET& dummy, 00394 const Quadratic_program_options& options) 00395 { 00396 return QP_functions_detail:: 00397 solve_program(qp, dummy, Tag_false(), Tag_false(), options); 00398 } 00399 00400 template <typename NonnegativeQuadraticProgram, typename ET> 00401 Quadratic_program_solution<ET> solve_nonnegative_quadratic_program 00402 (const NonnegativeQuadraticProgram &qp, const ET& dummy, 00403 const Quadratic_program_options& options) 00404 { 00405 return QP_functions_detail:: 00406 solve_program(qp, dummy, Tag_false(), Tag_true(), options); 00407 } 00408 00409 template <typename LinearProgram, typename ET> 00410 Quadratic_program_solution<ET> solve_linear_program 00411 (const LinearProgram &lp, const ET& dummy, 00412 const Quadratic_program_options& options) 00413 { 00414 return QP_functions_detail:: 00415 solve_program(lp, dummy, Tag_true(), Tag_false(), options); 00416 } 00417 00418 template <typename NonnegativeLinearProgram, typename ET> 00419 Quadratic_program_solution<ET> solve_nonnegative_linear_program 00420 (const NonnegativeLinearProgram &lp, const ET& dummy, 00421 const Quadratic_program_options& options) 00422 { 00423 return QP_functions_detail:: 00424 solve_program(lp, dummy, Tag_true(), Tag_true(), options); 00425 } 00426 00427 CGAL_END_NAMESPACE 00428 00429 #endif // CGAL_QP_FUNCTIONS_IMPL_H