Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/options #140

Merged
merged 15 commits into from
Jul 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/mp/convert/MIP/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ class MIPBackend :
using BaseBackend::AddStoredOption;
void InitMIPOptions() {
if (IMPL_HAS_STD_FEATURE( IIS ))
AddStoredOption("iisfind",
AddStoredOption("mip:iisfind iisfind",
"Whether to find and export the IIS. "
"Default = 0 (don't export).",
mipStoredOptions_.exportIIS_);

if (IMPL_HAS_STD_FEATURE( MIPGap ))
AddStoredOption("return_mipgap",
AddStoredOption("mip:return_gap return_mipgap",
"Whether to return mipgap suffixes or include mipgap values "
"(|objectve - best_bound|) in the solve_message: sum of\n"
"\n"
Expand Down
45 changes: 34 additions & 11 deletions include/mp/convert/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,9 @@ class BasicBackend :
Value& value_;
public:
using value_type = Value;
StoredOption(const char *name, const char *description,
StoredOption(const char *name_list, const char *description,
Value& v, ValueArrayRef values = ValueArrayRef())
: mp::TypedSolverOption<Value>(name, description, values), value_(v) {}
: mp::TypedSolverOption<Value>(name_list, description, values), value_(v) {}

void GetValue(Value &v) const override { v = value_; }
void SetValue(typename internal::OptionHelper<Value>::Arg v) override
Expand Down Expand Up @@ -481,16 +481,20 @@ class BasicBackend :
SOAType soa_;
public:
ConcreteOptionWrapper(Impl* impl_, const char *name, const char *description,
KeyType k) :
COType(name, description, &soa_, &SOAType::get, &SOAType::set, k),
KeyType k, ValueArrayRef values = ValueArrayRef()) :
COType(name, description, &soa_, &SOAType::get, &SOAType::set, k, values),
soa_(*impl_)
{ }
};

public:
using Solver::AddOption;
using Solver::AddOptionSynonymsFront;
using Solver::AddOptionSynonymsBack;
using Solver::AddOptionSynonym_OutOfLine;
using Solver::FindOption;


/// Simple stored option referencing a variable
template <class Value>
void AddStoredOption(const char *name, const char *description,
Expand All @@ -506,21 +510,40 @@ class BasicBackend :
/// If min/max omitted, assume ValueType=std::string
/// Assumes existence of Impl::Get/SetSolverOption(KeyType, ValueType(&))
template <class KeyType, class ValueType=std::string>
void AddSolverOption(const char *name, const char *description,
void AddSolverOption(const char *name_list, const char *description,
KeyType k,
ValueType ={}, ValueType ={}) {
ValueType , ValueType ) {
AddOption(Solver::OptionPtr(
new ConcreteOptionWrapper<
ValueType, KeyType>(
(Impl*)this, name, description, k)));
(Impl*)this, name_list, description, k)));
}

template <class KeyType, class ValueType = std::string>
void AddSolverOption(const char* name_list, const char* description,
KeyType k) {
AddOption(Solver::OptionPtr(
new ConcreteOptionWrapper<
ValueType, KeyType>(
(Impl*)this, name_list, description, k)));
}

/// TODO use vmin/vmax or rely on solver raising error?
/// TODO also with ValueTable, deduce type from it
template <class KeyType, class ValueType = std::string>
void AddSolverOption(const char* name_list, const char* description,
KeyType k, ValueArrayRef values, ValueType defaultValue) {
internal::Unused(defaultValue);
AddOption(Solver::OptionPtr(
new ConcreteOptionWrapper<
ValueType, KeyType>(
(Impl*)this, name_list, description, k, values)));
}

void ReplaceOptionDescription(const char* name, const char* desc) {
auto pOption = FindOption(name);
assert(pOption);
pOption->SetDesc(desc);
pOption->set_description(desc);
}

private:
Expand All @@ -532,9 +555,9 @@ class BasicBackend :
protected:
void InitStandardOptions() {
if (IMPL_HAS_STD_FEATURE( VarPriorities ))
AddStoredOption("priorities",
"Whether to read the branch and bound priorities from the"
" .priority suffix. Default: 1 (do read).",
AddStoredOption("mip:priorities priorities", // CP has it too
"0/1*: Whether to read the branch and bound priorities from the"
" .priority suffix..",
storedOptions_.importPriorities_);
}

Expand Down
4 changes: 2 additions & 2 deletions include/mp/convert/basic_converters.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,9 @@ class BasicMPConverter :

/// Simple stored option referencing a variable
template <class Value>
void AddOption(const char *name, const char *description,
void AddOption(const char *name_list, const char *description,
Value& value, ValueArrayRef values = ValueArrayRef()) {
GetBackend().AddStoredOption(name, description, value, values);
GetBackend().AddStoredOption(name_list, description, value, values);
}

////////////////////////////// UTILITIES //////////////////////////////
Expand Down
6 changes: 3 additions & 3 deletions include/mp/convert/converter_flat.h
Original file line number Diff line number Diff line change
Expand Up @@ -976,13 +976,13 @@ class BasicMPFlatConverter
Options options_;

void InitOptions() {
this->AddOption("cvt:prepro:all",
this->AddOption("cvt:pre:all",
"0/1*: Set to 0 to disable all presolve in the converter",
options_.preprocessAnything_);
this->AddOption("cvt:prepro:eqresult",
this->AddOption("cvt:pre:eqresult",
"0/1*: Preprocess reified equality comparison's boolean result bounds",
options_.preprocessEqualityResultBounds_);
this->AddOption("cvt:prepro:eqbinary",
this->AddOption("cvt:pre:eqbinary",
"0/1*: Preprocess reified equality comparison with a binary variable",
options_.preprocessEqualityBvar_);
}
Expand Down
96 changes: 66 additions & 30 deletions include/mp/solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,18 +211,20 @@ class Interrupter {
// A solver option.
class SolverOption {
private:
const char *name_;
const char *description_;
std::string name_ {};
std::vector<std::string> inline_synonyms_ {};
const char* description_;

ValueArrayRef values_;
bool is_flag_;

public:
// Constructs a SolverOption object.
//
// The solver option stores pointers to the passed name and description and
// doesn't copy the strings. Normally both the name and the description are
// string literals and have static storage duration but if this is not the
// case make sure that these strings' lifetimes are longer than that of the
// The solver option stores pointers to the passed name(s) and description and
// copies the strings for the names only. Normally the description is a
// string literal and has static storage duration but if this is not the
// case make sure that the string's lifetime is longer than that of the
// option object.
//
// The description should be written in a subset of reStructuredText (RST).
Expand All @@ -235,23 +237,40 @@ class SolverOption {
// * the value-table directive (.. value-table::) which is replaced by a
// table of option values as given by the values array
//
// name: option name
// names_list: option names list
// description: option description
// values: information about possible option values
SolverOption(const char *name, const char *description,
SolverOption(const char *names_list, const char *description,
ValueArrayRef values = ValueArrayRef(), bool is_flag = false)
: name_(name), description_(description),
values_(values), is_flag_(is_flag) {}
: description_(description),
values_(values), is_flag_(is_flag) {
auto synonyms = split_str(names_list);
if (synonyms.empty())
throw std::logic_error("Empty option name list");
name_ = synonyms.front();
for (size_t i=1; i<synonyms.size(); ++i)
inline_synonyms_.push_back(synonyms[i]);
}

virtual ~SolverOption() {}

// Returns the option name.
const char *name() const { return name_; }
// Return the option name.
const char *name() const { return name_.c_str(); }

// Returns the option description.
/// Return the ASL (not qualified) name as the first
/// inline synonym - or the name itself if no synonyms
/// are defined
const char* name_ASL() const;
/// Returns the "inline" synonyms
const std::vector<std::string>& inline_synonyms() const
{ return inline_synonyms_; }
/// Add additional "inline" synonyms
void add_synonyms_front(const char* names_list);
void add_synonyms_back(const char* names_list);

// Return/set the option description.
const char *description() const { return description_; }

// Sets new description.
void SetDesc(const char* d) { description_=d; }
void set_description(const char* d) { description_=d; }

// Returns the information about possible values.
ValueArrayRef values() const { return values_; }
Expand Down Expand Up @@ -308,8 +327,15 @@ class SolverOption {
// Parses a string and sets the option value. Throws InvalidOptionValue
// if the value is invalid or OptionError in case of another error.
virtual void Parse(const char *&s) = 0;

virtual std::string echo() {
return name();
}

static std::vector<std::string> split_str(const char* str);
};


// An exception thrown when an invalid value is provided for an option.
class InvalidOptionValue : public OptionError {
private:
Expand Down Expand Up @@ -521,12 +547,13 @@ class Solver : private ErrorHandler,
Info info_;

public:
ConcreteOptionWithInfo(const char *name, const char *description, Solver *s,
Get get, Set set, InfoArg info, ValueArrayRef values = ValueArrayRef())
ConcreteOptionWithInfo(const char *name,
const char *description, Solver *s, Get get, Set set, InfoArg info,
ValueArrayRef values = ValueArrayRef())
: TypedSolverOption<T>(name, description, values),
handler_(static_cast<Handler&>(*s)), get_(get), set_(set), info_(info) {}
ConcreteOptionWithInfo(const char *name, const char *description, Handler *s,
Get get, Set set, InfoArg info, ValueArrayRef values = ValueArrayRef())
ConcreteOptionWithInfo(const char *name, const char *description,
Handler *s, Get get, Set set, InfoArg info, ValueArrayRef values = ValueArrayRef())
: TypedSolverOption<T>(name, description, values),
handler_(*s), get_(get), set_(set), info_(info) {}

Expand Down Expand Up @@ -597,12 +624,17 @@ class Solver : private ErrorHandler,
// Add more text to be displayed before option descriptions.
void add_to_option_header(const char *header_more) { option_header_ += header_more; }

void AddOption(OptionPtr opt) {
// First insert the option, then release a pointer to it. Doing the other
// way around may lead to a memory leak if insertion throws an exception.
options_.insert(opt.get());
opt.release();
}
void AddOption(OptionPtr opt);

/// Add "online" option synonyms
/// The _Front version puts them in the front of the synonyms list
/// and the 1st of them is used in the -a output for sorting
void AddOptionSynonymsFront(const char* names_list, const char* realName);
void AddOptionSynonymsBack(const char* names_list, const char* realName);

/// Add an "out-of-line" synonym
/// Creates extra entry under -=
void AddOptionSynonym_OutOfLine(const char* name, const char* realName);

// Adds an integer option.
// The option stores pointers to the name and the description so make
Expand All @@ -611,8 +643,8 @@ class Solver : private ErrorHandler,
// The arguments get and set should be pointers to member functions in the
// solver class. They are used to get and set an option value respectively.
template <typename Handler, typename Int>
void AddIntOption(const char *name, const char *description,
Int (Handler::*get)(const SolverOption &) const,
void AddIntOption(const char *name,
const char *description, Int (Handler::*get)(const SolverOption &) const,
void (Handler::*set)(const SolverOption &, Int)) {
AddOption(OptionPtr(new ConcreteOption<Handler, fmt::LongLong, Int>(
name, description, this, get, set)));
Expand All @@ -636,12 +668,12 @@ class Solver : private ErrorHandler,

// The same as above but with Info argument passed by value.
template <typename Handler, typename Info>
void AddIntOption(const char *name, const char *description,
void AddIntOption(const char *name_list, const char *description,
int (Handler::*get)(const SolverOption &, Info) const,
void (Handler::*set)(const SolverOption &, int, Info), Info info) {
AddOption(OptionPtr(new ConcreteOptionWithInfo<
Handler, fmt::LongLong, Info, Info, int>(
name, description, this, get, set, info)));
name_list, description, this, get, set, info)));
}

// Adds a double option.
Expand Down Expand Up @@ -1092,6 +1124,8 @@ namespace internal {
// Not to be mistaken with solver option parser built into the Solver class.
class SolverAppOptionParser {
private:

std::string currentOptionString;
Solver &solver_;

// Command-line options.
Expand All @@ -1104,6 +1138,8 @@ class SolverAppOptionParser {

// Prints information about solver options.
bool ShowSolverOptions();
bool ShowSolverOptionsASL();


bool WantSol() {
solver_.set_wantsol(1);
Expand Down
Loading