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) - n_non_linear_oi);
00475 for (int i=start; i<end; i++) {
00476 var_types[i] = CONTINUOUS;
00477 }
00478
00479
00480 start = end;
00481 end = start + n_non_linear_oi;
00482 for (int i=start; i < end; i++) {
00483 var_types[i] = INTEGER;
00484 totalNumberOfNonContinuous++;
00485 }
00486
00487
00488
00489 start = end;
00490 end = n - n_binaries - n_integers;
00491 for (int i=start; i<end; i++) {
00492 var_types[i] = CONTINUOUS;
00493 }
00494
00495
00496 start = end;
00497 end = start + n_binaries;
00498 for (int i=start; i < end; i++) {
00499 var_types[i] = BINARY;
00500 totalNumberOfNonContinuous++;
00501 }
00502
00503
00504 start = end;
00505 end = start + n_integers;
00506 for (int i=start; i < end; i++) {
00507 var_types[i] = INTEGER;
00508 totalNumberOfNonContinuous++;
00509 }
00510 return true;
00511 }
00512
00513 bool AmplTMINLP::get_variables_linearity(Index n, Ipopt::TNLP::LinearityType* var_types)
00514 {
00515
00516
00517
00518
00519 Index n_non_linear_b= 0;
00520 Index n_non_linear_bi= 0;
00521 Index n_non_linear_c= 0;
00522 Index n_non_linear_ci = 0;
00523 Index n_non_linear_o= 0;
00524 Index n_non_linear_oi = 0;
00525 Index n_binaries = 0;
00526 Index n_integers = 0;
00527 ampl_tnlp_->get_discrete_info(n_non_linear_b, n_non_linear_bi, n_non_linear_c,
00528 n_non_linear_ci, n_non_linear_o, n_non_linear_oi,
00529 n_binaries, n_integers);
00530
00531
00532 int n_non_linear = n_non_linear_c + n_non_linear_o - n_non_linear_b;
00533
00534 int start = 0;
00535 int end = n_non_linear;
00536 for (int i=start; i<end; i++) {
00537 var_types[i] = Ipopt::TNLP::NON_LINEAR;
00538 }
00539
00540
00541
00542 start = end;
00543 end = n;
00544 for (int i=start; i<end; i++) {
00545 var_types[i] = Ipopt::TNLP::LINEAR;
00546 }
00547 return true;
00548 }
00549
00552 bool
00553 AmplTMINLP::get_constraints_linearity(Index m,
00554 Ipopt::TNLP::LinearityType* const_types)
00555 {
00556 return ampl_tnlp_->get_constraints_linearity(m, const_types);
00557 }
00558
00559 bool AmplTMINLP::get_bounds_info(Index n, Number* x_l, Number* x_u,
00560 Index m, Number* g_l, Number* g_u)
00561 {
00562 return ampl_tnlp_->get_bounds_info(n, x_l, x_u, m, g_l, g_u);
00563 }
00564
00565 bool AmplTMINLP::get_starting_point(Index n, bool init_x, Number* x,
00566 bool init_z, Number* z_L, Number* z_U,
00567 Index m, bool init_lambda, Number* lambda)
00568 {
00569 return ampl_tnlp_->get_starting_point(n, init_x, x,
00570 init_z, z_L, z_U,
00571 m, init_lambda, lambda);
00572 }
00573
00574 bool AmplTMINLP::eval_f(Index n, const Number* x, bool new_x, Number& obj_value)
00575 {
00576 return ampl_tnlp_->eval_f(n, x, new_x, obj_value);
00577 }
00578
00579 bool AmplTMINLP::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
00580 {
00581 return ampl_tnlp_->eval_grad_f(n, x, new_x, grad_f);
00582 }
00583
00584 bool AmplTMINLP::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g)
00585 {
00586 return ampl_tnlp_->eval_g(n, x, new_x, m, g);
00587 }
00588
00589 bool AmplTMINLP::eval_jac_g(Index n, const Number* x, bool new_x,
00590 Index m, Index nele_jac, Index* iRow,
00591 Index *jCol, Number* values)
00592 {
00593 return ampl_tnlp_->eval_jac_g(n, x, new_x,
00594 m, nele_jac, iRow, jCol,
00595 values);
00596 }
00597
00598 bool AmplTMINLP::eval_h(Index n, const Number* x, bool new_x,
00599 Number obj_factor, Index m, const Number* lambda,
00600 bool new_lambda, Index nele_hess, Index* iRow,
00601 Index* jCol, Number* values)
00602 {
00603 return ampl_tnlp_->eval_h(n, x, new_x, obj_factor,
00604 m, lambda, new_lambda, nele_hess, iRow,
00605 jCol, values);
00606 }
00607
00608 bool AmplTMINLP::eval_gi(Index n, const Number* x, bool new_x,
00609 Index i, Number& gi)
00610 {
00611 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00612
00613
00614 xunknown();
00615
00616 fint nerror = 0;
00617 gi = conival(i, const_cast<real*>(x), &nerror);
00618 if (nerror!=0) {
00619 return false;
00620 }
00621 else {
00622 return true;
00623 }
00624 }
00625
00626 bool AmplTMINLP::eval_grad_gi(Index n, const Number* x, bool new_x,
00627 Index i, Index& nele_grad_gi, Index* jCol,
00628 Number* values)
00629 {
00630 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00631
00632 if (jCol) {
00633
00634 DBG_ASSERT(!values);
00635 nele_grad_gi = 0;
00636 for (cgrad* cg=Cgrad[i]; cg; cg = cg->next) {
00637 jCol[nele_grad_gi++] = cg->varno + 1;
00638 }
00639 return true;
00640 }
00641 DBG_ASSERT(values);
00642
00643
00644 xunknown();
00645
00646 asl->i.congrd_mode = 1;
00647 fint nerror = 0;
00648 congrd(i, const_cast<real*>(x), values, &nerror);
00649 if (nerror!=0) {
00650 return false;
00651 }
00652 else {
00653 return true;
00654 }
00655 }
00656
00657 void AmplTMINLP::finalize_solution(TMINLP::SolverReturn status,
00658 Index n, const Number* x, Number obj_value)
00659 {
00660 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
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 solve_result_num = 3;
00667 }
00668 else if (status == TMINLP::INFEASIBLE) {
00669 status_str = "\t\"Finished\"";
00670 message = "\n" + appName_ + ": Infeasible problem";
00671 solve_result_num = 220;
00672 }
00673 else if (status == TMINLP::CONTINUOUS_UNBOUNDED) {
00674 status_str = "\t\"Finished\"";
00675 message = "\n" + appName_ +" Continuous relaxation is unbounded.";
00676 solve_result_num = 300;
00677 }
00678 else if (status == TMINLP::LIMIT_EXCEEDED) {
00679 status_str = "\t\"Not finished\"";
00680 message = "\n" + appName_ + ": Optimization interupted on limit.";
00681 if(x)
00682 solve_result_num = 421;
00683 else
00684 solve_result_num = 410;
00685 }
00686 else if (status == TMINLP::MINLP_ERROR) {
00687 status_str = "\t\"Aborted\"";
00688 message = "\n" + appName_ + ": Error encountered in optimization.";
00689 solve_result_num = 500;
00690 }
00691 if (writeAmplSolFile_) {
00692 write_solution(message, x);
00693 std::cout<<"\n "<<status_str<<std::endl;
00694 }
00695 else {
00696 std::cout<<status_str<<message<<std::endl;
00697 std::string fName = appName_ + ".sol";
00698 std::ofstream of(fName.c_str());
00699 for (int i = 0 ; i < n ; i++) {
00700 of<<i<<"\t"<<x[i]<<std::endl;
00701 }
00702 of<<"-1\n";
00703 }
00704 }
00705
00706 void AmplTMINLP::write_solution(const std::string & message, const Number *x_sol)
00707 {
00708 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00709
00710 DBG_ASSERT(asl);
00711
00712
00713
00714
00715 char* cmessage = new char[message.length()+1];
00716 strcpy(cmessage, message.c_str());
00717
00718
00719 double* x_sol_copy = NULL;
00720 if (x_sol) {
00721 x_sol_copy = new double[n_var];
00722 for (int i=0; i<n_var; i++) {
00723 x_sol_copy[i] = x_sol[i];
00724 }
00725 }
00726 write_sol(cmessage, x_sol_copy, NULL, NULL);
00727
00728 delete [] x_sol_copy;
00729 delete [] cmessage;
00730
00731 }
00732
00733
00735 void AmplTMINLP::getLinearPartOfObjective(double * obj)
00736 {
00737 Index n, m, nnz_jac_g, nnz_h_lag;
00738 TNLP::IndexStyleEnum index_style = TNLP::FORTRAN_STYLE;
00739 get_nlp_info( n, m, nnz_jac_g, nnz_h_lag, index_style);
00740 eval_grad_f(n, NULL, 0,obj);
00741 Index n_non_linear_b= 0;
00742 Index n_non_linear_bi= 0;
00743 Index n_non_linear_c= 0;
00744 Index n_non_linear_ci = 0;
00745 Index n_non_linear_o= 0;
00746 Index n_non_linear_oi = 0;
00747 Index n_binaries = 0;
00748 Index n_integers = 0;
00749 ampl_tnlp_->get_discrete_info(n_non_linear_b, n_non_linear_bi, n_non_linear_c,
00750 n_non_linear_ci, n_non_linear_o, n_non_linear_oi,
00751 n_binaries, n_integers);
00752
00753
00754
00755 Index start = 0;
00756 Index end = n_non_linear_b;
00757 for (int i=start; i<end; i++) {
00758 obj[i] = 0.;
00759 }
00760
00761
00762
00763
00764
00765
00766 start = end + n_non_linear_c;
00767 end = start + n_non_linear_o;
00768 for (int i=start; i < end; i++) {
00769 obj[i]=0.;
00770 }
00771
00772 }
00773
00774
00775
00778 bool
00779 AmplTMINLP::eval_upper_bound_f(Index n, const Number* x,
00780 Number& obj_value)
00781 {
00782 ASL_pfgh* asl = ampl_tnlp_->AmplSolverObject();
00783
00784 fint nerror = -1;
00785 obj_value = objval(upperBoundingObj_, const_cast<double *>(x), &nerror);
00786 if (nerror > 0) {
00787 jnlst_->Printf(J_ERROR, J_MAIN,
00788 "Error in evaluating upper bounding objecting");
00789 throw -1;
00790 }
00791 return nerror;
00792
00793 }
00795 const ASL_pfgh*
00796 AmplTMINLP::AmplSolverObject() const
00797 {
00798 return ampl_tnlp_->AmplSolverObject();
00799 }
00800
00801 }