jump-dev / MathOptInterface.jl

A data structure for mathematical optimization problems
http://jump.dev/MathOptInterface.jl/
Other
392 stars 87 forks source link

[FileFormats.MPS] wrong result after parsing file #2469

Closed foreverdyz closed 6 months ago

foreverdyz commented 6 months ago

Hi,

foreverdyz/ParallelCliqueMerge#1: when using JuMP + Gurobi for irish-electricity.mps from MIPLIB, Julia returns a wrong value with 0, though the correct value should be 3723497.591396. And Python with GRB can output the correct result as the issue 1 showing.

Thanks a lot.

torressa commented 6 months ago

Hi @foreverdyz! From your other issue, I cannot see the Gurobi version used in Python. Can you try upgrading to the latest version (right now 11.0.1)?

foreverdyz commented 6 months ago

I tried both Gurobi 10 and 11. Thanks

odow commented 6 months ago

Do you have a reproducible example? Which MPS file, specifically?

This is likely not a bug in Gurobi.jl, but a difference in how MathOptInterface parses the MPS file.

foreverdyz commented 6 months ago

The mps file is irish-electricity.mps.gz from https://miplib.zib.de/instance_details_irish-electricity.html (MIPLIB)

using JuMP, Gurobi
model = read_from_file("irish-electricity.mps.gz")
set_optimizer(model, Gurobi.Optimizer)
set_attribute(model, "Threads", 10)
optimize!(model)
odow commented 6 months ago

Can reproduce this with HiGHS as well, so we must be reading the file incorrectly.

odow commented 6 months ago

Also because

julia> using JuMP, Gurobi

julia> model = read_from_file("irish-electricity.mps.gz")
irish-electricity
Minimization problem with:
Variables: 61728
Objective function type: AffExpr
`AffExpr`-in-`MathOptInterface.EqualTo{Float64}`: 10537 constraints
`AffExpr`-in-`MathOptInterface.GreaterThan{Float64}`: 36195 constraints
`AffExpr`-in-`MathOptInterface.LessThan{Float64}`: 57527 constraints
`VariableRef`-in-`MathOptInterface.GreaterThan{Float64}`: 41472 constraints
`VariableRef`-in-`MathOptInterface.Interval{Float64}`: 10368 constraints
`VariableRef`-in-`MathOptInterface.ZeroOne`: 9888 constraints
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.

julia> set_optimizer(model, Gurobi.Optimizer)

julia> optimize!(model)
Gurobi Optimizer version 11.0.0 build v11.0.0rc2 (mac64[x86] - Darwin 22.6.0 22G91)

CPU model: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Optimize a model with 104259 rows, 61728 columns and 523257 nonzeros
Model fingerprint: 0x0d6fb5a4
Variable types: 51840 continuous, 9888 integer (9888 binary)
Coefficient statistics:
  Matrix range     [1e+00, 2e+04]
  Objective range  [1e+00, 1e+00]
  Bounds range     [1e+00, 1e+00]
  RHS range        [0e+00, 0e+00]
Found heuristic solution: objective 0.0000000

Explored 0 nodes (0 simplex iterations) in 0.03 seconds (0.02 work units)
Thread count was 1 (of 8 available processors)

Solution count 1: 0 

Optimal solution found (tolerance 1.00e-04)
Best objective 0.000000000000e+00, best bound 0.000000000000e+00, gap 0.0000%

User-callback calls 24, time in user-callback 0.00 sec

julia> report = primal_feasibility_report(model)
Dict{Any, Float64}()

whereas

oscar@Oscars-MBP grb % gurobi_cl irish-electricity.mps
Set parameter LogFile to value "gurobi.log"
Using license file /Users/oscar/gurobi.lic

Gurobi Optimizer version 11.0.0 build v11.0.0rc2 (mac64[x86] - Darwin 22.6.0 22G91)
Copyright (c) 2023, Gurobi Optimization, LLC

Read MPS format model from file irish-electricity.mps
Reading time = 0.16 seconds
irish-electricity: 104259 rows, 61728 columns, 523257 nonzeros

CPU model: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
Thread count: 4 physical cores, 8 logical processors, using up to 8 threads

Optimize a model with 104259 rows, 61728 columns and 523257 nonzeros
Model fingerprint: 0x7e2c6136
Variable types: 51840 continuous, 9888 integer (9888 binary)
Coefficient statistics:
  Matrix range     [1e+00, 2e+04]
  Objective range  [1e+00, 1e+00]
  Bounds range     [1e+00, 1e+00]
  RHS range        [3e-01, 5e+03]
Presolve removed 72359 rows and 33084 columns
Presolve time: 2.88s
Presolved: 31900 rows, 28644 columns, 156087 nonzeros
Variable types: 20831 continuous, 7813 integer (7813 binary)
Deterministic concurrent LP optimizer: primal and dual simplex
Showing primal log only...

Root simplex log...

Iteration    Objective       Primal Inf.    Dual Inf.      Time
   28491    3.7145437e+05   8.020643e+01   3.774897e+08      5s
   46118    6.1605370e+06   0.000000e+00   9.539042e+06      8s
   48740    5.0679108e+06   0.000000e+00   7.515759e+11     10s
odow commented 6 months ago

Difference is the RHS range [3e-01, 5e+03]

odow commented 6 months ago

The right-hand side vector is named *RHS* Demand_1 1938, and our reader assumes that all lines starting with * are comments, but it should be all lines with * in position 1...

But, WHY would you name the right-hand side vector *RHS* when * is used for comments... I hate file formats.

Fix incoming.

odow commented 6 months ago

Will be fixed by https://github.com/jump-dev/MathOptInterface.jl/pull/2470

foreverdyz commented 6 months ago

Thank you! @odow