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

Last change on this file since 501 was 501, checked in by claird, 15 years ago

Cleaned up all the Copyright comments.

  • 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 501 2005-08-26 15:43:07Z claird $
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      ret = false;
349    }
350
351    return ret;
352  }
353
354  bool OptionsList::GetNumericValue(const std::string& tag, Number& value,
355                                    const std::string& prefix) const
356  {
357    SmartPtr<const RegisteredOption> option = NULL;
358
359    if (IsValid(reg_options_)) {
360      option = reg_options_->GetOption(tag);
361      if (IsNull(option)) {
362        std::string msg = "IPOPT tried to get the value of Option: " + tag;
363        msg += ". It is not a valid registered option.";
364        THROW_EXCEPTION(OPTION_INVALID, msg);
365      }
366
367      if (option->Type() != OT_Number) {
368        std::string msg = "IPOPT tried to get the value of Option: " + tag;
369        msg += ". It is a valid option, but it is of type ";
370        if (option->Type() == OT_Integer) {
371          msg += " Integer";
372        }
373        else if (option->Type() == OT_String) {
374          msg += " String";
375        }
376        else {
377          msg += " Unknown";
378        }
379        msg += ", not of type Number. Please check the documentation for options.";
380        if (IsValid(jnlst_)) {
381          option->OutputDescription(*jnlst_);
382        }
383        THROW_EXCEPTION(OPTION_INVALID, msg);
384      }
385    }
386
387    std::string strvalue;
388    if (find_tag(tag, prefix, strvalue)) {
389      char* p_end;
390      Number retval = strtod(strvalue.c_str(), &p_end);
391      if (*p_end!='\0' && !isspace(*p_end)) {
392        std::string msg = "Option \"" + tag +
393                          "\": Double value expected, but non-numeric value \"" +
394                          strvalue+"\" found.\n";
395        THROW_EXCEPTION(OPTION_INVALID, msg);
396      }
397      value = retval;
398      return true;
399    }
400    else if (IsValid(option)) {
401      value = option->DefaultNumber();
402      return false;
403    }
404    return false;
405  }
406
407  bool OptionsList::GetIntegerValue(const std::string& tag, Index& value,
408                                    const std::string& prefix) const
409  {
410    SmartPtr<const RegisteredOption> option = NULL;
411
412    if (IsValid(reg_options_)) {
413      option = reg_options_->GetOption(tag);
414      if (IsNull(option)) {
415        std::string msg = "IPOPT tried to get the value of Option: " + tag;
416        msg += ". It is not a valid registered option.";
417        THROW_EXCEPTION(OPTION_INVALID, msg);
418      }
419
420      if (option->Type() != OT_Integer) {
421        std::string msg = "IPOPT tried to get the value of Option: " + tag;
422        msg += ". It is a valid option, but it is of type ";
423        if (option->Type() == OT_Number) {
424          msg += " Number";
425        }
426        else if (option->Type() == OT_String) {
427          msg += " String";
428        }
429        else {
430          msg += " Unknown";
431        }
432        msg += ", not of type Integer. Please check the documentation for options.";
433        if (IsValid(jnlst_)) {
434          option->OutputDescription(*jnlst_);
435        }
436        THROW_EXCEPTION(OPTION_INVALID, msg);
437      }
438    }
439
440    std::string strvalue;
441    if (find_tag(tag, prefix, strvalue)) {
442      char* p_end;
443      Index retval = strtol(strvalue.c_str(), &p_end, 10);
444      if (*p_end!='\0' && !isspace(*p_end)) {
445        std::string msg = "Option \"" + tag +
446                          "\": Integer value expected, but non-integer value \"" +
447                          strvalue+"\" found.\n";
448        THROW_EXCEPTION(OPTION_INVALID, msg);
449      }
450      value = retval;
451      return true;
452    }
453    else if (IsValid(option)) {
454      value = option->DefaultInteger();
455      return false;
456    }
457
458    return false;
459  }
460
461  const std::string& OptionsList::lowercase(const std::string tag) const
462  {
463    lowercase_buffer_ = tag;
464    for(Index i=0; i<(Index)tag.length(); i++) {
465      lowercase_buffer_[i] = tolower(tag[i]);
466    }
467    return lowercase_buffer_;
468  }
469
470  void OptionsList::PrintList(std::string& list) const
471  {
472    list.clear();
473    char buffer[256];
474    sprintf(buffer, "%40s   %-20s %s\n", "Name", "Value", "# times used");
475    list += buffer;
476    for(std::map< std::string, OptionValue >::const_iterator p = options_.begin();
477        p != options_.end();
478        p++ ) {
479      sprintf(buffer, "%40s = %-20s %6d\n", p->first.c_str(),
480              p->second.Value().c_str(), p->second.Counter());
481      list += buffer;
482    }
483  }
484
485  bool OptionsList::ReadFromFile(const Journalist& jnlst,
486                                 FILE* fp)
487  {
488    DBG_ASSERT(fp);
489
490    jnlst.Printf(J_DETAILED, J_MAIN, "Start reading options from file.\n");
491
492    while (true) {
493      std::string tag;
494      std::string value;
495
496      if (!readnexttoken(fp, tag)) {
497        // That's it - end of file reached.
498        jnlst.Printf(J_DETAILED, J_MAIN,
499                     "Finished reading options from file.\n");
500        return true;
501      }
502
503      if (!readnexttoken(fp, value)) {
504        // Can't read value for a given tag
505        jnlst.Printf(J_ERROR, J_MAIN,
506                     "Error reading value for tag %s from file.\n",
507                     tag.c_str());
508        return false;
509      }
510
511      // Now add the value for the options list
512      jnlst.Printf(J_DETAILED, J_MAIN,
513                   "Adding option \"%s\" with value \"%s\" to OptionsList.\n",
514                   tag.c_str(), value.c_str());
515
516      if (IsValid(reg_options_)) {
517        SmartPtr<const RegisteredOption> option = reg_options_->GetOption(tag);
518        if (IsNull(option)) {
519          std::string msg = "Read Option: ";
520          msg += tag;
521          msg += ". It is not a valid option. Check the list of available options.";
522          THROW_EXCEPTION(OPTION_INVALID, msg);
523        }
524
525        if (option->Type() == OT_String) {
526          bool result = SetStringValue(tag, value, false);
527          ASSERT_EXCEPTION(result, OPTION_INVALID,
528                           "Error setting string value read from option file.");
529        }
530        else if (option->Type() == OT_Number) {
531          char* p_end;
532          Number retval = strtod(value.c_str(), &p_end);
533          if (*p_end!='\0' && !isspace(*p_end)) {
534            std::string msg = "Option \"" + tag +
535                              "\": Double value expected, but non-numeric option value \"" +
536                              value + "\" found.\n";
537            THROW_EXCEPTION(OPTION_INVALID, msg);
538          }
539          bool result = SetNumericValue(tag, retval, false);
540          ASSERT_EXCEPTION(result, OPTION_INVALID,
541                           "Error setting numeric value read from file.");
542        }
543        else if (option->Type() == OT_Integer) {
544          char* p_end;
545          Index retval = strtol(value.c_str(), &p_end, 10);
546          if (*p_end!='\0' && !isspace(*p_end)) {
547            std::string msg = "Option \"" + tag +
548                              "\": Integer value expected, but non-integer option value \"" +
549                              value + "\" found.\n";
550            if (IsValid(jnlst_)) {
551              option->OutputDescription(*jnlst_);
552            }
553            THROW_EXCEPTION(OPTION_INVALID, msg);
554          }
555          bool result = SetIntegerValue(tag, retval, false);
556          ASSERT_EXCEPTION(result, OPTION_INVALID,
557                           "Error setting integer value read from option file.");
558        }
559        else {
560          DBG_ASSERT(false && "Option Type: Unknown");
561        }
562      }
563      else {
564        bool result = SetStringValue(tag, value, false);
565        ASSERT_EXCEPTION(result, OPTION_INVALID,
566                         "Error setting value read from option file.");
567      }
568    }
569  }
570
571  bool OptionsList::find_tag(const std::string& tag,
572                             const std::string& prefix,
573                             std::string& value) const
574  {
575    bool found=false;
576    std::map< std::string, OptionValue >::const_iterator p;
577
578    if (prefix != "") {
579      p = options_.find(lowercase(prefix+tag));
580      if (p != options_.end()) {
581        found = true;
582      }
583    }
584
585    if (!found) {
586      p = options_.find(lowercase(tag));
587      if (p != options_.end()) {
588        found = true;
589      }
590    }
591
592    if (found) {
593      value = p->second.GetValue();
594    }
595
596    return found;
597  }
598
599  bool OptionsList::will_allow_clobber(const std::string& tag) const
600  {
601    bool allow_clobber=true;
602    std::map< std::string, OptionValue >::const_iterator p;
603
604    p = options_.find(lowercase(tag));
605    if (p != options_.end()) {
606      allow_clobber = p->second.AllowClobber();
607    }
608
609    return allow_clobber;
610  }
611
612  bool OptionsList::readnexttoken(FILE* fp, std::string& token)
613  {
614    token.clear();
615    int c = fgetc(fp);
616
617    // First get rid of all comments and white spaces
618    while (c!=EOF && (isspace(c) || c=='#') ) {
619      if (c=='#') {
620        for (c=fgetc(fp);
621             c!='\n' && c!=EOF;
622             c=fgetc(fp))
623          ;
624      }
625      c=fgetc(fp);
626    }
627
628    // Now read the token
629    while (c!=EOF && !isspace(c)) {
630      token += c;
631      c = fgetc(fp);
632    }
633
634    return (c!=EOF);
635  }
636
637} // namespace Ipopt
638
Note: See TracBrowser for help on using the repository browser.