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

Generated on Thu Oct 8 03:02:54 2009 by  doxygen 1.4.7