-
Notifications
You must be signed in to change notification settings - Fork 9
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
Add support for indicator constraints in MPSolver #132
base: main
Are you sure you want to change the base?
Conversation
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if indicator_variable
is not a binary variable ?
/// Creates a named indicator constraint with given bounds and given | ||
/// indicator variable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Creates a named indicator constraint with given bounds and given | |
/// indicator variable. | |
/// Creates a named indicator constraint with given bounds and given | |
/// indicator variable. | |
/// The constraint is active if and only if *indicator_variable has value indicator_value | |
/// (Only available for MILP problems) |
MPConstraint* MPSolver::MakeIndicatorConstraint( | ||
double lb, double ub, const std::string& name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- This method should fail if the solver doesn't support integer variables
- You can call
MPVariable::integer
to check it's an integer variable on the indicator variable, and possibly test it's bounds (0 & 1).
const int constraint_index = NumConstraints(); | ||
MPConstraint* const constraint = | ||
new MPConstraint(constraint_index, lb, ub, name, interface_.get()); | ||
// TODO: check that variable is boolean? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
} | ||
constraints_.push_back(constraint); | ||
constraint_is_extracted_.push_back(false); | ||
interface_->AddIndicatorConstraint(constraint); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check the return value ?
Signed-off-by: Peter Mitri <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log improvement ideas
constraint->indicator_variable_ = indicator_variable; | ||
constraint->indicator_value_ = indicator_value; | ||
if (!interface_->AddIndicatorConstraint(constraint)) { | ||
LOG(ERROR) << "Solver doesn't support indicator constraints"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's necessary to display a log message here, it's already done in the base version of AddIndicatorConstraint
(linear_solver.cc)
virtual bool AddIndicatorConstraint(MPConstraint* const /*ct*/) {
LOG(ERROR) << "Solver doesn't support indicator constraints.";
return false;
}
It would be displayed twice. Not terrible, but not great either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, but then for interfaces that can sometimes handle indicator constraints, sometimes not (for example an interface that can handle MIP or LP problems), we'll have to log the issue before returning "false"
Co-authored-by: Florian Omnès <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
MPConstraint* MPSolver::MakeIndicatorConstraint( | ||
double lb, double ub, const std::string& name, | ||
const MPVariable* indicator_variable, bool indicator_value) { | ||
if (!indicator_variable->integer() || indicator_variable->lb() != 0 || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be consistent with e.g MPObjective::SetCoefficient
and MPConstraint::SetCoefficient
, you'd need the following lines
Although the 2nd line is currently included in the 1st.
DLOG_IF(DFATAL, !interface_->solver_->OwnsVariable(indicator_variable)) << indicator_variable;
if (indicator_variable == nullptr) return nullptr;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch!
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
No description provided.