00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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 ,
00085 const std::string& appName,
00086 std::string* nl_file_content
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 ,
00111 const std::string& appName,
00112 std::string* nl_file_content
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
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
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
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
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
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
00155 suffix_handler->AddAvailableSuffix("UBObj", AmplSuffixHandler::Objective_Source, AmplSuffixHandler::Index_Type);
00156
00157
00158
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
00171 read_obj_suffixes();
00172 read_priorities();
00173 read_convexities();
00174 read_sos();
00175
00176
00177
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;
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
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
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
00296 int lowerBoundingObj = (UBObj[0] == 1)? 1:0;
00297
00298 ampl_tnlp_->set_active_objective(lowerBoundingObj);
00299
00300
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
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) {
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) {
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
00420
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
00438
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
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
00453
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
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
00469
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
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
00485
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
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
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
00513
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
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
00538
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
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
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
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
00695
00696
00697
00698 char* cmessage = new char[message.length()+1];
00699 strcpy(cmessage, message.c_str());
00700
00701
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
00737
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
00745
00746
00747
00748
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
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
00826
00827
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
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 }