/home/coin/SVN-release/OS-2.4.1/Couenne/src/problem/checkNLP.cpp

Go to the documentation of this file.
00001 /* $Id: checkNLP.cpp 752 2011-08-08 03:45:07Z pbelotti $
00002  *
00003  * Name:    checkNLP.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: check NLP feasibility of incumbent integer solution
00006  *
00007  * (C) Carnegie-Mellon University, 2006-11.
00008  * This file is licensed under the Eclipse Public License (EPL)
00009  */
00010 
00011 #include "CouenneProblem.hpp"
00012 #include "CouenneProblemElem.hpp"
00013 #include "CouenneExprVar.hpp"
00014 #include "CoinHelperFunctions.hpp"
00015 #include "CoinFinite.hpp"
00016 
00017 #include "CouenneRecordBestSol.hpp"
00018 
00019 //#define FM_TRACE_NLP
00020 
00021 using namespace Couenne;
00022 
00023 // check if solution is MINLP feasible
00024 bool CouenneProblem::checkNLP (const double *solution, double &obj, bool recompute) const {
00025 
00026   if (Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_PROBLEM)) {
00027 
00028     printf ("Checking solution: %.12e (", obj);
00029 
00030     for (int i=0; i<nOrigVars_ - ndefined_; i++)
00031       printf ("%g ", solution [i]);
00032     printf (")\n");
00033   }
00034 
00035   // pre-check on original variables --- this is done after every LP,
00036   // and should be efficient
00037   for (register int i=0; i < nOrigVars_ - ndefined_; i++) {
00038 
00039     if (variables_ [i] -> Multiplicity () <= 0) 
00040       continue;
00041 
00042     CouNumber val = solution [i];
00043 
00044     // check (original and auxiliary) variables' integrality
00045 
00046     exprVar *v = variables_ [i];
00047 
00048     if ((v -> Type ()      == VAR) &&
00049         (v -> isDefinedInteger ()) &&
00050         (v -> Multiplicity () > 0) &&
00051         (fabs (val - COUENNE_round (val)) > feas_tolerance_)) {
00052 
00053       Jnlst()->Printf(Ipopt::J_MOREVECTOR, J_PROBLEM,
00054                       "checkNLP: integrality %d violated: %.6f [%g,%g]\n", 
00055                       i, val, domain_.lb (i), domain_.ub (i));
00056 
00057       Jnlst () -> Printf (Ipopt::J_ALL, J_PROBLEM, "Done: (0)\n");
00058 
00059       return false;
00060     }
00061   }
00062 
00063   const int infeasible = 1;
00064   const int wrong_obj  = 2;
00065 
00066   // copy solution, evaluate the corresponding aux, and then replace
00067   // the original variables again for checking
00068   CouNumber *sol = new CouNumber [nVars ()];
00069   CoinZeroN (sol     + nOrigVars_ - ndefined_, nVars() - (nOrigVars_ - ndefined_));
00070   CoinCopyN (solution, nOrigVars_ - ndefined_, sol);
00071   getAuxs (sol);
00072   CoinCopyN (solution, nOrigVars_ - ndefined_, sol);
00073 
00074   // install NL solution candidate in evaluation structure
00075   domain_.push (nVars (), sol, domain_.lb (), domain_.ub (), false);
00076 
00077   if (Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_PROBLEM)) {
00078     printf ("  checkNLP: %d vars -------------------\n    ", domain_.current () -> Dimension ());
00079     for (int i=0; i<domain_.current () -> Dimension (); i++) {
00080       if (i && !(i%5)) printf ("\n    ");
00081       printf ("%4d %16g [%16e %16e]  ", i, domain_.x (i), domain_.lb (i), domain_.ub (i));
00082     }
00083   }
00084 
00085   expression *objBody = Obj (0) -> Body ();
00086 
00087   // BUG: if Ipopt solution violates bounds of original variables and
00088   // objective depends on originals, we may have a "computed object"
00089   // out of bounds
00090 
00091   //CouNumber realobj = (*(objBody -> Image () ? objBody -> Image () : objBody)) ();
00092   CouNumber realobj = obj;
00093 
00094   if (objBody) 
00095     realobj = 
00096       (objBody -> Index () >= 0) ?
00097       sol [objBody -> Index ()] : 
00098       (*(objBody -> Image () ? objBody -> Image () : objBody)) ();
00099 
00100   if (Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_PROBLEM)) {
00101     printf ("  Objective: %.12e %.12e %.12e\n", 
00102             realobj, sol [objBody -> Index ()], 
00103             (*(objBody -> Image () ? objBody -> Image () : objBody)) ());
00104   }
00105 
00106   bool retval = true;
00107 
00108   try {
00109 
00110     // check if objective corresponds
00111     
00112     if (fabs (realobj - obj) / (1. + fabs (realobj)) > feas_tolerance_) {
00113 
00114       Jnlst()->Printf(Ipopt::J_MOREVECTOR, J_PROBLEM,
00115                       "  checkNLP, false objective: computed %g != %g xQ (diff. %g)\n", 
00116                       realobj, obj, realobj - obj);
00117 
00118       if (!recompute)
00119         throw wrong_obj;
00120     }
00121 
00122     if (recompute)
00123       obj = realobj;
00124 
00125     if (Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_PROBLEM))
00126       printf ("  recomputed: %.12e\n", obj);
00127 
00128     for (int i=0; i < nOrigVars_ - ndefined_; i++) {
00129 
00130       if (variables_ [i] -> Multiplicity () <= 0) 
00131         continue;
00132 
00133       CouNumber val = domain_.x (i);
00134 
00135       // check bounds
00136 
00137       if ((val > domain_.ub (i) + feas_tolerance_) ||
00138           (val < domain_.lb (i) - feas_tolerance_)) {
00139 
00140         Jnlst()->Printf(Ipopt::J_MOREVECTOR, J_PROBLEM,
00141                         "  checkNLP: variable %d out of bounds: %.6f [%g,%g] (diff %g)\n", 
00142                         i, val, domain_.lb (i), domain_.ub (i),
00143                         CoinMax (fabs (val - domain_.lb (i)), 
00144                                  fabs (val - domain_.ub (i))));
00145         throw infeasible;
00146       }
00147 
00148       // check (original and auxiliary) variables' integrality
00149 
00150       if (variables_ [i] -> isDefinedInteger () &&
00151           (fabs (val - COUENNE_round (val)) > feas_tolerance_)) {
00152 
00153         Jnlst()->Printf(Ipopt::J_MOREVECTOR, J_PROBLEM,
00154                         "  checkNLP: integrality %d violated: %.6f [%g,%g]\n", 
00155                         i, val, domain_.lb (i), domain_.ub (i));
00156 
00157         throw infeasible;
00158       }
00159     }
00160 
00161     // check ALL auxs
00162 
00163     for (int i=0; i < nVars (); i++) {
00164 
00165       exprVar *v = variables_ [i];
00166 
00167       if ((v -> Type         () != AUX) ||
00168           (v -> Multiplicity () <= 0))
00169         continue;
00170 
00171       if (Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_PROBLEM)) {
00172         printf ("    "); v -> print (); 
00173         CouNumber
00174           val = (*(v)) (), 
00175           img = (*(v -> Image ())) (), 
00176           diff = fabs (val - img);
00177         printf (": val = %15g; img = %-15g ", val, img);
00178         if (diff > 1e-9)
00179           printf ("[diff %12e] ", diff);
00180         //for (int j=0; j<nVars (); j++) printf ("%.12e ", (*(variables_ [j])) ());
00181         v -> Image () -> print (); 
00182         printf ("\n");
00183       }
00184       
00185       // check if auxiliary has zero infeasibility
00186 
00187       // same as in CouenneObject::checkInfeasibility -- main difference is use of gradientNorm()
00188 
00189       double 
00190         vval = (*v) (),
00191         fval = (*(v -> Image ())) (),
00192         denom  = CoinMax (1., v -> Image () -> gradientNorm (X ()));
00193 
00194       // check if fval is a number (happens with e.g. w13 = w12/w5 and w5=0, see test/harker.nl)
00195       if (CoinIsnan (fval)) {
00196         fval = vval + 1.;
00197         denom = 1.;
00198       }
00199 
00200       if (fabs (fval) > COUENNE_INFINITY)
00201         fval = COUENNE_INFINITY;
00202 
00203       double
00204         delta = 
00205         ((v -> sign () == expression::AUX_GEQ) && (vval >= fval)) ? 0. : 
00206         ((v -> sign () == expression::AUX_LEQ) && (vval <= fval)) ? 0. : fabs (vval - fval),
00207 
00208         ratio = (CoinMax (1., fabs (vval)) / 
00209                  CoinMax (1., fabs (fval)));
00210 
00211       // printf ("checkinf --> v=%e f=%e den=%e ret=%d ratio=%e delta=%e, delta/denom=%e, thres=%e [", 
00212       //              vval, fval, denom, retval, ratio, delta, delta/denom, CoinMin (COUENNE_EPS, feas_tolerance_));
00213       // v -> print ();
00214       // printf (" %c= ", v -> sign () == expression::AUX_LEQ ? '<' : 
00215       //                       v -> sign () == expression::AUX_GEQ ? '>' : ':');
00216       // v -> Image () -> print ();
00217       // printf ("]\n");
00218 
00219       if ((delta > 0.) &&
00220           (((ratio > 2.)  ||  // check delta > 0 to take into account semi-auxs
00221             (ratio <  .5)) ||
00222            ((delta /= denom) > CoinMin (COUENNE_EPS, feas_tolerance_)))) {
00223 
00224         Jnlst () -> Printf (Ipopt::J_MOREVECTOR, J_PROBLEM,
00225                             "  checkNLP: auxiliary %d violates tolerance %g by %g/%g = %g\n", 
00226                             i, CoinMin (COUENNE_EPS, feas_tolerance_), delta*denom, denom, delta);
00227 
00228         throw infeasible;
00229       }
00230     }
00231 
00232     // check constraints
00233 
00234     for (int i=0; i < nCons (); i++) {
00235 
00236       CouenneConstraint *c = Con (i);
00237 
00238       CouNumber
00239         body = (*(c -> Body ())) (),
00240         lhs  = (*(c -> Lb   ())) (),
00241         rhs  = (*(c -> Ub   ())) ();
00242 
00243       if (((rhs <  COUENNE_INFINITY) && (body > rhs + feas_tolerance_ * (1. + CoinMax (fabs (body), fabs (rhs))))) || 
00244           ((lhs > -COUENNE_INFINITY) && (body < lhs - feas_tolerance_ * (1. + CoinMax (fabs (body), fabs (lhs)))))) {
00245 
00246         if (Jnlst () -> ProduceOutput (Ipopt::J_MOREVECTOR, J_PROBLEM)) {
00247 
00248           printf ("  checkNLP: constraint %d violated (lhs=%+e body=%+e rhs=%+e, violation %g): ",
00249                   i, lhs, body, rhs, CoinMax (lhs-body, body-rhs));
00250 
00251           c -> print ();
00252         }
00253 
00254         throw infeasible;
00255       }
00256     }
00257   }
00258 
00259   catch (int exception) {
00260 
00261     switch (exception) {
00262 
00263     case wrong_obj:
00264       retval = false;
00265       break;
00266 
00267     case infeasible:
00268     default:
00269       retval = false;
00270       break;
00271     }
00272   }
00273 
00274   delete [] sol;
00275   domain_.pop ();
00276 
00277   Jnlst () -> Printf (Ipopt::J_ALL, J_PROBLEM, "Done: %d\n", retval);
00278 
00279   return retval;
00280 }
00281 
00282 /************************************************************************/
00283 // Recompute objective value for sol
00284 double CouenneProblem::checkObj(const CouNumber *sol, const double &precision) 
00285   const {
00286 
00287   expression *objBody = Obj(0)->Body();
00288 
00289   // BUG: if Ipopt couSol violates bounds of original variables and
00290   // objective depends on originals, we may have a "computed object"
00291   // out of bounds
00292 
00293   //CouNumber realobj = (*(objBody -> Image () ? objBody -> Image () : objBody)) ();
00294   CouNumber realObj = 0;
00295 
00296   if (objBody) {
00297     realObj = 
00298       (objBody ->Index() >= 0) ?
00299       sol[objBody->Index()] : 
00300       (*(objBody->Image() ? objBody->Image() : objBody)) ();
00301     
00302     if (
00303 #ifdef FM_TRACE_NLP
00304         (0) || 
00305 #endif
00306         (Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_PROBLEM))) {
00307       printf ("%.12e %.12e %.12e ------------------------------\n", 
00308               realObj, sol[objBody -> Index ()], 
00309               (*(objBody -> Image () ? objBody -> Image () : objBody)) ());
00310     }
00311   } 
00312   else {
00313     printf("### ERROR: CouenneProblem::checkObj(): no objective body\n");
00314     exit(1);
00315   }
00316   return realObj;
00317 }
00318 
00319 /************************************************************************/
00320 // check integrality of original vars in sol; return true if all
00321 // original integer vars are within precision of an integer value
00322 bool CouenneProblem::checkInt(const CouNumber *sol,
00323                               const int from, const int upto, 
00324                               const std::vector<int> listInt,
00325                               const bool origVarOnly,  
00326                               const bool stopAtFirstViol,  
00327                               const double precision, double &maxViol) const {
00328 
00329   bool isFeas = true;
00330 
00331   for(unsigned int i=0; i<listInt.size(); i++) {
00332 
00333     int ind = listInt[i];
00334 
00335     if((ind < from) || (variables_ [ind] -> Multiplicity () <= 0)) {
00336       continue;
00337     }
00338 
00339     if(ind >= upto) {
00340       break;
00341     }
00342 
00343     CouNumber val = sol[ind];
00344     exprVar *v = variables_ [ind];
00345 
00346     if ((!origVarOnly) || (v -> Type () == VAR)) {
00347 
00348       double viol = fabs (val - COUENNE_round (val));
00349       maxViol = (viol > maxViol ? viol : maxViol);
00350       if(viol > precision) {
00351 
00352       Jnlst()->Printf(Ipopt::J_MOREVECTOR, J_PROBLEM,
00353                       "checkInt(): integrality %d violated: %.6f [%g,%g]: integer distance %e > %e (by %e)\n", 
00354                       i, val, domain_.lb (i), domain_.ub (i), 
00355                       fabs (val - COUENNE_round (val)),  feas_tolerance_, 
00356                       fabs (val - COUENNE_round (val)) - feas_tolerance_);
00357 
00358 #ifdef FM_TRACE_NLP
00359         printf("CouenneProblem::checkInt(): integrality %d violated: %.6f [%g,%g]\n", 
00360                ind, val, domain_.lb (ind), domain_.ub (ind));
00361 
00362 #endif
00363 
00364         isFeas = false;
00365         if(stopAtFirstViol) {
00366           break;
00367         }
00368       }
00369     }
00370   }
00371   return(isFeas);
00372 }
00373 
00374 /************************************************************************/
00375 // Check bounds; returns true iff feasible for given precision
00376 bool CouenneProblem::checkBounds(const CouNumber *sol,
00377                                  const bool stopAtFirstViol,  
00378                                  const double precision, double &maxViol) const {
00379 
00380   bool isFeas = true;
00381   for(int i=0; i<nOrigVars_ - ndefined_; i++) {
00382     
00383     if (variables_[i]-> Multiplicity () <= 0) 
00384       continue;
00385     
00386     CouNumber val = domain_.x (i);
00387     double viol = 0;
00388     double violUb = val - domain_.ub (i);
00389     double violLb = domain_.lb (i) - val;
00390     
00391     viol = (viol < violUb ? violUb : viol); 
00392     viol = (viol < violLb ? violLb : viol); 
00393     
00394     maxViol = (maxViol > viol ? maxViol : viol);
00395     
00396     if (viol > precision) {
00397       
00398       Jnlst()->Printf(Ipopt::J_MOREVECTOR, J_PROBLEM,
00399                       "checkBounds(): variable %d out of bounds: %.6f [%g,%g] (diff %g)\n", 
00400                       i, val, domain_.lb (i), domain_.ub (i),
00401                       CoinMax (fabs (val - domain_.lb (i)), 
00402                                fabs (val - domain_.ub (i))));
00403       
00404 #ifdef FM_TRACE_NLP
00405       printf("CouenneProblem::checkBounds: variable %d out of bounds: %.6f [%g,%g] (diff %g)\n", 
00406              i, val, domain_.lb (i), domain_.ub (i),
00407              CoinMax (fabs (val - domain_.lb (i)), 
00408                       fabs (val - domain_.ub (i))));
00409 #endif
00410       
00411       isFeas = false;
00412       if(stopAtFirstViol) {
00413         break;
00414       }
00415     }
00416   }
00417   return isFeas;
00418 }
00419 
00420 /************************************************************************/
00421 // returns true iff value of all auxiliaries are within bounds
00422 bool CouenneProblem::checkAux(const CouNumber *sol,
00423                               const bool stopAtFirstViol,  
00424                               const double precision, double &maxViol) const {
00425 
00426   bool isFeas = true;
00427   for (int i=0; i<nVars(); i++) {
00428 
00429     exprVar *v = variables_ [i];
00430     
00431     if ((v -> Type         () != AUX) || 
00432         (v -> Multiplicity () <= 0)) 
00433       continue;
00434     
00435     if (
00436 #ifdef FM_TRACE_NLP
00437         (1) || 
00438 #endif
00439         
00440         (Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_PROBLEM))) {
00441       printf ("checking aux ");
00442       variables_ [i] -> print (); printf (" := ");
00443       variables_ [i] -> Image () -> print (); 
00444       printf (" --- %.12e", (*(variables_ [i])) ()); 
00445       printf("%.12e", (*(variables_ [i] -> Image ())) ());
00446       printf (" --- %.12e = %.12e [%.12e]; {", 
00447               (*(variables_ [i])) (), 
00448               (*(variables_ [i] -> Image ())) (),
00449               (*(variables_ [i])) () -
00450               (*(variables_ [i] -> Image ())) ());
00451       printf ("}\n");
00452     }
00453     
00454     double 
00455       vval = (*v) (),
00456       fval = (*(v -> Image ())) (),
00457       denom  = CoinMax (1., v -> Image () -> gradientNorm (X ()));
00458     
00459     // check if fval is a number (happens with e.g. w13 = w12/w5 and w5=0, see test/harker.nl)
00460     if (CoinIsnan (fval)) {
00461       fval = vval + 1.;
00462       denom = 1.;
00463     }
00464     
00465     if (fabs (fval) > COUENNE_INFINITY)
00466       fval = COUENNE_INFINITY;
00467     
00468 
00469     double
00470       delta = 
00471       ((v -> sign () == expression::AUX_GEQ) && (vval >= fval)) ? 0. : 
00472       ((v -> sign () == expression::AUX_LEQ) && (vval <= fval)) ? 0. : fabs (vval - fval),
00473       
00474       ratio = (CoinMax (1., fabs (vval)) / 
00475                CoinMax (1., fabs (fval)));
00476     
00477     //printf ("checkinf --> v=%e f=%e den=%e ret=%e ratio=%e\n", vval, fval, denom, retval, ratio);
00478     
00479     double deldenom = delta/denom;
00480     maxViol = (maxViol > deldenom ? maxViol : deldenom);
00481 
00482     if ((delta > 0.) &&
00483         (((ratio > 2.)  ||  // check delta > 0 to take into account semi-auxs
00484           (ratio <  .5)) ||
00485          ((delta /= denom) > CoinMin (COUENNE_EPS, feas_tolerance_)))) {
00486 
00487       Jnlst () -> Printf (Ipopt::J_MOREVECTOR, J_PROBLEM,
00488                           "checkAux(): auxiliary %d violates tolerance %g by %g (deldenom: %g ratio %g)\n", 
00489                           i, feas_tolerance_, delta, deldenom, ratio);
00490       
00491       isFeas = false;
00492 
00493 #ifdef FM_TRACE_NLP
00494       printf("CouenneProblem::checkAux(): auxiliary %d violates tolerance %g by %g (deldenom: %g  ratio %g  COUENNE_EPS: %g)\n", 
00495              i, feas_tolerance_, delta, deldenom, ratio, COUENNE_EPS);
00496 #endif
00497 
00498       if(stopAtFirstViol) {
00499         break;
00500       }
00501     }
00502   }
00503   return isFeas;
00504 }
00505 
00506 
00507 /************************************************************************/
00508 bool CouenneProblem::checkCons(const CouNumber *sol,
00509                                const bool stopAtFirstViol,
00510                                const double precision, double &maxViol) const {
00511 
00512   bool isFeas = true;
00513   for (int i=0; i<nCons(); i++) {
00514     
00515     CouenneConstraint *c = Con(i);
00516     
00517     CouNumber
00518       body = (*(c -> Body ())) (),
00519       lhs  = (*(c -> Lb   ())) (),
00520       rhs  = (*(c -> Ub   ())) ();
00521     
00522     double denomUb = 1 + CoinMax (fabs (body), fabs (rhs));
00523     double denomLb = 1 + CoinMax (fabs (body), fabs (lhs));
00524     double violUb = 0, violRelUb = 0, violAbsUb = 0;
00525     if(rhs < COUENNE_INFINITY) {
00526       violAbsUb = body - rhs;
00527       violRelUb = violAbsUb / denomUb;
00528       violUb = violAbsUb - precision * denomUb;
00529 
00530 #ifdef FM_USE_ABS_VIOL_CONS
00531       maxViol = (maxViol > violAbsUb ? maxViol : violAbsUb);
00532 #else
00533       maxViol = (maxViol > violRelUb ? maxViol : violRelUb);
00534 #endif
00535 
00536 #ifdef FM_TRACE_NLP
00537       printf("violAbsUb: %12.10f  violRelUb: %12.10f  violUb: %12.10f maxViol: %12.10f\n",
00538              violAbsUb, violRelUb, violUb, maxViol);
00539 #endif
00540     }
00541 
00542     double violLb = 0, violRelLb = 0, violAbsLb = 0;
00543     if(lhs > -COUENNE_INFINITY) {
00544       violAbsLb = - body + lhs;
00545       violRelLb = violAbsLb / denomLb;
00546       violLb = violAbsLb - precision * denomLb;
00547 
00548 #ifdef FM_USE_ABS_VIOL_CONS
00549       maxViol = (maxViol > violAbsLb ? maxViol : violAbsLb);
00550 #else
00551       maxViol = (maxViol > violRelLb ? maxViol : violRelLb);
00552 #endif
00553 
00554 #ifdef FM_TRACE_NLP
00555       printf("violAbsLb: %12.10f  violRelLb: %12.10f  violLb: %12.10f maxViol: %12.10f\n",
00556              violAbsLb, violRelLb, violLb, maxViol);
00557 #endif
00558     }
00559 
00560 #ifdef FM_USE_ABS_VIOL_CONS
00561     if((violAbsUb > precision) || (violAbsLb > precision)) {
00562       if (Jnlst()->ProduceOutput(Ipopt::J_MOREVECTOR, J_PROBLEM)) {
00563         
00564         printf ("CouenneProblem::checkCons(): constraint %d violated (lhs=%+e body=%+e rhs=%+e, absolute violation: %g)\n",
00565                 i, lhs, body, rhs, CoinMax(violAbsUb, violAbsLb));
00566         
00567         c -> print ();
00568       }
00569       
00570       
00571 #ifdef FM_TRACE_NLP
00572       printf ("CouenneProblem::checkCons(): constraint %d violated (lhs=%+e body=%+e rhs=%+e, absolute violation: %g)\n",
00573               i, lhs, body, rhs, CoinMax (violAbsUb, violAbsLb));
00574 #endif
00575 
00576       isFeas = false;
00577       if(stopAtFirstViol) {
00578         break;
00579       }
00580     }
00581 #else /* not FM_USE_ABS_VIOL_CONS */
00582     if((violUb > 0) || (violLb > 0)) {
00583       if (Jnlst()->ProduceOutput(Ipopt::J_MOREVECTOR, J_PROBLEM)) {
00584         
00585         printf ("CouenneProblem::checkCons(): constraint %d violated (lhs=%+e body=%+e rhs=%+e, relative violation: %g)\n",
00586                 i, lhs, body, rhs, CoinMax(violRelUb, violRelLb));
00587         
00588         c -> print ();
00589       }
00590       
00591       
00592 #ifdef FM_TRACE_NLP
00593       printf ("CouenneProblem::checkCons(): constraint %d violated (lhs=%+e body=%+e rhs=%+e, relative violation: %g)\n",
00594               i, lhs, body, rhs, CoinMax (violRelUb, violRelLb));
00595 #endif
00596       isFeas = false;
00597       if(stopAtFirstViol) {
00598         break;
00599       }
00600     }
00601 #endif /* not FM_USE_ABS_VIOL_CONS */
00602   }
00603   return(isFeas);
00604 }
00605 
00606 /************************************************************************/
00607 bool CouenneProblem::checkNLP2(const double *solution, 
00608                                const double obj, const bool careAboutObj,
00609                                const bool stopAtFirstViol,
00610                                const bool checkAll,
00611                                const double precision) const {
00612 
00613   if(careAboutObj) {
00614     if(stopAtFirstViol) {
00615       printf("CouenneProblem::checkNLP2(): ### ERROR: careAboutObj: true and stopAtFirstViol: true are incompatible\n");
00616       exit(1);
00617     }
00618   }
00619 
00620   const std::vector<int> listInt = getRecordBestSol()->getListInt();
00621   bool isFeas = false;
00622   double maxViolCouSol = 0;
00623   double maxViolRecSol = 0;
00624 
00625 #ifdef FM_TRACE_NLP
00626   const bool *initIsInt = getRecordBestSol()->getInitIsInt();
00627   printf("Integrality:\n");
00628   for (register int i=0; i<nVars(); i++) {
00629 
00630     if (variables_ [i] -> Multiplicity () <= 0) 
00631       continue;
00632 
00633     if(initIsInt[i]) {
00634       printf(" %d", i);
00635     }
00636   }
00637   printf("\n");
00638 
00639   printf("VAR:\n");
00640   for (register int i=0; i<nVars(); i++) {
00641 
00642     if (variables_ [i] -> Multiplicity () <= 0) 
00643       continue;
00644     exprVar *v = variables_ [i];
00645     if( (v -> Type () == VAR)) {
00646       printf(" %d", i);
00647     }
00648   }
00649   printf("\n");
00650 
00651   printf("AUX:\n");
00652   for (register int i=0; i<nVars(); i++) {
00653 
00654     if (variables_ [i] -> Multiplicity () <= 0) 
00655       continue;
00656     exprVar *v = variables_ [i];
00657     if( (v -> Type () == AUX)) {
00658       printf(" %d", i);
00659     }
00660   }
00661   printf("\n");
00662 
00663   printf("mult 0:\n");
00664   for (register int i=0; i<nVars(); i++) {
00665 
00666     if (variables_ [i] -> Multiplicity () <= 0) { 
00667       printf(" %d", i);
00668     }
00669   }
00670   printf("\n");
00671 #endif
00672 
00673   if ((Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_PROBLEM))) {
00674 
00675     printf ("checking solution:\n");
00676 
00677     for (int i=0; i<nOrigVars_ - ndefined_; i++)
00678       printf ("%.12e ", solution [i]);
00679     printf ("\n");
00680   }
00681 
00682 #ifdef FM_TRACE_NLP
00683   printf("CouenneProblem::checkNLP2(): Start checking computed_solution\n");
00684 #endif
00685 
00686   int from = 0;
00687   bool isFeasRec = checkInt(solution, from, nOrigVars_ - ndefined_, listInt,
00688                             false, stopAtFirstViol,
00689                             precision, maxViolRecSol);
00690   bool isFeasCou = isFeasRec;
00691   maxViolCouSol = maxViolRecSol;
00692 
00693   if(stopAtFirstViol && !isFeasRec) {
00694 
00695 #ifdef FM_TRACE_NLP
00696     printf("CouenneProblem::checkNLP2(): modified_solution is infeasible (some orig vars not integer feasible; violation: %12.10g)\n", maxViolRecSol);
00697 #endif
00698   }
00699 
00700 #ifdef CHECK
00701   if(getRecordBestSol()->getCardInitDom() != nVars()) {
00702     printf("CouenneProblem::checkNLP2(): ### ERROR: cardInitDom: %d  nVars: %d\n", (getRecordBestSol()->getCardInitDom(), nVars());
00703     exit(1);
00704   }
00705   if(getInitDomLb() == NULL) {
00706     printf("CouenneProblem::checkNLP2(): ### WARNING: initDomLb == NULL\n");
00707   }
00708   if(getInitDomUb() == NULL) {
00709     printf("CouenneProblem::checkNLP2(): ### WARNING: initDomUb == NULL\n");
00710   }
00711 #endif
00712 
00713   // install NL solution candidate and original bounds in evaluation structure
00714   // bounds are important so that getAuxs below works properly
00715   domain_.push(nVars(), domain_.x(), getRecordBestSol()->getInitDomLb(), 
00716                getRecordBestSol()->getInitDomUb(), false);
00717 
00718   CouNumber *couRecSol = new CouNumber[nVars()];
00719   CoinCopyN (solution, nOrigVars_ - ndefined_, couRecSol);
00720   getAuxs(couRecSol);
00721   //CoinCopyN (solution, nOrigVars_, couRecSol);
00722 
00723   // install couRecSol in evaluation structure
00724   domain_.push(nVars(), couRecSol, getRecordBestSol()->getInitDomLb(), 
00725                getRecordBestSol()->getInitDomUb(), false);
00726 
00727   if (
00728 #ifdef FM_TRACE_NLP
00729       (1) || 
00730 #endif
00731 
00732       (Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_PROBLEM))) {
00733     printf ("checkNLP2(): recomputed_solution: %d vars -------------------\n", domain_.current () -> Dimension ());
00734 
00735     double maxDelta = 0;
00736     for (int i=0; i<domain_.current () -> Dimension (); i++) {
00737       printf ("%4d %.12g %.12g [%.12g %.12g]\n", 
00738               i, solution[i], domain_.x (i), domain_.lb (i), domain_.ub (i));
00739       maxDelta = (maxDelta > fabs(solution[i] - domain_.x(i)) ? 
00740                   maxDelta : fabs(solution[i] - domain_.x(i)));
00741     }
00742     printf("maxDelta: %.12g\n", maxDelta);
00743   }
00744 
00745   if(checkAll) {
00746     if(!stopAtFirstViol || isFeasRec) {
00747       bool isFeasInt = checkInt(couRecSol, nOrigVars_ - ndefined_, nVars(), listInt,
00748                                 false, stopAtFirstViol,
00749                                 precision, maxViolRecSol);
00750       if(!isFeasInt) {
00751         
00752 #ifdef FM_TRACE_NLP
00753         printf("CouenneProblem::checkNLP2(): recomputed_solution is infeasible (some aux vars not integer feasible; violation: %12.10g)\n", maxViolRecSol);
00754 #endif
00755         
00756         isFeasRec = false;
00757       }
00758     }
00759   }
00760 
00761   double objRecSol = checkObj(couRecSol, precision);
00762   double objCouSol = 0;
00763 
00764   if(checkAll) {
00765     if(!stopAtFirstViol || isFeasRec) {
00766       bool isFeasBnd = checkBounds(couRecSol, stopAtFirstViol, 
00767                                    precision, maxViolRecSol);
00768       if(!isFeasBnd) {
00769         
00770 #ifdef FM_TRACE_NLP
00771         printf("CouenneProblem::checkNLP2(): recomputed_solution is infeasible (violated bounds; violation: %12.10g)\n", maxViolRecSol);
00772 #endif
00773         
00774         isFeasRec = false;
00775       }
00776     }
00777   }
00778 
00779   if(checkAll) {
00780     if(!stopAtFirstViol || isFeasRec) {
00781       bool isFeasAux = checkAux(couRecSol, stopAtFirstViol, 
00782                                 precision, maxViolRecSol);
00783       
00784       if(!isFeasAux) {
00785         
00786 #ifdef FM_TRACE_NLP
00787         printf("CouenneProblem::checkNLP2(): recomputed_solution is infeasible (violated Aux; violation: %12.10g)\n", maxViolRecSol);
00788 #endif
00789         
00790         isFeasRec = false;
00791       }
00792     }
00793   }
00794 
00795   if(!stopAtFirstViol || isFeasRec) {
00796     bool isFeasCons = checkCons(couRecSol, stopAtFirstViol, 
00797                                 precision, maxViolRecSol);
00798     if(!isFeasCons) {
00799 
00800 #ifdef FM_TRACE_NLP
00801       printf("CouenneProblem::checkNLP2(): recomputed_solution is infeasible (violated constraint; violation: %12.10g)\n", maxViolRecSol);
00802 #endif
00803 
00804       isFeasRec = false;
00805     }
00806   }
00807 
00808 #ifdef FM_TRACE_NLP
00809   printf("CouenneProblem::checkNLP2(): end check recomputed_solution (maxViol: %12.10g)\n", maxViolRecSol);
00810 #endif
00811 
00812   double objErrorRecSol = objRecSol - obj;
00813   if(!careAboutObj) {
00814     objErrorRecSol = 0;
00815   }
00816 
00817   CouNumber *couSol = new CouNumber[nVars()];
00818   bool useRecSol = false;
00819   if(isFeasRec && (objErrorRecSol < precision)) {
00820     useRecSol = true;
00821     isFeas = true;
00822   }
00823   else {
00824   
00825     if(checkAll) { // otherwise duplicates above calculations
00826 
00827     
00828 #ifdef FM_TRACE_NLP
00829       printf("CouenneProblem::checkNLP2(): Start checking solution (maxViol: %g)\n",
00830              maxViolCouSol);
00831 #endif
00832       
00833       CoinCopyN(solution, nVars(), couSol);
00834       restoreUnusedOriginals(couSol);
00835       domain_.push(nVars(), couSol, getRecordBestSol()->getInitDomLb(), 
00836                    getRecordBestSol()->getInitDomUb(), false);
00837     
00838       if (
00839 #ifdef FM_TRACE_NLP
00840           (1) || 
00841 #endif
00842           
00843           (Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_PROBLEM))) {
00844         printf ("checkNLP2(): solution: %d vars -------------------\n", domain_.current () -> Dimension ());
00845         
00846         double maxDelta = 0;
00847         for (int i=0; i<domain_.current()->Dimension(); i++) {
00848           printf ("%4d %.12g %.12g [%.12g %.12g]\n", 
00849                   i, solution[i], domain_.x(i), domain_.lb(i), domain_.ub(i));
00850           maxDelta = (maxDelta > fabs(solution[i] - domain_.x(i)) ? 
00851                       maxDelta : fabs(solution[i] - domain_.x(i)));
00852         }
00853         printf("maxDelta: %.12g\n", maxDelta);
00854       }
00855       
00856       if(!stopAtFirstViol || isFeasCou) {
00857         bool isFeasInt = checkInt(couSol, nOrigVars_ - ndefined_, nVars(), listInt,
00858                                   false, stopAtFirstViol,
00859                                   precision, maxViolCouSol);
00860         if(!isFeasInt) {
00861           
00862 #ifdef FM_TRACE_NLP
00863           printf("CouenneProblem::checkNLP2(): solution is infeasible (some aux vars not integer feasible; violation: %12.10g)\n", maxViolCouSol);
00864 #endif
00865           
00866           isFeasCou = false;
00867         }
00868       }
00869       
00870       objCouSol = checkObj(couSol, precision);
00871       
00872       if(!stopAtFirstViol || isFeasCou) {
00873         bool isFeasCouBnd = checkBounds(couSol, stopAtFirstViol, 
00874                                         precision, maxViolCouSol);
00875         if(!isFeasCouBnd) {
00876           
00877 #ifdef FM_TRACE_NLP
00878           printf("CouenneProblem::checkNLP2(): solution is infeasible (some bounds are violated; violation: %12.10g)\n", maxViolCouSol);
00879 #endif
00880           
00881           isFeasCou = false;
00882         }
00883       }
00884       
00885       if(!stopAtFirstViol || isFeasCou) {
00886         bool isFeasCouAux = checkAux(couSol, stopAtFirstViol, 
00887                                      precision, maxViolCouSol);
00888         if(!isFeasCouAux) {
00889           
00890 #ifdef FM_TRACE_NLP
00891           printf("CouenneProblem::checkNLP2(): solution is infeasible (violated Aux; violation: %12.10g)\n", maxViolCouSol);
00892 #endif
00893           
00894           isFeasCou = false;
00895         }
00896       }
00897       
00898       if(!stopAtFirstViol || isFeasCou) {
00899         bool isFeasCouCons = checkCons(couSol, stopAtFirstViol, 
00900                                        precision, maxViolCouSol);
00901         if(!isFeasCouCons) {
00902           
00903 #ifdef FM_TRACE_NLP
00904           printf("CouenneProblem::checkNLP2(): solution is infeasible (violated constraint; violation: %12.10g)\n", maxViolCouSol);
00905 #endif
00906           
00907           isFeasCou = false;
00908         }
00909       }
00910     
00911 #ifdef FM_TRACE_NLP
00912       printf("CouenneProblem::checkNLP2(): end check solution (maxViol: %12.10g)\n", maxViolCouSol);
00913 #endif
00914     
00915       double objErrorCouSol = objCouSol - obj;
00916       if(!careAboutObj) {
00917         objErrorCouSol = 0;
00918       }
00919       double delObj = objErrorCouSol - objErrorRecSol;
00920       double delViol = maxViolCouSol - maxViolRecSol;
00921 
00922       if(isFeasRec) {
00923         if(isFeasCou) {
00924           // careAboutObj must be true
00925           if(delObj > 0) {
00926             useRecSol = true;
00927           }
00928           else {
00929             useRecSol = false;            
00930           }
00931           isFeas = true;
00932         }
00933         else { /* isFeasRec == true and isFeasCou == false */
00934           useRecSol = true;
00935           isFeas = true;
00936         }
00937       }
00938       else { /* isFeasRec == false */
00939         if(isFeasCou) {
00940           useRecSol = false;            
00941           isFeas = true;
00942         }
00943         else { /* isFeasRec == false and isFeasCou == false */
00944           isFeas = false;
00945           if(careAboutObj) {
00946             if(fabs(delViol) < 10 * precision) {
00947               useRecSol = (delObj > 0 ? false : true);
00948             }
00949             else {
00950               if(fabs(delObj) < 10 * precision) {
00951                 useRecSol = (delViol > 0 ? false : true);
00952               }
00953               else {
00954                 double ratObj = fabs(delObj)/(1+fabs(obj));
00955                 if(ratObj < fabs(delViol)) {
00956                   useRecSol = (delViol > 0 ? false : true);
00957                 }
00958                 else {
00959                   useRecSol = (delObj > 0 ? false : true);
00960                 }
00961               }
00962             }
00963           }
00964           else {
00965             if(delViol < 0) {
00966               useRecSol = false;
00967             }
00968             else {
00969               useRecSol = true;
00970             }
00971           }
00972           useRecSol = true;
00973         }
00974       }
00975       domain_.pop (); // pop couSol
00976     } 
00977   }
00978   
00979   double maxViol = 0;
00980   
00981   if(!stopAtFirstViol || isFeas) {
00982     if(useRecSol) {
00983       recBSol->setModSol(couRecSol, nVars(), objRecSol, maxViolRecSol);
00984       maxViol = maxViolRecSol;
00985       
00986 #ifdef FM_TRACE_NLP
00987       printf("CouenneProblem::checkNLP2(): select recomputed_solution (maxViol: %12.10g)\n", maxViol);
00988 #endif
00989       
00990     }
00991     else {
00992       recBSol->setModSol(couSol, nVars(), objCouSol, maxViolCouSol);
00993       maxViol = maxViolCouSol;
00994       
00995 #ifdef FM_TRACE_NLP
00996       printf("CouenneProblem::checkNLP2(): select solution (maxViol: %12.10g)\n", maxViol);
00997 #endif
00998       
00999     }
01000   }
01001   delete[] couSol;
01002   delete[] couRecSol;
01003   domain_.pop();  // pop couRecSol
01004   domain_.pop (); // pop bounds
01005     
01006 #ifdef FM_TRACE_NLP
01007   if(isFeas) {
01008     printf ("checkNLP2(): RETURN: selected solution is feasible (maxViol: %g)\n", maxViol);
01009   }
01010   else {
01011     printf ("checkNLP2(): RETURN: modified_solution and solution are infeasible\n");
01012     if(!stopAtFirstViol) {
01013       printf("(maxViol: %g)\n", maxViol);
01014     }
01015     else {
01016       printf("\n");
01017     }
01018   }
01019 #endif
01020 
01021   return isFeas;
01022 }

Generated on Thu Nov 10 03:05:45 2011 by  doxygen 1.4.7