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
00025 using namespace Ipopt;
00026
00027 namespace Bonmin{
00028 void
00029 RegisteredOptions::fillAmplOptionList(ExtraCategoriesInfo which, Ipopt::AmplOptionsList * amplOptList){
00030 std::list<int> test;
00031 std::list< Ipopt::RegisteredOption * > options;
00032 chooseOptions(which, options);
00033 for(std::list< Ipopt::RegisteredOption * >::iterator i = options.begin();
00034 i != options.end() ; i++)
00035 {
00036 std::string name = "bonmin.";
00037 name += (*i)->Name();
00038 Ipopt::RegisteredOptionType T = (*i)->Type();
00039 Ipopt::AmplOptionsList::AmplOptionType type;
00040 switch(T){
00041 case Ipopt::OT_Number: type = Ipopt::AmplOptionsList::Number_Option;
00042 break;
00043 case Ipopt::OT_Integer: type = Ipopt::AmplOptionsList::Integer_Option;
00044 break;
00045 case Ipopt::OT_String: type = Ipopt::AmplOptionsList::String_Option;
00046 break;
00047 case Ipopt::OT_Unknown:
00048 default:
00049 throw CoinError("RegisteredOptions","fillAmplOptionList","Unknown option type");
00050 }
00051 amplOptList->AddAmplOption(name, name, type, (*i)->ShortDescription());
00052 }
00053 }
00054 }
00055 #include "asl.h"
00056 #include "asl_pfgh.h"
00057 #include "getstub.h"
00058
00059 namespace ampl_utils
00060 {
00061 void sos_kludge(int nsos, int *sosbeg, double *sosref);
00062 }
00063 namespace Bonmin
00064 {
00065
00066 AmplTMINLP::AmplTMINLP()
00067 :
00068 TMINLP(),
00069 appName_(),
00070 upperBoundingObj_(-1),
00071 ampl_tnlp_(NULL),
00072 branch_(),
00073 sos_(),
00074 suffix_handler_(NULL),
00075 constraintsConvexities_(NULL),
00076 numberNonConvex_(0),
00077 nonConvexConstraintsAndRelaxations_(NULL),
00078 numberSimpleConcave_(0),
00079 simpleConcaves_(NULL),
00080 hasLinearObjective_(false)
00081 {}
00082
00083
00084 AmplTMINLP::AmplTMINLP(const SmartPtr<const Journalist>& jnlst,
00085 const SmartPtr<Bonmin::RegisteredOptions> roptions,
00086 const SmartPtr<OptionsList> options,
00087 char**& argv,
00088 AmplSuffixHandler* suffix_handler ,
00089 const std::string& appName,
00090 std::string* nl_file_content
00091 )
00092 :
00093 TMINLP(),
00094 appName_(),
00095 upperBoundingObj_(-1),
00096 ampl_tnlp_(NULL),
00097 branch_(),
00098 sos_(),
00099 suffix_handler_(NULL),
00100 constraintsConvexities_(NULL),
00101 numberNonConvex_(0),
00102 nonConvexConstraintsAndRelaxations_(NULL),
00103 numberSimpleConcave_(0),
00104 simpleConcaves_(NULL),
00105 hasLinearObjective_(false)
00106 {
00107 Initialize(jnlst, roptions, options, argv, suffix_handler, appName, nl_file_content);
00108 }
00109
00110 void
00111 AmplTMINLP::Initialize(const SmartPtr<const Journalist>& jnlst,
00112 const SmartPtr<Bonmin::RegisteredOptions> roptions,
00113 const SmartPtr<OptionsList> options,
00114 char**& argv,
00115 AmplSuffixHandler* suffix_handler ,
00116 const std::string& appName,
00117 std::string* nl_file_content
00118 )
00119 {
00120 appName_ = appName;
00121 options->GetEnumValue("file_solution",writeAmplSolFile_,"bonmin.");
00122 jnlst_ = jnlst;
00123
00124 if (suffix_handler==NULL)
00125 suffix_handler_ = suffix_handler = new AmplSuffixHandler();
00126
00127
00128 suffix_handler->AddAvailableSuffix("scaling_factor", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00129 suffix_handler->AddAvailableSuffix("scaling_factor", AmplSuffixHandler::Constraint_Source, AmplSuffixHandler::Number_Type);
00130 suffix_handler->AddAvailableSuffix("scaling_factor", AmplSuffixHandler::Objective_Source, AmplSuffixHandler::Number_Type);
00131
00132
00133 suffix_handler->AddAvailableSuffix("ipopt_zL_out", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00134 suffix_handler->AddAvailableSuffix("ipopt_zU_out", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00135 suffix_handler->AddAvailableSuffix("ipopt_zL_in", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00136 suffix_handler->AddAvailableSuffix("ipopt_zU_in", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00137
00138
00139 suffix_handler->AddAvailableSuffix("priority", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Index_Type);
00140 suffix_handler->AddAvailableSuffix("direction", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00141 suffix_handler->AddAvailableSuffix("downPseudocost", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00142 suffix_handler->AddAvailableSuffix("upPseudocost", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00143
00144
00145
00146
00147 suffix_handler->AddAvailableSuffix("ref", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00148 suffix_handler->AddAvailableSuffix("sos",AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Index_Type);
00149 suffix_handler->AddAvailableSuffix("sos",AmplSuffixHandler::Constraint_Source, AmplSuffixHandler::Index_Type);
00150 suffix_handler->AddAvailableSuffix("sosno",AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00151 suffix_handler->AddAvailableSuffix("sosref",AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00152 suffix_handler->AddAvailableSuffix("sstatus", AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Index_Type);
00153 suffix_handler->AddAvailableSuffix("sstatus", AmplSuffixHandler::Constraint_Source, AmplSuffixHandler::Index_Type);
00154
00155
00156
00157 suffix_handler->AddAvailableSuffix("non_conv",AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Index_Type);
00158 suffix_handler->AddAvailableSuffix("primary_var",AmplSuffixHandler::Constraint_Source, AmplSuffixHandler::Index_Type);
00159
00160
00161 suffix_handler->AddAvailableSuffix("onoff_c",AmplSuffixHandler::Constraint_Source, AmplSuffixHandler::Index_Type);
00162 suffix_handler->AddAvailableSuffix("onoff_v",AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Index_Type);
00163
00164
00165 suffix_handler->AddAvailableSuffix("UBObj", AmplSuffixHandler::Objective_Source, AmplSuffixHandler::Index_Type);
00166
00167
00168
00169 suffix_handler->AddAvailableSuffix("perturb_radius",AmplSuffixHandler::Variable_Source, AmplSuffixHandler::Number_Type);
00170
00171 SmartPtr<AmplOptionsList> ampl_options_list = new AmplOptionsList();
00172 roptions->fillAmplOptionList(RegisteredOptions::BonminCategory, GetRawPtr(ampl_options_list));
00173 roptions->fillAmplOptionList(RegisteredOptions::FilterCategory, GetRawPtr(ampl_options_list));
00174 roptions->fillAmplOptionList(RegisteredOptions::BqpdCategory, GetRawPtr(ampl_options_list));
00175 fillApplicationOptions(GetRawPtr(ampl_options_list) );
00176 std::string options_id = appName + "_options";
00177 ampl_tnlp_ = new AmplTNLP(jnlst, options, argv, suffix_handler, true,
00178 ampl_options_list, options_id.c_str(),
00179 appName.c_str(), appName.c_str(), nl_file_content);
00180
00181
00182
00183 read_obj_suffixes();
00184 read_priorities();
00185 read_convexities();
00186 read_onoff();
00187 read_sos();
00188
00189
00190
00191 Index n_non_linear_b= 0;
00192 Index n_non_linear_bi= 0;
00193 Index n_non_linear_c= 0;
00194 Index n_non_linear_ci = 0;
00195 Index n_non_linear_o= 0;
00196 Index n_non_linear_oi = 0;
00197 Index n_binaries = 0;
00198 Index n_integers = 0;
00199 ampl_tnlp_->get_discrete_info(n_non_linear_b, n_non_linear_bi, n_non_linear_c,
00200 n_non_linear_ci, n_non_linear_o, n_non_linear_oi,
00201 n_binaries, n_integers);
00202 if (n_non_linear_b == 0 && n_non_linear_o == 0) {
00203 hasLinearObjective_ = true;
00204 }
00205 }
00206
00207 AmplTMINLP::~AmplTMINLP()
00208 {
00209 delete [] constraintsConvexities_;
00210 delete [] simpleConcaves_;
00211 delete [] nonConvexConstraintsAndRelaxations_;
00212 delete ampl_tnlp_;
00213 }
00214
00215 void
00216 AmplTMINLP::read_priorities()
00217 {
00218 int numcols, m, dummy1, dummy2;
00219 TNLP::IndexStyleEnum index_style;
00220 ampl_tnlp_->get_nlp_info(numcols, m, dummy1, dummy2, index_style);
00221
00222 const AmplSuffixHandler * suffix_handler = GetRawPtr(suffix_handler_);
00223
00224 const Index* pri = suffix_handler->GetIntegerSuffixValues("priority", AmplSuffixHandler::Variable_Source);
00225 const Index* brac = suffix_handler->GetIntegerSuffixValues("direction", AmplSuffixHandler::Variable_Source);
00226 const Number* upPs = suffix_handler->GetNumberSuffixValues("upPseudocost", AmplSuffixHandler::Variable_Source);
00227 const Number* dwPs = suffix_handler->GetNumberSuffixValues("downPseudocost", AmplSuffixHandler::Variable_Source);
00228
00229
00230 branch_.gutsOfDestructor();
00231 branch_.size = numcols;
00232 if (pri) {
00233 branch_.priorities = new int[numcols];
00234 for (int i = 0 ; i < numcols ; i++) {
00235 branch_.priorities [i] = -pri[i] + 9999;
00236 }
00237 }
00238 if (brac) {
00239 branch_.branchingDirections = CoinCopyOfArray(brac,numcols);
00240 }
00241 if (upPs && !dwPs) dwPs = upPs;
00242 else if (dwPs && !upPs) upPs = dwPs;
00243
00244 if (upPs) {
00245 branch_.upPsCosts = CoinCopyOfArray(upPs,numcols);
00246 }
00247 if (dwPs) {
00248 branch_.downPsCosts = CoinCopyOfArray(dwPs,numcols);
00249 }
00250
00251 const double* perturb_radius =
00252 suffix_handler->GetNumberSuffixValues("perturb_radius", AmplSuffixHandler::Variable_Source);
00253 perturb_info_.SetPerturbationArray(numcols, perturb_radius);
00254 }
00255
00256 void
00257 AmplTMINLP::read_sos()
00258 {
00259 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00260 int i = 0;
00261 int copri[2], **p_sospri;
00262 copri[0] = 0;
00263 copri[1] = 0;
00264 int * starts = NULL;
00265 int * indices = NULL;
00266 char * types = NULL;
00267 double * weights = NULL;
00268 int * priorities = NULL;
00269 p_sospri = &priorities;
00270
00271 sos_.gutsOfDestructor();
00272 int m = n_con;
00273 sos_.num = suf_sos(i, &sos_.numNz, &types, p_sospri, copri,
00274 &starts, &indices, &weights);
00275 if(m != n_con){
00276 throw CoinError("number of constraints changed by suf_sos. Not supported.",
00277 "read_sos","Bonmin::AmplTMINLP");
00278 }
00279 if (sos_.num) {
00280
00281 sos_.priorities = CoinCopyOfArray(priorities,sos_.num);
00282 sos_.starts = CoinCopyOfArray(starts, sos_.num + 1);
00283 sos_.indices = CoinCopyOfArray(indices, sos_.numNz);
00284 sos_.types = CoinCopyOfArray(types, sos_.num);
00285 sos_.weights = CoinCopyOfArray(weights, sos_.numNz);
00286
00287 ampl_utils::sos_kludge(sos_.num, sos_.starts, sos_.weights);
00288 for (int ii=0;ii<sos_.num;ii++) {
00289 int ichar = sos_.types[ii] - '0';
00290 if (ichar != 1 && ichar != 2) {
00291 std::cerr<<"Unsuported type of sos constraint: "<<sos_.types[ii]<<std::endl;
00292 throw;
00293 }
00294 sos_.types[ii]= static_cast<char>(ichar);
00295 }
00296 }
00297 }
00298
00299 void
00300 AmplTMINLP::read_obj_suffixes()
00301 {
00302 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00303 DBG_ASSERT(asl);
00304
00305 if (n_obj < 2) return;
00306
00307 const AmplSuffixHandler * suffix_handler = GetRawPtr(suffix_handler_);
00308
00309 const Index* UBObj = suffix_handler->GetIntegerSuffixValues("UBObj", AmplSuffixHandler::Objective_Source);
00310 if (UBObj) {
00311
00312 int lowerBoundingObj = (UBObj[0] == 1)? 1:0;
00313
00314 ampl_tnlp_->set_active_objective(lowerBoundingObj);
00315
00316
00317 for (int i = 0; i < n_obj; i++) {
00318 if (UBObj[i]==1) {
00319 if (upperBoundingObj_ != -1) {
00320 jnlst_->Printf(J_ERROR, J_MAIN,
00321 "Too many objectives for upper-bounding");
00322 }
00323 upperBoundingObj_ = i;
00324 }
00325 }
00326 }
00327 else {
00328 ampl_tnlp_->set_active_objective(0);
00329 }
00330 }
00332 struct NonConvexSuff
00333 {
00335 NonConvexSuff():
00336 cIdx(-1),relIdx(-1),scXIdx(-1),scYIdx(-1)
00337 {}
00339 NonConvexSuff(const NonConvexSuff& other):
00340 cIdx(other.cIdx), relIdx(other.relIdx),
00341 scXIdx(other.scXIdx), scYIdx(other.scYIdx)
00342 {}
00344 int cIdx;
00346 int relIdx;
00348 int scXIdx;
00350 int scYIdx;
00351 };
00352 void AmplTMINLP::read_convexities()
00353 {
00354 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00355 DBG_ASSERT(asl);
00356
00357 const AmplSuffixHandler * suffix_handler = GetRawPtr(suffix_handler_);
00358 const Index * id = suffix_handler->GetIntegerSuffixValues("non_conv", AmplSuffixHandler::Variable_Source);
00359 const Index * primary_var = suffix_handler->GetIntegerSuffixValues("primary_var", AmplSuffixHandler::Constraint_Source);
00360
00361
00362 if (primary_var!= NULL) {
00363 if (constraintsConvexities_ != NULL) {
00364 delete [] constraintsConvexities_;
00365 }
00366 constraintsConvexities_ = new TMINLP::Convexity[n_con];
00367 if (id == NULL) {
00368 std::cerr<<"Incorrect suffixes description in ampl model. n_conv's are not declared "<<std::endl;
00369 exit(ERROR_IN_AMPL_SUFFIXES);
00370 }
00371 int numberSimpleConcave = 0;
00372 std::map<int, int> id_map;
00373
00374 for (int i = 0 ; i < n_var ; i++) {
00375 id_map[id[i]] = i;
00376 }
00377
00378
00379 for (int i = 0 ; i < n_con ; i++) {
00380 if (primary_var[i] != 0) {
00381 constraintsConvexities_[i] = TMINLP::SimpleConcave;
00382 numberSimpleConcave++;
00383 }
00384 else constraintsConvexities_[i] = TMINLP::Convex;
00385 }
00386 simpleConcaves_ = new SimpleConcaveConstraint[numberSimpleConcave];
00387 nonConvexConstraintsAndRelaxations_ = new MarkedNonConvex[numberSimpleConcave];
00388 numberSimpleConcave = 0;
00389 int * jCol = new int[n_var];
00390 for (int i = 0 ; i < n_con ; i++) {
00391 if (primary_var[i] != 0) {
00392 nonConvexConstraintsAndRelaxations_[numberSimpleConcave].cIdx = i;
00393 nonConvexConstraintsAndRelaxations_[numberSimpleConcave].cRelaxIdx = -1;
00394 simpleConcaves_[numberSimpleConcave].cIdx = i;
00395 simpleConcaves_[numberSimpleConcave].yIdx = id_map[primary_var[i]];
00396
00397
00398 int nnz;
00399 int & yIdx = simpleConcaves_[numberSimpleConcave].yIdx;
00400 int & xIdx = simpleConcaves_[numberSimpleConcave].xIdx;
00401 eval_grad_gi(n_var, NULL, false, i, nnz, jCol, NULL);
00402 if (nnz != 2) {
00403 std::cout<<"Incorrect suffixes description in ampl model. Constraint with id "
00404 <<id<<" is simple concave and should have only two nonzero elements"<<std::endl;
00405 exit(ERROR_IN_AMPL_SUFFIXES);
00406 }
00407 if (jCol[0] - 1== yIdx) {
00408 xIdx = jCol[1] - 1;
00409 }
00410 else {
00411 if (jCol[1] - 1!= yIdx) {
00412 std::cout<<"Incorrect suffixes description in ampl model. Constraint with id "
00413 <<id<<" : variable marked as y does not appear in the constraint."<<std::endl;
00414 exit(ERROR_IN_AMPL_SUFFIXES);
00415 }
00416 xIdx = jCol[0] - 1;
00417 }
00418 numberSimpleConcave++;
00419 }
00420 }
00421 delete [] jCol;
00422 numberSimpleConcave_ = numberSimpleConcave;
00423 numberNonConvex_ = numberSimpleConcave;
00424 }
00425
00426 }
00427
00428
00429 void AmplTMINLP::read_onoff()
00430 {
00431 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00432 DBG_ASSERT(asl);
00433
00434 const AmplSuffixHandler * suffix_handler = GetRawPtr(suffix_handler_);
00435 const Index * onoff_c = suffix_handler->GetIntegerSuffixValues("onoff_c", AmplSuffixHandler::Constraint_Source);
00436 const Index * onoff_v = suffix_handler->GetIntegerSuffixValues("onoff_v", AmplSuffixHandler::Variable_Source);
00437
00438 if(onoff_c == NULL && onoff_v == NULL){
00439 return;
00440 }
00441 if(onoff_c == NULL || onoff_v == NULL){
00442 std::cerr<<"Incorrect suffixes description in ampl model. One of per_v or per_c is declared but not the other."<<std::endl;
00443 exit(ERROR_IN_AMPL_SUFFIXES);
00444 }
00445
00446 c_extra_id_.clear();
00447 c_extra_id_.resize(n_con, -1);
00448 std::map<int, int> id_map;
00449
00450 for (int i = 0 ; i < n_var ; i++) {
00451 if(onoff_v[i] > 0)
00452 id_map[onoff_v[i]] = i;
00453 }
00454
00455 for (int i = 0 ; i < n_con ; i++) {
00456 if(onoff_c[i] > 0){
00457 std::map<int, int >::iterator k = id_map.find(onoff_c[i]);
00458 if(k != id_map.end()){
00459 c_extra_id_[i] = (*k).second;
00460 }
00461 else{
00462 std::cerr<<"Incorrect suffixes description in ampl model. onoff_c has value attributed to no variable "<<std::endl;
00463 exit(ERROR_IN_AMPL_SUFFIXES);
00464 }
00465 }
00466 }
00467 }
00468
00469 bool AmplTMINLP::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, Index& nnz_h_lag, TNLP::IndexStyleEnum& index_style)
00470 {
00471 return ampl_tnlp_->get_nlp_info(n, m, nnz_jac_g, nnz_h_lag, index_style);
00472 }
00473
00474 bool AmplTMINLP::get_variables_types(Index n, VariableType* var_types)
00475 {
00476
00477
00478
00479
00480 Index n_non_linear_b= 0;
00481 Index n_non_linear_bi= 0;
00482 Index n_non_linear_c= 0;
00483 Index n_non_linear_ci = 0;
00484 Index n_non_linear_o= 0;
00485 Index n_non_linear_oi = 0;
00486 Index n_binaries = 0;
00487 Index n_integers = 0;
00488 ampl_tnlp_->get_discrete_info(n_non_linear_b, n_non_linear_bi, n_non_linear_c,
00489 n_non_linear_ci, n_non_linear_o, n_non_linear_oi,
00490 n_binaries, n_integers);
00491 int totalNumberOfNonContinuous = 0;
00492
00493
00494
00495
00496 Index start = 0;
00497 Index end = n_non_linear_b - n_non_linear_bi;
00498 for (int i=start; i<end; i++) {
00499 var_types[i] = CONTINUOUS;
00500 }
00501
00502
00503 start = end;
00504 end = start + n_non_linear_bi;
00505 for (int i=start; i < end; i++) {
00506 var_types[i] = INTEGER;
00507 totalNumberOfNonContinuous++;
00508 }
00509
00510
00511 start = end;
00512 end = std::max(start,end + n_non_linear_c - n_non_linear_ci - n_non_linear_b);
00513 for (int i=start; i<end; i++) {
00514 var_types[i] = CONTINUOUS;
00515 }
00516
00517
00518 start = end;
00519 end = start + n_non_linear_ci;
00520 for (int i=start; i < end; i++) {
00521 var_types[i] = INTEGER;
00522 totalNumberOfNonContinuous++;
00523 }
00524
00525
00526
00527 start = end;
00528 end = std::max(start,end + n_non_linear_o - std::max(n_non_linear_b, n_non_linear_c) - n_non_linear_oi);
00529 for (int i=start; i<end; i++) {
00530 var_types[i] = CONTINUOUS;
00531 }
00532
00533
00534 start = end;
00535 end = start + n_non_linear_oi;
00536 for (int i=start; i < end; i++) {
00537 var_types[i] = INTEGER;
00538 totalNumberOfNonContinuous++;
00539 }
00540
00541
00542
00543 start = end;
00544 end = n - n_binaries - n_integers;
00545 for (int i=start; i<end; i++) {
00546 var_types[i] = CONTINUOUS;
00547 }
00548
00549
00550 start = end;
00551 end = start + n_binaries;
00552 for (int i=start; i < end; i++) {
00553 var_types[i] = BINARY;
00554 totalNumberOfNonContinuous++;
00555 }
00556
00557
00558 start = end;
00559 end = start + n_integers;
00560 for (int i=start; i < end; i++) {
00561 var_types[i] = INTEGER;
00562 totalNumberOfNonContinuous++;
00563 }
00564 return true;
00565 }
00566
00567 bool AmplTMINLP::get_variables_linearity(Index n, Ipopt::TNLP::LinearityType* var_types)
00568 {
00569
00570
00571
00572
00573 Index n_non_linear_b= 0;
00574 Index n_non_linear_bi= 0;
00575 Index n_non_linear_c= 0;
00576 Index n_non_linear_ci = 0;
00577 Index n_non_linear_o= 0;
00578 Index n_non_linear_oi = 0;
00579 Index n_binaries = 0;
00580 Index n_integers = 0;
00581 ampl_tnlp_->get_discrete_info(n_non_linear_b, n_non_linear_bi, n_non_linear_c,
00582 n_non_linear_ci, n_non_linear_o, n_non_linear_oi,
00583 n_binaries, n_integers);
00584
00585
00586 int n_non_linear = std::max(n_non_linear_c, n_non_linear_o);
00587
00588
00589
00590 int start = 0;
00591 int end = n_non_linear;
00592 for (int i=start; i<end; i++) {
00593 var_types[i] = Ipopt::TNLP::NON_LINEAR;
00594 }
00595
00596
00597
00598 start = end;
00599 end = n;
00600 for (int i=start; i<end; i++) {
00601 var_types[i] = Ipopt::TNLP::LINEAR;
00602 }
00603 return true;
00604 }
00605
00608 bool
00609 AmplTMINLP::get_constraints_linearity(Index m,
00610 Ipopt::TNLP::LinearityType* const_types)
00611 {
00612 return ampl_tnlp_->get_constraints_linearity(m, const_types);
00613 }
00614
00615 bool AmplTMINLP::get_bounds_info(Index n, Number* x_l, Number* x_u,
00616 Index m, Number* g_l, Number* g_u)
00617 {
00618 return ampl_tnlp_->get_bounds_info(n, x_l, x_u, m, g_l, g_u);
00619 }
00620
00621 bool AmplTMINLP::get_starting_point(Index n, bool init_x, Number* x,
00622 bool init_z, Number* z_L, Number* z_U,
00623 Index m, bool init_lambda, Number* lambda)
00624 {
00625 return ampl_tnlp_->get_starting_point(n, init_x, x,
00626 init_z, z_L, z_U,
00627 m, init_lambda, lambda);
00628 }
00629
00630 bool AmplTMINLP::eval_f(Index n, const Number* x, bool new_x, Number& obj_value)
00631 {
00632 return ampl_tnlp_->eval_f(n, x, new_x, obj_value);
00633 }
00634
00635 bool AmplTMINLP::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
00636 {
00637 return ampl_tnlp_->eval_grad_f(n, x, new_x, grad_f);
00638 }
00639
00640 bool AmplTMINLP::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g)
00641 {
00642 return ampl_tnlp_->eval_g(n, x, new_x, m, g);
00643 }
00644
00645 bool AmplTMINLP::eval_jac_g(Index n, const Number* x, bool new_x,
00646 Index m, Index nele_jac, Index* iRow,
00647 Index *jCol, Number* values)
00648 {
00649 return ampl_tnlp_->eval_jac_g(n, x, new_x,
00650 m, nele_jac, iRow, jCol,
00651 values);
00652 }
00653
00654 bool AmplTMINLP::eval_h(Index n, const Number* x, bool new_x,
00655 Number obj_factor, Index m, const Number* lambda,
00656 bool new_lambda, Index nele_hess, Index* iRow,
00657 Index* jCol, Number* values)
00658 {
00659 return ampl_tnlp_->eval_h(n, x, new_x, obj_factor,
00660 m, lambda, new_lambda, nele_hess, iRow,
00661 jCol, values);
00662 }
00663
00664 bool AmplTMINLP::eval_gi(Index n, const Number* x, bool new_x,
00665 Index i, Number& gi)
00666 {
00667 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00668
00669
00670 xunknown();
00671
00672 fint nerror = 0;
00673 gi = conival(i, const_cast<real*>(x), &nerror);
00674 if (nerror!=0) {
00675 return false;
00676 }
00677 else {
00678 return true;
00679 }
00680 }
00681
00682 bool AmplTMINLP::eval_grad_gi(Index n, const Number* x, bool new_x,
00683 Index i, Index& nele_grad_gi, Index* jCol,
00684 Number* values)
00685 {
00686 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00687
00688 if (jCol) {
00689
00690 DBG_ASSERT(!values);
00691 nele_grad_gi = 0;
00692 for (cgrad* cg=Cgrad[i]; cg; cg = cg->next) {
00693 jCol[nele_grad_gi++] = cg->varno + 1;
00694 }
00695 return true;
00696 }
00697 DBG_ASSERT(values);
00698
00699
00700 xunknown();
00701
00702 asl->i.congrd_mode = 1;
00703 fint nerror = 0;
00704 congrd(i, const_cast<real*>(x), values, &nerror);
00705 if (nerror!=0) {
00706 return false;
00707 }
00708 else {
00709 return true;
00710 }
00711 }
00712
00713 void AmplTMINLP::finalize_solution(TMINLP::SolverReturn status,
00714 Index n, const Number* x, Number obj_value)
00715 {
00716 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00717 std::string message;
00718 std::string status_str;
00719 if (status == TMINLP::SUCCESS) {
00720 status_str = "\t\"Finished\"";
00721 message = "\n" + appName_ +": Optimal";
00722 solve_result_num = 3;
00723 }
00724 else if (status == TMINLP::INFEASIBLE) {
00725 status_str = "\t\"Finished\"";
00726 message = "\n" + appName_ + ": Infeasible problem";
00727 solve_result_num = 220;
00728 }
00729 else if (status == TMINLP::CONTINUOUS_UNBOUNDED) {
00730 status_str = "\t\"Finished\"";
00731 message = "\n" + appName_ +" Continuous relaxation is unbounded.";
00732 solve_result_num = 300;
00733 }
00734 else if (status == TMINLP::LIMIT_EXCEEDED) {
00735 status_str = "\t\"Not finished\"";
00736 message = "\n" + appName_ + ": Optimization interupted on limit.";
00737 if(x)
00738 solve_result_num = 421;
00739 else
00740 solve_result_num = 410;
00741 }
00742 else if (status == TMINLP::MINLP_ERROR) {
00743 status_str = "\t\"Aborted\"";
00744 message = "\n" + appName_ + ": Error encountered in optimization.";
00745 solve_result_num = 500;
00746 }
00747 if (writeAmplSolFile_) {
00748 write_solution(message, x);
00749 std::cout<<"\n "<<status_str<<std::endl;
00750 }
00751 else {
00752 std::cout<<status_str<<message<<std::endl;
00753 std::string fName = appName_ + ".sol";
00754 std::ofstream of(fName.c_str());
00755 for (int i = 0 ; i < n ; i++) {
00756 of<<i<<"\t"<<x[i]<<std::endl;
00757 }
00758 of<<"-1\n";
00759 }
00760 }
00761
00762 void AmplTMINLP::write_solution(const std::string & message, const Number *x_sol)
00763 {
00764 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00765
00766 DBG_ASSERT(asl);
00767
00768
00769
00770
00771 char* cmessage = new char[message.length()+1];
00772 strcpy(cmessage, message.c_str());
00773
00774
00775 double* x_sol_copy = NULL;
00776 if (x_sol) {
00777 x_sol_copy = new double[n_var];
00778 for (int i=0; i<n_var; i++) {
00779 x_sol_copy[i] = x_sol[i];
00780 }
00781 }
00782 write_sol(cmessage, x_sol_copy, NULL, NULL);
00783
00784 delete [] x_sol_copy;
00785 delete [] cmessage;
00786
00787 }
00788
00789
00791 void AmplTMINLP::getLinearPartOfObjective(double * obj)
00792 {
00793 Index n, m, nnz_jac_g, nnz_h_lag;
00794 TNLP::IndexStyleEnum index_style = TNLP::FORTRAN_STYLE;
00795 get_nlp_info( n, m, nnz_jac_g, nnz_h_lag, index_style);
00796 eval_grad_f(n, NULL, 0,obj);
00797 Index n_non_linear_b= 0;
00798 Index n_non_linear_bi= 0;
00799 Index n_non_linear_c= 0;
00800 Index n_non_linear_ci = 0;
00801 Index n_non_linear_o= 0;
00802 Index n_non_linear_oi = 0;
00803 Index n_binaries = 0;
00804 Index n_integers = 0;
00805 ampl_tnlp_->get_discrete_info(n_non_linear_b, n_non_linear_bi, n_non_linear_c,
00806 n_non_linear_ci, n_non_linear_o, n_non_linear_oi,
00807 n_binaries, n_integers);
00808
00809
00810
00811 Index start = 0;
00812 Index end = n_non_linear_b;
00813 for (int i=start; i<end; i++) {
00814 obj[i] = 0.;
00815 }
00816
00817
00818
00819
00820
00821
00822 start = end + n_non_linear_c;
00823 end = start + n_non_linear_o;
00824 for (int i=start; i < end; i++) {
00825 obj[i]=0.;
00826 }
00827
00828 }
00829
00830
00831
00834 bool
00835 AmplTMINLP::eval_upper_bound_f(Index n, const Number* x,
00836 Number& obj_value)
00837 {
00838 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00839
00840 fint nerror = -1;
00841 obj_value = objval(upperBoundingObj_, const_cast<double *>(x), &nerror);
00842 if (nerror > 0) {
00843 jnlst_->Printf(J_ERROR, J_MAIN,
00844 "Error in evaluating upper bounding objecting");
00845 throw -1;
00846 }
00847 return nerror;
00848
00849 }
00851 const ASL_pfgh*
00852 AmplTMINLP::AmplSolverObject() const
00853 {
00854 return ampl_tnlp_->AmplSolverObject();
00855 }
00856
00857 }