-
Notifications
You must be signed in to change notification settings - Fork 94
Closed
Description
@mlubin and I have been discussing the following example:
julia> using JuMP
julia> function main()
model = Model()
@variable(model, x)
@variable(model, y >= 0)
@objective(model, Min, x + y)
write_to_file(model, "file.mps")
print(read("file.mps", String))
end
main (generic function with 1 method)
julia> main()
NAME
ROWS
N OBJ
COLUMNS
y OBJ 1
x OBJ 1
RHS
RANGES
BOUNDS
LO bounds y 0
PL bounds y
FR bounds x
ENDATA
In JuMP, the columns are ordered x
, y
, but the MPS file, they are ordered as y
, x
.
Since the behavior of MIP solvers can depend on the column (and row) ordering, this can be undesirable.
The problem is:
MathOptInterface.jl/src/Utilities/copy.jl
Lines 199 to 234 in bca8a31
""" | |
_try_constrain_variables_on_creation( | |
dest::MOI.ModelLike, | |
src::MOI.ModelLike, | |
index_map::IndexMap, | |
::Type{S}, | |
) where {S<:MOI.AbstractScalarSet} | |
Copy the constraints of type `MOI.VariableIndex`-in-`S` from the model `src` to | |
the model `dest` and fill `index_map` accordingly. The copy is only done when the | |
variables to be copied are not already keys of `index_map`. | |
It returns a list of the constraints that were not added. | |
""" | |
function _try_constrain_variables_on_creation( | |
dest::MOI.ModelLike, | |
src::MOI.ModelLike, | |
index_map::IndexMap, | |
::Type{S}, | |
) where {S<:MOI.AbstractScalarSet} | |
not_added = MOI.ConstraintIndex{MOI.VariableIndex,S}[] | |
for ci_src in | |
MOI.get(src, MOI.ListOfConstraintIndices{MOI.VariableIndex,S}()) | |
f_src = MOI.get(src, MOI.ConstraintFunction(), ci_src) | |
if haskey(index_map, f_src) | |
# Can't add it because it contains a variable previously added | |
push!(not_added, ci_src) | |
else | |
set = MOI.get(src, MOI.ConstraintSet(), ci_src)::S | |
vi_dest, ci_dest = MOI.add_constrained_variable(dest, set) | |
index_map[ci_src] = ci_dest | |
index_map[f_src] = vi_dest | |
end | |
end | |
return not_added | |
end |
MathOptInterface.jl/src/Utilities/copy.jl
Lines 493 to 497 in bca8a31
else | |
Any[ | |
_try_constrain_variables_on_creation(dest, src, index_map, S) | |
for S in sorted_variable_sets_by_cost(dest, src) | |
] |
which eagerly tries to constrain variables on creation based on their set type.
I wonder if we should:
- not do this for scalar variables; or
- use a better heuristic, that adds variables in the correct order, but puts them in a set iff they are consecutive in the
VectorOfVariables
function.
The original motivation for doing this is so that variable bridges can be preferentially used.
I don't really have an answer yet. I'll explore some stuff and report here.
Metadata
Metadata
Assignees
Labels
No labels