#include "IpoptConfig.h"
#include "AmplTNLP.hpp"
#include "IpDenseVector.hpp"
#include "IpGenTMatrix.hpp"
#include "IpSymTMatrix.hpp"
#include "IpBlas.hpp"
#include <cstring>
#include "asl.h"
#include "asl_pfgh.h"
#include "getstub.h"
namespace Ipopt
{
#if IPOPT_VERBOSITY > 0
static const Index dbg_verbosity = 0;
#endif
void AmplTNLP::gutsOfConstructor(
const SmartPtr<RegisteredOptions> regoptions,
const SmartPtr<OptionsList> options,
const char* const* argv,
bool allow_discrete ,
SmartPtr<AmplOptionsList> ampl_options_list ,
const char* ampl_option_string ,
const char* ampl_invokation_string ,
const char* ampl_banner_string ,
std::string* nl_file_content
)
{
ASL_pfgh* asl = reinterpret_cast<ASL_pfgh*>(ASL_alloc(ASL_read_pfgh));
DBG_ASSERT(asl);
asl_ = asl;
nerror_ = (void*) new fint;
*(fint*)nerror_ = 0;
char* stub = get_options(regoptions, options, ampl_options_list, ampl_option_string, ampl_invokation_string, ampl_banner_string,
argv);
FILE* nl = NULL;
if( nl_file_content )
{
nl = jac0dim(const_cast<char*>(nl_file_content->c_str()), -(ftnlen )nl_file_content->length());
}
else
{
if( !stub )
{
jnlst_->Printf(J_ERROR, J_MAIN, "No .nl file given!\n");
THROW_EXCEPTION(INVALID_TNLP, "No .nl file given!\n");
}
nl = jac0dim(stub, (ftnlen)strlen(stub));
DBG_ASSERT(nl);
}
jnlst_->Printf(J_SUMMARY, J_MAIN, "\n");
DBG_ASSERT(n_var > 0); if( !allow_discrete && (nbv > 0 || niv > 0 || nlvbi > 0 || nlvci > 0 || nlvoi > 0) )
{
jnlst_->Printf(J_WARNING, J_MAIN, "==> Warning: Treating %d binary and %d integer variables as continuous.\n\n",
nbv, niv + nlvbi + nlvci + nlvoi);
}
allow_discrete = true;
ASSERT_EXCEPTION(allow_discrete || (nbv == 0 && niv == 0 && nlvbi == 0 && nlvci == 0 && nlvoi == 0), IpoptException,
"Discrete variables not allowed when the allow_discrete flag is false, "
"Either remove the integer variables, or change the flag in the constructor of AmplTNLP");
if( n_cc != 0 )
{
jnlst_->Printf(J_ERROR, J_MAIN,
"\n\n***** Ipopt does not support complementarity constraints. Aborting. *****\n\n");
ASSERT_EXCEPTION(n_cc == 0, IpoptException,
"Ipopt does not support complementarity constraints.");
}
DBG_ASSERT(nlo == 0 || nlo == 1); DBG_ASSERT(nwv == 0); DBG_ASSERT(nlnc == 0); DBG_ASSERT(lnc == 0);
want_xpi0 = 1 | 2; obj_no = 0;
DBG_ASSERT((want_xpi0 & 1) == 1 && (want_xpi0 & 2) == 2);
X0 = new real[n_var];
havex0 = new char[n_var];
pi0 = new real[n_con];
havepi0 = new char[n_con];
if( IsValid(suffix_handler_) )
{
suffix_handler_->PrepareAmplForSuffixes(asl);
}
#ifdef IPOPT_INT64
int retcode = pfgh_read(nl, ASL_return_read_err | ASL_findgroups | ASL_allow_Z | ASL_use_Z);
#else
int retcode = pfgh_read(nl, ASL_return_read_err | ASL_findgroups);
#endif
switch( retcode )
{
case ASL_readerr_none:
{
break;
}
case ASL_readerr_nofile:
{
jnlst_->Printf(J_ERROR, J_MAIN, "Cannot open .nl file\n");
THROW_EXCEPTION(INVALID_TNLP, "Cannot open .nl file");
}
case ASL_readerr_nonlin:
{
DBG_ASSERT(false); jnlst_->Printf(J_ERROR, J_MAIN, "model involves nonlinearities (ed0read)\n");
THROW_EXCEPTION(INVALID_TNLP, "model involves nonlinearities (ed0read)");
}
case ASL_readerr_argerr:
{
jnlst_->Printf(J_ERROR, J_MAIN, "user-defined function with bad args\n");
THROW_EXCEPTION(INVALID_TNLP, "user-defined function with bad args");
}
case ASL_readerr_unavail:
{
jnlst_->Printf(J_ERROR, J_MAIN, "user-defined function not available\n");
THROW_EXCEPTION(INVALID_TNLP, "user-defined function not available");
}
case ASL_readerr_corrupt:
{
jnlst_->Printf(J_ERROR, J_MAIN, "corrupt .nl file\n");
THROW_EXCEPTION(INVALID_TNLP, "corrupt .nl file");
}
case ASL_readerr_bug:
{
jnlst_->Printf(J_ERROR, J_MAIN, "bug in .nl reader\n");
THROW_EXCEPTION(INVALID_TNLP, "bug in .nl reader");
}
case ASL_readerr_CLP:
{
jnlst_->Printf(J_ERROR, J_MAIN, "Ampl model contains a constraint without \"=\", \">=\", or \"<=\".\n");
THROW_EXCEPTION(INVALID_TNLP, "Ampl model contains a constraint without \"=\", \">=\", or \"<=\".");
}
default:
{
jnlst_->Printf(J_ERROR, J_MAIN, "Unknown error in stub file read. retcode = %d\n", retcode);
THROW_EXCEPTION(INVALID_TNLP, "Unknown error in stub file read");
}
}
}
AmplTNLP::AmplTNLP(
const SmartPtr<const Journalist>& jnlst,
const SmartPtr<RegisteredOptions> regoptions,
const SmartPtr<OptionsList> options,
const char* const* argv,
SmartPtr<AmplSuffixHandler> suffix_handler ,
bool allow_discrete ,
SmartPtr<AmplOptionsList> ampl_options_list ,
const char* ampl_option_string ,
const char* ampl_invokation_string ,
const char* ampl_banner_string ,
std::string* nl_file_content
)
: TNLP(),
jnlst_(jnlst),
asl_(NULL),
obj_sign_(1),
nz_h_full_(-1),
x_sol_(NULL),
z_L_sol_(NULL),
z_U_sol_(NULL),
g_sol_(NULL),
lambda_sol_(NULL),
obj_sol_(0.0),
objval_called_with_current_x_(false),
conval_called_with_current_x_(false),
hesset_called_(false),
set_active_objective_called_(false),
Oinfo_ptr_(NULL),
suffix_handler_(suffix_handler)
{
DBG_START_METH("AmplTNLP::AmplTNLP", dbg_verbosity);
gutsOfConstructor(regoptions, options, argv, allow_discrete, ampl_options_list, ampl_option_string, ampl_invokation_string, ampl_banner_string, nl_file_content);
}
AmplTNLP::AmplTNLP(
const SmartPtr<const Journalist>& jnlst,
const SmartPtr<OptionsList> options,
char**& argv,
SmartPtr<AmplSuffixHandler> suffix_handler ,
bool allow_discrete ,
SmartPtr<AmplOptionsList> ampl_options_list ,
const char* ampl_option_string ,
const char* ampl_invokation_string ,
const char* ampl_banner_string ,
std::string* nl_file_content
)
: TNLP(),
jnlst_(jnlst),
asl_(NULL),
obj_sign_(1),
nz_h_full_(-1),
x_sol_(NULL),
z_L_sol_(NULL),
z_U_sol_(NULL),
g_sol_(NULL),
lambda_sol_(NULL),
obj_sol_(0.0),
objval_called_with_current_x_(false),
conval_called_with_current_x_(false),
hesset_called_(false),
set_active_objective_called_(false),
Oinfo_ptr_(NULL),
suffix_handler_(suffix_handler)
{
DBG_START_METH("AmplTNLP::AmplTNLP", dbg_verbosity);
gutsOfConstructor(NULL, options, argv, allow_discrete, ampl_options_list, ampl_option_string, ampl_invokation_string, ampl_banner_string, nl_file_content);
}
void AmplTNLP::set_active_objective(
Index in_obj_no
)
{
if( hesset_called_ )
{
jnlst_->Printf(J_ERROR, J_MAIN,
"Internal error: AmplTNLP::set_active_objective called after AmplTNLP::call_hesset.\n");
THROW_EXCEPTION(INVALID_TNLP,
"Internal error: AmplTNLP::set_active_objective called after AmplTNLP::call_hesset.");
}
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
obj_no = in_obj_no;
set_active_objective_called_ = true;
}
void AmplTNLP::call_hesset()
{
if( hesset_called_ )
{
jnlst_->Printf(J_ERROR, J_MAIN, "Internal error: AmplTNLP::call_hesset is called twice.\n");
THROW_EXCEPTION(INVALID_TNLP, "Internal error: AmplTNLP::call_hesset is called twice.");
}
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
if( n_obj == 0 )
{
hesset(1, 0, 0, 0, nlc);
}
else
{
if( n_obj > 1 && !set_active_objective_called_ )
{
jnlst_->Printf(J_ERROR, J_MAIN,
"There is more than one objective function in the AMPL model, but AmplTNLP::set_active_objective has not been called.\n");
THROW_EXCEPTION(INVALID_TNLP,
"There is more than one objective function in the AMPL model, but AmplTNLP::set_active_objective has not been called");
}
hesset(1, obj_no, 1, 0, nlc);
}
obj_sign_ = 1; if( n_obj > 0 && objtype[obj_no] != 0 )
{
obj_sign_ = -1;
}
int coeff_obj = 1;
int mult_supplied = 1; int uptri = 1; nz_h_full_ = sphsetup(-1, coeff_obj, mult_supplied, uptri);
hesset_called_ = true;
}
AmplTNLP::~AmplTNLP()
{
ASL_pfgh* asl = asl_;
if( asl )
{
if( X0 )
{
delete[] X0;
X0 = NULL;
}
if( havex0 )
{
delete[] havex0;
havex0 = NULL;
}
if( pi0 )
{
delete[] pi0;
pi0 = NULL;
}
if( havepi0 )
{
delete[] havepi0;
havepi0 = NULL;
}
ASL* asl_to_free = (ASL*) asl_;
ASL_free(&asl_to_free);
asl_ = NULL;
}
delete[] x_sol_;
x_sol_ = NULL;
delete[] z_L_sol_;
z_L_sol_ = NULL;
delete[] z_U_sol_;
z_U_sol_ = NULL;
delete[] g_sol_;
g_sol_ = NULL;
delete[] lambda_sol_;
lambda_sol_ = NULL;
if( Oinfo_ptr_ )
{
Option_Info* Oinfo = (Option_Info*) Oinfo_ptr_;
delete[] Oinfo->sname;
delete[] Oinfo->bsname;
delete[] Oinfo->opname;
delete Oinfo;
}
delete (fint*) nerror_;
}
bool AmplTNLP::get_nlp_info(
Index& n,
Index& m,
Index& nnz_jac_g,
Index& nnz_h_lag,
IndexStyleEnum& index_style
)
{
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
if( !hesset_called_ )
{
call_hesset();
}
n = n_var; m = n_con; #ifdef IPOPT_INT64
nnz_jac_g = nZc; #else
nnz_jac_g = nzc; #endif
nnz_h_lag = nz_h_full_;
index_style = TNLP::FORTRAN_STYLE;
return true;
}
bool AmplTNLP::get_var_con_metadata(
Index n,
StringMetaDataMapType& var_string_md,
IntegerMetaDataMapType& var_integer_md,
NumericMetaDataMapType& var_numeric_md,
Index m,
StringMetaDataMapType& con_string_md,
IntegerMetaDataMapType& con_integer_md,
NumericMetaDataMapType& con_numeric_md
)
{
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
Index rlen = maxrownamelen;
Index clen = maxcolnamelen;
if( clen > 0 )
{
std::vector<std::string> var_names(n);
for( Index i = 0; i < n; i++ )
{
var_names[i] = var_name(i);
}
var_string_md_["idx_names"] = var_names;
}
if( rlen > 0 )
{
std::vector<std::string> con_names(m);
for( Index i = 0; i < m; i++ )
{
con_names[i] = con_name(i);
}
con_string_md_["idx_names"] = con_names;
}
if( var_string_md_.size() > 0 || var_integer_md_.size() > 0 || var_numeric_md_.size() > 0
|| con_string_md_.size() > 0 || con_integer_md_.size() > 0 || con_numeric_md_.size() > 0 )
{
var_string_md = var_string_md_;
var_integer_md = var_integer_md_;
var_numeric_md = var_numeric_md_;
con_string_md = con_string_md_;
con_integer_md = con_integer_md_;
con_numeric_md = con_numeric_md_;
return true;
}
return false;
}
bool AmplTNLP::get_bounds_info(
Index n,
Number* x_l,
Number* x_u,
Index m,
Number* g_l,
Number* g_u
)
{
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
DBG_ASSERT(n == n_var);
DBG_ASSERT(m == n_con);
for( Index i = 0; i < n; i++ )
{
x_l[i] = LUv[2 * i];
x_u[i] = LUv[2 * i + 1];
}
for( Index i = 0; i < m; i++ )
{
g_l[i] = LUrhs[2 * i];
g_u[i] = LUrhs[2 * i + 1];
}
return true;
}
bool AmplTNLP::get_constraints_linearity(
Index n,
LinearityType* const_types
)
{
ASL_pfgh* asl = AmplSolverObject();
DBG_ASSERT(asl);
DBG_ASSERT(n == n_con);
(void) n;
DBG_ASSERT(nlnc == 0 && lnc == 0);
for( Index i = 0; i < nlc; i++ )
{
const_types[i] = NON_LINEAR;
}
for( Index i = nlc; i < n_con; i++ )
{
const_types[i] = LINEAR;
}
return true;
}
bool AmplTNLP::get_starting_point(
Index n,
bool init_x,
Number* x,
bool init_z,
Number* z_L,
Number* z_U,
Index m,
bool init_lambda,
Number* lambda
)
{
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
DBG_ASSERT(n == n_var);
DBG_ASSERT(m == n_con);
if( init_x )
for( Index i = 0; i < n; i++ )
{
x[i] = havex0[i] ? X0[i] : Max(LUv[2 * i], Min(LUv[2 * i + 1], 0.0));
}
if( init_z )
{
DBG_ASSERT(IsValid(suffix_handler_));
const Number* zL_init = suffix_handler_->GetNumberSuffixValues("ipopt_zL_in", AmplSuffixHandler::Variable_Source);
const Number* zU_init = suffix_handler_->GetNumberSuffixValues("ipopt_zU_in", AmplSuffixHandler::Variable_Source);
for( Index i = 0; i < n; i++ )
{
z_L[i] = zL_init != NULL ? obj_sign_ * zL_init[i] : 1.0;
z_U[i] = zU_init != NULL ? -obj_sign_ * zU_init[i] : 1.0;
}
}
if( init_lambda )
for( Index i = 0; i < m; i++ )
{
lambda[i] = havepi0[i] ? -obj_sign_ * pi0[i] : 0.0;
}
return true;
}
bool AmplTNLP::eval_f(
Index n,
const Number* x,
bool new_x,
Number& obj_value
)
{
DBG_START_METH("AmplTNLP::eval_f",
dbg_verbosity);
if( !apply_new_x(new_x, n, x) )
{
return false;
}
return internal_objval(x, obj_value);
}
bool AmplTNLP::eval_grad_f(
Index n,
const Number* x,
bool new_x,
Number* grad_f
)
{
DBG_START_METH("AmplTNLP::eval_grad_f",
dbg_verbosity);
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
if( !apply_new_x(new_x, n, x) )
{
return false;
}
if( n_obj == 0 )
{
for( Index i = 0; i < n; i++ )
{
grad_f[i] = 0.;
}
}
else
{
objgrd(obj_no, const_cast<Number*>(x), grad_f, (fint* )nerror_);
if( !nerror_ok(nerror_) )
{
return false;
}
if( obj_sign_ == -1 )
{
for( Index i = 0; i < n; i++ )
{
grad_f[i] *= -1.;
}
}
}
return true;
}
bool AmplTNLP::eval_g(
Index n,
const Number* x,
bool new_x,
Index m,
Number* g
)
{
DBG_START_METH("AmplTNLP::eval_g", dbg_verbosity);
DBG_DO(ASL_pfgh* asl = asl_);
DBG_ASSERT(asl);
DBG_ASSERT(n == n_var);
DBG_ASSERT(m == n_con);
if( !apply_new_x(new_x, n, x) )
{
return false;
}
return internal_conval(x, m, g);
}
bool AmplTNLP::eval_jac_g(
Index n,
const Number* x,
bool new_x,
Index m,
Index nele_jac,
Index* iRow,
Index* jCol,
Number* values
)
{
DBG_START_METH("AmplTNLP::eval_jac_g",
dbg_verbosity);
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
DBG_ASSERT(n == n_var);
DBG_ASSERT(m == n_con);
(void) m;
if( iRow && jCol && !values )
{
Index current_nz = 0;
for( Index i = 0; i < n_con; i++ )
{
for( cgrad* cg = Cgrad[i]; cg; cg = cg->next )
{
iRow[cg->goff] = i + 1;
jCol[cg->goff] = cg->varno + 1;
current_nz++;
}
}
DBG_ASSERT(current_nz == nele_jac);
(void) nele_jac;
return true;
}
else if( !iRow && !jCol && values )
{
if( !apply_new_x(new_x, n, x) )
{
return false;
}
jacval(const_cast<Number*>(x), values, (fint* )nerror_);
if( nerror_ok(nerror_) )
{
return true;
}
}
else
{
DBG_ASSERT(false && "Invalid combination of iRow, jCol, and values pointers");
}
return false;
}
bool AmplTNLP::eval_h(
Index n,
const Number* x,
bool new_x,
Number obj_factor,
Index m,
const Number* lambda,
bool ,
Index nele_hess,
Index* iRow,
Index* jCol,
Number* values
)
{
DBG_START_METH("AmplTNLP::eval_h",
dbg_verbosity);
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
DBG_ASSERT(n == n_var);
DBG_ASSERT(m == n_con);
if( iRow && jCol && !values )
{
Index k = 0;
for( Index i = 0; i < n; i++ )
{
#ifdef IPOPT_INT64
for( size_t j = sputinfo->hcolstartsZ[i]; j < sputinfo->hcolstartsZ[i + 1]; j++ )
#else
for( Index j = sputinfo->hcolstarts[i]; j < sputinfo->hcolstarts[i + 1]; j++ )
#endif
{
iRow[k] = i + 1;
jCol[k] = sputinfo->hrownos[j] + 1;
k++;
}
}
DBG_ASSERT(k == nele_hess);
(void) nele_hess;
return true;
}
else if( !iRow && !jCol && values )
{
if( !apply_new_x(new_x, n, x) )
{
return false;
}
if( !objval_called_with_current_x_ )
{
Number dummy;
internal_objval(x, dummy);
internal_conval(x, m);
}
if( !conval_called_with_current_x_ )
{
internal_conval(x, m);
}
real* OW = new real[Max(1, n_obj)];
if( n_obj > 0 )
{
for( Index i = 0; i < n_obj; i++ )
{
OW[i] = 0.;
}
OW[obj_no] = obj_sign_ * obj_factor;
}
sphes(values, -1, OW, const_cast<Number*>(lambda));
delete[] OW;
return true;
}
else
{
DBG_ASSERT(false && "Invalid combination of iRow, jCol, and values pointers");
}
return false;
}
void AmplTNLP::finalize_solution(
SolverReturn status,
Index n,
const Number* x,
const Number* z_L,
const Number* z_U,
Index m,
const Number* g,
const Number* lambda,
Number obj_value,
const IpoptData* ,
IpoptCalculatedQuantities*
)
{
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
if( !x_sol_ )
{
x_sol_ = new Number[n];
}
if( !z_L_sol_ )
{
z_L_sol_ = new Number[n];
}
if( !z_U_sol_ )
{
z_U_sol_ = new Number[n];
}
if( !g_sol_ )
{
g_sol_ = new Number[m];
}
if( !lambda_sol_ )
{
lambda_sol_ = new Number[m];
}
IpBlasCopy(n, x, 1, x_sol_, 1);
IpBlasCopy(m, g, 1, g_sol_, 1);
if( obj_sign_ == -1.0 ) {
for( Index i = 0; i < n; ++i )
{
z_L_sol_[i] = -z_L[i];
}
IpBlasCopy(n, z_U, 1, z_U_sol_, 1);
IpBlasCopy(m, lambda, 1, lambda_sol_, 1);
}
else
{
IpBlasCopy(n, z_L, 1, z_L_sol_, 1);
for( Index i = 0; i < n; ++i )
{
z_U_sol_[i] = -z_U[i];
}
for( Index i = 0; i < m; ++i )
{
lambda_sol_[i] = -lambda[i];
}
}
obj_sol_ = obj_value;
std::string message = " \nIpopt " IPOPT_VERSION ": ";
switch( status )
{
case SUCCESS:
message += "Optimal Solution Found";
solve_result_num = 0;
break;
case STOP_AT_ACCEPTABLE_POINT:
message += "Solved To Acceptable Level.";
solve_result_num = 1;
break;
case FEASIBLE_POINT_FOUND:
message += "Found feasible point for square problem.";
solve_result_num = 2;
break;
case LOCAL_INFEASIBILITY:
message += "Converged to a locally infeasible point. Problem may be infeasible.";
solve_result_num = 200;
break;
case DIVERGING_ITERATES:
message += "Iterates diverging; problem might be unbounded.";
solve_result_num = 300;
break;
case MAXITER_EXCEEDED:
message += "Maximum Number of Iterations Exceeded.";
solve_result_num = 400;
break;
case CPUTIME_EXCEEDED:
message += "Maximum CPU Time Exceeded.";
solve_result_num = 401;
break;
case WALLTIME_EXCEEDED:
message += "Maximum Wallclock Time Exceeded.";
solve_result_num = 402;
break;
case USER_REQUESTED_STOP:
message += "User requested stop.";
solve_result_num = 403;
break;
case STOP_AT_TINY_STEP:
message += "Search Direction becomes Too Small.";
solve_result_num = 500;
break;
case RESTORATION_FAILURE:
message += "Restoration Phase Failed.";
solve_result_num = 501;
break;
case ERROR_IN_STEP_COMPUTATION:
message += "Error in step computation.";
solve_result_num = 502;
break;
case INVALID_NUMBER_DETECTED:
message += "Invalid number in NLP function or derivative detected.";
solve_result_num = 550;
break;
case TOO_FEW_DEGREES_OF_FREEDOM:
message += "NLP has too few degrees of freedom.";
solve_result_num = 551;
break;
case INVALID_OPTION:
message += "Invalid option setting.";
solve_result_num = 552;
break;
case OUT_OF_MEMORY:
message += "Out of memory.";
solve_result_num = 553;
break;
case INTERNAL_ERROR:
message += "Internal error.";
solve_result_num = 554;
break;
case UNASSIGNED:
message += "Unknown Error";
solve_result_num = 599;
break;
}
if( IsValid(suffix_handler_) )
{
suf_rput("ipopt_zL_out", ASL_Sufkind_var, z_L_sol_);
suf_rput("ipopt_zU_out", ASL_Sufkind_var, z_U_sol_);
}
write_solution_file(message);
}
bool AmplTNLP::internal_objval(
const Number* x,
Number& obj_val
)
{
DBG_START_METH("AmplTNLP::internal_objval",
dbg_verbosity);
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
objval_called_with_current_x_ = false;
if( n_obj == 0 )
{
obj_val = 0;
objval_called_with_current_x_ = true;
return true;
}
else
{
Number retval = objval(obj_no, const_cast<Number*>(x), (fint* )nerror_);
if( nerror_ok(nerror_) )
{
obj_val = obj_sign_ * retval;
objval_called_with_current_x_ = true;
return true;
}
}
return false;
}
bool AmplTNLP::internal_conval(
const Number* x,
Index m,
Number* g
)
{
DBG_START_METH("AmplTNLP::internal_conval",
dbg_verbosity);
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
DBG_ASSERT(m == n_con);
conval_called_with_current_x_ = false;
bool allocated = false;
if( !g )
{
g = new Number[m];
allocated = true;
}
conval(const_cast<Number*>(x), g, (fint* )nerror_);
if( allocated )
{
delete[] g;
}
if( nerror_ok(nerror_) )
{
conval_called_with_current_x_ = true;
return true;
}
return false;
}
bool AmplTNLP::apply_new_x(
bool new_x,
Index ,
const Number* x
)
{
DBG_START_METH("AmplTNLP::apply_new_x",
dbg_verbosity);
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
if( new_x )
{
if( !hesset_called_ )
{
call_hesset();
}
DBG_PRINT((1, "Set new x.\n"));
conval_called_with_current_x_ = false;
objval_called_with_current_x_ = false;
xknowne(const_cast<Number*>(x), (fint* )nerror_);
return nerror_ok(nerror_);
}
return true;
}
void AmplTNLP::write_solution_file(
const std::string& message
) const
{
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
DBG_ASSERT(x_sol_ && lambda_sol_);
char* cmessage = new char[message.length() + 1];
strcpy(cmessage, message.c_str());
write_sol(cmessage, x_sol_, lambda_sol_, (Option_Info* )Oinfo_ptr_);
delete[] cmessage;
}
void AmplTNLP::get_discrete_info(
Index& nlvb_,
Index& nlvbi_,
Index& nlvc_,
Index& nlvci_,
Index& nlvo_,
Index& nlvoi_,
Index& nbv_,
Index& niv_
) const
{
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
nlvb_ = nlvb;
nlvbi_ = nlvbi;
nlvc_ = nlvc;
nlvci_ = nlvci;
nlvo_ = nlvo;
nlvoi_ = nlvoi;
nbv_ = nbv;
niv_ = niv;
}
bool AmplTNLP::get_scaling_parameters(
Number& obj_scaling,
bool& use_x_scaling,
Index n,
Number* x_scaling,
bool& use_g_scaling,
Index m,
Number* g_scaling
)
{
DBG_ASSERT(IsValid(suffix_handler_));
const Number* obj = suffix_handler_->GetNumberSuffixValues("scaling_factor", AmplSuffixHandler::Objective_Source);
obj_scaling = (obj) ? obj[0] : 1.0;
const Number* x = suffix_handler_->GetNumberSuffixValues("scaling_factor", AmplSuffixHandler::Variable_Source);
if( x )
{
use_x_scaling = true;
for( Index i = 0; i < n; i++ )
{
if( x[i] > 0.0 )
{
x_scaling[i] = x[i];
}
else
{
x_scaling[i] = 1.0;
}
}
}
else
{
use_x_scaling = false;
}
const Number* g = suffix_handler_->GetNumberSuffixValues("scaling_factor", AmplSuffixHandler::Constraint_Source);
if( g )
{
use_g_scaling = true;
for( Index i = 0; i < m; i++ )
{
if( g[i] > 0 )
{
g_scaling[i] = g[i];
}
else
{
g_scaling[i] = 1.0;
}
}
}
else
{
use_g_scaling = false;
}
return true;
}
Index AmplTNLP::get_number_of_nonlinear_variables()
{
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
return Max(nlvo, nlvc);
}
bool AmplTNLP::get_list_of_nonlinear_variables(
Index num_nonlin_vars,
Index* pos_nonlin_vars
)
{
DBG_DO(ASL_pfgh* asl = asl_);
DBG_ASSERT(asl);
DBG_ASSERT(num_nonlin_vars == Max(nlvo, nlvc));
for( Index i = 0; i < num_nonlin_vars; i++ )
{
pos_nonlin_vars[i] = i + 1;
}
return true;
}
extern "C"
{
static char* get_num_opt(
Option_Info* oi,
keyword* kw,
char* value
)
{
AmplOptionsList::PrivatInfo* pinfo = (AmplOptionsList::PrivatInfo*) kw->info;
real real_val;
kw->info = &real_val;
char* retval = D_val(oi, kw, value);
kw->info = (void*) pinfo;
if( !pinfo->Options()->SetNumericValue(pinfo->IpoptName().c_str(), real_val) )
{
pinfo->Jnlst()->Printf(J_ERROR, J_MAIN, "\nInvalid value \"%s\" for option %s.\n", value, kw->name);
THROW_EXCEPTION(OPTION_INVALID, "Invalid numeric option");
}
return retval;
}
static char* get_int_opt(
Option_Info* oi,
keyword* kw,
char* value
)
{
AmplOptionsList::PrivatInfo* pinfo = (AmplOptionsList::PrivatInfo*) kw->info;
int int_val;
kw->info = &int_val;
char* retval = I_val(oi, kw, value);
kw->info = (void*) pinfo;
if( !pinfo->Options()->SetIntegerValue(pinfo->IpoptName().c_str(), int_val) )
{
pinfo->Jnlst()->Printf(J_ERROR, J_MAIN, "\nInvalid value \"%s\" for option %s.\n", value, kw->name);
THROW_EXCEPTION(OPTION_INVALID, "Invalid integer option");
}
return retval;
}
static char* get_str_opt(
Option_Info* oi,
keyword* kw,
char* value
)
{
AmplOptionsList::PrivatInfo* pinfo = (AmplOptionsList::PrivatInfo*) kw->info;
char* str_val;
kw->info = &str_val;
char* retval = C_val(oi, kw, value);
kw->info = (void*) pinfo;
if( !pinfo->Options()->SetStringValue(pinfo->IpoptName().c_str(), str_val) )
{
pinfo->Jnlst()->Printf(J_ERROR, J_MAIN, "\nInvalid value \"%s\" for option %s.\n", value, kw->name);
THROW_EXCEPTION(OPTION_INVALID, "Invalid string option");
}
return retval;
}
static char* get_haltonerror_opt(
Option_Info* oi,
keyword* kw,
char* value
)
{
AmplOptionsList::PrivatInfo* pinfo = (AmplOptionsList::PrivatInfo*) kw->info;
char* str_val;
kw->info = &str_val;
char* retval = C_val(oi, kw, value);
kw->info = (void*) pinfo;
fint** nerror = (fint**) pinfo->NError();
if( strcmp(str_val, "yes") == 0 )
{
delete *nerror;
*nerror = NULL;
}
else if( strcmp(str_val, "no") == 0 )
{
delete *nerror;
*nerror = new fint;
** nerror = 0;
}
else
{
pinfo->Jnlst()->Printf(J_ERROR, J_MAIN, "\nInvalid value \"%s\" for option %s.\n", value, kw->name);
THROW_EXCEPTION(OPTION_INVALID, "Invalid option");
}
return retval;
}
}
AmplOptionsList::AmplOption::AmplOption(
const std::string& ipopt_option_name,
AmplOptionType type,
const std::string& description
)
: ipopt_option_name_(ipopt_option_name),
type_(type)
{
description_ = new char[description.size() + 1];
strcpy(description_, description.c_str());
}
AmplOptionsList::~AmplOptionsList()
{
if( keywds_ )
{
DBG_ASSERT(nkeywds_ > 0);
keyword* keywords = (keyword*) keywds_;
for( Index i = 0; i < nkeywds_; i++ )
{
PrivatInfo* pinfo = static_cast<PrivatInfo*>(keywords[i].info);
delete pinfo;
delete[] keywords[i].name;
}
delete[] keywords;
}
}
void* AmplOptionsList::Keywords(
const SmartPtr<OptionsList>& options,
SmartPtr<const Journalist> jnlst,
void** nerror
)
{
if( keywds_ )
{
DBG_ASSERT(nkeywds_ > 0);
keyword* keywords = (keyword*) keywds_;
for( Index i = 0; i < nkeywds_; i++ )
{
PrivatInfo* pinfo = static_cast<PrivatInfo*>(keywords[i].info);
delete pinfo;
delete[] keywords[i].name;
}
delete[] keywords;
nkeywds_ = 0;
}
Index n_options = NumberOfAmplOptions();
keyword* keywords = new keyword[n_options];
Index ioption = 0;
for( std::map<std::string, SmartPtr<const AmplOption> >::iterator iter = ampl_options_map_.begin();
iter != ampl_options_map_.end(); ++iter )
{
keywords[ioption].name = new char[iter->first.size() + 1];
strcpy(keywords[ioption].name, iter->first.c_str());
keywords[ioption].desc = iter->second->Description();
switch( iter->second->Type() )
{
case String_Option:
{
PrivatInfo* pinfo = new PrivatInfo(iter->second->IpoptOptionName(), options, jnlst);
keywords[ioption].info = (void*) pinfo;
keywords[ioption].kf = get_str_opt;
}
break;
case Number_Option:
{
PrivatInfo* pinfo = new PrivatInfo(iter->second->IpoptOptionName(), options, jnlst);
keywords[ioption].info = (void*) pinfo;
keywords[ioption].kf = get_num_opt;
}
break;
case Integer_Option:
{
PrivatInfo* pinfo = new PrivatInfo(iter->second->IpoptOptionName(), options, jnlst);
keywords[ioption].info = (void*) pinfo;
keywords[ioption].kf = get_int_opt;
}
break;
case WS_Option:
keywords[ioption].info = NULL;
keywords[ioption].kf = WS_val;
break;
case HaltOnError_Option:
PrivatInfo* pinfo = new PrivatInfo(iter->second->IpoptOptionName(), options, jnlst, nerror);
keywords[ioption].info = (void*) pinfo;
keywords[ioption].kf = get_haltonerror_opt;
break;
}
ioption++;
}
DBG_ASSERT(ioption == n_options);
nkeywds_ = n_options;
keywds_ = (void*) keywords;
return keywds_;
}
void AmplOptionsList::MakeValidLatexString(
std::string source,
std::string& dest
) const
{
for( std::string::iterator c = source.begin(); c != source.end(); ++c )
{
if( *c == '_' )
{
dest.append("\\_");
}
else if( *c == '^' )
{
dest.append("\\^");
}
else if( *c == '>' || *c == '<' )
{
;
}
else if( *c == '\n' )
{
dest += ", ";
}
else
{
dest += *c;
}
}
}
void AmplOptionsList::PrintLatex(
SmartPtr<const Journalist> jnlst
)
{
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, "\\begin{description}\n");
for( std::map<std::string, SmartPtr<const AmplOption> >::iterator iter = ampl_options_map_.begin();
iter != ampl_options_map_.end(); ++iter )
{
std::string amplname;
std::string ipoptname;
std::string descr;
MakeValidLatexString(iter->first.c_str(), amplname);
MakeValidLatexString(iter->second->IpoptOptionName(), ipoptname);
MakeValidLatexString(iter->second->Description(), descr);
if( ipoptname.length() > 0 )
{
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, "\\item[{\\htmlref{%s}{opt:%s}}]", amplname.c_str(),
iter->second->IpoptOptionName().c_str());
if( amplname != ipoptname )
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, " (Ipopt name: \\htmlref{%s}{opt:%s})", ipoptname.c_str(),
iter->second->IpoptOptionName().c_str());
}
else
{
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, "\\item[%s]", amplname.c_str());
}
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, " %s\n", descr.c_str());
}
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, "\\end{description}\n");
}
void AmplOptionsList::PrintDoxygen(
SmartPtr<const Journalist> jnlst
)
{
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, "| Option | Description |\n");
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, "|:-------|:------------|\n");
for( std::map<std::string, SmartPtr<const AmplOption> >::iterator iter = ampl_options_map_.begin();
iter != ampl_options_map_.end(); ++iter )
{
if( iter->second->IpoptOptionName().length() > 0 )
{
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, "| \\ref OPT_%s \"%s\"", iter->second->IpoptOptionName().c_str(), iter->first.c_str());
if( iter->first != iter->second->IpoptOptionName() )
{
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, " (Ipopt name: %s)", iter->second->IpoptOptionName().c_str());
}
}
else
{
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, "| %s", iter->first.c_str());
}
std::string descr = iter->second->Description();
for( std::string::iterator it = descr.begin(); it != descr.end(); ++it )
if( *it == '\n' )
{
*it = ';';
}
jnlst->Printf(J_SUMMARY, J_DOCUMENTATION, " | %s |\n", descr.c_str());
}
}
static const char sname_default[] = "ipopt";
static const char bsname_default[] = "Ipopt " IPOPT_VERSION;
static const char opname_default[] = "ipopt_options";
char*
AmplTNLP::get_options(
const SmartPtr<RegisteredOptions> regoptions,
const SmartPtr<OptionsList>& options,
SmartPtr<AmplOptionsList>& ampl_options_list,
const char* ampl_option_string,
const char* ampl_invokation_string,
const char* ampl_banner_string,
const char* const* argv
)
{
ASL_pfgh* asl = asl_;
if( !IsValid(ampl_options_list) )
{
ampl_options_list = new AmplOptionsList();
}
if( IsValid(regoptions) )
{
for( RegisteredOptions::RegOptionsList::const_iterator it_opt(regoptions->RegisteredOptionsList().begin()); it_opt != regoptions->RegisteredOptionsList().end(); ++it_opt )
{
AmplOptionsList::AmplOptionType ampltype = AmplOptionsList::Number_Option;
switch( it_opt->second->Type() )
{
case Ipopt::OT_Number:
ampltype = AmplOptionsList::Number_Option;
break;
case Ipopt::OT_Integer:
ampltype = AmplOptionsList::Integer_Option;
break;
case Ipopt::OT_String:
ampltype = AmplOptionsList::String_Option;
break;
case Ipopt::OT_Unknown:
continue;
}
ampl_options_list->AddAmplOption(it_opt->first, it_opt->first, ampltype, it_opt->second->ShortDescription());
}
}
else
{
ampl_options_list->AddAmplOption("print_level", "print_level", AmplOptionsList::Integer_Option, "Verbosity level");
ampl_options_list->AddAmplOption("print_user_options", "print_user_options", AmplOptionsList::String_Option,
"Toggle printing of user options");
ampl_options_list->AddAmplOption("print_options_documentation", "print_options_documentation",
AmplOptionsList::String_Option, "Print all available options (for ipopt.opt)");
ampl_options_list->AddAmplOption("output_file", "output_file", AmplOptionsList::String_Option,
"File name of an output file (leave unset for no file output)");
ampl_options_list->AddAmplOption("file_print_level", "file_print_level", AmplOptionsList::Integer_Option,
"Verbosity level for output file");
ampl_options_list->AddAmplOption("option_file_name", "option_file_name", AmplOptionsList::String_Option,
"File name of options file (default: ipopt.opt)");
ampl_options_list->AddAmplOption("tol", "tol", AmplOptionsList::Number_Option,
"Desired convergence tolerance (relative)");
ampl_options_list->AddAmplOption("max_iter", "max_iter", AmplOptionsList::Integer_Option,
"Maximum number of iterations");
ampl_options_list->AddAmplOption("max_wall_time", "max_wall_time", AmplOptionsList::Number_Option, "Wallclock time limit");
ampl_options_list->AddAmplOption("max_cpu_time", "max_cpu_time", AmplOptionsList::Number_Option, "CPU time limit");
ampl_options_list->AddAmplOption("compl_inf_tol", "compl_inf_tol", AmplOptionsList::Number_Option,
"Acceptance threshold for the complementarity conditions");
ampl_options_list->AddAmplOption("dual_inf_tol", "dual_inf_tol", AmplOptionsList::Number_Option,
"Desired threshold for the dual infeasibility");
ampl_options_list->AddAmplOption("constr_viol_tol", "constr_viol_tol", AmplOptionsList::Number_Option,
"Desired threshold for the constraint violation");
ampl_options_list->AddAmplOption("acceptable_tol", "acceptable_tol", AmplOptionsList::Number_Option,
"Acceptable convergence tolerance (relative)");
ampl_options_list->AddAmplOption("acceptable_compl_inf_tol", "acceptable_compl_inf_tol",
AmplOptionsList::Number_Option, "Acceptance threshold for the complementarity conditions");
ampl_options_list->AddAmplOption("acceptable_dual_inf_tol", "acceptable_dual_inf_tol",
AmplOptionsList::Number_Option, "Acceptance threshold for the dual infeasibility");
ampl_options_list->AddAmplOption("acceptable_constr_viol_tol", "acceptable_constr_viol_tol",
AmplOptionsList::Number_Option, "Acceptance threshold for the constraint violation");
ampl_options_list->AddAmplOption("diverging_iterates_tol", "diverging_iterates_tol", AmplOptionsList::Number_Option,
"Threshold for maximal value of primal iterates");
ampl_options_list->AddAmplOption("obj_scaling_factor", "obj_scaling_factor", AmplOptionsList::Number_Option,
"Scaling factor for the objective function");
ampl_options_list->AddAmplOption("nlp_scaling_method", "nlp_scaling_method", AmplOptionsList::String_Option,
"Select the technique used for scaling the NLP");
ampl_options_list->AddAmplOption("nlp_scaling_max_gradient", "nlp_scaling_max_gradient",
AmplOptionsList::Number_Option, "Maximum gradient after scaling");
ampl_options_list->AddAmplOption("bound_relax_factor", "bound_relax_factor", AmplOptionsList::Number_Option,
"Factor for initial relaxation of the bounds");
ampl_options_list->AddAmplOption("honor_original_bounds", "honor_original_bounds", AmplOptionsList::String_Option,
"If no, solution might slightly violate bounds");
ampl_options_list->AddAmplOption("mu_strategy", "mu_strategy", AmplOptionsList::String_Option,
"Update strategy for barrier parameter");
ampl_options_list->AddAmplOption("mu_oracle", "mu_oracle", AmplOptionsList::String_Option,
"Oracle for a new barrier parameter in the adaptive strategy");
ampl_options_list->AddAmplOption("mu_max", "mu_max", AmplOptionsList::Number_Option,
"Maximal value for barrier parameter for adaptive strategy");
ampl_options_list->AddAmplOption("mu_init", "mu_init", AmplOptionsList::Number_Option,
"Initial value for the barrier parameter");
ampl_options_list->AddAmplOption("bound_frac", "bound_frac", AmplOptionsList::Number_Option,
"Desired minimal relative distance of initial point to bound");
ampl_options_list->AddAmplOption("bound_push", "bound_push", AmplOptionsList::Number_Option,
"Desired minimal absolute distance of initial point to bound");
ampl_options_list->AddAmplOption("slack_bound_frac", "slack_bound_frac", AmplOptionsList::Number_Option,
"Desired minimal relative distance of initial slack to bound");
ampl_options_list->AddAmplOption("slack_bound_push", "slack_bound_push", AmplOptionsList::Number_Option,
"Desired minimal absolute distance of initial slack to bound");
ampl_options_list->AddAmplOption("bound_mult_init_val", "bound_mult_init_val", AmplOptionsList::Number_Option,
"Initial value for the bound multipliers");
ampl_options_list->AddAmplOption("constr_mult_init_max", "constr_mult_init_max", AmplOptionsList::Number_Option,
"Maximal allowed least-square guess of constraint multipliers");
ampl_options_list->AddAmplOption("alpha_for_y", "alpha_for_y", AmplOptionsList::String_Option,
"Step size for constraint multipliers");
ampl_options_list->AddAmplOption("max_soc", "max_soc", AmplOptionsList::Integer_Option,
"Maximal number of second order correction trial steps");
ampl_options_list->AddAmplOption("watchdog_shortened_iter_trigger", "watchdog_shortened_iter_trigger",
AmplOptionsList::Integer_Option, "Trigger counter for watchdog procedure");
ampl_options_list->AddAmplOption("expect_infeasible_problem", "expect_infeasible_problem",
AmplOptionsList::String_Option, "Enable heuristics to quickly detect an infeasible problem");
ampl_options_list->AddAmplOption("required_infeasibility_reduction", "required_infeasibility_reduction",
AmplOptionsList::Number_Option, "Required infeasibility reduction in restoration phase");
ampl_options_list->AddAmplOption("warm_start_init_point", "warm_start_init_point", AmplOptionsList::String_Option,
"Enables to specify bound multiplier values");
ampl_options_list->AddAmplOption("warm_start_bound_push", "warm_start_bound_push", AmplOptionsList::Number_Option,
"Enables to specify how much should variables should be pushed inside the feasible region");
ampl_options_list->AddAmplOption("warm_start_mult_bound_push", "warm_start_mult_bound_push",
AmplOptionsList::Number_Option,
"Enables to specify how much should bound multipliers should be pushed inside the feasible region");
ampl_options_list->AddAmplOption("hessian_approximation", "hessian_approximation", AmplOptionsList::String_Option,
"Can enable Quasi-Newton approximation of hessian");
ampl_options_list->AddAmplOption("linear_solver", "linear_solver", AmplOptionsList::String_Option,
"Linear solver to be used for step calculation");
ampl_options_list->AddAmplOption("linear_system_scaling", "linear_system_scaling", AmplOptionsList::String_Option,
"Method for scaling the linear systems");
ampl_options_list->AddAmplOption("linear_scaling_on_demand", "linear_scaling_on_demand",
AmplOptionsList::String_Option, "Enables heuristic for scaling only when seems required");
ampl_options_list->AddAmplOption("max_refinement_steps", "max_refinement_steps", AmplOptionsList::Integer_Option,
"Maximal number of iterative refinement steps per linear system solve");
ampl_options_list->AddAmplOption("min_refinement_steps", "min_refinement_steps", AmplOptionsList::Integer_Option,
"Minimum number of iterative refinement steps per linear system solve");
ampl_options_list->AddAmplOption("hessian_approximation", "hessian_approximation", AmplOptionsList::String_Option,
"Can enable Quasi-Newton approximation of hessian");
}
ampl_options_list->AddAmplOption("outlev", "print_level", AmplOptionsList::Integer_Option, "Verbosity level");
ampl_options_list->AddAmplOption("maxit", "max_iter", AmplOptionsList::Integer_Option,
"Maximum number of iterations");
ampl_options_list->AddAmplOption("wantsol", "", AmplOptionsList::WS_Option,
"solution report without -AMPL: sum of 1 (write .sol file), 2 (print primal variable values), 4 (print dual variable values), 8 (do not print solution message)");
ampl_options_list->AddAmplOption("halt_on_ampl_error", "", AmplOptionsList::HaltOnError_Option,
"Exit with message on evaluation error");
Index n_options = ampl_options_list->NumberOfAmplOptions();
keyword* keywds = (keyword*) ampl_options_list->Keywords(options, jnlst_, (void**) &nerror_);
const char* sname;
const char* bsname;
const char* opname;
if( ampl_option_string )
{
opname = ampl_option_string;
}
else
{
opname = opname_default;
}
if( ampl_invokation_string )
{
sname = ampl_invokation_string;
}
else
{
sname = sname_default;
}
if( ampl_banner_string )
{
bsname = ampl_banner_string;
}
else
{
bsname = bsname_default;
}
DBG_ASSERT(!Oinfo_ptr_);
Option_Info* Oinfo = new Option_Info;
Oinfo->sname = new char[strlen(sname) + 1];
strcpy(Oinfo->sname, sname);
Oinfo->bsname = new char[strlen(bsname) + 1];
strcpy(Oinfo->bsname, bsname);
Oinfo->opname = new char[strlen(opname) + 1];
strcpy(Oinfo->opname, opname);
Oinfo->keywds = keywds;
Oinfo->n_keywds = (int)n_options;
Oinfo->flags = 0;
Oinfo->version = NULL;
Oinfo->usage = NULL;
Oinfo->kwf = NULL;
Oinfo->feq = NULL;
Oinfo->options = NULL;
Oinfo->n_options = 0;
Oinfo->driver_date = 0;
Oinfo->wantsol = 0;
Oinfo->nS = 0;
Oinfo->S = NULL;
Oinfo->uinfo = NULL;
Oinfo->asl = NULL;
Oinfo->eqsign = NULL;
Oinfo->n_badopts = 0;
Oinfo->option_echo = 0;
Oinfo->nnl = 0;
Oinfo_ptr_ = Oinfo;
char* stub = getstops(const_cast<char**>(argv), Oinfo);
return stub;
}
bool AmplTNLP::nerror_ok(
void* nerror
)
{
DBG_START_METH("AmplTNLP::nerror_ok",
dbg_verbosity);
if( nerror == NULL || *((fint*) nerror) == 0 )
{
return true;
}
jnlst_->Printf(J_ERROR, J_MAIN,
"Error in an AMPL evaluation. Run with \"halt_on_ampl_error yes\" to see details.\n");
DBG_PRINT((1, "nerror = %d\n", *((fint*)nerror)));
return false;
}
AmplSuffixHandler::AmplSuffixHandler()
: asl_(NULL),
suftab_(NULL)
{
}
AmplSuffixHandler::~AmplSuffixHandler()
{
if( suftab_ )
{
Index n = (Index) suffix_ids_.size();
for( Index i = 0; i < n; i++ )
{
free(suftab_[i].name);
suftab_[i].name = NULL;
}
}
delete[] suftab_;
suftab_ = NULL;
}
void AmplSuffixHandler::PrepareAmplForSuffixes(
ASL_pfgh* asl
)
{
DBG_ASSERT(asl);
asl_ = asl;
Index n = (Index) suffix_ids_.size();
suftab_ = new SufDecl[n];
for( Index i = 0; i < n; i++ )
{
suftab_[i].name = strdup(suffix_ids_[i].c_str());
suftab_[i].table = 0;
if( suffix_sources_[i] == Variable_Source )
{
suftab_[i].kind = ASL_Sufkind_var;
}
else if( suffix_sources_[i] == Constraint_Source )
{
suftab_[i].kind = ASL_Sufkind_con;
}
else if( suffix_sources_[i] == Objective_Source )
{
suftab_[i].kind = ASL_Sufkind_obj;
}
else if( suffix_sources_[i] == Problem_Source )
{
suftab_[i].kind = ASL_Sufkind_prob;
}
else
{
DBG_ASSERT(false && "Unknown suffix source in PrepareAmplForSuffixes");
}
if( suffix_types_[i] == Number_Type )
{
suftab_[i].kind = suftab_[i].kind | ASL_Sufkind_real;
}
suftab_[i].nextra = 0;
}
suf_declare(suftab_, n);
}
const int*
AmplSuffixHandler::GetIntegerSuffixValues(
const std::string& suffix_string,
Suffix_Source source
) const
{
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
int kind;
if( source == Variable_Source )
{
kind = ASL_Sufkind_var;
}
else if( source == Constraint_Source )
{
kind = ASL_Sufkind_con;
}
else if( source == Objective_Source )
{
kind = ASL_Sufkind_obj;
}
else if( source == Problem_Source )
{
kind = ASL_Sufkind_prob;
}
else
{
THROW_EXCEPTION(IpoptException, "Unknown suffix source in GetIntegerSuffixValues");
}
SufDesc* dp = suf_get(suffix_string.c_str(), kind);
return dp->u.i;
}
std::vector<int> AmplSuffixHandler::GetIntegerSuffixValues(
Index n,
const std::string& suffix_string,
Suffix_Source source
) const
{
std::vector<int> ret;
const int* ptr = GetIntegerSuffixValues(suffix_string, source);
if( ptr )
{
ret.reserve(n);
for( Index i = 0; i < n; i++ )
{
ret.push_back(ptr[i]);
}
}
return ret;
}
const Number* AmplSuffixHandler::GetNumberSuffixValues(
const std::string& suffix_string,
Suffix_Source source
) const
{
ASL_pfgh* asl = asl_;
DBG_ASSERT(asl);
int kind;
if( source == Variable_Source )
{
kind = ASL_Sufkind_var;
}
else if( source == Constraint_Source )
{
kind = ASL_Sufkind_con;
}
else if( source == Objective_Source )
{
kind = ASL_Sufkind_obj;
}
else if( source == Problem_Source )
{
kind = ASL_Sufkind_prob;
}
else
{
THROW_EXCEPTION(IpoptException, "Unknown suffix source in GetNumberSuffixValues");
}
SufDesc* dp = suf_get(suffix_string.c_str(), kind);
return dp->u.r;
}
std::vector<Number> AmplSuffixHandler::GetNumberSuffixValues(
Index n,
const std::string& suffix_string,
Suffix_Source source
) const
{
std::vector<Number> ret;
const Number* ptr = GetNumberSuffixValues(suffix_string, source);
if( ptr )
{
ret.reserve(n);
for( Index i = 0; i < n; i++ )
{
ret.push_back(ptr[i]);
}
}
return ret;
}
}