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

Add support for indicator constraints in MPSolver #132

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

pet-mit
Copy link
Collaborator

@pet-mit pet-mit commented Jul 12, 2024

No description provided.

Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
@pet-mit
Copy link
Collaborator Author

pet-mit commented Jul 12, 2024

@flomnes @klorel
do you have initial thoughts on this?
(next step would be adding XPRESS support, in another PR)

Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
Signed-off-by: Peter Mitri <[email protected]>
@pet-mit pet-mit marked this pull request as ready for review July 17, 2024 09:00
@pet-mit pet-mit requested review from klorel and flomnes July 17, 2024 09:00
Copy link
Collaborator

@flomnes flomnes left a 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 ?

Comment on lines +446 to +447
/// Creates a named indicator constraint with given bounds and given
/// indicator variable.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// 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)

Comment on lines +1514 to +1515
MPConstraint* MPSolver::MakeIndicatorConstraint(
double lb, double ub, const std::string& name,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This method should fail if the solver doesn't support integer variables
  2. 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?
Copy link
Collaborator

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);
Copy link
Collaborator

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]>
@pet-mit pet-mit requested a review from flomnes July 17, 2024 12:08
Copy link
Collaborator

@flomnes flomnes left a 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";
Copy link
Collaborator

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.

Copy link
Collaborator Author

@pet-mit pet-mit Jul 17, 2024

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"

ortools/linear_solver/linear_solver.cc Outdated Show resolved Hide resolved
pet-mit and others added 2 commits July 17, 2024 14:57
Signed-off-by: Peter Mitri <[email protected]>
@pet-mit pet-mit requested a review from flomnes July 17, 2024 14:03
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 ||
Copy link
Collaborator

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;

Copy link
Collaborator Author

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]>
@pet-mit pet-mit requested a review from flomnes July 17, 2024 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants