1 // Copyright (C) 2004, 2006 International Business Machines and others. 2 // All Rights Reserved. 3 // This code is published under the Common Public License. 4 // 5 // $Id: IpRegOptions.hpp 759 2006-07-07 03:07:08Z andreasw $ 6 // 7 // Authors: Carl Laird, Andreas Waechter IBM 2005-06-18 8 9 #ifndef __IPREGOPTIONS_HPP__ 10 #define __IPREGOPTIONS_HPP__ 11 12 #include "IpUtils.hpp" 13 #include "IpReferenced.hpp" 14 #include "IpException.hpp" 15 #include "IpSmartPtr.hpp" 16 17 #include <map> 18 19 namespace SimTKIpopt 20 { 21 22 enum RegisteredOptionType 23 { 24 OT_Number, 25 OT_Integer, 26 OT_String, 27 OT_Unknown 28 }; 29 30 /** Base class for registered options. The derived types are more 31 * specific to a string option or a Number (real) option, etc. 32 */ 33 class RegisteredOption : public ReferencedObject 34 { 35 public: 36 /** Constructors / Destructors */ 37 //@{ RegisteredOption()38 RegisteredOption() 39 : 40 type_(OT_Unknown), 41 has_lower_(false), 42 has_upper_(false), 43 counter_(0) 44 {} 45 RegisteredOption(const std::string & name,const std::string & short_description,const std::string & long_description,const std::string & registering_category)46 RegisteredOption(const std::string& name, 47 const std::string& short_description, 48 const std::string& long_description, 49 const std::string& registering_category) 50 : 51 name_(name), 52 short_description_(short_description), 53 long_description_(long_description), 54 registering_category_(registering_category), 55 type_(OT_Unknown), 56 has_lower_(false), 57 has_upper_(false), 58 counter_(next_counter_++) 59 {} 60 RegisteredOption(const RegisteredOption & copy)61 RegisteredOption(const RegisteredOption& copy) 62 : 63 name_(copy.name_), 64 short_description_(copy.short_description_), 65 long_description_(copy.long_description_), 66 registering_category_(copy.registering_category_), 67 type_(copy.type_), 68 has_lower_(copy.has_lower_), 69 lower_(copy.lower_), 70 has_upper_(copy.has_upper_), 71 upper_(copy.upper_), 72 valid_strings_(copy.valid_strings_), 73 counter_(copy.counter_) 74 {} 75 ~RegisteredOption()76 virtual ~RegisteredOption() 77 {} 78 //@} 79 80 DECLARE_STD_EXCEPTION(ERROR_CONVERTING_STRING_TO_ENUM); 81 82 /** Standard Get / Set Methods */ 83 //@{ 84 /** Get the option's name (tag in the input file) */ Name() const85 const std::string& Name() const 86 { 87 return name_; 88 } 89 /** Set the option's name (tag in the input file) */ SetName(const std::string & name)90 void SetName(const std::string& name) 91 { 92 name_ = name; 93 } 94 /** Get the short description */ ShortDescription() const95 const std::string& ShortDescription() const 96 { 97 return short_description_; 98 } 99 /** Get the long description */ LongDescription() const100 const std::string& LongDescription() const 101 { 102 return long_description_; 103 } 104 /** Set the short description */ SetShortDescription(const std::string & short_description)105 void SetShortDescription(const std::string& short_description) 106 { 107 short_description_ = short_description; 108 } 109 /** Set the long description */ SetLongDescription(const std::string & long_description)110 void SetLongDescription(const std::string& long_description) 111 { 112 long_description_ = long_description; 113 } 114 /** Get the registering class */ RegisteringCategory() const115 const std::string& RegisteringCategory() const 116 { 117 return registering_category_; 118 } 119 /** Set the registering class */ SetRegisteringCategory(const std::string & registering_category)120 void SetRegisteringCategory(const std::string& registering_category) 121 { 122 registering_category_ = registering_category; 123 } 124 /** Get the Option's type */ Type() const125 const RegisteredOptionType& Type() const 126 { 127 return type_; 128 } 129 /** Get the Option's type */ SetType(const RegisteredOptionType & type)130 void SetType(const RegisteredOptionType& type) 131 { 132 type_ = type; 133 } 134 /** Counter */ Counter() const135 Index Counter() const 136 { 137 return counter_; 138 } 139 //@} 140 141 /** @name Get / Set methods valid for specific types - NOTE: the Type 142 * must be set before calling these methods. 143 */ 144 //@{ 145 /** check if the option has a lower bound - can be called for 146 * OT_Number & OT_Integer*/ HasLower() const147 const bool& HasLower() const 148 { 149 DBG_ASSERT(type_ == OT_Number || type_ == OT_Integer); 150 return has_lower_; 151 } 152 /** check if the lower bound is strict - can be called for 153 OT_Number */ LowerStrict() const154 const bool& LowerStrict() const 155 { 156 DBG_ASSERT(type_ == OT_Number && has_lower_ == true); 157 return lower_strict_; 158 } 159 /** get the Number version of the lower bound - can be called for 160 * OT_Number */ LowerNumber() const161 Number LowerNumber() const 162 { 163 DBG_ASSERT(has_lower_ == true && type_ == OT_Number); 164 return lower_; 165 } 166 /** set the Number version of the lower bound - can be called for 167 * OT_Number */ SetLowerNumber(const Number & lower,const bool & strict)168 void SetLowerNumber(const Number& lower, const bool& strict) 169 { 170 DBG_ASSERT(type_ == OT_Number); 171 lower_ = lower; 172 lower_strict_ = strict, has_lower_ = true; 173 } 174 /** get the Integer version of the lower bound can be called for 175 * OT_Integer*/ LowerInteger() const176 Index LowerInteger() const 177 { 178 DBG_ASSERT(has_lower_ == true && type_ == OT_Integer); 179 return (Index)lower_; 180 } 181 /** set the Integer version of the lower bound - can be called for 182 * OT_Integer */ SetLowerInteger(const Index & lower)183 void SetLowerInteger(const Index& lower) 184 { 185 DBG_ASSERT(type_ == OT_Integer); 186 lower_ = (Number)lower; 187 has_lower_ = true; 188 } 189 /** check if the option has an upper bound - can be called for 190 * OT_Number & OT_Integer*/ HasUpper() const191 const bool& HasUpper() const 192 { 193 DBG_ASSERT(type_ == OT_Number || type_ == OT_Integer); 194 return has_upper_; 195 } 196 /** check if the upper bound is strict - can be called for 197 * OT_Number */ UpperStrict() const198 const bool& UpperStrict() const 199 { 200 DBG_ASSERT(type_ == OT_Number && has_upper_ == true); 201 return upper_strict_; 202 } 203 /** get the Number version of the upper bound - can be called for 204 * OT_Number */ UpperNumber()205 Number UpperNumber() 206 { 207 DBG_ASSERT(has_upper_ == true && type_ == OT_Number); 208 return upper_; 209 } 210 /** set the Number version of the upper bound - can be called for 211 * OT_Number */ SetUpperNumber(const Number & upper,const bool & strict)212 void SetUpperNumber(const Number& upper, const bool& strict) 213 { 214 DBG_ASSERT(type_ == OT_Number); 215 upper_ = upper; 216 upper_strict_ = strict; 217 has_upper_ = true; 218 } 219 /** get the Integer version of the upper bound - can be called for 220 * OT_Integer*/ UpperInteger() const221 Index UpperInteger() const 222 { 223 DBG_ASSERT(has_upper_ == true && type_ == OT_Integer); 224 return (Index)upper_; 225 } 226 /** set the Integer version of the upper bound - can be called for 227 * OT_Integer */ SetUpperInteger(const Index & upper)228 void SetUpperInteger(const Index& upper) 229 { 230 DBG_ASSERT(type_ == OT_Integer); 231 upper_ = (Number)upper; 232 has_upper_ = true; 233 } 234 /** method to add valid string entries - can be called for 235 * OT_String */ AddValidStringSetting(const std::string value,const std::string description)236 void AddValidStringSetting(const std::string value, 237 const std::string description) 238 { 239 DBG_ASSERT(type_ == OT_String); 240 valid_strings_.push_back(string_entry(value, description)); 241 } 242 /** get the default as a Number - can be called for OT_Number */ DefaultNumber() const243 Number DefaultNumber() const 244 { 245 DBG_ASSERT(type_ == OT_Number); 246 return default_number_; 247 } 248 /** Set the default as a Number - can be called for OT_Number */ SetDefaultNumber(const Number & default_value)249 void SetDefaultNumber(const Number& default_value) 250 { 251 DBG_ASSERT(type_ == OT_Number); 252 default_number_ = default_value; 253 } 254 /** get the default as an Integer - can be called for OT_Integer*/ DefaultInteger() const255 Index DefaultInteger() const 256 { 257 DBG_ASSERT(type_ == OT_Integer); 258 return (Index)default_number_; 259 } 260 /** Set the default as an Integer - can be called for 261 OT_Integer */ SetDefaultInteger(const Index & default_value)262 void SetDefaultInteger(const Index& default_value) 263 { 264 DBG_ASSERT(type_ == OT_Integer); 265 default_number_ = (Number)default_value; 266 } 267 /** get the default as a string - can be called for OT_String */ DefaultString() const268 std::string DefaultString() const 269 { 270 DBG_ASSERT(type_ == OT_String); 271 return default_string_; 272 } 273 /** get the default as a string, but as the index of the string in 274 * the list - helps map from a string to an enum- can be called 275 * for OT_String */ DefaultStringAsEnum() const276 Index DefaultStringAsEnum() const 277 { 278 DBG_ASSERT(type_ == OT_String); 279 return MapStringSettingToEnum(default_string_); 280 } 281 /** Set the default as a string - can be called for OT_String */ SetDefaultString(const std::string & default_value)282 void SetDefaultString(const std::string& default_value) 283 { 284 DBG_ASSERT(type_ == OT_String); 285 default_string_ = default_value; 286 } 287 /** Check if the Number value is a valid setting - can be called 288 * for OT_Number */ IsValidNumberSetting(const Number & value) const289 bool IsValidNumberSetting(const Number& value) const 290 { 291 DBG_ASSERT(type_ == OT_Number); 292 if (has_lower_ && ((lower_strict_ == true && value <= lower_) || 293 (lower_strict_ == false && value < lower_))) { 294 return false; 295 } 296 if (has_upper_ && ((upper_strict_ == true && value >= upper_) || 297 (upper_strict_ == false && value > upper_))) { 298 return false; 299 } 300 return true; 301 } 302 /** Check if the Integer value is a valid setting - can be called 303 * for OT_Integer */ IsValidIntegerSetting(const Index & value) const304 bool IsValidIntegerSetting(const Index& value) const 305 { 306 DBG_ASSERT(type_ == OT_Integer); 307 if (has_lower_ && value < lower_) { 308 return false; 309 } 310 if (has_upper_ && value > upper_) { 311 return false; 312 } 313 return true; 314 } 315 /** Check if the String value is a valid setting - can be called 316 * for OT_String */ 317 bool IsValidStringSetting(const std::string& value) const; 318 319 /** Map a user setting (allowing any case) to the case used when 320 * the setting was registered. 321 */ 322 std::string MapStringSetting(const std::string& value) const; 323 324 /** Map a user setting (allowing any case) to the index of the 325 * matched setting in the list of string settings. Helps map a 326 * string setting to an enumeration. 327 */ 328 Index MapStringSettingToEnum(const std::string& value) const; 329 //@} 330 331 /** output a description of the option */ 332 void OutputDescription(const Journalist& jnlst) const; 333 /** output a more concise version */ 334 void OutputShortDescription(const Journalist& jnlst) const; 335 /** output a latex version */ 336 void OutputLatexDescription(const Journalist& jnlst) const; 337 338 private: 339 std::string name_; 340 std::string short_description_; 341 std::string long_description_; 342 std::string registering_category_; 343 RegisteredOptionType type_; 344 345 bool has_lower_; 346 bool lower_strict_; 347 Number lower_; 348 bool has_upper_; 349 bool upper_strict_; 350 Number upper_; 351 Number default_number_; 352 353 void MakeValidLatexString(std::string source, std::string& dest) const; 354 std::string MakeValidLatexNumber(Number value) const; 355 356 /** Compare two strings and return true if they are equal (case 357 insensitive comparison) */ 358 bool string_equal_insensitive(const std::string& s1, 359 const std::string& s2) const; 360 361 /** class to hold the valid string settings for a string option */ 362 class string_entry 363 { 364 public: string_entry(const std::string & value,const std::string & description)365 string_entry(const std::string& value, const std::string& description) 366 : value_(value), description_(description) 367 {} 368 std::string value_; 369 std::string description_; 370 }; 371 372 std::vector<string_entry> valid_strings_; 373 std::string default_string_; 374 375 /** Has the information as how many-th option this one was 376 * registered. */ 377 const Index counter_; 378 379 static Index next_counter_; 380 }; 381 382 /** Class for storing registered options. Used for validation and 383 * documentation. 384 */ 385 class RegisteredOptions : public ReferencedObject 386 { 387 public: 388 /** Constructors / Destructors */ 389 //@{ 390 /** Standard Constructor */ RegisteredOptions()391 RegisteredOptions() 392 : 393 current_registering_category_("Uncategorized") 394 {} 395 396 /** Standard Destructor */ ~RegisteredOptions()397 ~RegisteredOptions() 398 {} 399 //@} 400 401 DECLARE_STD_EXCEPTION(OPTION_ALREADY_REGISTERED); 402 403 /** Methods to interact with registered options */ 404 //@{ 405 /** set the registering class. All subsequent options will be 406 * added with the registered class */ SetRegisteringCategory(const std::string & registering_category)407 void SetRegisteringCategory(const std::string& registering_category) 408 { 409 current_registering_category_ = registering_category; 410 } 411 412 /** retrieve the value of the current registering category */ RegisteringCategory()413 std::string RegisteringCategory() 414 { 415 return current_registering_category_; 416 } 417 418 /** Add a Number option (with no restrictions) */ 419 void AddNumberOption(const std::string& name, 420 const std::string& short_description, 421 Number default_value, 422 const std::string& long_description=""); 423 /** Add a Number option (with a lower bound) */ 424 void AddLowerBoundedNumberOption(const std::string& name, 425 const std::string& short_description, 426 Number lower, bool strict, 427 Number default_value, 428 const std::string& long_description=""); 429 /** Add a Number option (with a upper bound) */ 430 void AddUpperBoundedNumberOption(const std::string& name, 431 const std::string& short_description, 432 Number upper, bool strict, 433 Number default_value, 434 const std::string& long_description=""); 435 /** Add a Number option (with a both bounds) */ 436 void AddBoundedNumberOption(const std::string& name, 437 const std::string& short_description, 438 Number lower, bool lower_strict, 439 Number upper, bool upper_strict, 440 Number default_value, 441 const std::string& long_description=""); 442 /** Add a Integer option (with no restrictions) */ 443 void AddIntegerOption(const std::string& name, 444 const std::string& short_description, 445 Index default_value, 446 const std::string& long_description=""); 447 /** Add a Integer option (with a lower bound) */ 448 void AddLowerBoundedIntegerOption(const std::string& name, 449 const std::string& short_description, 450 Index lower, Index default_value, 451 const std::string& long_description=""); 452 /** Add a Integer option (with a upper bound) */ 453 void AddUpperBoundedIntegerOption(const std::string& name, 454 const std::string& short_description, 455 Index upper, Index default_value, 456 const std::string& long_description=""); 457 /** Add a Integer option (with a both bounds) */ 458 void AddBoundedIntegerOption(const std::string& name, 459 const std::string& short_description, 460 Index lower, Index upper, 461 Index default_value, 462 const std::string& long_description=""); 463 464 /** Add a String option (with no restrictions) */ 465 void AddStringOption(const std::string& name, 466 const std::string& short_description, 467 const std::string& default_value, 468 const std::vector<std::string>& settings, 469 const std::vector<std::string>& descriptions, 470 const std::string& long_description=""); 471 /** Methods that make adding string options with only a few 472 * entries easier */ 473 void AddStringOption1(const std::string& name, 474 const std::string& short_description, 475 const std::string& default_value, 476 const std::string& setting1, 477 const std::string& description1, 478 const std::string& long_description=""); 479 void AddStringOption2(const std::string& name, 480 const std::string& short_description, 481 const std::string& default_value, 482 const std::string& setting1, 483 const std::string& description1, 484 const std::string& setting2, 485 const std::string& description2, 486 const std::string& long_description=""); 487 void AddStringOption3(const std::string& name, 488 const std::string& short_description, 489 const std::string& default_value, 490 const std::string& setting1, 491 const std::string& description1, 492 const std::string& setting2, 493 const std::string& description2, 494 const std::string& setting3, 495 const std::string& description3, 496 const std::string& long_description=""); 497 void AddStringOption4(const std::string& name, 498 const std::string& short_description, 499 const std::string& default_value, 500 const std::string& setting1, 501 const std::string& description1, 502 const std::string& setting2, 503 const std::string& description2, 504 const std::string& setting3, 505 const std::string& description3, 506 const std::string& setting4, 507 const std::string& description4, 508 const std::string& long_description=""); 509 void AddStringOption5(const std::string& name, 510 const std::string& short_description, 511 const std::string& default_value, 512 const std::string& setting1, 513 const std::string& description1, 514 const std::string& setting2, 515 const std::string& description2, 516 const std::string& setting3, 517 const std::string& description3, 518 const std::string& setting4, 519 const std::string& description4, 520 const std::string& setting5, 521 const std::string& description5, 522 const std::string& long_description=""); 523 void AddStringOption6(const std::string& name, 524 const std::string& short_description, 525 const std::string& default_value, 526 const std::string& setting1, 527 const std::string& description1, 528 const std::string& setting2, 529 const std::string& description2, 530 const std::string& setting3, 531 const std::string& description3, 532 const std::string& setting4, 533 const std::string& description4, 534 const std::string& setting5, 535 const std::string& description5, 536 const std::string& setting6, 537 const std::string& description6, 538 const std::string& long_description=""); 539 void AddStringOption7(const std::string& name, 540 const std::string& short_description, 541 const std::string& default_value, 542 const std::string& setting1, 543 const std::string& description1, 544 const std::string& setting2, 545 const std::string& description2, 546 const std::string& setting3, 547 const std::string& description3, 548 const std::string& setting4, 549 const std::string& description4, 550 const std::string& setting5, 551 const std::string& description5, 552 const std::string& setting6, 553 const std::string& description6, 554 const std::string& setting7, 555 const std::string& description7, 556 const std::string& long_description=""); 557 558 /** Get a registered option - this will return NULL if the option 559 * does not exist */ 560 SmartPtr<const RegisteredOption> GetOption(const std::string& name); 561 562 /** Output documentation for the options - gives a description, 563 * etc. */ 564 void OutputOptionDocumentation(const Journalist& jnlst, std::list<std::string>& categories); 565 566 /** Output documentation in Latex format to include in a latex file */ 567 void OutputLatexOptionDocumentation(const Journalist& jnlst, std::list<std::string>& categories); 568 //@} 569 570 private: 571 std::string current_registering_category_; 572 std::map<std::string, SmartPtr<RegisteredOption> > registered_options_; 573 }; 574 } // namespace Ipopt 575 576 #endif 577