Skip to content

[BUG] Negative gap on air05 instance #855

@mtanneau

Description

@mtanneau

[Edit]: issue updated following discussion in #858 to focus on negative difference between upper and lower bound.

Describe the bug

Solving instance air05 (see below for MPS file) on a DGX Spark desktop results in a final dual bound that exceeds the final primal bound.

Sample log (see logs from additional runs on v26.02 below)

Setting CUDA_MODULE_LOADING to EAGER
Reading file air05.mps
cuOpt version: 26.4.0, git hash: b3bb21e4, host arch: aarch64, device archs: 121a-real
CPU: Unknown, threads (physical/logical): 1/20, RAM: 96.08 GiB
CUDA 12.9, device: NVIDIA GB10 (ID 0), VRAM: 119.70 GiB
CUDA device UUID: 43bce240-d7d6-65e5-ca7a-e351bab5de7a

Solving a problem with 426 constraints, 7195 variables (7195 integers), and 52121 nonzeros
Problem scaling:
Objective coefficents range:          [4e+01, 3e+03]
Constraint matrix coefficients range: [1e+00, 1e+00]
Constraint rhs / bounds range:        [1e+00, 1e+00]
Variable bounds range:                [0e+00, 1e+00]

Original problem: 426 constraints, 7195 variables, 52121 nonzeros
Calling Papilo presolver (git hash 741a2b9c)
Presolve status: reduced the problem
Presolve removed: 90 constraints, 1116 variables, 16171 nonzeros
Presolved problem: 336 constraints, 6079 variables, 35950 nonzeros
Objective function is integral
Papilo presolve time: 0.42
Objective offset 9167.000000 scaling_factor 1.000000
Model fingerprint: 0x3257a27
Running presolve!
Unused variables detected, eliminating them! Unused var count 4
After cuOpt presolve: 335 constraints, 6075 variables, objective offset 9167.000000.
cuOpt presolve time: 3.85

Solving LP root relaxation in concurrent mode
Skipping column scaling
Dual Simplex Phase 1
Dual feasible solution found.
Dual Simplex Phase 2
 Iter     Objective           Num Inf.  Sum Inf.     Perturb  Time
    0 -8.1936000000000000e+04     277 2.31020000e+04 0.00e+00 4.51
    1 -8.0926000000000000e+04     266 1.48790000e+04 0.00e+00 4.51
 1000 -5.7784953825729302e+04     127 1.13852044e+02 0.00e+00 4.61


Root relaxation solution found in 1194 iterations and 0.13s by Dual Simplex
Root relaxation objective +2.58776093e+04


 | Explored | Unexplored |    Objective    |     Bound     | IntInf | Depth | Iter/Node |   Gap    |  Time  |
           0            0             +inf    +2.588508e+04      228      0   1.2e+03        -        4.74
Gomory    cuts : 1
MIR       cuts : 0
Knapsack  cuts : 0
Strong CG cuts : 0
Cut pool size  : 211
Size with cuts : 336 constraints, 6411 variables, -1488061860 nonzeros
Strong branching using 19 threads and 228 fractional variables
Strong branching completed in 0.47s
Exploring the B&B tree using 19 threads

 | Explored | Unexplored |    Objective    |     Bound     | IntInf | Depth | Iter/Node |   Gap    |  Time  |
H                            +4.466800e+04    +2.588508e+04                                42.1%      5.28
H                            +4.448000e+04    +2.588508e+04                                41.8%      5.28
H                            +4.430000e+04    +2.588508e+04                                41.6%      5.29
H                            +4.387300e+04    +2.588508e+04                                41.0%      5.29
H                            +4.354400e+04    +2.588508e+04                                40.6%      5.30
H                            +4.287600e+04    +2.588508e+04                                39.6%      5.31
H                            +4.191500e+04    +2.588508e+04                                38.2%      5.32
H                            +4.166800e+04    +2.588508e+04                                37.9%      5.34
H                            +4.149500e+04    +2.588508e+04                                37.6%      5.35
H                            +4.121300e+04    +2.588508e+04                                37.2%      5.37
D         42           44    +2.657100e+04    +2.591578e+04        0     16   1.4e+02       2.5%      6.78
B         44           44    +2.645600e+04    +2.591578e+04        0     19   1.3e+02       2.0%      6.78
D         62           56    +2.644800e+04    +2.591578e+04        0     30   1.3e+02       2.0%      6.85
D         71           63    +2.644500e+04    +2.595460e+04        0     30   1.3e+02       1.9%      6.87
D         71           63    +2.644100e+04    +2.595460e+04        0     29   1.3e+02       1.8%      6.87
D         77           63    +2.643900e+04    +2.595460e+04        0     27   1.3e+02       1.8%      6.88
B        170          110    +2.640200e+04    +2.610151e+04        0     12   1.1e+02       1.1%      7.16
D        342          127    +2.640000e+04    +2.624972e+04        0     19   9.6e+01       0.6%      7.60
D        344          129    +2.637500e+04    +2.624972e+04        0     17   9.6e+01       0.5%      7.61
D        348          128    +2.637400e+04    +2.626036e+04        0     17   9.6e+01       0.4%      7.62
Explored 485 nodes in 7.79s.
Absolute Gap -5.595838e+00 Objective 2.6374000000000022e+04 Lower Bound 2.6379595837897017e+04
Optimal solution found.
Solution objective: 26374.000000 , relative_mip_gap 0.000212 solution_bound 26379.595838 presolve_time 4.275866 total_solve_time 7.854454 max constraint violation 0.000000 max int violation 0.000000 max var bounds violation 0.000000 nodes 485 simplex_iterations 40126

^^ this was obtained from a source build on main.

Steps/Code to reproduce bug

I installed cuopt in a python virtual environment as follows

uv venv
uv pip install   --extra-index-url=https://pypi.nvidia.com   cuopt-server-cu13==26.02.* cuopt-sh-client==26.02.*

and then executed the following command

/.venv/bin/cuopt_cli air05.mps

I also encountered this issue after building cuopt from source from the main branch.

Expected behavior

The dual (lower) bound should not exceed the primal (upper) bound.

Environment details (please complete the following information):

  • Environment location: DGX Spark desktop with GB10 GPU, 20-core CPU, 128GB unified memory, running aarch64 linux
  • Method of cuOpt install:
    • pip, see steps above.
    • also encountered when building from source using Conda; see instructions in CONTRIBUTING.md file

Additional context

MPS file (uploaded as a .txt because GitHub does not support .mps files):
air05.txt
Also available here: https://github.com/jump-dev/cuOpt.jl/blob/main/test/datasets/air05.mps

Log files: all the logs below were obtained by running the following command:

./.venv/bin/cuopt_cli  air05.mps > air05.X.log

I ran this 5 times to exhibit the non-deterministic nature and range of the behavior.

air05.1.log
air05.2.log
air05.3.log
air05.4.log
air05.5.log

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions