1 // Copyright (C) 2004, 2007 International Business Machines and others.
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // Authors:  Carl Laird, Andreas Waechter     IBM    2005-06-18
6 
7 #ifndef __IPREGOPTIONS_HPP__
8 #define __IPREGOPTIONS_HPP__
9 
10 #include "IpUtils.hpp"
11 #include "IpReferenced.hpp"
12 #include "IpException.hpp"
13 #include "IpSmartPtr.hpp"
14 
15 #include <map>
16 
17 namespace Ipopt
18 {
19 
20 enum RegisteredOptionType
21 {
22    OT_Number,
23    OT_Integer,
24    OT_String,
25    OT_Unknown
26 };
27 
28 /** Base class for registered options.
29  *
30  *  The derived types are more
31  *  specific to a string option or a Number (real) option, etc.
32  */
33 class IPOPTLIB_EXPORT RegisteredOption: public ReferencedObject
34 {
35 public:
36    /** class to hold the valid string settings for a string option */
37    class string_entry
38    {
39    public:
string_entry(const std::string & value,const std::string & description)40       string_entry(
41          const std::string& value,
42          const std::string& description
43       )
44          : value_(value),
45            description_(description)
46       { }
47 
48       std::string value_;
49       std::string description_;
50    };
51 
52    /** Constructors / Destructors */
53    //@{
RegisteredOption(Index counter)54    RegisteredOption(
55       Index counter
56    )
57       : type_(OT_Unknown),
58         has_lower_(false),
59         has_upper_(false),
60         counter_(counter)
61    {
62    }
63 
RegisteredOption(const std::string & name,const std::string & short_description,const std::string & long_description,const std::string & registering_category,Index counter)64    RegisteredOption(
65       const std::string& name,
66       const std::string& short_description,
67       const std::string& long_description,
68       const std::string& registering_category,
69       Index counter
70    )
71       : name_(name),
72         short_description_(short_description),
73         long_description_(long_description),
74         registering_category_(registering_category),
75         type_(OT_Unknown),
76         has_lower_(false),
77         has_upper_(false),
78         counter_(counter)
79    {
80    }
81 
RegisteredOption(const RegisteredOption & copy)82    RegisteredOption(
83       const RegisteredOption& copy
84    )
85       : name_(copy.name_),
86         short_description_(copy.short_description_),
87         long_description_(copy.long_description_),
88         registering_category_(copy.registering_category_),
89         type_(copy.type_),
90         has_lower_(copy.has_lower_),
91         lower_(copy.lower_),
92         has_upper_(copy.has_upper_),
93         upper_(copy.upper_),
94         valid_strings_(copy.valid_strings_),
95         counter_(copy.counter_)
96    {
97    }
98 
~RegisteredOption()99    virtual ~RegisteredOption()
100    { }
101    //@}
102 
103    DECLARE_STD_EXCEPTION(ERROR_CONVERTING_STRING_TO_ENUM)
104    ;
105 
106    /** Standard Get / Set Methods */
107    //@{
108    /** Get the option's name (tag in the input file) */
Name() const109    virtual const std::string& Name() const
110    {
111       return name_;
112    }
113    /** Set the option's name (tag in the input file) */
SetName(const std::string & name)114    virtual void SetName(
115       const std::string& name
116    )
117    {
118       name_ = name;
119    }
120    /** Get the short description */
ShortDescription() const121    virtual const std::string& ShortDescription() const
122    {
123       return short_description_;
124    }
125 
126    /** Get the long description */
LongDescription() const127    virtual const std::string& LongDescription() const
128    {
129       return long_description_;
130    }
131 
132    /** Set the short description */
SetShortDescription(const std::string & short_description)133    virtual void SetShortDescription(
134       const std::string& short_description
135    )
136    {
137       short_description_ = short_description;
138    }
139 
140    /** Set the long description */
SetLongDescription(const std::string & long_description)141    virtual void SetLongDescription(
142       const std::string& long_description
143    )
144    {
145       long_description_ = long_description;
146    }
147 
148    /** Get the registering class */
RegisteringCategory() const149    virtual const std::string& RegisteringCategory() const
150    {
151       return registering_category_;
152    }
153 
154    /** Set the registering class */
SetRegisteringCategory(const std::string & registering_category)155    virtual void SetRegisteringCategory(
156       const std::string& registering_category
157    )
158    {
159       registering_category_ = registering_category;
160    }
161 
162    /** Get the Option's type */
Type() const163    virtual const RegisteredOptionType& Type() const
164    {
165       return type_;
166 
167    }
168    /** Get the Option's type */
SetType(const RegisteredOptionType & type)169    virtual void SetType(
170       const RegisteredOptionType& type
171    )
172    {
173       type_ = type;
174    }
175 
176    /** Counter */
Counter() const177    virtual Index Counter() const
178    {
179       return counter_;
180    }
181    //@}
182 
183    /** @name Get / Set methods valid for specific types
184     *
185     * @note The Type must be set before calling these methods.
186     */
187    //@{
188    /** check if the option has a lower bound
189     *
190     * can be called for OT_Number & OT_Integer
191     */
HasLower() const192    virtual const bool& HasLower() const
193    {
194       DBG_ASSERT(type_ == OT_Number || type_ == OT_Integer);
195       return has_lower_;
196    }
197 
198    /** check if the lower bound is strict
199     *
200     * can be called for OT_Number
201     */
LowerStrict() const202    virtual const bool& LowerStrict() const
203    {
204       DBG_ASSERT(type_ == OT_Number && has_lower_ == true);
205       return lower_strict_;
206    }
207 
208    /** get the Number version of the lower bound
209     *
210     * can be called for OT_Number
211     */
LowerNumber() const212    virtual Number LowerNumber() const
213    {
214       DBG_ASSERT(has_lower_ == true && type_ == OT_Number);
215       return lower_;
216    }
217 
218    /** set the Number version of the lower bound
219     *
220     * can be called for OT_Number
221     */
SetLowerNumber(const Number & lower,const bool & strict)222    virtual void SetLowerNumber(
223       const Number& lower,
224       const bool&   strict
225    )
226    {
227       DBG_ASSERT(type_ == OT_Number);
228       lower_ = lower;
229       lower_strict_ = strict, has_lower_ = true;
230    }
231 
232    /** get the Integer version of the lower bound
233     *
234     * can be called for OT_Integer
235     */
LowerInteger() const236    virtual Index LowerInteger() const
237    {
238       DBG_ASSERT(has_lower_ == true && type_ == OT_Integer);
239       return (Index) lower_;
240    }
241 
242    /** set the Integer version of the lower bound
243     *
244     * can be called for OT_Integer
245     */
SetLowerInteger(const Index & lower)246    virtual void SetLowerInteger(
247       const Index& lower
248    )
249    {
250       DBG_ASSERT(type_ == OT_Integer);
251       lower_ = (Number) lower;
252       has_lower_ = true;
253    }
254 
255    /** check if the option has an upper bound
256     *
257     * can be called for OT_Number & OT_Integer
258     */
HasUpper() const259    virtual const bool& HasUpper() const
260    {
261       DBG_ASSERT(type_ == OT_Number || type_ == OT_Integer);
262       return has_upper_;
263    }
264 
265    /** check if the upper bound is strict
266     *
267     * can be called for OT_Number
268     */
UpperStrict() const269    virtual const bool& UpperStrict() const
270    {
271       DBG_ASSERT(type_ == OT_Number && has_upper_ == true);
272       return upper_strict_;
273    }
274 
275    /** get the Number version of the upper bound
276     *
277     * can be called for OT_Number
278     */
UpperNumber() const279    virtual Number UpperNumber() const
280    {
281       DBG_ASSERT(has_upper_ == true && type_ == OT_Number);
282       return upper_;
283    }
284 
285    /** set the Number version of the upper bound
286     *
287     * can be called for OT_Number
288     */
SetUpperNumber(const Number & upper,const bool & strict)289    virtual void SetUpperNumber(
290       const Number& upper,
291       const bool&   strict
292    )
293    {
294       DBG_ASSERT(type_ == OT_Number);
295       upper_ = upper;
296       upper_strict_ = strict;
297       has_upper_ = true;
298    }
299 
300    /** get the Integer version of the upper bound
301     *
302     * can be called for OT_Integer
303     */
UpperInteger() const304    virtual Index UpperInteger() const
305    {
306       DBG_ASSERT(has_upper_ == true && type_ == OT_Integer);
307       return (Index) upper_;
308    }
309 
310    /** set the Integer version of the upper bound
311     *
312     * can be called for OT_Integer
313     */
SetUpperInteger(const Index & upper)314    virtual void SetUpperInteger(
315       const Index& upper
316    )
317    {
318       DBG_ASSERT(type_ == OT_Integer);
319       upper_ = (Number) upper;
320       has_upper_ = true;
321    }
322 
323    /** method to add valid string entries
324     *
325     * can be called for OT_String
326     */
AddValidStringSetting(const std::string value,const std::string description)327    virtual void AddValidStringSetting(
328       const std::string value,
329       const std::string description)
330    {
331       DBG_ASSERT(type_ == OT_String);
332       valid_strings_.push_back(string_entry(value, description));
333    }
334 
335    /** get the default as a Number
336     *
337     * can be called for OT_Number
338     */
DefaultNumber() const339    virtual Number DefaultNumber() const
340    {
341       DBG_ASSERT(type_ == OT_Number);
342       return default_number_;
343    }
344 
345    /** Set the default as a Number
346     *
347     * can be called for OT_Number
348     */
SetDefaultNumber(const Number & default_value)349    virtual void SetDefaultNumber(
350       const Number& default_value
351    )
352    {
353       DBG_ASSERT(type_ == OT_Number);
354       default_number_ = default_value;
355    }
356 
357    /** get the default as an Integer
358     *
359     * can be called for OT_Integer
360     */
DefaultInteger() const361    virtual Index DefaultInteger() const
362    {
363       DBG_ASSERT(type_ == OT_Integer);
364       return (Index) default_number_;
365    }
366 
367    /** Set the default as an Integer
368     *
369     * can be called for OT_Integer
370     */
SetDefaultInteger(const Index & default_value)371    virtual void SetDefaultInteger(
372       const Index& default_value
373    )
374    {
375       DBG_ASSERT(type_ == OT_Integer);
376       default_number_ = (Number) default_value;
377    }
378 
379    /** get the default as a string
380     *
381     * can be called for OT_String
382     */
DefaultString() const383    virtual std::string DefaultString() const
384    {
385       DBG_ASSERT(type_ == OT_String);
386       return default_string_;
387    }
388 
389    /** get the default as a string, but as the index of the string in the list
390     *
391     *  helps map from a string to an enum
392     *
393     *  can be called for OT_String
394     */
DefaultStringAsEnum() const395    virtual Index DefaultStringAsEnum() const
396    {
397       DBG_ASSERT(type_ == OT_String);
398       return MapStringSettingToEnum(default_string_);
399    }
400 
401    /** Set the default as a string
402     *
403     * can be called for OT_String
404     */
SetDefaultString(const std::string & default_value)405    virtual void SetDefaultString(
406       const std::string& default_value
407    )
408    {
409       DBG_ASSERT(type_ == OT_String);
410       default_string_ = default_value;
411    }
412 
413    /** get the valid string settings
414     *
415     * can be called for OT_String
416     */
GetValidStrings() const417    virtual std::vector<string_entry> GetValidStrings() const
418    {
419       DBG_ASSERT(type_ == OT_String);
420       return valid_strings_;
421    }
422 
423    /** Check if the Number value is a valid setting
424     *
425     * can be called for OT_Number
426     * */
IsValidNumberSetting(const Number & value) const427    virtual bool IsValidNumberSetting(
428       const Number& value
429    ) const
430    {
431       DBG_ASSERT(type_ == OT_Number);
432       if( has_lower_ && ((lower_strict_ == true && value <= lower_) || (lower_strict_ == false && value < lower_)) )
433       {
434          return false;
435       }
436       if( has_upper_ && ((upper_strict_ == true && value >= upper_) || (upper_strict_ == false && value > upper_)) )
437       {
438          return false;
439       }
440       return true;
441    }
442 
443    /** Check if the Integer value is a valid setting
444     *
445     * can be called for OT_Integer
446     */
IsValidIntegerSetting(const Index & value) const447    virtual bool IsValidIntegerSetting(
448       const Index& value
449    ) const
450    {
451       DBG_ASSERT(type_ == OT_Integer);
452       if( has_lower_ && value < lower_ )
453       {
454          return false;
455       }
456       if( has_upper_ && value > upper_ )
457       {
458          return false;
459       }
460       return true;
461    }
462 
463    /** Check if the String value is a valid setting
464     *
465     * can be called for OT_String
466     */
467    virtual bool IsValidStringSetting(
468       const std::string& value
469    ) const;
470 
471    /** Map a user setting (allowing any case) to the case used when
472     *  the setting was registered.
473     */
474    virtual std::string MapStringSetting(
475       const std::string& value
476    ) const;
477 
478    /** Map a user setting (allowing any case) to the index of the
479     *  matched setting in the list of string settings.
480     *
481     *  Helps map a string setting to an enumeration.
482     */
483    virtual Index MapStringSettingToEnum(
484       const std::string& value
485    ) const;
486    //@}
487 
488    /** output a description of the option */
489    virtual void OutputDescription(
490       const Journalist& jnlst
491    ) const;
492 
493    /** output a more concise version */
494    virtual void OutputShortDescription(
495       const Journalist& jnlst
496    ) const;
497 
498    /** output a latex version */
499    virtual void OutputLatexDescription(
500       const Journalist& jnlst
501    ) const;
502 
503    /** output a doxygen version */
504    virtual void OutputDoxygenDescription(
505       const Journalist& jnlst
506    ) const;
507 
508 private:
509    std::string name_;
510    std::string short_description_;
511    std::string long_description_;
512    std::string registering_category_;
513    RegisteredOptionType type_;
514 
515    bool has_lower_;
516    bool lower_strict_;
517    Number lower_;
518    bool has_upper_;
519    bool upper_strict_;
520    Number upper_;
521    Number default_number_;
522 
523    void MakeValidLatexString(
524       std::string source,
525       std::string& dest
526    ) const;
527 
528    std::string MakeValidLatexNumber(
529       Number value
530    ) const;
531 
532    std::string MakeValidHTMLNumber(
533       Number value
534    ) const;
535 
536    /** Compare two strings and return true if they are equal (case insensitive comparison) */
537    bool string_equal_insensitive(
538       const std::string& s1,
539       const std::string& s2
540    ) const;
541 
542    std::vector<string_entry> valid_strings_;
543    std::string default_string_;
544 
545    /** Has the information as how many-th option this one was
546     *  registered. */
547    const Index counter_;
548 };
549 
550 /** Class for storing registered options.
551  *
552  * Used for validation and documentation.
553  */
554 class IPOPTLIB_EXPORT RegisteredOptions: public ReferencedObject
555 {
556 public:
557    /** Constructors / Destructors */
558    //@{
559    /** Default Constructor */
RegisteredOptions()560    RegisteredOptions()
561       : next_counter_(0),
562         current_registering_category_("Uncategorized")
563    { }
564 
565    /** Destructor */
~RegisteredOptions()566    virtual ~RegisteredOptions()
567    { }
568    //@}
569 
570    DECLARE_STD_EXCEPTION(OPTION_ALREADY_REGISTERED)
571    ;
572 
573    /** Methods to interact with registered options */
574    //@{
575    /** set the registering class
576     *
577     * All subsequent options will be added with the registered class
578     */
SetRegisteringCategory(const std::string & registering_category)579    virtual void SetRegisteringCategory(
580       const std::string& registering_category
581    )
582    {
583       current_registering_category_ = registering_category;
584    }
585 
586    /** retrieve the value of the current registering category */
RegisteringCategory()587    virtual std::string RegisteringCategory()
588    {
589       return current_registering_category_;
590    }
591 
592    /** Add a Number option (with no restrictions) */
593    virtual void AddNumberOption(
594       const std::string& name,
595       const std::string& short_description,
596       Number             default_value,
597       const std::string& long_description = ""
598    );
599 
600    /** Add a Number option (with a lower bound) */
601    virtual void AddLowerBoundedNumberOption(
602       const std::string& name,
603       const std::string& short_description,
604       Number             lower,
605       bool               strict,
606       Number             default_value,
607       const std::string& long_description = ""
608    );
609 
610    /** Add a Number option (with a upper bound) */
611    virtual void AddUpperBoundedNumberOption(
612       const std::string& name,
613       const std::string& short_description,
614       Number             upper,
615       bool               strict,
616       Number             default_value,
617       const std::string& long_description = ""
618    );
619 
620    /** Add a Number option (with a both bounds) */
621    virtual void AddBoundedNumberOption(
622       const std::string& name,
623       const std::string& short_description,
624       Number             lower,
625       bool               lower_strict,
626       Number             upper,
627       bool               upper_strict,
628       Number             default_value,
629       const std::string& long_description = ""
630    );
631 
632    /** Add a Integer option (with no restrictions) */
633    virtual void AddIntegerOption(
634       const std::string& name,
635       const std::string& short_description,
636       Index              default_value,
637       const std::string& long_description = ""
638    );
639 
640    /** Add a Integer option (with a lower bound) */
641    virtual void AddLowerBoundedIntegerOption(
642       const std::string& name,
643       const std::string& short_description,
644       Index              lower,
645       Index              default_value,
646       const std::string& long_description = ""
647    );
648 
649    /** Add a Integer option (with a upper bound) */
650    virtual void AddUpperBoundedIntegerOption(
651       const std::string& name,
652       const std::string& short_description,
653       Index              upper,
654       Index              default_value,
655       const std::string& long_description = ""
656    );
657 
658    /** Add a Integer option (with a both bounds) */
659    virtual void AddBoundedIntegerOption(
660       const std::string& name,
661       const std::string& short_description,
662       Index              lower,
663       Index              upper,
664       Index              default_value,
665       const std::string& long_description = ""
666    );
667 
668    /** Add a String option (with no restrictions) */
669    virtual void AddStringOption(
670       const std::string&              name,
671       const std::string&              short_description,
672       const std::string&              default_value,
673       const std::vector<std::string>& settings,
674       const std::vector<std::string>& descriptions,
675       const std::string&              long_description = ""
676    );
677 
678    /** Methods that make adding string options with only a few entries easier */
679    virtual void AddStringOption1(
680       const std::string& name,
681       const std::string& short_description,
682       const std::string& default_value,
683       const std::string& setting1,
684       const std::string& description1,
685       const std::string& long_description = ""
686    );
687 
688    virtual void AddStringOption2(
689       const std::string& name,
690       const std::string& short_description,
691       const std::string& default_value,
692       const std::string& setting1,
693       const std::string& description1,
694       const std::string& setting2,
695       const std::string& description2,
696       const std::string& long_description = ""
697    );
698 
699    virtual void AddStringOption3(
700       const std::string& name,
701       const std::string& short_description,
702       const std::string& default_value,
703       const std::string& setting1,
704       const std::string& description1,
705       const std::string& setting2,
706       const std::string& description2,
707       const std::string& setting3,
708       const std::string& description3,
709       const std::string& long_description = ""
710    );
711 
712    virtual void AddStringOption4(
713       const std::string& name,
714       const std::string& short_description,
715       const std::string& default_value,
716       const std::string& setting1,
717       const std::string& description1,
718       const std::string& setting2,
719       const std::string& description2,
720       const std::string& setting3,
721       const std::string& description3,
722       const std::string& setting4,
723       const std::string& description4,
724       const std::string& long_description = ""
725    );
726 
727    virtual void AddStringOption5(
728       const std::string& name,
729       const std::string& short_description,
730       const std::string& default_value,
731       const std::string& setting1,
732       const std::string& description1,
733       const std::string& setting2,
734       const std::string& description2,
735       const std::string& setting3,
736       const std::string& description3,
737       const std::string& setting4,
738       const std::string& description4,
739       const std::string& setting5,
740       const std::string& description5,
741       const std::string& long_description = ""
742    );
743 
744    virtual void AddStringOption6(
745       const std::string& name,
746       const std::string& short_description,
747       const std::string& default_value,
748       const std::string& setting1,
749       const std::string& description1,
750       const std::string& setting2,
751       const std::string& description2,
752       const std::string& setting3,
753       const std::string& description3,
754       const std::string& setting4,
755       const std::string& description4,
756       const std::string& setting5,
757       const std::string& description5,
758       const std::string& setting6,
759       const std::string& description6,
760       const std::string& long_description = ""
761    );
762 
763    virtual void AddStringOption7(
764       const std::string& name,
765       const std::string& short_description,
766       const std::string& default_value,
767       const std::string& setting1,
768       const std::string& description1,
769       const std::string& setting2,
770       const std::string& description2,
771       const std::string& setting3,
772       const std::string& description3,
773       const std::string& setting4,
774       const std::string& description4,
775       const std::string& setting5,
776       const std::string& description5,
777       const std::string& setting6,
778       const std::string& description6,
779       const std::string& setting7,
780       const std::string& description7,
781       const std::string& long_description = ""
782    );
783 
784    virtual void AddStringOption8(
785       const std::string& name,
786       const std::string& short_description,
787       const std::string& default_value,
788       const std::string& setting1,
789       const std::string& description1,
790       const std::string& setting2,
791       const std::string& description2,
792       const std::string& setting3,
793       const std::string& description3,
794       const std::string& setting4,
795       const std::string& description4,
796       const std::string& setting5,
797       const std::string& description5,
798       const std::string& setting6,
799       const std::string& description6,
800       const std::string& setting7,
801       const std::string& description7,
802       const std::string& setting8,
803       const std::string& description8,
804       const std::string& long_description = ""
805    );
806 
807    virtual void AddStringOption9(
808       const std::string& name,
809       const std::string& short_description,
810       const std::string& default_value,
811       const std::string& setting1,
812       const std::string& description1,
813       const std::string& setting2,
814       const std::string& description2,
815       const std::string& setting3,
816       const std::string& description3,
817       const std::string& setting4,
818       const std::string& description4,
819       const std::string& setting5,
820       const std::string& description5,
821       const std::string& setting6,
822       const std::string& description6,
823       const std::string& setting7,
824       const std::string& description7,
825       const std::string& setting8,
826       const std::string& description8,
827       const std::string& setting9,
828       const std::string& description9,
829       const std::string& long_description = ""
830    );
831 
832    virtual void AddStringOption10(
833       const std::string& name,
834       const std::string& short_description,
835       const std::string& default_value,
836       const std::string& setting1,
837       const std::string& description1,
838       const std::string& setting2,
839       const std::string& description2,
840       const std::string& setting3,
841       const std::string& description3,
842       const std::string& setting4,
843       const std::string& description4,
844       const std::string& setting5,
845       const std::string& description5,
846       const std::string& setting6,
847       const std::string& description6,
848       const std::string& setting7,
849       const std::string& description7,
850       const std::string& setting8,
851       const std::string& description8,
852       const std::string& setting9,
853       const std::string& description9,
854       const std::string& setting10,
855       const std::string& description10,
856       const std::string& long_description = ""
857    );
858 
859    /** Get a registered option
860     *
861     * @return NULL, if the option does not exist
862     */
863    virtual SmartPtr<const RegisteredOption> GetOption(
864       const std::string& name
865    );
866 
867    /** Output documentation for the options - gives a description, etc. */
868    virtual void OutputOptionDocumentation(
869       const Journalist&       jnlst,
870       std::list<std::string>& categories
871    );
872 
873    /** Output documentation in Latex format to include in a latex file */
874    virtual void OutputLatexOptionDocumentation(
875       const Journalist&       jnlst,
876       std::list<std::string>& categories
877    );
878 
879    /** Output documentation in Doxygen format to include in doxygen documentation */
880    virtual void OutputDoxygenOptionDocumentation(
881       const Journalist&       jnlst,
882       std::list<std::string>& categories
883    );
884    //@}
885 
886    typedef std::map<std::string, SmartPtr<RegisteredOption> > RegOptionsList;
887 
888    /** Giving access to iteratable representation of the registered options */
RegisteredOptionsList() const889    virtual const RegOptionsList& RegisteredOptionsList() const
890    {
891       return registered_options_;
892    }
893 
894 private:
895    Index next_counter_;
896    std::string current_registering_category_;
897    std::map<std::string, SmartPtr<RegisteredOption> > registered_options_;
898 };
899 
900 } // namespace Ipopt
901 
902 #endif
903