/home/coin/SVN-release/OS-1.1.1/Bonmin/src/Interfaces/Ampl/BonAmplTMINLP.cpp

Go to the documentation of this file.
00001 // (C) Copyright International Business Machines Corporation and
00002 // Carnegie Mellon University 2004, 2007
00003 //
00004 // All Rights Reserved.
00005 // This code is published under the Common Public License.
00006 //
00007 // Authors :
00008 // Carl D. Laird, Carnegie Mellon University,
00009 // Andreas Waechter, International Business Machines Corporation
00010 // Pierre Bonami, Carnegie Mellon University,
00011 //
00012 // Date : 12/01/2004
00013 #include "IpBlas.hpp"
00014 
00015 #include <list>
00016 
00017 #include "AmplTNLP.hpp"
00018 #include "BonAmplTMINLP.hpp"
00019 #include <iostream>
00020 #include <fstream>
00021 
00022 #include "CoinHelperFunctions.hpp"
00023 #include "BonExitCodes.hpp"
00024 namespace Bonmin{
00025   void 
00026   RegisteredOptions::fillAmplOptionList(ExtraCategoriesInfo which, Ipopt::AmplOptionsList * amplOptList){
00027       std::list<int> test;
00028       std::list< Ipopt::RegisteredOption * > options;
00029       chooseOptions(which, options);
00030       for(std::list< Ipopt::RegisteredOption * >::iterator i = options.begin();
00031            i != options.end() ; i++)
00032        {
00033            std::string name = "bonmin.";
00034            name += (*i)->Name();
00035            Ipopt::RegisteredOptionType T = (*i)->Type();
00036            Ipopt::AmplOptionsList::AmplOptionType  type;
00037            switch(T){
00038              case Ipopt::OT_Number: type = Ipopt::AmplOptionsList::Number_Option;
00039                   break;
00040              case Ipopt::OT_Integer: type = Ipopt::AmplOptionsList::Integer_Option;
00041                   break;
00042              case Ipopt::OT_String: type = Ipopt::AmplOptionsList::String_Option;
00043                   break;
00044              case Ipopt::OT_Unknown:
00045              default:
00046                 throw CoinError("RegisteredOptions","fillAmplOptionList","Unknown option type");
00047            }
00048            amplOptList->AddAmplOption(name, name, type, (*i)->ShortDescription());
00049        }
00050 }
00051 }
00052 #include "asl.h"
00053 #include "asl_pfgh.h"
00054 #include "getstub.h"
00055 
00056 namespace ampl_utils
00057 {
00058   void sos_kludge(int nsos, int *sosbeg, double *sosref);
00059 }
00060 namespace Bonmin
00061 {
00062 
00063   AmplTMINLP::AmplTMINLP()
00064       :
00065       TMINLP(),
00066       upperBoundingObj_(-1),
00067       ampl_tnlp_(NULL),
00068       branch_(),
00069       sos_(),
00070       suffix_handler_(NULL),
00071       constraintsConvexities_(NULL),
00072       numberNonConvex_(0),
00073       nonConvexConstraintsAndRelaxations_(NULL),
00074       numberSimpleConcave_(0),
00075       simpleConcaves_(NULL),
00076       hasLinearObjective_(false)
00077   {}
00078 
00079 
00080   AmplTMINLP::AmplTMINLP(const SmartPtr<const Journalist>& jnlst,
00081       const SmartPtr<Bonmin::RegisteredOptions> roptions,
00082       const SmartPtr<OptionsList> options,
00083       char**& argv,
00084       AmplSuffixHandler* suffix_handler /*=NULL*/,
00085       const std::string& appName,
00086       std::string* nl_file_content /* = NULL */
00087                         )
00088       :
00089       TMINLP(),
00090       upperBoundingObj_(-1),
00091       ampl_tnlp_(NULL),
00092       branch_(),
00093       sos_(),
00094       suffix_handler_(NULL),
00095       constraintsConvexities_(NULL),
00096       numberNonConvex_(0),
00097       nonConvexConstraintsAndRelaxations_(NULL),
00098       numberSimpleConcave_(0),
00099       simpleConcaves_(NULL),
00100       hasLinearObjective_(false)
00101   {
00102     Initialize(jnlst, roptions, options, argv, suffix_handler, appName, nl_file_content);
00103   }
00104 
00105   void
00106   AmplTMINLP::Initialize(const SmartPtr<const Journalist>& jnlst,
00107       const SmartPtr<Bonmin::RegisteredOptions> roptions,
00108       const SmartPtr<OptionsList> options,
00109       char**& argv,
00110       AmplSuffixHandler* suffix_handler /*=NULL*/,
00111       const std::string& appName,
00112       std::string* nl_file_content /* = NULL */
00113                         )
00114   {
00115     options->GetEnumValue("file_solution",writeAmplSolFile_,"bonmin.");
00116     jnlst_ = jnlst;
00117 
00118     if (suffix_handler==NULL)
00119       suffix_handler_ = suffix_handler = new AmplSuffixHandler();
00120 
00121     // Add the suffix handler for scaling
00122     suffix_handler->AddAvailableSuffix("scaling_factor", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00123     suffix_handler->AddAvailableSuffix("scaling_factor", AmplSuffixHandler::Constraint_Source, AmplSuffixHandler::Number_Type);
00124     suffix_handler->AddAvailableSuffix("scaling_factor", AmplSuffixHandler::Objective_Source, AmplSuffixHandler::Number_Type);
00125 
00126     // Modified for warm-start from AMPL
00127     suffix_handler->AddAvailableSuffix("ipopt_zL_out", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00128     suffix_handler->AddAvailableSuffix("ipopt_zU_out", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00129     suffix_handler->AddAvailableSuffix("ipopt_zL_in", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00130     suffix_handler->AddAvailableSuffix("ipopt_zU_in", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00131 
00132     // priority suffix
00133     suffix_handler->AddAvailableSuffix("priority", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Index_Type);
00134     suffix_handler->AddAvailableSuffix("direction", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00135     suffix_handler->AddAvailableSuffix("downPseudocost", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00136     suffix_handler->AddAvailableSuffix("upPseudocost", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00137 
00138 
00139 
00140     // sos suffixes
00141     suffix_handler->AddAvailableSuffix("ref", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00142     suffix_handler->AddAvailableSuffix("sos",AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Index_Type);
00143     suffix_handler->AddAvailableSuffix("sos",AmplSuffixHandler::Constraint_Source, AmplSuffixHandler::Index_Type);
00144     suffix_handler->AddAvailableSuffix("sosno",AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00145     suffix_handler->AddAvailableSuffix("sosref",AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00146     suffix_handler->AddAvailableSuffix("sstatus", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Index_Type);
00147     suffix_handler->AddAvailableSuffix("sstatus", AmplSuffixHandler::Constraint_Source, AmplSuffixHandler::Index_Type);
00148 
00149 
00150     // For marking convex/nonconvex constraints
00151     suffix_handler->AddAvailableSuffix("id",AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Index_Type);
00152     suffix_handler->AddAvailableSuffix("primary_var",AmplSuffixHandler::Constraint_Source, AmplSuffixHandler::Index_Type);
00153 
00154     // For objectives
00155     suffix_handler->AddAvailableSuffix("UBObj", AmplSuffixHandler::Objective_Source, AmplSuffixHandler::Index_Type);
00156 
00157 
00158     // Perturbation radius
00159     suffix_handler->AddAvailableSuffix("perturb_radius",AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00160 
00161     SmartPtr<AmplOptionsList> ampl_options_list = new AmplOptionsList();
00162     roptions->fillAmplOptionList(RegisteredOptions::BonminCategory, GetRawPtr(ampl_options_list));
00163     roptions->fillAmplOptionList(RegisteredOptions::FilterCategory, GetRawPtr(ampl_options_list));
00164     roptions->fillAmplOptionList(RegisteredOptions::BqpdCategory, GetRawPtr(ampl_options_list));
00165     fillApplicationOptions(GetRawPtr(ampl_options_list) );
00166     std::string options_id = appName + "_options";
00167     ampl_tnlp_ = new AmplTNLP(jnlst, options, argv, suffix_handler, true,
00168         ampl_options_list, options_id.c_str(),
00169         appName.c_str(), appName.c_str(), nl_file_content);
00170     /* Read suffixes */
00171     read_obj_suffixes();
00172     read_priorities();
00173     read_convexities();
00174     read_sos();
00175 
00176 
00177     /* Determine if objective is linear.*/
00178     Index n_non_linear_b= 0;
00179     Index n_non_linear_bi= 0;
00180     Index n_non_linear_c= 0;
00181     Index n_non_linear_ci = 0;
00182     Index n_non_linear_o= 0;
00183     Index n_non_linear_oi = 0;
00184     Index n_binaries = 0;
00185     Index n_integers = 0;
00186     ampl_tnlp_->get_discrete_info(n_non_linear_b, n_non_linear_bi, n_non_linear_c,
00187         n_non_linear_ci, n_non_linear_o, n_non_linear_oi,
00188         n_binaries, n_integers);
00189     if (n_non_linear_b == 0 && n_non_linear_o == 0) {
00190       hasLinearObjective_ = true;
00191     }
00192   }
00193 
00194   AmplTMINLP::~AmplTMINLP()
00195   {
00196     delete [] constraintsConvexities_;
00197     delete [] simpleConcaves_;
00198     delete [] nonConvexConstraintsAndRelaxations_;
00199     delete ampl_tnlp_;
00200   }
00201 
00202   void
00203   AmplTMINLP::read_priorities()
00204   {
00205     int numcols, m, dummy1, dummy2;
00206     TNLP::IndexStyleEnum index_style;
00207     ampl_tnlp_->get_nlp_info(numcols, m, dummy1, dummy2, index_style);
00208 
00209     const AmplSuffixHandler * suffix_handler = GetRawPtr(suffix_handler_);
00210 
00211     const Index* pri = suffix_handler->GetIntegerSuffixValues("priority", AmplSuffixHandler::Variable_Source);
00212     const Index* brac = suffix_handler->GetIntegerSuffixValues("direction", AmplSuffixHandler::Variable_Source);
00213     const Number* upPs = suffix_handler->GetNumberSuffixValues("upPseudocost", AmplSuffixHandler::Variable_Source);
00214     const Number* dwPs = suffix_handler->GetNumberSuffixValues("downPseudocost", AmplSuffixHandler::Variable_Source);
00215 
00216 
00217     branch_.gutsOfDestructor();
00218     branch_.size = numcols;
00219     if (pri) {
00220       branch_.priorities = new int[numcols];
00221       for (int i = 0 ; i < numcols ; i++) {
00222         branch_.priorities [i] = -pri[i] + 9999;
00223       }
00224     }
00225     if (brac) {
00226       branch_.branchingDirections = CoinCopyOfArray(brac,numcols);
00227     }
00228     if (upPs && !dwPs) dwPs = upPs;
00229     else if (dwPs && !upPs) upPs = dwPs;
00230 
00231     if (upPs) {
00232       branch_.upPsCosts = CoinCopyOfArray(upPs,numcols);
00233     }
00234     if (dwPs) {
00235       branch_.downPsCosts = CoinCopyOfArray(dwPs,numcols);
00236     }
00237 
00238     const double* perturb_radius =
00239       suffix_handler->GetNumberSuffixValues("perturb_radius", AmplSuffixHandler::Variable_Source);
00240     perturb_info_.SetPerturbationArray(numcols, perturb_radius);
00241   }
00242 
00243   void
00244   AmplTMINLP::read_sos()
00245   {
00246     ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00247 
00248     int i = 0;//ASL_suf_sos_explict_free;
00249     int copri[2], **p_sospri;
00250     copri[0] = 0;
00251     copri[1] = 0;
00252     int * starts = NULL;
00253     int * indices = NULL;
00254     char * types = NULL;
00255     double * weights = NULL;
00256     int * priorities = NULL;
00257     p_sospri = &priorities;
00258 
00259     sos_.gutsOfDestructor();
00260 
00261     sos_.num = suf_sos(i, &sos_.numNz, &types, p_sospri, copri,
00262         &starts, &indices, &weights);
00263     if (sos_.num) {
00264       //Copy sos information
00265       sos_.priorities = CoinCopyOfArray(priorities,sos_.num);
00266       sos_.starts = CoinCopyOfArray(starts, sos_.num + 1);
00267       sos_.indices = CoinCopyOfArray(indices, sos_.numNz);
00268       sos_.types = CoinCopyOfArray(types, sos_.num);
00269       sos_.weights = CoinCopyOfArray(weights, sos_.numNz);
00270 
00271       ampl_utils::sos_kludge(sos_.num, sos_.starts, sos_.weights);
00272       for (int ii=0;ii<sos_.num;ii++) {
00273         int ichar = sos_.types[ii];
00274         if (ichar != '1' && ichar != '2') {
00275           std::cerr<<"Unsuported type of sos constraint: "<<sos_.types[ii]<<std::endl;
00276           throw;
00277         }
00278         sos_.types[ii]= 1;
00279       }
00280     }
00281   }
00282 
00283   void
00284   AmplTMINLP::read_obj_suffixes()
00285   {
00286     ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00287     DBG_ASSERT(asl);
00288     //Get the values
00289     if (n_obj < 2) return;
00290 
00291     const AmplSuffixHandler * suffix_handler = GetRawPtr(suffix_handler_);
00292 
00293     const Index* UBObj = suffix_handler->GetIntegerSuffixValues("UBObj", AmplSuffixHandler::Objective_Source);
00294     if (UBObj) {
00295       //get index of lower bounding objective
00296       int lowerBoundingObj = (UBObj[0] == 1)? 1:0;
00297       // Pass information to Ipopt
00298       ampl_tnlp_->set_active_objective(lowerBoundingObj);
00299 
00300       //get the index of upper bounding objective
00301       for (int i = 0; i < n_obj; i++) {
00302         if (UBObj[i]==1) {
00303           if (upperBoundingObj_ != -1) {
00304             jnlst_->Printf(J_ERROR, J_MAIN,
00305                 "Too many objectives for upper-bounding");
00306           }
00307           upperBoundingObj_ = i;
00308         }
00309       }
00310     }
00311     else {
00312       ampl_tnlp_->set_active_objective(0);
00313     }
00314   }
00316   struct NonConvexSuff
00317   {
00319     NonConvexSuff():
00320         cIdx(-1),relIdx(-1),scXIdx(-1),scYIdx(-1)
00321     {}
00323     NonConvexSuff(const NonConvexSuff& other):
00324         cIdx(other.cIdx), relIdx(other.relIdx),
00325         scXIdx(other.scXIdx), scYIdx(other.scYIdx)
00326     {}
00328     int cIdx;
00330     int relIdx;
00332     int scXIdx;
00334     int scYIdx;
00335   };
00336   void AmplTMINLP::read_convexities()
00337   {
00338     ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00339     DBG_ASSERT(asl);
00340 
00341     const AmplSuffixHandler * suffix_handler = GetRawPtr(suffix_handler_);
00342     const Index * id = suffix_handler->GetIntegerSuffixValues("id", AmplSuffixHandler::Variable_Source);
00343     const Index * primary_var = suffix_handler->GetIntegerSuffixValues("primary_var", AmplSuffixHandler::Constraint_Source);
00344 
00345 
00346     if (primary_var!= NULL) {
00347       if (constraintsConvexities_ != NULL) {
00348         delete [] constraintsConvexities_;
00349       }
00350       constraintsConvexities_ = new TMINLP::Convexity[n_con];
00351       if (id == NULL) {
00352         std::cerr<<"Incorrect suffixes description in ampl model. id's are not declared "<<std::endl;
00353         exit(ERROR_IN_AMPL_SUFFIXES);
00354       }
00355       int numberSimpleConcave = 0;
00356       std::map<int, int> id_map;
00357 
00358       for (int i = 0 ; i < n_var ; i++) {
00359         id_map[id[i]] = i;
00360       }
00361 
00362 
00363       for (int i = 0 ; i < n_con ; i++) {
00364         if (primary_var[i] != 0) {
00365           constraintsConvexities_[i] = TMINLP::SimpleConcave;
00366           numberSimpleConcave++;
00367         }
00368         else constraintsConvexities_[i] = TMINLP::Convex;
00369       }
00370       simpleConcaves_ = new SimpleConcaveConstraint[numberSimpleConcave];
00371       nonConvexConstraintsAndRelaxations_ = new MarkedNonConvex[numberSimpleConcave];
00372       numberSimpleConcave = 0;
00373       int * jCol = new int[n_var];
00374       for (int i = 0 ; i < n_con ; i++) {
00375         if (primary_var[i] != 0) {
00376           nonConvexConstraintsAndRelaxations_[numberSimpleConcave].cIdx = i;
00377           nonConvexConstraintsAndRelaxations_[numberSimpleConcave].cRelaxIdx = -1;
00378           simpleConcaves_[numberSimpleConcave].cIdx = i;
00379           simpleConcaves_[numberSimpleConcave].yIdx = id_map[primary_var[i]];
00380 
00381           //Now get gradient of i to get xIdx.
00382           int nnz;
00383           int & yIdx = simpleConcaves_[numberSimpleConcave].yIdx;
00384           int & xIdx = simpleConcaves_[numberSimpleConcave].xIdx;
00385           eval_grad_gi(n_var, NULL, false, i, nnz, jCol, NULL);
00386           if (nnz != 2) {//Error in ampl model
00387             std::cout<<"Incorrect suffixes description in ampl model. Constraint with id "
00388             <<id<<" is simple concave and should have only two nonzero elements"<<std::endl;
00389             exit(ERROR_IN_AMPL_SUFFIXES);
00390           }
00391           if (jCol[0] - 1== yIdx) {
00392             xIdx = jCol[1] - 1;
00393           }
00394           else {
00395             if (jCol[1] - 1!= yIdx) {//Error in ampl model
00396               std::cout<<"Incorrect suffixes description in ampl model. Constraint with id "
00397               <<id<<" : variable marked as y does not appear in the constraint."<<std::endl;
00398               exit(ERROR_IN_AMPL_SUFFIXES);
00399             }
00400             xIdx = jCol[0] - 1;
00401           }
00402           numberSimpleConcave++;
00403         }
00404       }
00405       delete [] jCol;
00406       numberSimpleConcave_ = numberSimpleConcave;
00407       numberNonConvex_ = numberSimpleConcave;
00408     }
00409 
00410   }
00411 
00412   bool AmplTMINLP::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, Index& nnz_h_lag, TNLP::IndexStyleEnum& index_style)
00413   {
00414     return ampl_tnlp_->get_nlp_info(n, m, nnz_jac_g, nnz_h_lag, index_style);
00415   }
00416 
00417   bool AmplTMINLP::get_variables_types(Index n, VariableType* var_types)
00418   {
00419     // The variables are sorted by type in AMPL, so all we need to
00420     // know are the counts of each type.
00421 
00422 
00423     Index n_non_linear_b= 0;
00424     Index n_non_linear_bi= 0;
00425     Index n_non_linear_c= 0;
00426     Index n_non_linear_ci = 0;
00427     Index n_non_linear_o= 0;
00428     Index n_non_linear_oi = 0;
00429     Index n_binaries = 0;
00430     Index n_integers = 0;
00431     ampl_tnlp_->get_discrete_info(n_non_linear_b, n_non_linear_bi, n_non_linear_c,
00432         n_non_linear_ci, n_non_linear_o, n_non_linear_oi,
00433         n_binaries, n_integers);
00434     int totalNumberOfNonContinuous = 0;
00435 
00436 
00437     //begin with variables non-linear both in the objective function and in some constraints
00438     // The first ones are continuous
00439     Index start = 0;
00440     Index end = n_non_linear_b - n_non_linear_bi;
00441     for (int i=start; i<end; i++) {
00442       var_types[i] = CONTINUOUS;
00443     }
00444 
00445     // The second ones are integers
00446     start = end;
00447     end = start + n_non_linear_bi;
00448     for (int i=start; i < end; i++) {
00449       var_types[i] = INTEGER;
00450       totalNumberOfNonContinuous++;
00451     }
00452     //next variables non-linear in some constraints
00453     // The first ones are continuous
00454     start = end;
00455     end = max(start,end + n_non_linear_c - n_non_linear_ci - n_non_linear_b);
00456     for (int i=start; i<end; i++) {
00457       var_types[i] = CONTINUOUS;
00458     }
00459 
00460     // The second ones are integers
00461     start = end;
00462     end = start + n_non_linear_ci;
00463     for (int i=start; i < end; i++) {
00464       var_types[i] = INTEGER;
00465       totalNumberOfNonContinuous++;
00466     }
00467 
00468     //next variables non-linear in the objective function
00469     // The first ones are continuous
00470     start = end;
00471     end = max(start,end + n_non_linear_o - max(n_non_linear_b, n_non_linear_c) - n_non_linear_oi);
00472     for (int i=start; i<end; i++) {
00473       var_types[i] = CONTINUOUS;
00474     }
00475 
00476     // The second ones are integers
00477     start = end;
00478     end = start + n_non_linear_oi;
00479     for (int i=start; i < end; i++) {
00480       var_types[i] = INTEGER;
00481       totalNumberOfNonContinuous++;
00482     }
00483 
00484     //At last the linear variables
00485     // The first ones are continuous
00486     start = end;
00487     end = n - n_binaries - n_integers;
00488     for (int i=start; i<end; i++) {
00489       var_types[i] = CONTINUOUS;
00490     }
00491 
00492     // The second ones are binaries
00493     start = end;
00494     end = start + n_binaries;
00495     for (int i=start; i < end; i++) {
00496       var_types[i] = BINARY;
00497       totalNumberOfNonContinuous++;
00498     }
00499 
00500     // The third ones are integers
00501     start = end;
00502     end = start + n_integers;
00503     for (int i=start; i < end; i++) {
00504       var_types[i] = INTEGER;
00505       totalNumberOfNonContinuous++;
00506     }
00507     return true;
00508   }
00509 
00510   bool AmplTMINLP::get_variables_linearity(Index n, Ipopt::TNLP::LinearityType* var_types)
00511   {
00512     // The variables are sorted by type in AMPL, so all we need to
00513     // know are the counts of each type.
00514 
00515 
00516     Index n_non_linear_b= 0;
00517     Index n_non_linear_bi= 0;
00518     Index n_non_linear_c= 0;
00519     Index n_non_linear_ci = 0;
00520     Index n_non_linear_o= 0;
00521     Index n_non_linear_oi = 0;
00522     Index n_binaries = 0;
00523     Index n_integers = 0;
00524     ampl_tnlp_->get_discrete_info(n_non_linear_b, n_non_linear_bi, n_non_linear_c,
00525         n_non_linear_ci, n_non_linear_o, n_non_linear_oi,
00526         n_binaries, n_integers);
00527 
00528     //Compute the number of non linear variables:
00529     int n_non_linear = n_non_linear_c + n_non_linear_o - n_non_linear_b;
00530 
00531     int start = 0;
00532     int end = n_non_linear;
00533     for (int i=start; i<end; i++) {
00534       var_types[i] = Ipopt::TNLP::NON_LINEAR;
00535     }
00536 
00537     //At last the linear variables
00538     // The first ones are continuous
00539     start = end;
00540     end = n;
00541     for (int i=start; i<end; i++) {
00542       var_types[i] = Ipopt::TNLP::LINEAR;
00543     }
00544     return true;
00545   }
00546 
00549   bool
00550   AmplTMINLP::get_constraints_linearity(Index m,
00551       Ipopt::TNLP::LinearityType* const_types)
00552   {
00553     return ampl_tnlp_->get_constraints_linearity(m, const_types);
00554   }
00555 
00556   bool AmplTMINLP::get_bounds_info(Index n, Number* x_l, Number* x_u,
00557       Index m, Number* g_l, Number* g_u)
00558   {
00559     return ampl_tnlp_->get_bounds_info(n, x_l, x_u, m, g_l, g_u);
00560   }
00561 
00562   bool AmplTMINLP::get_starting_point(Index n, bool init_x, Number* x,
00563       bool init_z, Number* z_L, Number* z_U,
00564       Index m, bool init_lambda, Number* lambda)
00565   {
00566     return ampl_tnlp_->get_starting_point(n, init_x, x,
00567         init_z, z_L, z_U,
00568         m, init_lambda, lambda);
00569   }
00570 
00571   bool AmplTMINLP::eval_f(Index n, const Number* x, bool new_x, Number& obj_value)
00572   {
00573     return ampl_tnlp_->eval_f(n, x, new_x, obj_value);
00574   }
00575 
00576   bool AmplTMINLP::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
00577   {
00578     return ampl_tnlp_->eval_grad_f(n, x, new_x, grad_f);
00579   }
00580 
00581   bool AmplTMINLP::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g)
00582   {
00583     return ampl_tnlp_->eval_g(n, x, new_x, m, g);
00584   }
00585 
00586   bool AmplTMINLP::eval_jac_g(Index n, const Number* x, bool new_x,
00587       Index m, Index nele_jac, Index* iRow,
00588       Index *jCol, Number* values)
00589   {
00590     return ampl_tnlp_->eval_jac_g(n, x, new_x,
00591         m, nele_jac, iRow, jCol,
00592         values);
00593   }
00594 
00595   bool AmplTMINLP::eval_h(Index n, const Number* x, bool new_x,
00596       Number obj_factor, Index m, const Number* lambda,
00597       bool new_lambda, Index nele_hess, Index* iRow,
00598       Index* jCol, Number* values)
00599   {
00600     return ampl_tnlp_->eval_h(n, x, new_x, obj_factor,
00601         m, lambda, new_lambda, nele_hess, iRow,
00602         jCol, values);
00603   }
00604 
00605   bool AmplTMINLP::eval_gi(Index n, const Number* x, bool new_x,
00606       Index i, Number& gi)
00607   {
00608     ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00609 
00610     // ignore new_x for now
00611     xunknown();
00612 
00613     fint nerror = 0;
00614     gi = conival(i, const_cast<real*>(x), &nerror);
00615     if (nerror!=0) {
00616       return false;
00617     }
00618     else {
00619       return true;
00620     }
00621   }
00622 
00623   bool AmplTMINLP::eval_grad_gi(Index n, const Number* x, bool new_x,
00624       Index i, Index& nele_grad_gi, Index* jCol,
00625       Number* values)
00626   {
00627     ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00628 
00629     if (jCol) {
00630       // Only compute the number of nonzeros and the indices
00631       DBG_ASSERT(!values);
00632       nele_grad_gi = 0;
00633       for (cgrad* cg=Cgrad[i]; cg; cg = cg->next) {
00634         jCol[nele_grad_gi++] = cg->varno + 1;
00635       }
00636       return true;
00637     }
00638     DBG_ASSERT(values);
00639 
00640     // ignore new_x for now
00641     xunknown();
00642 
00643     asl->i.congrd_mode = 1;
00644     fint nerror = 0;
00645     congrd(i, const_cast<real*>(x), values, &nerror);
00646     if (nerror!=0) {
00647       return false;
00648     }
00649     else {
00650       return true;
00651     }
00652   }
00653 
00654   void AmplTMINLP::finalize_solution(TMINLP::SolverReturn status,
00655       Index n, const Number* x, Number obj_value)
00656   {
00657     std::string message;
00658     std::string status_str;
00659     if (status == TMINLP::SUCCESS) {
00660       status_str = "\t\"Finished\"";
00661       message = "\nbonmin: Optimal";
00662     }
00663     else if (status == TMINLP::INFEASIBLE) {
00664       status_str = "\t\"Finished\"";
00665       message = "\nbonmin: Infeasible problem";
00666     }
00667     else if (status == TMINLP::LIMIT_EXCEEDED) {
00668       status_str = "\t\"Not finished\"";
00669       message = "\n Optimization interrupted on limit.";
00670     }
00671     else if (status == TMINLP::MINLP_ERROR) {
00672       status_str = "\t\"Aborted\"";
00673       message = "\n Error encountered in optimization.";
00674     }
00675     if (writeAmplSolFile_) {
00676       write_solution(message, x);
00677       std::cout<<"\n "<<status_str<<std::endl;
00678     }
00679     else {
00680       std::cout<<status_str<<message<<std::endl;
00681       std::ofstream of("bonmin.sol");
00682       for (int i = 0 ; i < n ; i++) {
00683         of<<i<<"\t"<<x[i]<<std::endl;
00684       }
00685       of<<"-1\n";
00686     }
00687   }
00688 
00689   void AmplTMINLP::write_solution(const std::string & message, const Number *x_sol)
00690   {
00691     ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00692 
00693     DBG_ASSERT(asl);
00694     //    DBG_ASSERT(x_sol);
00695 
00696     // We need to copy the message into a non-const char array to make
00697     // it work with the AMPL C function.
00698     char* cmessage = new char[message.length()+1];
00699     strcpy(cmessage, message.c_str());
00700 
00701     // In order to avoid casting into non-const, we copy the data here...
00702     double* x_sol_copy = NULL;
00703     if (x_sol) {
00704       x_sol_copy = new double[n_var];
00705       for (int i=0; i<n_var; i++) {
00706         x_sol_copy[i] = x_sol[i];
00707       }
00708     }
00709     write_sol(cmessage, x_sol_copy, NULL, NULL);
00710 
00711     delete [] x_sol_copy;
00712     delete [] cmessage;
00713 
00714   }
00715 
00716 
00718   void AmplTMINLP::getLinearPartOfObjective(double * obj)
00719   {
00720     Index n, m, nnz_jac_g, nnz_h_lag;
00721     TNLP::IndexStyleEnum index_style = TNLP::FORTRAN_STYLE;
00722     get_nlp_info( n, m, nnz_jac_g, nnz_h_lag, index_style);
00723     eval_grad_f(n, NULL, 0,obj);
00724     Index n_non_linear_b= 0;
00725     Index n_non_linear_bi= 0;
00726     Index n_non_linear_c= 0;
00727     Index n_non_linear_ci = 0;
00728     Index n_non_linear_o= 0;
00729     Index n_non_linear_oi = 0;
00730     Index n_binaries = 0;
00731     Index n_integers = 0;
00732     ampl_tnlp_->get_discrete_info(n_non_linear_b, n_non_linear_bi, n_non_linear_c,
00733         n_non_linear_ci, n_non_linear_o, n_non_linear_oi,
00734         n_binaries, n_integers);
00735 
00736     // Now get the coefficients of variables wich are linear in the objective
00737     // The first ones are not
00738     Index start = 0;
00739     Index end = n_non_linear_b;
00740     for (int i=start; i<end; i++) {
00741       obj[i] = 0.;
00742     }
00743 
00744     //next variables should be linear in the objective just skip them
00745     // (from current end to (end + n_non_linear_c - n_non_linear_ci - n_non_linear_b;)
00746 
00747 
00748     // Those are nonlinear in the objective
00749     start = end + n_non_linear_c;
00750     end = start + n_non_linear_o;
00751     for (int i=start; i < end; i++) {
00752       obj[i]=0.;
00753     }
00754     //The rest is linear keep the values of the gradient
00755   }
00756 
00757 
00758   void
00759   AmplTMINLP::fillAmplOptionList(AmplOptionsList* amplOptList)
00760   {
00761     amplOptList->AddAmplOption("bonmin.algorithm","bonmin.algorithm",
00762         AmplOptionsList::String_Option,
00763         "Choice of the algorithm.");
00764 
00765     amplOptList->AddAmplOption("bonmin.bb_log_level","bonmin.bb_log_level",
00766         AmplOptionsList::Integer_Option,
00767         "specify BB log level");
00768 
00769     amplOptList->AddAmplOption("bonmin.lp_log_level","bonmin.lp_log_level",
00770         AmplOptionsList::Integer_Option,
00771         "specify sub-LP log level");
00772 
00773     amplOptList->AddAmplOption("bonmin.milp_log_level","bonmin.milp_log_level",
00774         AmplOptionsList::Integer_Option,
00775         "specify sub-MILP log level");
00776 
00777     amplOptList->AddAmplOption("bonmin.oa_log_level","bonmin.oa_log_level",
00778         AmplOptionsList::Integer_Option,
00779         "specify OA log level");
00780 
00781     amplOptList->AddAmplOption("bonmin.oa_log_frequency","bonmin.oa_log_frequency",
00782         AmplOptionsList::Number_Option,
00783         "specify OA log frequency");
00784 
00785     amplOptList->AddAmplOption("bonmin.nlp_log_level","bonmin.nlp_log_level",
00786         AmplOptionsList::Integer_Option,
00787         "specify sub-NLP log level");
00788 
00789     amplOptList->AddAmplOption("bonmin.print_user_options","bonmin.print_user_options",
00790         AmplOptionsList::String_Option,
00791         "print options list");
00792 
00793     amplOptList->AddAmplOption("bonmin.bb_log_interval","bonmin.bb_log_interval",
00794         AmplOptionsList::Integer_Option,
00795         "Interval at which bound output is given");
00796 
00797     amplOptList->AddAmplOption("bonmin.allowable_gap","bonmin.allowable_gap",
00798         AmplOptionsList::Number_Option,
00799         "Specify allowable absolute gap");
00800 
00801     amplOptList->AddAmplOption("bonmin.allowable_fraction_gap","bonmin.allowable_fraction_gap",
00802         AmplOptionsList::Number_Option,
00803         "Specify allowable relative gap");
00804 
00805     amplOptList->AddAmplOption("bonmin.cutoff_decr","bonmin.cutoff_decr",
00806         AmplOptionsList::Number_Option,
00807         "Specify cutoff decrement");
00808 
00809     amplOptList->AddAmplOption("bonmin.cutoff","bonmin.cutoff",
00810         AmplOptionsList::Number_Option,
00811         "Specify cutoff");
00812 
00813     amplOptList->AddAmplOption("bonmin.node_comparison","bonmin.node_comparison",
00814         AmplOptionsList::String_Option,
00815         "Choose the node comparison function");
00816 
00817     amplOptList->AddAmplOption("bonmin.tree_search_strategy","bonmin.tree_search_strategy",
00818         AmplOptionsList::String_Option,
00819         "Choose the node selection strategy");
00820 
00821     amplOptList->AddAmplOption("bonmin.variable_selection","bonmin.variable_selection",
00822         AmplOptionsList::String_Option,
00823         "Choose the variable selection strategy");
00824 
00825     /*amplOptList->AddAmplOption("couenne.branch_pt_select","couenne.branch_pt_select",
00826         AmplOptionsList::String_Option,
00827         "Choose policy to select branching point");*/
00828 
00829     amplOptList->AddAmplOption("bonmin.number_strong_branch", "bonmin.number_strong_branch",
00830         AmplOptionsList::Integer_Option,
00831         "Chooes number of variable for strong branching");
00832 
00833     amplOptList->AddAmplOption("bonmin.number_before_trust", "bonmin.number_before_trust",
00834         AmplOptionsList::Integer_Option,
00835         "Set number of branches on a variable before its pseudo-costs are to be believed");
00836 
00837     amplOptList->AddAmplOption("bonmin.time_limit", "bonmin.time_limit",
00838         AmplOptionsList::Number_Option,
00839         "Set maximum computation time for Algorithm");
00840 
00841     amplOptList->AddAmplOption("bonmin.node_limit","bonmin.node_limit",
00842         AmplOptionsList::Integer_Option,
00843         "Set maximum number of nodes explored");
00844 
00845     amplOptList->AddAmplOption("bonmin.solution_limit","bonmin.solution_limit",
00846         AmplOptionsList::Integer_Option,
00847         "Set maximum of new best integer before aborting.");
00848 
00849     amplOptList->AddAmplOption("bonmin.iteration_limit","bonmin.iteration_limit",
00850         AmplOptionsList::Integer_Option,
00851         "Set cummulated maximum number of iterations in sub-algorithm used for nodes relaxations");
00852 
00853     amplOptList->AddAmplOption("bonmin.integer_tolerance", "bonmin.integer_tolerance",
00854         AmplOptionsList::Number_Option,
00855         "Set integer tolerance");
00856 
00857     amplOptList->AddAmplOption("bonmin.warm_start","bonmin.warm_start",
00858         AmplOptionsList::String_Option,
00859         "Set warm start method");
00860 
00861     amplOptList->AddAmplOption("bonmin.sos_constraints","bonmin.sos_constraints",
00862         AmplOptionsList::String_Option,
00863         "Disable SOS contraints");
00864 
00865     amplOptList->AddAmplOption("bonmin.max_random_point_radius",
00866         "bonmin.max_random_point_radius",
00867         AmplOptionsList::Number_Option,
00868         "Set max value for a random point");
00869 
00870     amplOptList->AddAmplOption("bonmin.max_consecutive_failures",
00871         "bonmin.max_consecutive_failures",
00872         AmplOptionsList::Integer_Option,
00873         "Number of consecutive unsolved problems before aborting.");
00874 
00875     amplOptList->AddAmplOption("bonmin.num_iterations_suspect",
00876         "bonmin.num_iterations_suspect",
00877         AmplOptionsList::Integer_Option,
00878         "Number of iteration over which a node is considered suspect");
00879 
00880     amplOptList->AddAmplOption("bonmin.nlp_failure_behavior",
00881         "bonmin.nlp_failure_behavior",
00882         AmplOptionsList::String_Option,
00883         "Set the behavior when the nlp fails.");
00884 
00885     amplOptList->AddAmplOption("bonmin.num_retry_unsolved_random_point",
00886         "bonmin.num_retry_unsolved_random_point",
00887         AmplOptionsList::Integer_Option,
00888         "Number of tries to resolve a failed NLP with a random starting point");
00889 
00890     amplOptList->AddAmplOption("bonmin.max_consecutive_infeasible",
00891         "bonmin.max_consecutive_infeasible",
00892         AmplOptionsList::Integer_Option,
00893         "Number of consecutive infeasible problems before continuing a"
00894         " branch.");
00895 
00896     amplOptList->AddAmplOption("bonmin.num_resolve_at_root", "bonmin.num_resolve_at_root",
00897         AmplOptionsList::Integer_Option,
00898         "Number of tries to resolve the root node with different starting point (only usefull in non-convex).");
00899 
00900     amplOptList->AddAmplOption("bonmin.num_resolve_at_node","bonmin.num_resolve_at_node",
00901         AmplOptionsList::Integer_Option,
00902         "Number of tries to resolve a non root node with different starting point (only usefull in non-convex).");
00903 
00904 
00905     amplOptList->AddAmplOption("bonmin.nlp_solve_frequency","bonmin.nlp_solve_frequency",
00906         AmplOptionsList::Integer_Option,
00907         "Specify the frequency at which nlp relaxations are solved in hybrid.");
00908 
00909     amplOptList->AddAmplOption("bonmin.filmint_ecp_cuts","bonmin.filmint_ecp_cuts",
00910         AmplOptionsList::Integer_Option,
00911         "Specify the frequency (in terms of nodes) at which some a la filmint ecp cuts are generated.");
00912 
00913     amplOptList->AddAmplOption("bonmin.couenne_ecp_cuts","bonmin.couenne_ecp_cuts",
00914         AmplOptionsList::Integer_Option,
00915         "Specify the frequency (in terms of nodes) at which couenne cuts are generated.");
00916 
00917     amplOptList->AddAmplOption("bonmin.oa_dec_time_limit", "bonmin.oa_dec_time_limit",
00918         AmplOptionsList::Number_Option,
00919         "Specify the maximum amount of time spent in OA decomposition iteratrions.");
00920 
00921     amplOptList->AddAmplOption("bonmin.tiny_element","bonmin.tiny_element",
00922         AmplOptionsList::Number_Option,
00923         "Value for tiny element in OA cut");
00924 
00925     amplOptList->AddAmplOption("bonmin.very_tiny_element","bonmin.very_tiny_element",
00926         AmplOptionsList::Number_Option,
00927         "Value for very tiny element in OA cut");
00928 
00929     amplOptList->AddAmplOption("bonmin.milp_subsolver", "bonmin.milp_subsolver",
00930         AmplOptionsList::String_Option,
00931         "Choose the subsolver to solve MILPs sub-problems in OA decompositions.");
00932 
00933     amplOptList->AddAmplOption("bonmin.Gomory_cuts", "bonmin.Gomory_cuts",
00934         AmplOptionsList::Integer_Option,
00935         "Frequency for Generating Gomory cuts in branch-and-cut.");
00936 
00937     amplOptList->AddAmplOption("bonmin.probing_cuts", "bonmin.probing_cuts",
00938         AmplOptionsList::Integer_Option,
00939         "Frequency for Generating probing cuts in branch-and-cut");
00940 
00941     amplOptList->AddAmplOption("bonmin.cover_cuts", "bonmin.cover_cuts",
00942         AmplOptionsList::Integer_Option,
00943         "Frequency for Generating cover cuts in branch-and-cut");
00944 
00945 
00946     amplOptList->AddAmplOption("bonmin.mir_cuts", "bonmin.mir_cuts",
00947         AmplOptionsList::Integer_Option,
00948         "Frequency for Generating MIR cuts in branch-and-cut");
00949 
00950   }
00951 
00954   bool
00955   AmplTMINLP::eval_upper_bound_f(Index n, const Number* x,
00956       Number& obj_value)
00957   {
00958     ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00959     //xknown(x);    // This tells ampl to use a new x
00960     fint nerror = -1;
00961     obj_value = objval(upperBoundingObj_, const_cast<double *>(x), &nerror);
00962     if (nerror > 0) {
00963       jnlst_->Printf(J_ERROR, J_MAIN,
00964           "Error in evaluating upper bounding objecting");
00965       throw -1;
00966     }
00967     return nerror;
00968 
00969   }
00971   const ASL_pfgh*
00972   AmplTMINLP::AmplSolverObject() const
00973   {
00974     return ampl_tnlp_->AmplSolverObject();
00975   }
00976 
00977 } // namespace Bonmin

Generated on Tue Sep 30 03:01:23 2008 by  doxygen 1.4.7