source: branches/dev/Apps/AmplSolver/AmplTNLP.cpp @ 477

Last change on this file since 477 was 477, checked in by claird, 14 years ago

Reworked options:

  • Changed the order of options do they document better.
  • Changed SetValue? and GetValue? to SetStringValue? and GetStringValue?
  • Added an allow_clobber flag to options that defaults to true (set to false when options are read from PARAMS.DAT)
  • started the options documentation
  • Added options to the cpp example


Ran astyle to clean up the code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.3 KB
Line 
1// Copyright (C) 2004, 2005 International Business Machines and others.
2// All Rights Reserved.
3// This code is published under the Common Public License.
4//
5// $Id: AmplTNLP.cpp 477 2005-08-23 17:54:58Z claird $
6//
7// Authors:  Carl Laird, Andreas Waechter     IBM    2004-08-13
8
9#include "AmplTNLP.hpp"
10#include "IpDenseVector.hpp"
11#include "IpGenTMatrix.hpp"
12#include "IpSymTMatrix.hpp"
13#include "IpBlas.hpp"
14
15/* AMPL includes */
16#include "asl.h"
17#include "asl_pfgh.h"
18#include "getstub.h"
19
20namespace Ipopt
21{
22#ifdef IP_DEBUG
23  static const Index dbg_verbosity = 0;
24#endif
25
26  AmplTNLP::AmplTNLP(const SmartPtr<const Journalist>& jnlst,
27                     const SmartPtr<OptionsList> options,
28                     char**& argv,
29                     SmartPtr<AmplSuffixHandler> suffix_handler /* = NULL */,
30                     bool allow_discrete /* = false */)
31      :
32      TNLP(),
33      jnlst_(jnlst),
34      asl_(NULL),
35      obj_sign_(1),
36      nz_h_full_(-1),
37      non_const_x_(NULL),
38      x_sol_(NULL),
39      z_L_sol_(NULL),
40      z_U_sol_(NULL),
41      g_sol_(NULL),
42      lambda_sol_(NULL),
43      obj_sol_(0.0),
44      objval_called_with_current_x_(false),
45      conval_called_with_current_x_(false),
46      suffix_handler_(suffix_handler)
47  {
48    DBG_START_METH("AmplTNLP::AmplTNLP",
49                   dbg_verbosity);
50    // The ASL include files #define certain
51    // variables that they expect you to work with.
52    // These variables then appear as though they are
53    // global variables when, in fact, they are not
54    // Most of them are data members of an asl object
55
56    // Create the ASL structure
57    ASL_pfgh* asl = (ASL_pfgh*)ASL_alloc(ASL_read_pfgh);
58    DBG_ASSERT(asl);
59    asl_ = asl; // keep the pointer for ourselves to use later...
60
61    // Read the options and stub
62    char* stub = get_options(options, argv);
63    if (!stub) {
64      jnlst_->Printf(J_ERROR, J_MAIN, "No .nl file given!\n");
65      exit(-1);
66    }
67
68    FILE* nl = jac0dim(stub, (fint)strlen(stub));
69    DBG_ASSERT(nl);
70    jnlst_->Printf(J_SUMMARY, J_MAIN, "\n");
71
72    // check the problem statistics (see Table 1 in AMPL doc)
73    DBG_ASSERT(n_var > 0); // need some continuous variables
74    if (!allow_discrete && (nbv>0 || niv>0) ) {
75      jnlst_->Printf(J_WARNING, J_MAIN, "==> Warning: Treating %d binary and %d integer variables as continous.\n\n", nbv, niv);
76      allow_discrete = true;
77    }
78    allow_discrete = true;
79    ASSERT_EXCEPTION(allow_discrete || (nbv == 0 && niv == 0),
80                     IpoptException,
81                     "Discrete variables not allowed when the allow_discrete flag is false, "
82                     "Either remove the integer variables, or change the flag in the constructor of AmplTNLP"
83                    );
84    // n_con can be >= 0
85    DBG_ASSERT(n_obj == 1); // Currently can handle only 1 objective
86    DBG_ASSERT(nlo == 0 || nlo == 1); // Can handle nonlinear obj.
87    DBG_ASSERT(nwv == 0); // Don't know what "linear arc" variables are
88    DBG_ASSERT(nlnc == 0); // Don't know what "nonlinear network"constraints are
89    DBG_ASSERT(lnc == 0); // Don't know what "linear network" constraints are
90
91    // Set options in the asl structure
92    want_xpi0 = 1 | 2;  // allocate initial values for primal and dual if available
93    DBG_ASSERT((want_xpi0 & 1) == 1 && (want_xpi0 & 2) == 2);
94    obj_no = 0; // always want to work with the first (and only?) objective
95
96    // allocate space for initial values
97    X0 = new real[n_var];
98    havex0 = new char[n_var];
99    pi0 = new real[n_con];
100    havepi0 = new char[n_con];
101
102    // prepare for suffixes
103    if (IsValid(suffix_handler)) {
104      suffix_handler->PrepareAmplForSuffixes(asl_);
105    }
106
107    // read the rest of the nl file
108    int retcode = pfgh_read(nl, ASL_return_read_err | ASL_findgroups);
109
110    // see "changes" in solvers directory of ampl code...
111    hesset(1,0,1,0,nlc);
112
113    switch (retcode) {
114      case ASL_readerr_none : {}
115      break;
116      case ASL_readerr_nofile : {
117        jnlst_->Printf(J_ERROR, J_MAIN, "Cannot open .nl file\n");
118        exit(-1);
119      }
120      break;
121      case ASL_readerr_nonlin : {
122        DBG_ASSERT(false); // this better not be an error!
123        jnlst_->Printf(J_ERROR, J_MAIN, "model involves nonlinearities (ed0read)\n");
124        exit(-1);
125      }
126      break;
127      case  ASL_readerr_argerr : {
128        jnlst_->Printf(J_ERROR, J_MAIN, "user-defined function with bad args\n");
129        exit(-1);
130      }
131      break;
132      case ASL_readerr_unavail : {
133        jnlst_->Printf(J_ERROR, J_MAIN, "user-defined function not available\n");
134        exit(-1);
135      }
136      break;
137      case ASL_readerr_corrupt : {
138        jnlst_->Printf(J_ERROR, J_MAIN, "corrupt .nl file\n");
139        exit(-1);
140      }
141      break;
142      case ASL_readerr_bug : {
143        jnlst_->Printf(J_ERROR, J_MAIN, "bug in .nl reader\n");
144        exit(-1);
145      }
146      break;
147      default: {
148        jnlst_->Printf(J_ERROR, J_MAIN, "Unknown error in stub file read\n");
149        exit(-1);
150      }
151      break;
152    }
153
154    obj_sign_ = 1; // minimization
155    if (objtype[obj_no] != 0) {
156      obj_sign_ = -1;
157    }
158
159    // find the nonzero structure for the hessian
160    // parameters to sphsetup:
161    int coeff_obj = 1; // coefficient of the objective fn ???
162    int mult_supplied = 1; // multipliers will be supplied
163    int uptri = 1; // only need the upper triangular part
164    nz_h_full_ = sphsetup(-1, coeff_obj, mult_supplied, uptri);
165  }
166
167  AmplTNLP::~AmplTNLP()
168  {
169    ASL_pfgh* asl = asl_;
170
171    if (asl) {
172      if (X0) {
173        delete [] X0;
174        X0 = NULL;
175      }
176      if (havex0) {
177        delete [] havex0;
178        havex0 = NULL;
179      }
180      if (pi0) {
181        delete [] pi0;
182        pi0 = NULL;
183      }
184      if (havepi0) {
185        delete [] havepi0;
186        havepi0 = NULL;
187      }
188      ASL_free((ASL**)&asl_);
189      asl_ = NULL;
190    }
191
192    delete [] non_const_x_;
193    non_const_x_ = NULL;
194    delete [] x_sol_;
195    x_sol_ = NULL;
196    delete [] z_L_sol_;
197    z_L_sol_ = NULL;
198    delete [] z_U_sol_;
199    z_U_sol_ = NULL;
200    delete [] g_sol_;
201    g_sol_ = NULL;
202    delete [] lambda_sol_;
203    lambda_sol_ = NULL;
204  }
205
206  bool AmplTNLP::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
207                              Index& nnz_h_lag, IndexStyleEnum& index_style)
208  {
209    ASL_pfgh* asl = asl_;
210    DBG_ASSERT(asl_);
211
212    n = n_var; // # of variables (variable types have been asserted in the constructor
213    m = n_con; // # of constraints
214    nnz_jac_g = nzc; // # of non-zeros in the jacobian
215    nnz_h_lag = nz_h_full_; // # of non-zeros in the hessian
216
217    index_style = TNLP::FORTRAN_STYLE;
218
219    return true;
220  }
221
222  bool AmplTNLP::get_bounds_info(Index n, Number* x_l, Number* x_u, Index m, Number* g_l, Number* g_u)
223  {
224    ASL_pfgh* asl = asl_;
225    DBG_ASSERT(asl_);
226
227    DBG_ASSERT(n == n_var);
228    DBG_ASSERT(m == n_con);
229
230    for (Index i=0; i<n; i++) {
231      x_l[i] = LUv[2*i];
232      x_u[i] = LUv[2*i+1];
233    }
234
235    for (Index i=0; i<m; i++) {
236      g_l[i] = LUrhs[2*i];
237      g_u[i] = LUrhs[2*i+1];
238    }
239
240    return true;
241  }
242
243  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)
244  {
245    ASL_pfgh* asl = asl_;
246    DBG_ASSERT(asl_);
247    DBG_ASSERT(n == n_var);
248    DBG_ASSERT(m == n_con);
249
250    if (init_x) {
251      for (Index i=0; i<n; i++) {
252        if (havex0[i]) {
253          x[i] = X0[i];
254        }
255        else {
256          x[i] = 0.0;
257        }
258      }
259    }
260
261    if (init_z) {
262      for (Index i=0; i<n; i++) {
263        z_L[i] = z_U[i] = 1.0;
264      }
265    }
266
267    if (init_lambda) {
268      for (Index i=0; i<m; i++) {
269        if (havepi0[i]) {
270          lambda[i] = pi0[i];
271        }
272        else {
273          lambda[i] = 0.0;
274        }
275      }
276    }
277
278    return true;
279  }
280
281  bool AmplTNLP::eval_f(Index n, const Number* x, bool new_x, Number& obj_value)
282  {
283    DBG_START_METH("AmplTNLP::eval_f",
284                   dbg_verbosity);
285    apply_new_x(new_x, n, x);
286
287    return internal_objval(obj_value);
288  }
289
290  bool AmplTNLP::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
291  {
292    DBG_START_METH("AmplTNLP::eval_grad_f",
293                   dbg_verbosity);
294    ASL_pfgh* asl = asl_;
295    DBG_ASSERT(asl_);
296
297    apply_new_x(new_x, n, x);
298
299    fint nerror = 0;
300    objgrd(0, non_const_x_, grad_f, &nerror);
301    if (nerror != 0) {
302      DBG_PRINT((1, "nerror = %d\n", nerror));
303      return false;
304    }
305    if (obj_sign_==-1) {
306      for (Index i=0; i<n; i++) {
307        grad_f[i] *= -1.;
308      }
309    }
310    return true;
311  }
312
313  bool AmplTNLP::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g)
314  {
315    DBG_START_METH("AmplTNLP::eval_g", dbg_verbosity);
316#ifdef IP_DEBUG
317
318    ASL_pfgh* asl = asl_;
319    DBG_ASSERT(n == n_var);
320    DBG_ASSERT(m == n_con);
321#endif
322
323    apply_new_x(new_x, n, x);
324
325    return internal_conval(m, g);
326  }
327
328  bool AmplTNLP::eval_jac_g(Index n, const Number* x, bool new_x,
329                            Index m, Index nele_jac, Index* iRow,
330                            Index *jCol, Number* values)
331  {
332    DBG_START_METH("AmplTNLP::eval_jac_g",
333                   dbg_verbosity);
334    ASL_pfgh* asl = asl_;
335    DBG_ASSERT(asl_);
336    DBG_ASSERT(n == n_var);
337    DBG_ASSERT(m == n_con);
338
339    if (iRow && jCol && !values) {
340      // setup the structure
341      Index current_nz = 0;
342      for (Index i=0; i<n_con; i++) {
343        for (cgrad* cg=Cgrad[i]; cg; cg = cg->next) {
344          iRow[cg->goff] = i + 1;
345          jCol[cg->goff] = cg->varno + 1;
346          //                            iRow[current_nz] = i + 1;
347          //                            jCol[current_nz] = cg->varno+1;
348          current_nz++;
349        }
350      }
351      DBG_ASSERT(current_nz == nele_jac);
352      return true;
353    }
354    else if (!iRow && !jCol && values) {
355      apply_new_x(new_x, n, x);
356
357      fint nerror = 0;
358      jacval(non_const_x_, values, &nerror);
359
360      if (nerror == 0) {
361        return true;
362      }
363      DBG_PRINT((1, "nerror = %d\n", nerror));
364    }
365    else {
366      DBG_ASSERT(false && "Invalid combination of iRow, jCol, and values pointers");
367    }
368
369    return false;
370  }
371
372  bool AmplTNLP::eval_h(Index n, const Number* x, bool new_x,
373                        Number obj_factor, Index m, const Number* lambda,
374                        bool new_lambda, Index nele_hess, Index* iRow,
375                        Index* jCol, Number* values)
376  {
377    DBG_START_METH("AmplTNLP::eval_h",
378                   dbg_verbosity);
379    ASL_pfgh* asl = asl_;
380    DBG_ASSERT(asl_);
381    DBG_ASSERT(n == n_var);
382    DBG_ASSERT(m == n_con);
383
384    if (iRow && jCol && !values) {
385      // setup the structure
386      int k=0;
387      for (int i=0; i<n; i++) {
388        for (int j=sputinfo->hcolstarts[i]; j<sputinfo->hcolstarts[i+1]; j++) {
389          iRow[k] = i + 1;
390          jCol[k] = sputinfo->hrownos[j]+1;
391          k++;
392        }
393      }
394      DBG_ASSERT(k==nele_hess);
395      return true;
396    }
397    else if (!iRow & !jCol && values) {
398      apply_new_x(new_x, n, x);
399      if (!objval_called_with_current_x_) {
400        Number dummy;
401        internal_objval(dummy);
402        internal_conval(m);
403      }
404      if (!conval_called_with_current_x_) {
405        internal_conval(m);
406      }
407      // copy lambda to non_const_lambda - note, we do not store a copy like
408      // we do with x since lambda is only used here and not in other calls
409      Number* non_const_lambda = new Number[m];
410      for (Index i=0; i<m; i++) {
411        non_const_lambda[i] = lambda[i];
412      }
413
414      real ow=obj_sign_*obj_factor;
415      sphes(values, -1, &ow, non_const_lambda);
416
417      delete [] non_const_lambda;
418      return true;
419    }
420    else {
421      DBG_ASSERT(false && "Invalid combination of iRow, jCol, and values pointers");
422    }
423
424    return false;
425  }
426
427  void AmplTNLP::finalize_solution(SolverReturn status,
428                                   Index n, const Number* x, const Number* z_L, const Number* z_U,
429                                   Index m, const Number* g, const Number* lambda,
430                                   Number obj_value)
431  {
432    if (!x_sol_) {
433      x_sol_ = new Number[n];
434    }
435    if (!z_L_sol_) {
436      z_L_sol_ = new Number[n];
437    }
438    if (!z_U_sol_) {
439      z_U_sol_ = new Number[n];
440    }
441    if (!g_sol_) {
442      g_sol_ = new Number[m];
443    }
444    if (!lambda_sol_) {
445      lambda_sol_ = new Number[m];
446    }
447
448    IpBlasDcopy(n, x, 1, x_sol_, 1);
449    IpBlasDcopy(n, z_L, 1, z_L_sol_, 1);
450    IpBlasDcopy(n, z_U, 1, z_U_sol_, 1);
451    IpBlasDcopy(m, g, 1, g_sol_, 1);
452    IpBlasDcopy(m, lambda, 1, lambda_sol_, 1);
453    obj_sol_ = obj_value;
454
455    std::string message;
456    if (status == SUCCESS) {
457      message = "Optimal Solution Found";
458    }
459    else if (status == MAXITER_EXCEEDED) {
460      message = "Maximum Number of Iterations Exceeded";
461    }
462    else if (status == STOP_AT_TINY_STEP) {
463      message = "Solved To Best Possible Precision";
464    }
465    else if (status == STOP_AT_ACCEPTABLE_POINT) {
466      message = "Solved To Acceptable Level";
467    }
468    else if (status == LOCAL_INFEASIBILITY) {
469      message = "Converged to a locally infeasible point. Problem may be infeasible.";
470    }
471    else if (status == RESTORATION_FAILURE) {
472      message = "Restoration Phase Failed.";
473    }
474    else {
475      message = "Unknown Error";
476    }
477
478    // Write the .sol file
479    message = " \n" PACKAGE_STRING ": " + message;
480    write_solution_file(message.c_str());
481  }
482
483  bool AmplTNLP::internal_objval(Number& obj_val)
484  {
485    DBG_START_METH("AmplTNLP::internal_objval",
486                   dbg_verbosity);
487    ASL_pfgh* asl = asl_;
488    DBG_ASSERT(asl_);
489    objval_called_with_current_x_ = false; // in case the call below fails
490
491    fint nerror = 0;
492    Number retval = objval(0, non_const_x_, &nerror);
493    if (nerror == 0) {
494      obj_val = obj_sign_*retval;
495      objval_called_with_current_x_ = true;
496      return true;
497    }
498
499    //DBG_ASSERT(false && "Error evaluating AMPL objective.\n");
500    DBG_PRINT((1, "nerror = %d\n", nerror));
501    return false;
502  }
503
504  bool AmplTNLP::internal_conval(Index m, Number* g)
505  {
506    DBG_START_METH("AmplTNLP::internal_conval",
507                   dbg_verbosity);
508    ASL_pfgh* asl = asl_;
509    DBG_ASSERT(asl_);
510    DBG_ASSERT(m == n_con);
511    conval_called_with_current_x_ = false; // in case the call below fails
512
513    bool allocated = false;
514    if (!g) {
515      g = new double[m];
516      allocated = true;
517    }
518
519    fint nerror = 0;
520    conval(non_const_x_, g, &nerror);
521
522    if (allocated) {
523      delete [] g;
524      g = NULL;
525    }
526
527    if (nerror == 0) {
528      conval_called_with_current_x_ = true;
529      return true;
530    }
531    DBG_PRINT((1, "nerror = %d\n", nerror));
532    return false;
533  }
534
535
536  void AmplTNLP::apply_new_x(bool new_x, Index n, const Number* x)
537  {
538    DBG_START_METH("AmplTNLP::apply_new_x",
539                   dbg_verbosity);
540    ASL_pfgh* asl = asl_;
541    DBG_ASSERT(asl_);
542
543    if (new_x) {
544      DBG_PRINT((1, "Set new x.\n"));
545      // update the flags so these methods are called
546      // before evaluating the hessian
547      conval_called_with_current_x_ = false;
548      objval_called_with_current_x_ = false;
549
550      //copy the data to the non_const_x_
551      if (!non_const_x_) {
552        non_const_x_ = new Number[n];
553      }
554
555      for (Index i=0; i<n; i++) {
556        non_const_x_[i] = x[i];
557      }
558
559      // tell ampl that we have a new x
560      xknown(non_const_x_);
561    }
562  }
563
564  void AmplTNLP::write_solution_file(const std::string& message) const
565  {
566    ASL_pfgh* asl = asl_;
567    DBG_ASSERT(asl);
568    DBG_ASSERT(x_sol_ && lambda_sol_);
569
570    // We need to copy the message into a non-const char array to make
571    // it work with the AMPL C function.
572    char* cmessage = new char[message.length()+1];
573    strcpy(cmessage, message.c_str());
574
575    write_sol(cmessage, x_sol_, lambda_sol_, NULL);
576
577    delete [] cmessage;
578  }
579
580  void AmplTNLP::get_discrete_info(Index& nlvb_,
581                                   Index& nlvbi_,
582                                   Index& nlvc_,
583                                   Index& nlvci_,
584                                   Index& nlvo_,
585                                   Index& nlvoi_,
586                                   Index& nbv_,
587                                   Index& niv_) const
588  {
589    ASL_pfgh* asl = asl_;
590    DBG_ASSERT(asl);
591
592    nlvb_ = nlvb;
593    nlvbi_ = nlvbi;
594    nlvc_ = nlvc;
595    nlvci_ = nlvci;
596    nlvo_ = nlvo;
597    nlvoi_ = nlvoi;
598    nbv_ = nbv;
599    niv_ = niv;
600  }
601
602  void AmplTNLP::get_scaling_parameters(Number& obj_scaling,
603                                        Index n, Number* x_scaling,
604                                        Index m, Number* g_scaling)
605  {
606    DBG_ASSERT(IsValid(suffix_handler_));
607    const double* obj = suffix_handler_->GetNumberSuffixValues("scaling_factor", AmplSuffixHandler::Objective_Source);
608    obj_scaling = (obj) ? obj[0] : 1.0;
609
610    const double* x = suffix_handler_->GetNumberSuffixValues("scaling_factor", AmplSuffixHandler::Variable_Source);
611    for (int i=0; i < n; i++) {
612      if (x && x[i] > 0.0) {
613        x_scaling[i] = x[i];
614      }
615      else {
616        x_scaling[i] = 1.0;
617      }
618    }
619
620    const double* g = suffix_handler_->GetNumberSuffixValues("scaling_factor", AmplSuffixHandler::Constraint_Source);
621    for (int i=0; i < m; i++) {
622      if (g && g[i] > 0) {
623        g_scaling[i] = g[i];
624      }
625      else {
626        g_scaling[i] = 1.0;
627      }
628    }
629  }
630
631  struct privat_info
632  {
633    SmartPtr<OptionsList> options;
634    SmartPtr<const Journalist> jnlst;
635  };
636
637  extern "C"
638  {
639    static char* get_num_opt(Option_Info *oi, keyword *kw, char *value) {
640      privat_info* pinfo = (privat_info*) kw->info;
641
642      real real_val;
643      kw->info = &real_val;
644      char* retval = D_val(oi, kw, value);
645      kw->info = (void*) pinfo;
646
647      if (!pinfo->options->SetNumericValue(kw->name, real_val)) {
648        pinfo->jnlst->Printf(J_ERROR, J_MAIN,
649                             "\nInvalid value for option %s.\n", kw->name);
650        exit(-1);
651      }
652
653      return retval;
654    }
655
656    static char* get_int_opt(Option_Info *oi, keyword *kw, char *value) {
657      privat_info* pinfo = (privat_info*) kw->info;
658
659      int int_val;
660      kw->info = &int_val;
661      char* retval = I_val(oi, kw, value);
662      kw->info = (void*) pinfo;
663
664      if (!pinfo->options->SetIntegerValue(kw->name, int_val)) {
665        pinfo->jnlst->Printf(J_ERROR, J_MAIN,
666                             "\nInvalid value for option %s.\n", kw->name);
667        exit(-1);
668      }
669
670      return retval;
671    }
672
673    static char* get_str_opt(Option_Info *oi, keyword *kw, char *value) {
674      privat_info* pinfo = (privat_info*) kw->info;
675
676      char* str_val;
677      kw->info = &str_val;
678      char* retval = C_val(oi, kw, value);
679      kw->info = (void*) pinfo;
680
681      if (!pinfo->options->SetStringValue(kw->name, str_val)) {
682        pinfo->jnlst->Printf(J_ERROR, J_MAIN,
683                             "\nInvalid value for option %s.\n", kw->name);
684        exit(-1);
685      }
686
687      return retval;
688    }
689  }
690
691  // Define some macros for convenience
692#define ADDNUMOPT(__NAME__, __DESC__) \
693    static char name_ ## __NAME__ [] = #__NAME__; \
694    static char desc_ ## __NAME__ [] = __DESC__; \
695    privat_info pinfo_ ## __NAME__ = {options, jnlst_}; \
696    keywds[count_options].name = name_ ## __NAME__; \
697    keywds[count_options].kf = get_num_opt; \
698    keywds[count_options].info = (void*) &pinfo_ ## __NAME__; \
699    keywds[count_options].desc = desc_ ## __NAME__; \
700    count_options++;
701
702#define ADDINTOPT(__NAME__, __DESC__) \
703    static char name_ ## __NAME__ [] = #__NAME__; \
704    static char desc_ ## __NAME__ [] = __DESC__; \
705    privat_info pinfo_ ## __NAME__ = {options, jnlst_}; \
706    keywds[count_options].name = name_ ## __NAME__; \
707    keywds[count_options].kf = get_int_opt; \
708    keywds[count_options].info = (void*) &pinfo_ ## __NAME__; \
709    keywds[count_options].desc = desc_ ## __NAME__; \
710    count_options++;
711
712#define ADDSTROPT(__NAME__, __DESC__) \
713    static char name_ ## __NAME__ [] = #__NAME__; \
714    static char desc_ ## __NAME__ [] = __DESC__; \
715    privat_info pinfo_ ## __NAME__ = {options, jnlst_}; \
716    keywds[count_options].name = name_ ## __NAME__; \
717    keywds[count_options].kf = get_str_opt; \
718    keywds[count_options].info = (void*) &pinfo_ ## __NAME__; \
719    keywds[count_options].desc = desc_ ## __NAME__; \
720    count_options++;
721
722  char*
723  AmplTNLP::get_options(const SmartPtr<OptionsList>& options,
724                        char**& argv)
725  {
726    ASL_pfgh* asl = asl_;
727
728    // Now we list all options with one-line descriptions, using the
729    // macros defined above.  The names must be ordered
730    // alphabetically!!!
731    static const int n_options = 31; // This must be the total number
732    // of options defined below
733    keyword keywds[n_options];
734    int count_options=0;
735    ADDNUMOPT(acceptable_compl_inf_tol,
736              "Acceptance threshold for the complementarity conditions");
737    ADDNUMOPT(acceptable_constr_viol_tol,
738              "Acceptance threshold for the constraint violation");
739    ADDNUMOPT(acceptable_dual_inf_tol,
740              "Acceptance threshold for the dual infeasibility");
741    ADDNUMOPT(acceptable_tol,
742              "Acceptable convergence tolerance (relative)");
743    ADDSTROPT(alpha_for_y,
744              "Step size for constraint multipliers");
745    ADDNUMOPT(bound_frac,
746              "Desired minimal relative distance of initial point to bound");
747    ADDNUMOPT(bound_mult_init_val,
748              "Initial value for the bound multipliers");
749    ADDNUMOPT(bound_push,
750              "Desired minimal absolute distance of initial point to bound");
751    ADDNUMOPT(bound_relax_factor,
752              "Factor for initial relaxation of the bounds");
753    ADDNUMOPT(compl_inf_tol,
754              "Acceptance threshold for the complementarity conditions");
755    ADDNUMOPT(constr_mult_init_max,
756              "Maximal allowed least-square guess of constraint multipliers");
757    ADDNUMOPT(constr_viol_tol,
758              "Desired threshold for the constraint violation");
759    ADDSTROPT(corrector_type,
760              "Type of corrector steps");
761    ADDNUMOPT(dual_inf_tol,
762              "Desired threshold for the dual infeasibility");
763    ADDSTROPT(expect_infeasible_problem,
764              "Enable heuristics to quickly detect an infeasible problem");
765    ADDINTOPT(file_print_level,
766              "Verbosity level for output file");
767    ADDINTOPT(max_iter,
768              "Maximum number of iterations");
769    ADDINTOPT(max_refinement_steps,
770              "Maximal number of iterative refinement steps per linear system solve");
771    ADDINTOPT(max_soc,
772              "Maximal number of second order correction trial steps");
773    ADDINTOPT(min_refinement_steps,
774              "Minimum number of iterative refinement steps per linear system solve");
775    ADDNUMOPT(mu_init,
776              "Initial value for the barrier parameter");
777    ADDSTROPT(mu_oracle,
778              "Oracle for a new barrier parameter in the adaptive strategy");
779    ADDSTROPT(mu_strategy,
780              "Update strategy for barrier parameter");
781    ADDNUMOPT(nlp_scaling_max_gradient,
782              "Maximum gradient after scaling");
783    ADDSTROPT(nlp_scaling_method,
784              "Select the technique used for scaling the NLP");
785    ADDNUMOPT(obj_scaling_factor,
786              "Scaling factor for the objective function");
787    ADDSTROPT(output_file,
788              "File name of an output file (leave unset for no file output)");
789    ADDNUMOPT(pivtol,
790              "Pivot tolerance for the linear solver");
791    ADDNUMOPT(pivtolmax,
792              "Maximal pivot tolerance for the linear solver");
793    ADDINTOPT(print_level,
794              "Verbosity level");
795    ADDNUMOPT(tol,
796              "Desired convergence tolerance (relative)");
797
798    DBG_ASSERT(count_options == n_options);
799
800    static char sname[] = "ipopt";
801    static char bsname[] = PACKAGE_STRING;
802    static char opname[] = "ipopt_options";
803    Option_Info Oinfo = {sname,
804                         bsname,
805                         opname,
806                         keywds,
807                         n_options};
808
809    char* stub = getstops(argv, &Oinfo);
810
811    return stub;
812  }
813
814  AmplSuffixHandler::AmplSuffixHandler()
815      :
816      asl_(NULL),
817      suftab_ (NULL)
818  {}
819
820  AmplSuffixHandler::~AmplSuffixHandler()
821  {
822    if (suftab_) {
823      Index n = suffix_ids_.size();
824      for (Index i=0; i<n; i++) {
825        delete [] suftab_[i].name;
826        suftab_[i].name = NULL;
827      }
828    }
829    delete [] suftab_;
830    suftab_ = NULL;
831  }
832
833  void AmplSuffixHandler::PrepareAmplForSuffixes(ASL_pfgh* asl)
834  {
835    DBG_ASSERT(asl);
836    asl_ = asl;
837
838    Index n = suffix_ids_.size();
839    suftab_ = new SufDecl[n];
840    for (Index i=0; i<n; i++) {
841      Index id_len = strlen(suffix_ids_[i].c_str());
842      suftab_[i].name = new char[id_len + 1];
843      strcpy(suftab_[i].name, suffix_ids_[i].c_str());
844
845      suftab_[i].table = 0;
846
847      if (suffix_sources_[i] == Variable_Source) {
848        suftab_[i].kind = ASL_Sufkind_var;
849      }
850      else if (suffix_sources_[i]  == Constraint_Source) {
851        suftab_[i].kind = ASL_Sufkind_con;
852      }
853      else if (suffix_sources_[i] == Objective_Source) {
854        suftab_[i].kind = ASL_Sufkind_obj;
855      }
856      else if (suffix_sources_[i] == Problem_Source) {
857        suftab_[i].kind = ASL_Sufkind_prob;
858      }
859      else {
860        DBG_ASSERT(false && "Unknown suffix source in PrepareAmplForSuffixes");
861      }
862
863      if (suffix_types_[i] == Number_Type) {
864        suftab_[i].kind = suftab_[i].kind | ASL_Sufkind_real;
865      }
866
867      suftab_[i].nextra = 0;
868    }
869
870    suf_declare(suftab_, n);
871  }
872
873  const Index*
874  AmplSuffixHandler::GetIntegerSuffixValues(std::string suffix_string,
875      Suffix_Source source) const
876  {
877    ASL_pfgh* asl = asl_;
878    DBG_ASSERT(asl);
879
880    int kind;
881    if (source == Variable_Source) {
882      kind = ASL_Sufkind_var;
883    }
884    else if (source == Constraint_Source) {
885      kind = ASL_Sufkind_con;
886    }
887    else if (source == Objective_Source) {
888      kind = ASL_Sufkind_obj;
889    }
890    else if (source == Problem_Source) {
891      kind = ASL_Sufkind_prob;
892    }
893    else {
894      kind = 0;
895      DBG_ASSERT(false && "Unknown suffix source in GetIntegerSuffixValues");
896    }
897    SufDesc* dp = suf_get(suffix_string.c_str(), kind);
898    return dp->u.i;
899  }
900
901  const Number*
902  AmplSuffixHandler::GetNumberSuffixValues(std::string suffix_string,
903      Suffix_Source source) const
904  {
905    ASL_pfgh* asl = asl_;
906    DBG_ASSERT(asl);
907
908    int kind;
909    if (source == Variable_Source) {
910      kind = ASL_Sufkind_var;
911    }
912    else if (source == Constraint_Source) {
913      kind = ASL_Sufkind_con;
914    }
915    else if (source == Objective_Source) {
916      kind = ASL_Sufkind_obj;
917    }
918    else if (source == Problem_Source) {
919      kind = ASL_Sufkind_prob;
920    }
921    else {
922      kind = 0;
923      DBG_ASSERT(false && "Unknown suffix source in GetNumberSuffixValues");
924    }
925    SufDesc* dp = suf_get(suffix_string.c_str(), kind);
926    return dp->u.r;
927  }
928
929} // namespace Ipopt
930
931
932
Note: See TracBrowser for help on using the repository browser.