Skip to content

Commit

Permalink
XPRESS fix alg:barrier #220
Browse files Browse the repository at this point in the history
Allowing space for '=' requires dedicated 'flagged' options (no value)
  • Loading branch information
glebbelov committed Aug 14, 2023
1 parent 05d9536 commit e727348
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 13 deletions.
43 changes: 36 additions & 7 deletions include/mp/solver-opt.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class SolverOption {
ValueArrayRef values() const { return values_; }

/// Returns true if this option is a flag, i.e. it doesn't take a value.
bool is_flag() const { return is_flag_; }
virtual bool is_flag() const { return is_flag_; }

/// Returns the option value.
virtual void GetValue(fmt::LongLong &) const {
Expand Down Expand Up @@ -312,7 +312,7 @@ class TypedSolverOption : public SolverOption {
ValueArrayRef values = ValueArrayRef())
: SolverOption(name, description, values) {}

void Write(fmt::Writer &w) { w << GetValue<T>(); }
void Write(fmt::Writer &w) override { w << GetValue<T>(); }

/// Parses the string for an option value, throws an exception if the value
/// is invalid.
Expand All @@ -322,7 +322,7 @@ class TypedSolverOption : public SolverOption {
/// so it is now in the format of null terminated substrings.
/// If parsed from the environment variable, the string is
/// monolithic, space separated and quotes have to be considered.
void Parse(const char *&s, bool splitString=false) {
void Parse(const char *&s, bool splitString=false) override {
const char *start = s;
T value = internal::OptionHelper<T>::Parse(s, splitString);
if (*s && !std::isspace(*s)) {
Expand All @@ -333,7 +333,7 @@ class TypedSolverOption : public SolverOption {
SetValue(value);
}

virtual Option_Type type() {
virtual Option_Type type() override {
if (std::is_integral<T>::value)
return Option_Type::INT;
if (std::is_arithmetic<T>::value)
Expand Down Expand Up @@ -489,15 +489,17 @@ class SolverOptionManager {


public:
/// Stored option: references a variable
/// Stored option: references a variable.
/// StoredOption<bool> is specialized.
template <class Value>
class StoredOption : public mp::TypedSolverOption<Value> {
Value& value_;
public:
using value_type = Value;
StoredOption(const char *name_list, const char *description,
Value& v, ValueArrayRef values = ValueArrayRef())
: mp::TypedSolverOption<Value>(name_list, 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 @@ -795,9 +797,36 @@ class SolverOptionManager {
set_option_iterator set_option_end() const {
return set_option_iterator(options_.end());
}
~SolverOptionManager();
virtual ~SolverOptionManager();
};


/// Stored option <bool>.
/// Can only be set to True.
template <>
class SolverOptionManager::StoredOption<bool>
: public mp::TypedSolverOption<int> {
bool& value_;
public:
using value_type = bool;
StoredOption(const char *name_list, const char *description,
bool& v, ValueArrayRef values = ValueArrayRef())
: mp::TypedSolverOption<int>(name_list, description, values),
value_(v) {}

/// We are a flag
bool is_flag() const override { return true; }

/// Parse: only set to True
void Parse(const char *&, bool =false) override
{ value_ = true; }

/// Dummy
void GetValue(int &v) const override { v = value_; }
void SetValue(int v) override { value_ = v; }
};


} // namespace mp

#endif // SOLVEROPT_H
8 changes: 7 additions & 1 deletion solvers/visitor/visitorbackend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -337,16 +337,22 @@ void VisitorBackend::InitCustomOptions() {
"\n"
" ampl: option visitor_options 'mipgap=1e-6';\n");

// Use AddSolverOption() for proper solver parameters.
// Below are examples of options stored in variables for own use.

AddStoredOption("tech:option_example opt_example example_opt",
"Example option. "
"Default = \"\" (don't work too hard).",
storedOptions_.option_example_);

AddStoredOption("tech:flag1 flag1",
"Flag option. Use without value. Can only be set to True.",
storedOptions_.flag_option_);

AddListOption("tech:list_option opt_list multi_valued_option",
"Multi-valued option when repeated.",
storedOptions_.list_option_);

// Use AddSolverOption() for solver parameters
}


Expand Down
1 change: 1 addition & 0 deletions solvers/visitor/visitorbackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class VisitorBackend :
/// These options are stored in the class
struct Options {
std::string option_example_;
bool flag_option_ = false;
std::vector<double> list_option_;
};
Options storedOptions_;
Expand Down
2 changes: 1 addition & 1 deletion solvers/xpress/xpressbackend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ std::string XpressmpBackend::XPRESSSolveFlags() {
if (bool(storedOptions_.fBarrier_)
+ bool(storedOptions_.fPrimal_)
+ bool(storedOptions_.fDual_)
+ bool(storedOptions_.fNetwork_)) {
+ bool(storedOptions_.fNetwork_) >= 2) {
AddWarning("Ambiguous LP method",
"Only one of barrier/primal/dual/network should be specified.");
}
Expand Down
8 changes: 4 additions & 4 deletions solvers/xpress/xpressbackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,10 @@ class XpressmpBackend :
int pooldupcol_;
int poollimit_ = 10;
int nPoolMode_ = 0;
int fBarrier_ = 0;
int fPrimal_ = 0;
int fDual_ = 0;
int fNetwork_ = 0;
bool fBarrier_ = 0;
bool fPrimal_ = 0;
bool fDual_ = 0;
bool fNetwork_ = 0;
std::string tunebase_;
std::string tunename_;
std::string logFile_;
Expand Down
7 changes: 7 additions & 0 deletions test/end2end/cases/categorized/fast/tech/modellist.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,12 @@
"solve_result_num": 500,
"solve_exitcode": 0
}
},
{
"name" : "Check_Barrier_Flag",
"tags" : ["option_flag_barrier"],
"files" : ["diet.mod", "diet.dat"],
"options": { "ANYSOLVER_options": "outlev 1 barrier outlev 0" },
"objective": 88.2
}
]
3 changes: 3 additions & 0 deletions test/end2end/scripts/python/Model.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ class ModelTags(enum.Enum):
check_sos2_from_pl = 51000 # Solvers accepting SOS2 constraints but wishing
# to test SOS2 conversion, by acc:sos2=1

## Specific options (e.g., XPRESS)
option_flag_barrier = 61000

## Solver-specific
gurobi_cloud = 100000
gurobi_server=100001
Expand Down
2 changes: 2 additions & 0 deletions test/end2end/scripts/python/Solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,8 @@ def __init__(self, exeName, timeout=None, nthreads=None,

ModelTags.writelp, ModelTags.writesol,

ModelTags.option_flag_barrier,

}
super().__init__(exeName, timeout, nthreads, otherOptions, stags)

Expand Down

0 comments on commit e727348

Please sign in to comment.