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://gaertner@scm.gforge.inria.fr/svn/cgal/trunk/QP_solver/include/CGAL/QP_solver/QP_solution_impl.h $ 00015 // $Id: QP_solution_impl.h 38416 2007-04-23 09:12:34Z gaertner $ 00016 // 00017 // 00018 // Author(s) : Bernd Gaertner <gaertner@inf.ethz.ch> 00019 #ifndef CGAL_QP_SOLUTION_IMPL_H 00020 #define CGAL_QP_SOLUTION_IMPL_H 00021 00022 #include<iterator> 00023 00024 CGAL_BEGIN_NAMESPACE 00025 // checks whether the solution actually solves program p 00026 // this performs exactly the checks described in the doc 00027 // of the class Quadratic_program_solution 00028 // ----------------------------------------------------- 00029 template <typename ET> 00030 template <class Program, typename Is_linear, typename Is_nonnegative> 00031 bool Quadratic_program_solution<ET>::solves_program 00032 (const Program& p, 00033 Is_linear is_linear, Is_nonnegative is_nonnegative) 00034 { 00035 CGAL_qpe_assertion_msg(!is_void(), "Solution not initialized"); 00036 00037 // first check whether the dimensions agree 00038 int n = variable_numerators_end() - variable_numerators_begin(); 00039 if (n != p.get_n()) 00040 return error ("wrong number of variables"); 00041 int m = solver()->lambda_end() - solver()->lambda_begin(); 00042 if (m != p.get_m()) 00043 return error("wrong number of constraints"); 00044 00045 // now distinguish between the three possible cases 00046 switch (status()) { 00047 case QP_OPTIMAL: { 00048 std::vector<ET> ax_minus_b (m, et0); // d(Ax-b) 00049 std::vector<ET> two_Dx (n, et0); // d(2Dx) 00050 return 00051 // the following fills ax_minus_b... 00052 is_feasible (p, ax_minus_b, is_nonnegative) && // feasible? 00053 // the following fills two_Dx... 00054 is_value_correct (p, two_Dx, is_linear) && // obj. value? 00055 is_optimal_1 (p) && // condition 1? 00056 // ...and the following uses ax_minus_b 00057 is_optimal_2 (p, ax_minus_b) && // condition 2? 00058 // ...and the following uses two_Dx 00059 is_optimal_3 (p, two_Dx, is_linear, is_nonnegative); // condition 3? 00060 } 00061 case QP_INFEASIBLE: { 00062 std::vector<ET> lambda_a (n, et0); // lambda^TA 00063 return 00064 is_infeasible_1 (p) && // condition 1? 00065 // the following fills lambda_a... 00066 is_infeasible_2 (p, lambda_a, is_nonnegative) && // condition 2? 00067 // ...and the following uses lambda_a 00068 is_infeasible_3 (p, lambda_a, is_nonnegative); // condition 3? 00069 } 00070 case QP_UNBOUNDED: { 00071 std::vector<ET> ax_minus_b (m, et0); 00072 return 00073 is_feasible (p, ax_minus_b, is_nonnegative) && // feasible? 00074 is_unbounded_1 (p) && // condition 1? 00075 is_unbounded_2 (p, is_nonnegative) && // condition 2? 00076 is_unbounded_3 (p, is_linear); // condition 3? 00077 } 00078 default: 00079 return error ("solution in undefined state"); 00080 } 00081 } 00082 00083 // tests whether Ax ~ b is satisfied and computes d(Ax-b); 00084 // precondition: ax_minus_b has length m and is zero 00085 // ------------------------------------------------------ 00086 template <typename ET> 00087 template <typename Program> 00088 bool Quadratic_program_solution<ET>::are_constraints_feasible 00089 (const Program& p, 00090 typename std::vector<ET>& ax_minus_b) 00091 { 00092 typedef typename Program::B_iterator B_column_iterator; 00093 typedef typename Program::R_iterator R_column_iterator; 00094 00095 // fill ax_minus_b (length m) 00096 int m = p.get_m(); 00097 B_column_iterator b = p.get_b(); 00098 add_Az (p, variable_numerators_begin(), ax_minus_b); // d(Ax) 00099 ET d = variables_common_denominator(); 00100 for (int i=0; i<m; ++i, ++b) 00101 ax_minus_b[i] -= ET (*b) * d; // d(Ax-b) 00102 00103 // now validate constraints 00104 if (d <= et0) 00105 return error ("common variable denominator is negative"); 00106 R_column_iterator r = p.get_r(); 00107 for (int i=0; i<m; ++i, ++r) 00108 switch (*r) { 00109 case SMALLER: // <= 00110 if (ax_minus_b[i] > et0) return error("inequality (<=) violated"); 00111 break; 00112 case EQUAL: // == 00113 if (ax_minus_b[i] != et0) return error("inequality (==) violated"); 00114 break; 00115 case LARGER: // >= 00116 if (ax_minus_b[i] < et0) return error("inequality (>=) violated"); 00117 break; 00118 } 00119 return true; 00120 } 00121 00122 // tests whether Ax ~ b, x >= 0 is satisfied and computes d(Ax-b) 00123 // precondition: ax_minus_b has length m and is zero 00124 // -------------------------------------------------------------- 00125 template <typename ET> 00126 template <typename Program> 00127 bool Quadratic_program_solution<ET>::is_feasible 00128 (const Program& p, 00129 typename std::vector<ET>& ax_minus_b, 00130 Tag_true /*is_nonnegative*/) 00131 { 00132 // test Ax ~ b 00133 if (!are_constraints_feasible (p, ax_minus_b)) return false; 00134 // test x >= 0 00135 if (variables_common_denominator() <= et0) 00136 return error ("common variable denominator is negative"); 00137 for (Variable_numerator_iterator v = variable_numerators_begin(); 00138 v < variable_numerators_end(); ++v) 00139 if (*v < et0) return error("bound (>= 0) violated"); 00140 return true; 00141 } 00142 00143 // tests whether Ax ~ b, l <= x <= u is satisfied and computes d(Ax-b) 00144 // precondition: ax_minus_b has length m and is zero 00145 // ------------------------------------------------------------------- 00146 template <typename ET> 00147 template <typename Program> 00148 bool Quadratic_program_solution<ET>::is_feasible 00149 (const Program& p, 00150 typename std::vector<ET>& ax_minus_b, 00151 Tag_false /*is_nonnegative*/) 00152 { 00153 // test Ax ~ b 00154 if (!are_constraints_feasible (p, ax_minus_b)) return false; // (*) 00155 // test l <= x <= u 00156 ET d = variables_common_denominator(); 00157 if (d <= et0) 00158 return error ("common variable denominator is negative"); 00159 typedef typename Program::FL_iterator FL_column_iterator; 00160 typedef typename Program::L_iterator L_column_iterator; 00161 typedef typename Program::FU_iterator FU_column_iterator; 00162 typedef typename Program::U_iterator U_column_iterator; 00163 FL_column_iterator fl = p.get_fl(); 00164 FU_column_iterator fu = p.get_fu(); 00165 L_column_iterator l = p.get_l(); 00166 U_column_iterator u = p.get_u(); 00167 for (Variable_numerator_iterator v = variable_numerators_begin(); 00168 v < variable_numerators_end(); ++v, ++fl, ++l, ++fu, ++u) { 00169 if (*fl && (*v < ET(*l) * d)) 00170 return error("bound (>=l) violated"); 00171 if (*fu && (*v > ET(*u) * d)) 00172 return error("bound (<=u) violated"); 00173 } 00174 return true; 00175 } 00176 00177 // checks whether constraint type <= (>=) implies lambda >= (<=) 0 00178 // --------------------------------------------------------------- 00179 template <typename ET> 00180 template <typename Program> 00181 bool Quadratic_program_solution<ET>::is_optimal_1 00182 (const Program& p) 00183 { 00184 if (variables_common_denominator() <= et0) 00185 return error ("wrong sign of optimality certificate"); 00186 typedef typename Program::R_iterator R_column_iterator; 00187 int m = p.get_m(); 00188 R_column_iterator r = p.get_r(); 00189 Optimality_certificate_numerator_iterator opt = 00190 optimality_certificate_numerators_begin(); 00191 for (int i=0; i<m; ++i, ++r, ++opt) { 00192 if (*r == SMALLER && *opt < et0) 00193 return error("constraint (<=) with lambda < 0"); 00194 if (*r == LARGER && *opt > et0) 00195 return error("constraint (>=) with lambda > 0"); 00196 } 00197 return true; 00198 } 00199 00200 // checks whether constraint type <= (>=) implies lambda >= (<=) 0 00201 // --------------------------------------------------------------- 00202 template <typename ET> 00203 template <typename Program> 00204 bool Quadratic_program_solution<ET>::is_infeasible_1 00205 (const Program& p) 00206 { 00207 int m = p.get_m(); 00208 typedef typename Program::R_iterator R_column_iterator; 00209 R_column_iterator r = p.get_r(); 00210 Infeasibility_certificate_iterator inf = infeasibility_certificate_begin(); 00211 for (int i=0; i<m; ++i, ++r, ++inf) { 00212 if (*r == SMALLER && *inf < et0) 00213 return error("constraint (<=) with lambda < 0"); 00214 if (*r == LARGER && *inf > et0) 00215 return error("constraint (>=) with lambda > 0"); 00216 } 00217 return true; 00218 } 00219 00220 // checks whether lambda and Ax-b are complementary 00221 // ------------------------------------------------ 00222 template <typename ET> 00223 template <typename Program> 00224 bool Quadratic_program_solution<ET>::is_optimal_2 00225 (const Program& p, 00226 const typename std::vector<ET>& ax_minus_b) 00227 { 00228 int m = p.get_m(); 00229 Optimality_certificate_numerator_iterator opt = 00230 optimality_certificate_numerators_begin(); 00231 for (int i=0; i<m; ++i, ++opt) 00232 if (*opt != et0 && ax_minus_b[i] != et0) 00233 return error("lambda and Ax-b are not complementary"); 00234 return true; 00235 } 00236 00237 // checks whether (c^T + lambda^TA)_j >= (==) 0 if x_j = (>) 0 00238 // ----------------------------------------------------------- 00239 template <typename ET> 00240 template <typename Program> 00241 bool Quadratic_program_solution<ET>::is_optimal_3 00242 (const Program& p, std::vector<ET>& q, 00243 Tag_true /*is_linear*/, Tag_true /*is_nonnegative*/) 00244 { 00245 int n = p.get_n(); // q = 0 00246 add_c (p, q); // d c^T 00247 add_zA (p, optimality_certificate_numerators_begin(), q); // d lambda^T A 00248 Variable_numerator_iterator v = variable_numerators_begin(); 00249 for (int j=0; j<n; ++j, ++v) { 00250 if (q[j] < et0) 00251 return error("some (c^T + lambda^TA)_j is negative"); 00252 if (*v > et0 && q[j] > et0) 00253 return error("(c^T + lambda^TA) and x are not complementary"); 00254 } 00255 return true; 00256 } 00257 00258 // checks whether (c^T + lambda^TA + 2x^TD)_j >= (==) 0 if x_j = (>) 0 00259 // ------------------------------------------------------------------- 00260 template <typename ET> 00261 template <typename Program> 00262 bool Quadratic_program_solution<ET>::is_optimal_3 00263 (const Program& p, std::vector<ET>& q, 00264 Tag_false /*is_linear*/, Tag_true /*is_nonnegative*/) 00265 { 00266 int n = p.get_n(); // q = 2Dx 00267 add_c (p, q); // d * c^T 00268 add_zA (p, optimality_certificate_numerators_begin(), q); // d * lambda^T A 00269 Variable_numerator_iterator v = variable_numerators_begin(); 00270 for (int j=0; j<n; ++j, ++v) { 00271 if (q[j] < et0) 00272 return error("some (c^T + lambda^TA + 2Dx)_j is negative"); 00273 if (*v > et0 && q[j] > et0) 00274 return error("(c^T + lambda^TA + 2Dx) and x are not complementary"); 00275 } 00276 return true; 00277 } 00278 00279 // checks whether (c^T + lambda^TA )_j >= (==, <=) 0 if 00280 // x_j = l_j < u_j (l_j < x_j < u_j, l_j < u_j = x_j) 00281 // --------------------------------------------------- 00282 template <typename ET> 00283 template <typename Program> 00284 bool Quadratic_program_solution<ET>::is_optimal_3 00285 (const Program& p, std::vector<ET>& q, 00286 Tag_true /*is_linear*/, Tag_false /*is_nonnegative*/) 00287 { 00288 int n = p.get_n(); // q = 0 00289 add_c (p, q); // d * c^T 00290 add_zA (p, optimality_certificate_numerators_begin(), q); // d * lambda^T A 00291 typedef typename Program::FL_iterator FL_column_iterator; 00292 typedef typename Program::L_iterator L_column_iterator; 00293 typedef typename Program::FU_iterator FU_column_iterator; 00294 typedef typename Program::U_iterator U_column_iterator; 00295 FL_column_iterator fl = p.get_fl(); 00296 FU_column_iterator fu = p.get_fu(); 00297 L_column_iterator l = p.get_l(); 00298 U_column_iterator u = p.get_u(); 00299 Variable_numerator_iterator v = variable_numerators_begin(); 00300 ET d = variables_common_denominator(); 00301 if (d <= et0) 00302 return error ("common variable denominator is negative"); 00303 for (int j=0; j<n; ++j, ++v, ++fl, ++l, ++fu, ++u) { 00304 if (*fl && *v == ET(*l) * d && (!*fu || *l < *u) && q[j] < et0) 00305 return error("x_j = l_j < u_j but (c^T + lambda^TA )_j < 0"); 00306 if ( (!*fl || *v > ET(*l) * d) && (!*fu || *v < ET(*u) * d) && q[j] != et0) 00307 return error("l_j < x_j < u_j but (c^T + lambda^TA )_j != 0"); 00308 if (*fu && *v == ET(*u) * d && (!*fl || *l < *u) && q[j] > et0) 00309 return error("x_j = u_j > l_j but (c^T + lambda^TA )_j > 0"); 00310 } 00311 return true; 00312 } 00313 00314 // checks whether (c^T + lambda^TA +2x^*D)_j >= (==, <=) 0 if 00315 // x_j = l_j < u_j (l_j < x_j < u_j, l_j < u_j = x_j) 00316 // ---------------------------------------------------------- 00317 template <typename ET> 00318 template <typename Program> 00319 bool Quadratic_program_solution<ET>::is_optimal_3 00320 (const Program& p, std::vector<ET>& q, 00321 Tag_false /*is_linear*/, Tag_false /*is_nonnegative*/) 00322 { 00323 int n = p.get_n(); // q = d * 2Dx 00324 add_c (p, q); // d * c^T 00325 add_zA (p, optimality_certificate_numerators_begin(), q); // d * lambda^T A 00326 typedef typename Program::FL_iterator FL_column_iterator; 00327 typedef typename Program::L_iterator L_column_iterator; 00328 typedef typename Program::FU_iterator FU_column_iterator; 00329 typedef typename Program::U_iterator U_column_iterator; 00330 FL_column_iterator fl = p.get_fl(); 00331 FU_column_iterator fu = p.get_fu(); 00332 L_column_iterator l = p.get_l(); 00333 U_column_iterator u = p.get_u(); 00334 Variable_numerator_iterator v = variable_numerators_begin(); 00335 ET d = variables_common_denominator(); 00336 if (d <= et0) 00337 return error ("common variable denominator is negative"); 00338 for (int j=0; j<n; ++j, ++v, ++fl, ++l, ++fu, ++u) { 00339 if (*fl && *v == ET(*l) * d && (!*fu || *l < *u) && q[j] < et0) 00340 return error("x_j = l_j < u_j but (c^T + lambda^TA + 2Dx)_j < 0"); 00341 if ( (!*fl || *v > ET(*l) * d) && (!*fu || *v < ET(*u) * d) && q[j] != et0) 00342 return error("l_j < x_j < u_j but (c^T + lambda^TA + 2Dx)_j != 0"); 00343 if (*fu && *v == ET(*u) * d && (!*fl || *l < *u) && q[j] > et0) 00344 return error("x_j = u_j > l_j but (c^T + lambda^TA + 2Dx)_j > 0"); 00345 } 00346 return true; 00347 } 00348 00349 // checks whether objective function value is c^T x + c_0, but 00350 // leaves the vector q alone 00351 // -------------------------------------------------------------- 00352 template <typename ET> 00353 template <typename Program> 00354 bool Quadratic_program_solution<ET>::is_value_correct 00355 (const Program& p, std::vector<ET>& /*q*/, Tag_true /*is_linear*/) 00356 { 00357 // check objective value c^T x + c_0 00358 ET d = variables_common_denominator(); 00359 if (d <= et0) 00360 return error ("common variable denominator is negative"); 00361 Variable_numerator_iterator v = variable_numerators_begin(); 00362 ET obj = d * ET(p.get_c0()); // d * c_0 00363 typedef typename Program::C_iterator C_column_iterator; 00364 C_column_iterator c = p.get_c(); 00365 int n = p.get_n(); 00366 for (int j=0; j<n; ++j, ++v, ++c) 00367 obj += ET(*c) * *v; // d * c^T x 00368 if (Quotient<ET>(obj, d) != objective_value()) 00369 return error ("optimal objective value c^T x + c_0 incorrect"); 00370 return true; 00371 } 00372 00373 // checks whether objective function value is x^TDx + c^T x + c_0 00374 // and fills the vector q with 2Dx 00375 // -------------------------------------------------------------- 00376 template <typename ET> 00377 template <typename Program> 00378 bool Quadratic_program_solution<ET>::is_value_correct 00379 (const Program& p, std::vector<ET>& q, Tag_false /*is_linear*/) 00380 { 00381 ET d = variables_common_denominator(); 00382 if (d <= et0) 00383 return error ("common variable denominator is negative"); 00384 Variable_numerator_iterator v = variable_numerators_begin(); 00385 int n = p.get_n(); 00386 add_two_Dz (p, v, q); // 2d * Dx 00387 ET et2(2); 00388 ET obj = et2 * d * d * ET(p.get_c0()); // 2d^2 * c_0 00389 typedef typename Program::C_iterator C_column_iterator; 00390 C_column_iterator c = p.get_c(); 00391 for (int j=0; j<n; ++j, ++v, ++c) { 00392 obj += et2 * d * ET(*c) * *v; // 2d^2 * c^T x 00393 obj += q[j] * *v; // 2d^2 * x^TDx 00394 } 00395 if (Quotient<ET>(obj, et2*d*d) != objective_value()) 00396 return error ("optimal objective value x^TDx + c^T x + c_0 incorrect"); 00397 return true; 00398 } 00399 00400 // checks whether lambda^TA >= 0 00401 // ----------------------------- 00402 template <typename ET> 00403 template <typename Program> 00404 bool Quadratic_program_solution<ET>::is_infeasible_2 00405 (const Program& p, typename std::vector<ET>& lambda_a, 00406 Tag_true /*is_nonnegative*/) 00407 { 00408 // fill lambda_a 00409 add_zA (p, infeasibility_certificate_begin(), lambda_a); 00410 int n = p.get_n(); 00411 for (int j=0; j<n; ++j) 00412 if (lambda_a[j] < et0) 00413 return error ("(lambda^TA)_j < 0 for some j"); 00414 return true; 00415 } 00416 00417 // checks whether lambda^TA >= 0 (<= 0) if u_j = infty (l_j = -infty) 00418 // ------------------------------------------------------------------ 00419 template <typename ET> 00420 template <typename Program> 00421 bool Quadratic_program_solution<ET>::is_infeasible_2 00422 (const Program& p, typename std::vector<ET>& lambda_a, 00423 Tag_false /*is_nonnegative*/) 00424 { 00425 // fill lambda_a 00426 add_zA (p, infeasibility_certificate_begin(), lambda_a); 00427 int n = p.get_n(); 00428 typedef typename Program::FL_iterator FL_column_iterator; 00429 typedef typename Program::FU_iterator FU_column_iterator; 00430 FL_column_iterator fl = p.get_fl(); 00431 FU_column_iterator fu = p.get_fu(); 00432 for (int j=0; j<n; ++j, ++fl, ++fu) { 00433 if (!*fu && lambda_a[j] < et0) 00434 return error ("u_j = infty but (lambda^TA)_j < 0"); 00435 if (!*fl && lambda_a[j] > et0) 00436 return error ("l_j = -infty but (lambda^TA)_j > 0"); 00437 } 00438 return true; 00439 } 00440 00441 // checks whether lambda^T b < 0 00442 // ----------------------------- 00443 template <typename ET> 00444 template <typename Program> 00445 bool Quadratic_program_solution<ET>::is_infeasible_3 00446 (const Program& p, const typename std::vector<ET>& /*lambda_a*/, 00447 Tag_true /*is_nonnegative*/) 00448 { 00449 ET lambda_b(0); 00450 int m = p.get_m(); 00451 typedef typename Program::B_iterator B_column_iterator; 00452 B_column_iterator b = p.get_b(); 00453 Infeasibility_certificate_iterator inf = infeasibility_certificate_begin(); 00454 for (int i=0; i<m; ++i, ++b, ++inf) 00455 lambda_b += ET(*b) * *inf; 00456 if (lambda_b >= et0) 00457 return error ("lambda_b >= 0"); 00458 return true; 00459 } 00460 00461 // checks whether lambda^T b < \sum_{j: lambda^TA_j < 0}lambda^TA_j u_j + 00462 // \sum_{j: lambda^TA_j > 0}lambda^TA_j l_j 00463 // ---------------------------------------------------------------------- 00464 template <typename ET> 00465 template <typename Program> 00466 bool Quadratic_program_solution<ET>::is_infeasible_3 00467 (const Program& p, const typename std::vector<ET>& lambda_a, 00468 Tag_false /*is_nonnegative*/) 00469 { 00470 ET lambda_b(0); 00471 int m = p.get_m(); 00472 typedef typename Program::B_iterator B_column_iterator; 00473 B_column_iterator b = p.get_b(); 00474 Infeasibility_certificate_iterator inf = infeasibility_certificate_begin(); 00475 for (int i=0; i<m; ++i, ++b, ++inf) 00476 lambda_b += ET(*b) * *inf; 00477 00478 ET sum(0); 00479 int n = p.get_n(); 00480 typedef typename Program::L_iterator L_column_iterator; 00481 typedef typename Program::U_iterator U_column_iterator; 00482 L_column_iterator l = p.get_l(); 00483 U_column_iterator u = p.get_u(); 00484 for (int j=0; j<n; ++j, ++l, ++u) { 00485 if (lambda_a[j] < et0) sum += lambda_a[j] * ET(*u); 00486 if (lambda_a[j] > et0) sum += lambda_a[j] * ET(*l); 00487 } 00488 // now compare 00489 if (lambda_b >= sum) 00490 return error("lambda^T b >= sum"); 00491 return true; 00492 } 00493 00494 // checks whether (Aw)_i <= (>=, ==) 0 if i-th constraint is <= (>=, ==) 00495 // --------------------------------------------------------------------- 00496 template <typename ET> 00497 template <typename Program> 00498 bool Quadratic_program_solution<ET>::is_unbounded_1 00499 (const Program& p) 00500 { 00501 int m = p.get_m(); 00502 std::vector<ET> aw (m, et0); 00503 add_Az (p, unboundedness_certificate_begin(), aw); 00504 typedef typename Program::R_iterator R_column_iterator; 00505 R_column_iterator r = p.get_r(); 00506 for (int i=0; i<m; ++i, ++r) 00507 switch (*r) { 00508 case SMALLER: 00509 if (aw[i] > et0) 00510 return error ("i-th constraint <= but (Aw)_i > 0"); 00511 break; 00512 case EQUAL: 00513 if (aw[i] != et0) 00514 return error ("i-th constraint == but (Aw)_i != 0"); 00515 break; 00516 case LARGER: 00517 if (aw[i] < et0) 00518 return error ("i-th constraint >= but (Aw)_i < 0"); 00519 break; 00520 } 00521 return true; 00522 } 00523 00524 // checks whether w >= 0 00525 // --------------------- 00526 template <typename ET> 00527 template <typename Program> 00528 bool Quadratic_program_solution<ET>::is_unbounded_2 00529 (const Program& p, Tag_true /*is_nonnegative*/) 00530 { 00531 int n = p.get_n(); 00532 Unboundedness_certificate_iterator unb = unboundedness_certificate_begin(); 00533 for (int j=0; j<n; ++j, ++unb) 00534 if (*unb < et0) 00535 return error ("some w_j < 0"); 00536 return true; 00537 } 00538 00539 // checks whether w_j >= (<=) 0 if l_j (u_j) is finite 00540 // --------------------------------------------------- 00541 template <typename ET> 00542 template <typename Program> 00543 bool Quadratic_program_solution<ET>::is_unbounded_2 00544 (const Program& p, Tag_false /*is_nonnegative*/) 00545 { 00546 int n = p.get_n(); 00547 typedef typename Program::FL_iterator FL_column_iterator; 00548 typedef typename Program::FU_iterator FU_column_iterator; 00549 FL_column_iterator fl = p.get_fl(); 00550 FU_column_iterator fu = p.get_fu(); 00551 Unboundedness_certificate_iterator unb = unboundedness_certificate_begin(); 00552 for (int j=0; j<n; ++j, ++unb, ++fl, ++fu) { 00553 if (*fl && *unb < et0) 00554 return error ("some l_j is finite but w_j < 0"); 00555 if (*fu && *unb > et0) 00556 return error ("some u_j is finite but w_j > 0"); 00557 } 00558 return true; 00559 } 00560 00561 // checks whether c^Tw < 0 00562 // ----------------------- 00563 template <typename ET> 00564 template <typename Program> 00565 bool Quadratic_program_solution<ET>::is_unbounded_3 00566 (const Program& p, Tag_true /*is_linear*/) 00567 { 00568 ET cw(0); 00569 int n = p.get_n(); 00570 typedef typename Program::C_iterator C_column_iterator; 00571 C_column_iterator c = p.get_c(); 00572 Unboundedness_certificate_iterator unb = unboundedness_certificate_begin(); 00573 for (int j=0; j<n; ++j, ++c, ++unb) 00574 cw += ET(*c) * *unb; 00575 if (cw >= et0) 00576 return error("c^Tw >= 0"); 00577 return true; 00578 } 00579 00580 // checks whether w^TDw = 0 and (c^T + 2x^TD)w < 0 00581 // ----------------------------------------------- 00582 template <typename ET> 00583 template <typename Program> 00584 bool Quadratic_program_solution<ET>::is_unbounded_3 00585 (const Program& p, Tag_false /*is_linear*/) 00586 { 00587 int n = p.get_n(); 00588 std::vector<ET> two_dw (n, et0); 00589 add_two_Dz(p, unboundedness_certificate_begin(), two_dw); // 2Dw 00590 // check w^TDw = 0 00591 Unboundedness_certificate_iterator unb = unboundedness_certificate_begin(); 00592 ET wdw(0); 00593 for (int j=0; j<n; ++j, ++unb) 00594 wdw += two_dw[j] * *unb; 00595 if (wdw != et0) 00596 return error("w^TDw != 0"); 00597 // check (c^T + 2x^TD)w = c^Tw + 2x^T Dw < 0 00598 typedef typename Program::C_iterator C_column_iterator; 00599 C_column_iterator c = p.get_c(); 00600 unb = unboundedness_certificate_begin(); 00601 Variable_numerator_iterator v = variable_numerators_begin(); 00602 ET d = variables_common_denominator(); 00603 if (d <= et0) 00604 return error ("common variable denominator is negative"); 00605 ET res(0); 00606 for (int j=0; j<n; ++j, ++c, ++unb, ++v) 00607 res += ET(*c) * *unb * d + two_dw[j] * *v; 00608 if (res >= 0) 00609 return error("c^T + 2x^TD)w >= 0"); 00610 return true; 00611 } 00612 00613 // computes the product of A with the n-vector given by z 00614 // and adds the result to v; precondition: v has size m 00615 // ------------------------------------------------------ 00616 template <typename ET> 00617 template <typename Program, typename Z_iterator > 00618 void Quadratic_program_solution<ET>::add_Az 00619 (const Program& p, Z_iterator z, typename std::vector<ET>& v) 00620 { 00621 // iterator types 00622 typedef typename Program::A_iterator 00623 A_matrix_iterator; 00624 typedef typename std::iterator_traits<A_matrix_iterator>::value_type 00625 A_column_iterator; 00626 // now compute the product 00627 A_matrix_iterator a = p.get_a(); 00628 int n = p.get_n(); 00629 for (int j=0; j<n; ++j, ++a, ++z) { 00630 if (!CGAL::is_zero(*z)) { 00631 // add A_j * z_j to az 00632 A_column_iterator a_j = *a; 00633 for (int i=0; i<p.get_m(); ++i, ++a_j) 00634 v[i] += *z * ET(*a_j); 00635 } 00636 } 00637 } 00638 00639 // computes the product of 2D with the n-vector given by z 00640 // and adds the result to v; precondition: v has size n 00641 // ------------------------------------------------------- 00642 template <typename ET> 00643 template <typename Program, typename Z_iterator > 00644 void Quadratic_program_solution<ET>::add_two_Dz 00645 (const Program& p, Z_iterator z, typename std::vector<ET>& v) 00646 { 00647 // we compute the contribution from the enries of D on or below 00648 // the diagonal rowwise, and the remaining entries columnwise 00649 typedef typename Program::D_iterator 00650 D_matrix_iterator; 00651 typedef typename std::iterator_traits<D_matrix_iterator>::value_type 00652 D_row_iterator; 00653 int n = p.get_n(); 00654 // make sure that we only handle the nonzero terms of z 00655 std::vector<int> z_indices; 00656 Z_iterator l = z; 00657 for (int i=0; i<n; ++i, ++l) 00658 if (*l != 0) z_indices.push_back(i); 00659 00660 // the rowwise contribution: on/below the diagonal 00661 D_matrix_iterator d = p.get_d(); 00662 for (int i=0; i<n; ++i, ++d) { 00663 // handle row i 00664 D_row_iterator d_i = *d; // row i on/below diagonal 00665 for (std::vector<int>::const_iterator 00666 k = z_indices.begin(); k < z_indices.end(); ++k) { 00667 int j = *k; 00668 if (j <= i) v[i] += *(z+j) * ET (*(d_i+j)); 00669 } 00670 } 00671 00672 // the columnwise contribution: above the diagonal 00673 d = p.get_d(); 00674 for (std::vector<int>::const_iterator 00675 k = z_indices.begin(); k < z_indices.end(); ++k) { 00676 int j = *k; 00677 // handle column j 00678 D_row_iterator d_j = *(d+j); // column j above diagonal 00679 for (int i=0; i<j; ++i, ++d_j) 00680 v[i] += *(z+j) * ET (*d_j); 00681 } 00682 } 00683 00684 00685 // computes the product of the m-vector given by z with the matrix 00686 // A and adds the result to v; precondition: v has size n 00687 // ---------------------------------------------------------------- 00688 template <typename ET> 00689 template <typename Program, typename Z_iterator > 00690 void Quadratic_program_solution<ET>::add_zA 00691 (const Program& p, Z_iterator z, typename std::vector<ET>& v) 00692 { 00693 typedef typename Program::A_iterator 00694 A_matrix_iterator; 00695 typedef typename std::iterator_traits<A_matrix_iterator>::value_type 00696 A_column_iterator; 00697 A_matrix_iterator a = p.get_a(); 00698 int n = p.get_n(); 00699 int m = p.get_m(); 00700 // make sure that we only handle the nonzero terms of z 00701 std::vector<int> z_indices; // indices of nonzero entries 00702 Z_iterator l = z; 00703 for (int i=0; i<m; ++i, ++l) 00704 if (*l != 0) z_indices.push_back(i); 00705 // now compute the product columnwise 00706 for (int j=0; j<n; ++j, ++a) { 00707 // add z^T * A_j to v[j] 00708 A_column_iterator a_j = *a; 00709 for (std::vector<int>::const_iterator 00710 k = z_indices.begin(); k < z_indices.end(); ++k) 00711 v[j] += *(z+*k) * ET(*(a_j+*k)); 00712 } 00713 } 00714 00715 // adds d c^T to v; precondition: v has length n 00716 // --------------------------------------------- 00717 template <typename ET> 00718 template <typename Program> 00719 void Quadratic_program_solution<ET>::add_c 00720 (const Program& p, typename std::vector<ET>& v) 00721 { 00722 int n = p.get_n(); 00723 typedef typename Program::C_iterator C_column_iterator; 00724 C_column_iterator c = p.get_c(); 00725 ET d = variables_common_denominator(); 00726 for (int j=0; j<n; ++j, ++c) 00727 v[j] += ET(*c) * d; 00728 } 00729 00730 00731 CGAL_END_NAMESPACE 00732 00733 #endif // CGAL_QP_SOLUTION_IMPL_H 00734