Describe the bug
io::read accepts .sif and routes it to read_mps():
if (lower.ends_with(".mps") || lower.ends_with(".qps") || lower.ends_with(".sif")) {
...
return read_mps<i_t, f_t>(path, fixed_mps_format);
}
There is no SIF parser. SIF (the format CUTEst/SIFDEC problem sets ship in) uses VARIABLES, GROUPS and CONSTANTS sections where MPS uses ROWS, COLUMNS and RHS, so a genuine SIF file cannot be read by an MPS reader. The extension is effectively an undocumented alias for "parse this as MPS".
Three separate problems:
-
It only works for files that are already MPS. Verified against a 26.10 nightly libcuopt through cuOptReadProblem:
| file |
content |
result |
model.mps |
MPS |
CUOPT_SUCCESS, 2 vars / 1 constraint |
renamed.sif |
identical bytes, .sif name |
CUOPT_SUCCESS, 2 vars / 1 constraint |
real.sif |
genuine SIF (VARIABLES/GROUPS/CONSTANTS) |
CUOPT_MPS_PARSE_ERROR (3) |
-
No test coverage anywhere. grep -rIn "\.sif\|SIF" cpp/tests python/cuopt/cuopt/tests java/cuopt/src/test returns nothing, and the repo contains no .sif fixture. Nothing would catch a regression, in any language.
-
parser.hpp contradicts itself. The Routing block in the doc comment lists only .mps/.qps/.lp, while the code matches .sif and the logic_error message enumerates .sif, .sif.gz, .sif.bz2, .sif.lz4.
Steps/Code to reproduce bug
cuOptOptimizationProblem p = NULL;
cuOptReadProblem("real.sif", &p); // CUOPT_MPS_PARSE_ERROR, with a valid SIF file
Reproduces through every interface, since cuOptReadProblem (cuopt_c.cpp:292), the Python Read path (cython_parser.cpp:19) and the Java bindings all call the same io::read.
Expected behavior
Either support SIF properly — a parser, a fixture, and tests — or drop the extension. Advertising it in the error message while the routing docs omit it, with nothing tested behind it, is the worst of the three options.
Additional context
.sif entered in #1643 ("Include Q matrix in Ruiz scale computations", merged 2026-07-31), which is unrelated to file formats and does not mention .sif in its description. git log -S'.sif' -- cpp/ returns that commit alone, and no other issue or PR discusses SIF support, so this looks unintentional rather than a designed feature.
Noticed while documenting the read formats for the Java bindings (#1524), after @tmckayus asked what .sif is: #1524 (comment)
cc @rg20
Describe the bug
io::readaccepts.sifand routes it toread_mps():There is no SIF parser. SIF (the format CUTEst/SIFDEC problem sets ship in) uses
VARIABLES,GROUPSandCONSTANTSsections where MPS usesROWS,COLUMNSandRHS, so a genuine SIF file cannot be read by an MPS reader. The extension is effectively an undocumented alias for "parse this as MPS".Three separate problems:
It only works for files that are already MPS. Verified against a
26.10nightlylibcuoptthroughcuOptReadProblem:model.mpsCUOPT_SUCCESS, 2 vars / 1 constraintrenamed.sif.sifnameCUOPT_SUCCESS, 2 vars / 1 constraintreal.sifVARIABLES/GROUPS/CONSTANTS)CUOPT_MPS_PARSE_ERROR(3)No test coverage anywhere.
grep -rIn "\.sif\|SIF" cpp/tests python/cuopt/cuopt/tests java/cuopt/src/testreturns nothing, and the repo contains no.siffixture. Nothing would catch a regression, in any language.parser.hppcontradicts itself. TheRoutingblock in the doc comment lists only.mps/.qps/.lp, while the code matches.sifand thelogic_errormessage enumerates.sif, .sif.gz, .sif.bz2, .sif.lz4.Steps/Code to reproduce bug
Reproduces through every interface, since
cuOptReadProblem(cuopt_c.cpp:292), the PythonReadpath (cython_parser.cpp:19) and the Java bindings all call the sameio::read.Expected behavior
Either support SIF properly — a parser, a fixture, and tests — or drop the extension. Advertising it in the error message while the routing docs omit it, with nothing tested behind it, is the worst of the three options.
Additional context
.sifentered in #1643 ("Include Q matrix in Ruiz scale computations", merged 2026-07-31), which is unrelated to file formats and does not mention.sifin its description.git log -S'.sif' -- cpp/returns that commit alone, and no other issue or PR discusses SIF support, so this looks unintentional rather than a designed feature.Noticed while documenting the read formats for the Java bindings (#1524), after @tmckayus asked what
.sifis: #1524 (comment)cc @rg20