BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/QP_solver/QP_solution_impl.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines