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 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 ,
00086 const std::string& appName,
00087 std::string* nl_file_content
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 ,
00113 const std::string& appName,
00114 std::string* nl_file_content
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
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
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
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
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
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
00158 suffix_handler->AddAvailableSuffix("UBObj", AmplSuffixHandler::Objective_Source, AmplSuffixHandler::Index_Type);
00159
00160
00161
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
00174 read_obj_suffixes();
00175 read_priorities();
00176 read_convexities();
00177 read_sos();
00178
00179
00180
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;
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
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
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
00299 int lowerBoundingObj = (UBObj[0] == 1)? 1:0;
00300
00301 ampl_tnlp_->set_active_objective(lowerBoundingObj);
00302
00303
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
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) {
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) {
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
00423
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
00441
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
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
00456
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
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
00472
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
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
00489
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
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
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
00517
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
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
00542
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
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
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
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 std::string message;
00662 std::string status_str;
00663 if (status == TMINLP::SUCCESS) {
00664 status_str = "\t\"Finished\"";
00665 message = "\n"+ appName_ +" Optimal";
00666 }
00667 else if (status == TMINLP::INFEASIBLE) {
00668 status_str = "\t\"Finished\"";
00669 message = "\n" + appName_ +" Infeasible problem";
00670 }
00671 else if (status == TMINLP::CONTINUOUS_UNBOUNDED) {
00672 status_str = "\t\"Finished\"";
00673 message = "\n" + appName_ +" Continuous relaxation is unbounded.";
00674 }
00675 else if (status == TMINLP::LIMIT_EXCEEDED) {
00676 status_str = "\t\"Not finished\"";
00677 message = "\n" + appName_ +" Optimization interrupted on limit.";
00678 }
00679 else if (status == TMINLP::MINLP_ERROR) {
00680 status_str = "\t\"Aborted\"";
00681 message = "\n" + appName_ + " Error encountered in optimization.";
00682 }
00683 if (writeAmplSolFile_) {
00684 write_solution(message, x);
00685 std::cout<<"\n "<<status_str<<std::endl;
00686 }
00687 else {
00688 std::cout<<status_str<<message<<std::endl;
00689 std::string fName = appName_ + ".sol";
00690 std::ofstream of(fName.c_str());
00691 for (int i = 0 ; i < n ; i++) {
00692 of<<i<<"\t"<<x[i]<<std::endl;
00693 }
00694 of<<"-1\n";
00695 }
00696 }
00697
00698 void AmplTMINLP::write_solution(const std::string & message, const Number *x_sol)
00699 {
00700 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00701
00702 DBG_ASSERT(asl);
00703
00704
00705
00706
00707 char* cmessage = new char[message.length()+1];
00708 strcpy(cmessage, message.c_str());
00709
00710
00711 double* x_sol_copy = NULL;
00712 if (x_sol) {
00713 x_sol_copy = new double[n_var];
00714 for (int i=0; i<n_var; i++) {
00715 x_sol_copy[i] = x_sol[i];
00716 }
00717 }
00718 write_sol(cmessage, x_sol_copy, NULL, NULL);
00719
00720 delete [] x_sol_copy;
00721 delete [] cmessage;
00722
00723 }
00724
00725
00727 void AmplTMINLP::getLinearPartOfObjective(double * obj)
00728 {
00729 Index n, m, nnz_jac_g, nnz_h_lag;
00730 TNLP::IndexStyleEnum index_style = TNLP::FORTRAN_STYLE;
00731 get_nlp_info( n, m, nnz_jac_g, nnz_h_lag, index_style);
00732 eval_grad_f(n, NULL, 0,obj);
00733 Index n_non_linear_b= 0;
00734 Index n_non_linear_bi= 0;
00735 Index n_non_linear_c= 0;
00736 Index n_non_linear_ci = 0;
00737 Index n_non_linear_o= 0;
00738 Index n_non_linear_oi = 0;
00739 Index n_binaries = 0;
00740 Index n_integers = 0;
00741 ampl_tnlp_->get_discrete_info(n_non_linear_b, n_non_linear_bi, n_non_linear_c,
00742 n_non_linear_ci, n_non_linear_o, n_non_linear_oi,
00743 n_binaries, n_integers);
00744
00745
00746
00747 Index start = 0;
00748 Index end = n_non_linear_b;
00749 for (int i=start; i<end; i++) {
00750 obj[i] = 0.;
00751 }
00752
00753
00754
00755
00756
00757
00758 start = end + n_non_linear_c;
00759 end = start + n_non_linear_o;
00760 for (int i=start; i < end; i++) {
00761 obj[i]=0.;
00762 }
00763
00764 }
00765
00766
00767 void
00768 AmplTMINLP::fillAmplOptionList(AmplOptionsList* amplOptList)
00769 {
00770 amplOptList->AddAmplOption("bonmin.algorithm","bonmin.algorithm",
00771 AmplOptionsList::String_Option,
00772 "Choice of the algorithm.");
00773
00774 amplOptList->AddAmplOption("bonmin.bb_log_level","bonmin.bb_log_level",
00775 AmplOptionsList::Integer_Option,
00776 "specify BB log level");
00777
00778 amplOptList->AddAmplOption("bonmin.lp_log_level","bonmin.lp_log_level",
00779 AmplOptionsList::Integer_Option,
00780 "specify sub-LP log level");
00781
00782 amplOptList->AddAmplOption("bonmin.milp_log_level","bonmin.milp_log_level",
00783 AmplOptionsList::Integer_Option,
00784 "specify sub-MILP log level");
00785
00786 amplOptList->AddAmplOption("bonmin.oa_log_level","bonmin.oa_log_level",
00787 AmplOptionsList::Integer_Option,
00788 "specify OA log level");
00789
00790 amplOptList->AddAmplOption("bonmin.oa_log_frequency","bonmin.oa_log_frequency",
00791 AmplOptionsList::Number_Option,
00792 "specify OA log frequency");
00793
00794 amplOptList->AddAmplOption("bonmin.nlp_log_level","bonmin.nlp_log_level",
00795 AmplOptionsList::Integer_Option,
00796 "specify sub-NLP log level");
00797
00798 amplOptList->AddAmplOption("bonmin.print_user_options","bonmin.print_user_options",
00799 AmplOptionsList::String_Option,
00800 "print options list");
00801
00802 amplOptList->AddAmplOption("bonmin.bb_log_interval","bonmin.bb_log_interval",
00803 AmplOptionsList::Integer_Option,
00804 "Interval at which bound output is given");
00805
00806 amplOptList->AddAmplOption("bonmin.allowable_gap","bonmin.allowable_gap",
00807 AmplOptionsList::Number_Option,
00808 "Specify allowable absolute gap");
00809
00810 amplOptList->AddAmplOption("bonmin.allowable_fraction_gap","bonmin.allowable_fraction_gap",
00811 AmplOptionsList::Number_Option,
00812 "Specify allowable relative gap");
00813
00814 amplOptList->AddAmplOption("bonmin.cutoff_decr","bonmin.cutoff_decr",
00815 AmplOptionsList::Number_Option,
00816 "Specify cutoff decrement");
00817
00818 amplOptList->AddAmplOption("bonmin.cutoff","bonmin.cutoff",
00819 AmplOptionsList::Number_Option,
00820 "Specify cutoff");
00821
00822 amplOptList->AddAmplOption("bonmin.node_comparison","bonmin.node_comparison",
00823 AmplOptionsList::String_Option,
00824 "Choose the node comparison function");
00825
00826 amplOptList->AddAmplOption("bonmin.tree_search_strategy","bonmin.tree_search_strategy",
00827 AmplOptionsList::String_Option,
00828 "Choose the node selection strategy");
00829
00830 amplOptList->AddAmplOption("bonmin.variable_selection","bonmin.variable_selection",
00831 AmplOptionsList::String_Option,
00832 "Choose the variable selection strategy");
00833
00834
00835
00836
00837
00838 amplOptList->AddAmplOption("bonmin.number_strong_branch", "bonmin.number_strong_branch",
00839 AmplOptionsList::Integer_Option,
00840 "Chooes number of variable for strong branching");
00841
00842 amplOptList->AddAmplOption("bonmin.number_before_trust", "bonmin.number_before_trust",
00843 AmplOptionsList::Integer_Option,
00844 "Set number of branches on a variable before its pseudo-costs are to be believed");
00845
00846 amplOptList->AddAmplOption("bonmin.time_limit", "bonmin.time_limit",
00847 AmplOptionsList::Number_Option,
00848 "Set maximum computation time for Algorithm");
00849
00850 amplOptList->AddAmplOption("bonmin.node_limit","bonmin.node_limit",
00851 AmplOptionsList::Integer_Option,
00852 "Set maximum number of nodes explored");
00853
00854 amplOptList->AddAmplOption("bonmin.solution_limit","bonmin.solution_limit",
00855 AmplOptionsList::Integer_Option,
00856 "Set maximum of new best integer before aborting.");
00857
00858 amplOptList->AddAmplOption("bonmin.iteration_limit","bonmin.iteration_limit",
00859 AmplOptionsList::Integer_Option,
00860 "Set cummulated maximum number of iterations in sub-algorithm used for nodes relaxations");
00861
00862 amplOptList->AddAmplOption("bonmin.integer_tolerance", "bonmin.integer_tolerance",
00863 AmplOptionsList::Number_Option,
00864 "Set integer tolerance");
00865
00866 amplOptList->AddAmplOption("bonmin.warm_start","bonmin.warm_start",
00867 AmplOptionsList::String_Option,
00868 "Set warm start method");
00869
00870 amplOptList->AddAmplOption("bonmin.sos_constraints","bonmin.sos_constraints",
00871 AmplOptionsList::String_Option,
00872 "Disable SOS contraints");
00873
00874 amplOptList->AddAmplOption("bonmin.max_random_point_radius",
00875 "bonmin.max_random_point_radius",
00876 AmplOptionsList::Number_Option,
00877 "Set max value for a random point");
00878
00879 amplOptList->AddAmplOption("bonmin.max_consecutive_failures",
00880 "bonmin.max_consecutive_failures",
00881 AmplOptionsList::Integer_Option,
00882 "Number of consecutive unsolved problems before aborting.");
00883
00884 amplOptList->AddAmplOption("bonmin.num_iterations_suspect",
00885 "bonmin.num_iterations_suspect",
00886 AmplOptionsList::Integer_Option,
00887 "Number of iteration over which a node is considered suspect");
00888
00889 amplOptList->AddAmplOption("bonmin.nlp_failure_behavior",
00890 "bonmin.nlp_failure_behavior",
00891 AmplOptionsList::String_Option,
00892 "Set the behavior when the nlp fails.");
00893
00894 amplOptList->AddAmplOption("bonmin.num_retry_unsolved_random_point",
00895 "bonmin.num_retry_unsolved_random_point",
00896 AmplOptionsList::Integer_Option,
00897 "Number of tries to resolve a failed NLP with a random starting point");
00898
00899 amplOptList->AddAmplOption("bonmin.max_consecutive_infeasible",
00900 "bonmin.max_consecutive_infeasible",
00901 AmplOptionsList::Integer_Option,
00902 "Number of consecutive infeasible problems before continuing a"
00903 " branch.");
00904
00905 amplOptList->AddAmplOption("bonmin.num_resolve_at_root", "bonmin.num_resolve_at_root",
00906 AmplOptionsList::Integer_Option,
00907 "Number of tries to resolve the root node with different starting point (only usefull in non-convex).");
00908
00909 amplOptList->AddAmplOption("bonmin.num_resolve_at_node","bonmin.num_resolve_at_node",
00910 AmplOptionsList::Integer_Option,
00911 "Number of tries to resolve a non root node with different starting point (only usefull in non-convex).");
00912
00913
00914 amplOptList->AddAmplOption("bonmin.nlp_solve_frequency","bonmin.nlp_solve_frequency",
00915 AmplOptionsList::Integer_Option,
00916 "Specify the frequency at which nlp relaxations are solved in hybrid.");
00917
00918 amplOptList->AddAmplOption("bonmin.filmint_ecp_cuts","bonmin.filmint_ecp_cuts",
00919 AmplOptionsList::Integer_Option,
00920 "Specify the frequency (in terms of nodes) at which some a la filmint ecp cuts are generated.");
00921
00922 amplOptList->AddAmplOption("bonmin.couenne_ecp_cuts","bonmin.couenne_ecp_cuts",
00923 AmplOptionsList::Integer_Option,
00924 "Specify the frequency (in terms of nodes) at which couenne cuts are generated.");
00925
00926 amplOptList->AddAmplOption("bonmin.oa_dec_time_limit", "bonmin.oa_dec_time_limit",
00927 AmplOptionsList::Number_Option,
00928 "Specify the maximum amount of time spent in OA decomposition iteratrions.");
00929
00930 amplOptList->AddAmplOption("bonmin.tiny_element","bonmin.tiny_element",
00931 AmplOptionsList::Number_Option,
00932 "Value for tiny element in OA cut");
00933
00934 amplOptList->AddAmplOption("bonmin.very_tiny_element","bonmin.very_tiny_element",
00935 AmplOptionsList::Number_Option,
00936 "Value for very tiny element in OA cut");
00937
00938 amplOptList->AddAmplOption("bonmin.milp_subsolver", "bonmin.milp_subsolver",
00939 AmplOptionsList::String_Option,
00940 "Choose the subsolver to solve MILPs sub-problems in OA decompositions.");
00941
00942 amplOptList->AddAmplOption("bonmin.Gomory_cuts", "bonmin.Gomory_cuts",
00943 AmplOptionsList::Integer_Option,
00944 "Frequency for Generating Gomory cuts in branch-and-cut.");
00945
00946 amplOptList->AddAmplOption("bonmin.probing_cuts", "bonmin.probing_cuts",
00947 AmplOptionsList::Integer_Option,
00948 "Frequency for Generating probing cuts in branch-and-cut");
00949
00950 amplOptList->AddAmplOption("bonmin.cover_cuts", "bonmin.cover_cuts",
00951 AmplOptionsList::Integer_Option,
00952 "Frequency for Generating cover cuts in branch-and-cut");
00953
00954
00955 amplOptList->AddAmplOption("bonmin.mir_cuts", "bonmin.mir_cuts",
00956 AmplOptionsList::Integer_Option,
00957 "Frequency for Generating MIR cuts in branch-and-cut");
00958
00959 }
00960
00963 bool
00964 AmplTMINLP::eval_upper_bound_f(Index n, const Number* x,
00965 Number& obj_value)
00966 {
00967 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00968
00969 fint nerror = -1;
00970 obj_value = objval(upperBoundingObj_, const_cast<double *>(x), &nerror);
00971 if (nerror > 0) {
00972 jnlst_->Printf(J_ERROR, J_MAIN,
00973 "Error in evaluating upper bounding objecting");
00974 throw -1;
00975 }
00976 return nerror;
00977
00978 }
00980 const ASL_pfgh*
00981 AmplTMINLP::AmplSolverObject() const
00982 {
00983 return ampl_tnlp_->AmplSolverObject();
00984 }
00985
00986 }