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

[FileFormats.LP] support indicator constraints #2354

Closed
hdavid16 opened this issue Dec 4, 2023 · 9 comments · Fixed by #2483
Closed

[FileFormats.LP] support indicator constraints #2354

hdavid16 opened this issue Dec 4, 2023 · 9 comments · Fixed by #2483
Labels
Submodule: FileFormats About the FileFormats submodule
Milestone

Comments

@hdavid16
Copy link

hdavid16 commented Dec 4, 2023

The following works:

julia> model=Model();
julia> @variable(model,x);
julia> @variable(model,y,Bin);
julia> @constraint(model, y => {x == 0});
julia> write_to_file(model,"test.lp")

However if the indicator constraint is changed to @constraint(model, !y => {x == 0}), writing the LP file fails:

ERROR: Unable to use IndicatorToMILPBridge because element 2 in the function has a non-finite domain: 0.0 + 1.0 MOI.VariableIndex(2)
@odow
Copy link
Member

odow commented Dec 4, 2023

What is the original output of test.lp?

Our LP file format does not support indicator constraints, so it'll be getting reformulated somehow.

@odow odow changed the title [Bug] Writing an LP file with indicator constraints that ACTIVATE_ON_ZERO [FileFormats.LP] Writing an LP file with indicator constraints that ACTIVATE_ON_ZERO Dec 4, 2023
@odow
Copy link
Member

odow commented Dec 4, 2023

shell> cat test.lp
minimize
obj: 
subject to
c1: 1 x + 1 x3 = 0
Bounds
x free
x3 free
Binary
y
SOS
c1_1: S1:: x3:0.4 y:0.6
End

@odow
Copy link
Member

odow commented Dec 4, 2023

So this reformulates your indicator constraint as an SOS1 constraint. when you do the negation, it tries to instead reformulate as a big-M MIP, which it can't do because x is free.

We could improve the error message, but this seems like it is working as expected.

@odow
Copy link
Member

odow commented Dec 4, 2023

It looks like CPLEX and Gurobi support indicators

https://www.ibm.com/docs/en/icos/22.1.0?topic=representation-mip-features-in-lp-file-format#d360454e288

[constraintname:] binaryvariable = value -> linear constraint

https://www.gurobi.com/documentation/11.0/refman/lp_format.html

c0: b1 = 1 -> 2.5 x + 2.3 y + 5.3 z <= 8.1

But I'm not in a rush to add support for this. Why is it useful?

@hdavid16
Copy link
Author

hdavid16 commented Dec 5, 2023

Using a SOS reformulation is fine. When the negation is used, it can be reformulated as:

minimize
obj: 
subject to
c1: 1 y + 1 x3 = 1
Bounds
x free
Binary
y
x3
SOS
c1_1: S1:: x3:0.4 x:0.6
End

It is useful when examining a model file since the .LP format is more understandable than an MOF file (wether that is supporting the indicator constraint directly or using a reformulation)

@odow
Copy link
Member

odow commented Dec 5, 2023

I get that we can reformulate the indicator constraint a different way. But the current bridge supports only ACTIVATE_ON_ONE:

"""
IndicatorSOS1Bridge{T,S} <: Bridges.Constraint.AbstractBridge
`IndicatorSOS1Bridge` implements the following reformulation:
* ``z \\implies {f(x) \\in S}`` into ``f(x) + y \\in S``,
``SOS1(y, z)``
!!! warning
This bridge assumes that the solver supports [`MOI.SOS1{T}`](@ref)
constraints in which one of the variables (``y``) is continuous.
## Source node
`IndicatorSOS1Bridge` supports:
* [`MOI.VectorAffineFunction{T}`](@ref) in
[`MOI.Indicator{MOI.ACTIVATE_ON_ONE,S}`](@ref)

But this is unrelated to the file format issue.

It is useful when examining a model file since the .LP format is more understandable

But in this case the model you are examining is not the same as the model you wrote down.

It seems like you're really asking for tools to make MOF files more understandable.

But if you're looking for a readable output, then you could just print(model) instead?

@hdavid16
Copy link
Author

hdavid16 commented Dec 5, 2023

So to give some context, I have some .lp files for some models (made by someone else) that I am trying to implement myself (develop the general model so that it can be solved on different input datasets). When I develop my version of the model, I use JuMP to compare my model with the one in the .lp file and find the differences between the two. However, these models get big and thus print(model) is not helpful for inspection. However, saving my version of the model to an .lp file helps me dig into the differences because I can search for text in the file as I drill into some of the differences between my version of the model and the one in the external .lp file.

@odow
Copy link
Member

odow commented Dec 5, 2023

You can print to file:

open("model.txt") do io
    print(io, model)
end

But oh, reverse engineering a model from the LP file does not sound like fun.

@hdavid16
Copy link
Author

hdavid16 commented Dec 5, 2023

Yes, writing to a text file is a good idea. Thanks. Haha...yeah...

@odow odow changed the title [FileFormats.LP] Writing an LP file with indicator constraints that ACTIVATE_ON_ZERO [FileFormats.LP] support indicator constraints Dec 5, 2023
@odow odow added the Submodule: FileFormats About the FileFormats submodule label Dec 5, 2023
@odow odow added this to the v1.x milestone Dec 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Submodule: FileFormats About the FileFormats submodule
Development

Successfully merging a pull request may close this issue.

2 participants