BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/QP_solver/QP_functions_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://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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines