source: branches/dev/Common/IpOptionsList.cpp @ 567

Last change on this file since 567 was 567, checked in by andreasw, 15 years ago

adapted for Portland compilers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.2 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: IpOptionsList.cpp 567 2005-11-01 23:27:11Z andreasw $
6//
7// Authors:  Carl Laird, Andreas Waechter     IBM    2004-08-13
8
9#include "IpOptionsList.hpp"
10
11#ifdef HAVE_CCTYPE
12# include <cctype>
13#else
14# ifdef HAVE_CTYPE_H
15#  include <ctype.h>
16# else
17#  error "don't have header file for ctype"
18# endif
19#endif
20
21#ifdef HAVE_CSTDIO
22# include <cstdio>
23#else
24# ifdef HAVE_STDIO_H
25#  include <stdio.h>
26# else
27#  error "don't have header file for stdio"
28# endif
29#endif
30
31namespace Ipopt
32{
33
34  bool OptionsList::SetStringValue(const std::string& tag,
35                                   const std::string& value,
36                                   bool allow_clobber /* = true */)
37  {
38    if (IsValid(reg_options_)) {
39      SmartPtr<const RegisteredOption> option = reg_options_->GetOption(tag);
40
41      if (IsNull(option)) {
42        if (IsValid(jnlst_)) {
43          std::string msg = "Tried to set Option: " + tag;
44          msg += ". It is not a valid option. Please check the list of available options.\n";
45          jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
46        }
47        //THROW_EXCEPTION(OPTION_INVALID, msg);
48        return false;
49      }
50
51      if (option->Type() != OT_String) {
52        if (IsValid(jnlst_)) {
53          std::string msg = "Tried to set Option: " + tag;
54          msg += ". It is a valid option, but it is of type ";
55          if (option->Type() == OT_Number) {
56            msg += " Number";
57          }
58          else if (option->Type() == OT_Integer) {
59            msg += " Integer";
60          }
61          else {
62            msg += " Unknown";
63          }
64          msg += ", not of type String. Please check the documentation for options.\n";
65          jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
66          option->OutputDescription(*jnlst_);
67        }
68        //THROW_EXCEPTION(OPTION_INVALID, msg);
69        return false;
70      }
71
72      if (!option->IsValidStringSetting(value)) {
73        if (IsValid(jnlst_)) {
74          std::string msg = "Setting: " + value;
75          msg += " is not a valid setting for Option: ";
76          msg += tag;
77          msg += ". Check the option documentation.\n";
78          jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
79          option->OutputDescription(*jnlst_);
80        }
81        //THROW_EXCEPTION(OPTION_INVALID, msg);
82        return false;
83      }
84    }
85
86    if (will_allow_clobber(tag)) {
87      OptionsList::OptionValue optval(lowercase(value), allow_clobber);
88      options_[lowercase(tag)] = optval;
89      return true;
90    }
91
92    std::string msg = "Option: \"" + tag;
93    msg += " ";
94    msg += value;
95    msg += "\" not taken because a value of \n\"" ;
96    msg += options_[lowercase(tag)].GetValue();
97    msg += "\" already exists and is set to disallow clobbering.\n\n";
98    jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
99    return false;
100  }
101
102  bool OptionsList::SetNumericValue(const std::string& tag, Number value,
103                                    bool allow_clobber /* = true */)
104  {
105    char buffer[256];
106    sprintf(buffer, "%g", value);
107
108    if (IsValid(reg_options_)) {
109      SmartPtr<const RegisteredOption> option = reg_options_->GetOption(tag);
110
111      if (IsNull(option)) {
112        if (IsValid(jnlst_)) {
113          std::string msg = "Tried to set Option: " + tag;
114          msg += ". It is not a valid option. Please check the list of available options.\n";
115          jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
116        }
117        //THROW_EXCEPTION(OPTION_INVALID, msg);
118        return false;
119      }
120
121      if (option->Type() != OT_Number) {
122        if (IsValid(jnlst_)) {
123          std::string msg = "Tried to set Option: " + tag;
124          msg += ". It is a valid option, but it is of type ";
125          if (option->Type() == OT_String) {
126            msg += " String";
127          }
128          else if (option->Type() == OT_Integer) {
129            msg += " Integer";
130          }
131          else {
132            msg += " Unknown";
133          }
134          msg += ", not of type Number. Please check the documentation for options.\n";
135          jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
136          option->OutputDescription(*jnlst_);
137        }
138        //THROW_EXCEPTION(OPTION_INVALID, msg);
139        return false;
140      }
141
142      if (!option->IsValidNumberSetting(value)) {
143        if (IsValid(jnlst_)) {
144          std::string msg = "Setting: ";
145          msg += buffer;
146          msg += " is not a valid setting for Option: ";
147          msg += tag;
148          msg += ". Check the option documentation.\n";
149          jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
150          option->OutputDescription(*jnlst_);
151        }
152        //THROW_EXCEPTION(OPTION_INVALID, msg);
153        return false;
154      }
155    }
156
157    if (will_allow_clobber(tag)) {
158      OptionsList::OptionValue optval(buffer, allow_clobber);
159      options_[lowercase(tag)] = optval;
160      return true;
161    }
162
163    std::string msg = "Option: \"" + tag;
164    msg += " ";
165    msg += buffer;
166    msg += "\" not taken because a value of\n\"" ;
167    msg += options_[lowercase(tag)].GetValue();
168    msg += "\" already exists and is set to disallow clobbering.\n\n";
169    jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
170    return false;
171  }
172
173  bool OptionsList::SetIntegerValue(const std::string& tag, Index value,
174                                    bool allow_clobber /* = true */)
175  {
176    char buffer[256];
177    sprintf(buffer, "%d", value);
178
179    if (IsValid(reg_options_)) {
180      SmartPtr<const RegisteredOption> option = reg_options_->GetOption(tag);
181
182      if (IsNull(option)) {
183        std::string msg = "Tried to set Option: " + tag;
184        msg += ". It is not a valid option. Please check the list of available options.\n";
185        if (IsValid(jnlst_)) {
186          jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
187        }
188        //THROW_EXCEPTION(OPTION_INVALID, msg);
189        return false;
190      }
191
192      if (option->Type() != OT_Integer) {
193        if (IsValid(jnlst_)) {
194          std::string msg = "Tried to set Option: " + tag;
195          msg += ". It is a valid option, but it is of type ";
196          if (option->Type() == OT_String) {
197            msg += " String";
198          }
199          else if (option->Type() == OT_Number) {
200            msg += " Number";
201          }
202          else {
203            msg += " Unknown";
204          }
205          msg += ", not of type Integer. Please check the documentation for options.\n";
206          jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
207          option->OutputDescription(*jnlst_);
208        }
209        //THROW_EXCEPTION(OPTION_INVALID, msg);
210        return false;
211      }
212
213      if (!option->IsValidIntegerSetting(value)) {
214        if (IsValid(jnlst_)) {
215          std::string msg = "Setting: ";
216          msg += buffer;
217          msg += " is not a valid setting for Option: ";
218          msg += tag;
219          msg += ". Check the option documentation.\n";
220          jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
221          option->OutputDescription(*jnlst_);
222        }
223        //THROW_EXCEPTION(OPTION_INVALID, msg);
224        return false;
225      }
226    }
227
228    if (will_allow_clobber(tag)) {
229      OptionsList::OptionValue optval(buffer, allow_clobber);
230      options_[lowercase(tag)] = optval;
231      return true;
232    }
233
234    std::string msg = "Option: \"" + tag;
235    msg += " ";
236    msg += buffer;
237    msg += "\" not taken because a value of \n\"" ;
238    msg += options_[lowercase(tag)].GetValue();
239    msg += "\" already exists and is set to disallow clobbering.\n\n";
240    jnlst_->Printf(J_ERROR, J_MAIN, msg.c_str());
241    return false;
242  }
243
244  bool OptionsList::GetStringValue(const std::string& tag, std::string& value,
245                                   const std::string& prefix) const
246  {
247    SmartPtr<const RegisteredOption> option = NULL;
248
249    bool found = find_tag(tag, prefix, value);
250
251    if (IsValid(reg_options_)) {
252      option = reg_options_->GetOption(tag);
253      if (IsNull(option)) {
254        std::string msg = "IPOPT tried to get the value of Option: " + tag;
255        msg += ". It is not a valid registered option.";
256        THROW_EXCEPTION(OPTION_INVALID, msg);
257      }
258
259      if (option->Type() != OT_String) {
260        std::string msg = "IPOPT tried to get the value of Option: " + tag;
261        msg += ". It is a valid option, but it is of type ";
262        if (option->Type() == OT_Integer) {
263          msg += " Integer";
264        }
265        else if (option->Type() == OT_Number) {
266          msg += " Number";
267        }
268        else {
269          msg += " Unknown";
270        }
271        msg += ", not of type String. Please check the documentation for options.";
272        if (IsValid(jnlst_)) {
273          option->OutputDescription(*jnlst_);
274        }
275        THROW_EXCEPTION(OPTION_INVALID, msg);
276      }
277
278      if (found) {
279        value = option->MapStringSetting(value);
280      }
281      else {
282        value = option->DefaultString();
283      }
284    }
285
286    return found;
287  }
288
289  bool OptionsList::GetEnumValue(const std::string& tag, Index& value,
290                                 const std::string& prefix) const
291  {
292    std::string str;
293    SmartPtr<const RegisteredOption> option = NULL;
294
295    bool found = find_tag(tag, prefix, str);
296
297    if (IsValid(reg_options_)) {
298      option = reg_options_->GetOption(tag);
299      if (IsNull(option)) {
300        std::string msg = "IPOPT tried to get the value of Option: " + tag;
301        msg += ". It is not a valid registered option.";
302        THROW_EXCEPTION(OPTION_INVALID, msg);
303      }
304
305      if (option->Type() != OT_String) {
306        std::string msg = "IPOPT tried to get the value of Option: " + tag;
307        msg += ". It is a valid option, but it is of type ";
308        if (option->Type() == OT_Integer) {
309          msg += " Integer";
310        }
311        else if (option->Type() == OT_Number) {
312          msg += " Number";
313        }
314        else {
315          msg += " Unknown";
316        }
317        msg += ", not of type String. Please check the documentation for options.";
318        if (IsValid(jnlst_)) {
319          option->OutputDescription(*jnlst_);
320        }
321        THROW_EXCEPTION(OPTION_INVALID, msg);
322      }
323
324      if (found) {
325        value = option->MapStringSettingToEnum(str);
326      }
327      else {
328        value = option->DefaultStringAsEnum();
329      }
330    }
331
332    return found;
333  }
334
335  bool OptionsList::GetBoolValue(const std::string& tag, bool& value,
336                                 const std::string& prefix) const
337  {
338    std::string str;
339    bool ret = GetStringValue(tag, str, prefix);
340    if (str == "no" || str == "false" || str == "off") {
341      value = false;
342    }
343    else if (str == "yes" || str == "true" || str == "on") {
344      value = true;
345    }
346    else {
347      THROW_EXCEPTION(OPTION_INVALID, "Tried to get a boolean from an option and failed.");
348    }
349
350    return ret;
351  }
352
353  bool OptionsList::GetNumericValue(const std::string& tag, Number& value,
354                                    const std::string& prefix) const
355  {
356    SmartPtr<const RegisteredOption> option = NULL;
357
358    if (IsValid(reg_options_)) {
359      option = reg_options_->GetOption(tag);
360      if (IsNull(option)) {
361        std::string msg = "IPOPT tried to get the value of Option: " + tag;
362        msg += ". It is not a valid registered option.";
363        THROW_EXCEPTION(OPTION_INVALID, msg);
364      }
365
366      if (option->Type() != OT_Number) {
367        std::string msg = "IPOPT tried to get the value of Option: " + tag;
368        msg += ". It is a valid option, but it is of type ";
369        if (option->Type() == OT_Integer) {
370          msg += " Integer";
371        }
372        else if (option->Type() == OT_String) {
373          msg += " String";
374        }
375        else {
376          msg += " Unknown";
377        }
378        msg += ", not of type Number. Please check the documentation for options.";
379        if (IsValid(jnlst_)) {
380          option->OutputDescription(*jnlst_);
381        }
382        THROW_EXCEPTION(OPTION_INVALID, msg);
383      }
384    }
385
386    std::string strvalue;
387    if (find_tag(tag, prefix, strvalue)) {
388      char* p_end;
389      Number retval = strtod(strvalue.c_str(), &p_end);
390      if (*p_end!='\0' && !isspace(*p_end)) {
391        std::string msg = "Option \"" + tag +
392                          "\": Double value expected, but non-numeric value \"" +
393                          strvalue+"\" found.\n";
394        THROW_EXCEPTION(OPTION_INVALID, msg);
395      }
396      value = retval;
397      return true;
398    }
399    else if (IsValid(option)) {
400      value = option->DefaultNumber();
401      return false;
402    }
403    return false;
404  }
405
406  bool OptionsList::GetIntegerValue(const std::string& tag, Index& value,
407                                    const std::string& prefix) const
408  {
409    SmartPtr<const RegisteredOption> option = NULL;
410
411    if (IsValid(reg_options_)) {
412      option = reg_options_->GetOption(tag);
413      if (IsNull(option)) {
414        std::string msg = "IPOPT tried to get the value of Option: " + tag;
415        msg += ". It is not a valid registered option.";
416        THROW_EXCEPTION(OPTION_INVALID, msg);
417      }
418
419      if (option->Type() != OT_Integer) {
420        std::string msg = "IPOPT tried to get the value of Option: " + tag;
421        msg += ". It is a valid option, but it is of type ";
422        if (option->Type() == OT_Number) {
423          msg += " Number";
424        }
425        else if (option->Type() == OT_String) {
426          msg += " String";
427        }
428        else {
429          msg += " Unknown";
430        }
431        msg += ", not of type Integer. Please check the documentation for options.";
432        if (IsValid(jnlst_)) {
433          option->OutputDescription(*jnlst_);
434        }
435        THROW_EXCEPTION(OPTION_INVALID, msg);
436      }
437    }
438
439    std::string strvalue;
440    if (find_tag(tag, prefix, strvalue)) {
441      char* p_end;
442      Index retval = strtol(strvalue.c_str(), &p_end, 10);
443      if (*p_end!='\0' && !isspace(*p_end)) {
444        std::string msg = "Option \"" + tag +
445                          "\": Integer value expected, but non-integer value \"" +
446                          strvalue+"\" found.\n";
447        THROW_EXCEPTION(OPTION_INVALID, msg);
448      }
449      value = retval;
450      return true;
451    }
452    else if (IsValid(option)) {
453      value = option->DefaultInteger();
454      return false;
455    }
456
457    return false;
458  }
459
460  const std::string& OptionsList::lowercase(const std::string tag) const
461  {
462    lowercase_buffer_ = tag;
463    for(Index i=0; i<(Index)tag.length(); i++) {
464      lowercase_buffer_[i] = tolower(tag[i]);
465    }
466    return lowercase_buffer_;
467  }
468
469  void OptionsList::PrintList(std::string& list) const
470  {
471    list.clear();
472    char buffer[256];
473    sprintf(buffer, "%40s   %-20s %s\n", "Name", "Value", "# times used");
474    list += buffer;
475    for(std::map< std::string, OptionValue >::const_iterator p = options_.begin();
476        p != options_.end();
477        p++ ) {
478      sprintf(buffer, "%40s = %-20s %6d\n", p->first.c_str(),
479              p->second.Value().c_str(), p->second.Counter());
480      list += buffer;
481    }
482  }
483
484  bool OptionsList::ReadFromFile(const Journalist& jnlst,
485                                 FILE* fp)
486  {
487    DBG_ASSERT(fp);
488
489    jnlst.Printf(J_DETAILED, J_MAIN, "Start reading options from file.\n");
490
491    while (true) {
492      std::string tag;
493      std::string value;
494
495      if (!readnexttoken(fp, tag)) {
496        // That's it - end of file reached.
497        jnlst.Printf(J_DETAILED, J_MAIN,
498                     "Finished reading options from file.\n");
499        return true;
500      }
501
502      if (!readnexttoken(fp, value)) {
503        // Can't read value for a given tag
504        jnlst.Printf(J_ERROR, J_MAIN,
505                     "Error reading value for tag %s from file.\n",
506                     tag.c_str());
507        return false;
508      }
509
510      // Now add the value for the options list
511      jnlst.Printf(J_DETAILED, J_MAIN,
512                   "Adding option \"%s\" with value \"%s\" to OptionsList.\n",
513                   tag.c_str(), value.c_str());
514
515      if (IsValid(reg_options_)) {
516        SmartPtr<const RegisteredOption> option = reg_options_->GetOption(tag);
517        if (IsNull(option)) {
518          std::string msg = "Read Option: ";
519          msg += tag;
520          msg += ". It is not a valid option. Check the list of available options.";
521          THROW_EXCEPTION(OPTION_INVALID, msg);
522        }
523
524        if (option->Type() == OT_String) {
525          bool result = SetStringValue(tag, value, false);
526          ASSERT_EXCEPTION(result, OPTION_INVALID,
527                           "Error setting string value read from option file.");
528        }
529        else if (option->Type() == OT_Number) {
530          char* p_end;
531          Number retval = strtod(value.c_str(), &p_end);
532          if (*p_end!='\0' && !isspace(*p_end)) {
533            std::string msg = "Option \"" + tag +
534                              "\": Double value expected, but non-numeric option value \"" +
535                              value + "\" found.\n";
536            THROW_EXCEPTION(OPTION_INVALID, msg);
537          }
538          bool result = SetNumericValue(tag, retval, false);
539          ASSERT_EXCEPTION(result, OPTION_INVALID,
540                           "Error setting numeric value read from file.");
541        }
542        else if (option->Type() == OT_Integer) {
543          char* p_end;
544          Index retval = strtol(value.c_str(), &p_end, 10);
545          if (*p_end!='\0' && !isspace(*p_end)) {
546            std::string msg = "Option \"" + tag +
547                              "\": Integer value expected, but non-integer option value \"" +
548                              value + "\" found.\n";
549            if (IsValid(jnlst_)) {
550              option->OutputDescription(*jnlst_);
551            }
552            THROW_EXCEPTION(OPTION_INVALID, msg);
553          }
554          bool result = SetIntegerValue(tag, retval, false);
555          ASSERT_EXCEPTION(result, OPTION_INVALID,
556                           "Error setting integer value read from option file.");
557        }
558        else {
559          DBG_ASSERT(false && "Option Type: Unknown");
560        }
561      }
562      else {
563        bool result = SetStringValue(tag, value, false);
564        ASSERT_EXCEPTION(result, OPTION_INVALID,
565                         "Error setting value read from option file.");
566      }
567    }
568  }
569
570  bool OptionsList::find_tag(const std::string& tag,
571                             const std::string& prefix,
572                             std::string& value) const
573  {
574    bool found=false;
575    std::map< std::string, OptionValue >::const_iterator p;
576
577    if (prefix != "") {
578      p = options_.find(lowercase(prefix+tag));
579      if (p != options_.end()) {
580        found = true;
581      }
582    }
583
584    if (!found) {
585      p = options_.find(lowercase(tag));
586      if (p != options_.end()) {
587        found = true;
588      }
589    }
590
591    if (found) {
592      value = p->second.GetValue();
593    }
594
595    return found;
596  }
597
598  bool OptionsList::will_allow_clobber(const std::string& tag) const
599  {
600    bool allow_clobber=true;
601    std::map< std::string, OptionValue >::const_iterator p;
602
603    p = options_.find(lowercase(tag));
604    if (p != options_.end()) {
605      allow_clobber = p->second.AllowClobber();
606    }
607
608    return allow_clobber;
609  }
610
611  bool OptionsList::readnexttoken(FILE* fp, std::string& token)
612  {
613    token.clear();
614    int c = fgetc(fp);
615
616    // First get rid of all comments and white spaces
617    while (c!=EOF && (isspace(c) || c=='#') ) {
618      if (c=='#') {
619        for (c=fgetc(fp);
620             c!='\n' && c!=EOF;
621             c=fgetc(fp))
622          ;
623      }
624      c=fgetc(fp);
625    }
626
627    // Now read the token
628    while (c!=EOF && !isspace(c)) {
629      token += c;
630      c = fgetc(fp);
631    }
632
633    return (c!=EOF);
634  }
635
636} // namespace Ipopt
637
Note: See TracBrowser for help on using the repository browser.