Giter Club home page Giter Club logo

qpsreader.jl's Issues

Use CITATION.cff instead of CITATION.bib

I am reviewing the CITATION usage in the repos and in particular moving to CFF files. The bib can still be generated using Github menu.
Here are a couple of suggestions to adapt this repo:

Performance benchmark

I'll write a benchmark script before working on performance improvements.

I propose to use 3 benchmark sets:

  • The Netlib LPs (available here): these are small LPs, in .SIF files and fixed MPS format.
  • The Maros-Meszaros QPs (here)
  • The LPs of Hans Mittelmann's benchmark (see here). These are (much) larger LPs in .mps, some with integer variables, and some in free MPS format.

The reason for including a larger testset of instances would be to allow modifications that improve performance on large instances, while allowing a limited degradation on smaller instances.

For information, the readers in C/C++ solvers (commercial and open-source) are ~10-30x faster than the ones we have in Julia.

Error reading certain Netlib problems

julia> using QPSReader
julia> netlib_path = fetch_netlib()

julia> blend = readqps(joinpath(netlib_path, "BLEND.SIF"))
[ Info: Using 'BLEND' as NAME (l. 5)
[ Info: Using 'C' as objective (l. 98)
[ Info: Using '65' as RHS (l. 376)
ERROR: Unknown row 23.26.
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] read_rhs_line!(::QPSData, ::QPSReader.MPSCard{QPSReader.FreeMPS}) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:498
 [3] readqps(::String; mpsformat::Symbol) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:800
 [4] readqps(::String) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:703
 [5] top-level scope at REPL[5]:1
 [6] eval(::Module, ::Any) at ./boot.jl:331
 [7] eval_user_input(::Any, ::REPL.REPLBackend) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
 [8] run_backend(::REPL.REPLBackend) at /Users/dpo/.julia/packages/Revise/Pcs5V/src/Revise.jl:1073
 [9] top-level scope at none:0

julia> prob = readqps(joinpath(netlib_path, "DFL001.SIF"))
[ Info: Using 'DFL001' as NAME (l. 5)
[ Info: Using 'NIL' as objective (l. 6098)
[ Info: Using 'R0006' as RHS (l. 29101)
ERROR: ArgumentError: cannot parse "R0009" as Float64
Stacktrace:
 [1] _parse_failure(::Type{T} where T, ::String, ::Int64, ::Int64) at ./parse.jl:370 (repeats 2 times)
 [2] #tryparse_internal#347 at ./parse.jl:366 [inlined]
 [3] tryparse_internal at ./parse.jl:364 [inlined]
 [4] #parse#348 at ./parse.jl:376 [inlined]
 [5] parse at ./parse.jl:376 [inlined]
 [6] read_rhs_line!(::QPSData, ::QPSReader.MPSCard{QPSReader.FreeMPS}) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:478
 [7] readqps(::String; mpsformat::Symbol) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:800
 [8] readqps(::String) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:703
 [9] top-level scope at REPL[6]:1
 [10] eval(::Module, ::Any) at ./boot.jl:331
 [11] eval_user_input(::Any, ::REPL.REPLBackend) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
 [12] run_backend(::REPL.REPLBackend) at /Users/dpo/.julia/packages/Revise/Pcs5V/src/Revise.jl:1073
 [13] top-level scope at none:0

julia> prob = readqps(joinpath(netlib_path, "FORPLAN.SIF"))
[ Info: Using 'FORPLAN' as NAME (l. 5)
[ Info: Using 'OB1PNW20' as objective (l. 21)
ERROR: Duplicate row name DEDO3 at line 23
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] read_rows_line!(::QPSData, ::QPSReader.MPSCard{QPSReader.FreeMPS}) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:363
 [3] readqps(::String; mpsformat::Symbol) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:796
 [4] readqps(::String) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:703
 [5] top-level scope at REPL[7]:1
 [6] eval(::Module, ::Any) at ./boot.jl:331
 [7] eval_user_input(::Any, ::REPL.REPLBackend) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
 [8] run_backend(::REPL.REPLBackend) at /Users/dpo/.julia/packages/Revise/Pcs5V/src/Revise.jl:1073
 [9] top-level scope at none:0

julia> prob = readqps(joinpath(netlib_path, "GFRD-PNC.SIF"))
[ Info: Using 'GFRD-PNC' as NAME (l. 5)
[ Info: Using 'OBJ' as objective (l. 20)
[ Info: Using 'PAF' as RHS (l. 2821)
ERROR: ArgumentError: cannot parse "PEE" as Float64
Stacktrace:
 [1] _parse_failure(::Type{T} where T, ::String, ::Int64, ::Int64) at ./parse.jl:370 (repeats 2 times)
 [2] #tryparse_internal#347 at ./parse.jl:366 [inlined]
 [3] tryparse_internal at ./parse.jl:364 [inlined]
 [4] #parse#348 at ./parse.jl:376 [inlined]
 [5] parse at ./parse.jl:376 [inlined]
 [6] read_rhs_line!(::QPSData, ::QPSReader.MPSCard{QPSReader.FreeMPS}) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:478
 [7] readqps(::String; mpsformat::Symbol) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:800
 [8] readqps(::String) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:703
 [9] top-level scope at REPL[8]:1
 [10] eval(::Module, ::Any) at ./boot.jl:331
 [11] eval_user_input(::Any, ::REPL.REPLBackend) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
 [12] run_backend(::REPL.REPLBackend) at /Users/dpo/.julia/packages/Revise/Pcs5V/src/Revise.jl:1073
 [13] top-level scope at none:0

julia> prob = readqps(joinpath(netlib_path, "SIERRA.SIF"))
[ Info: Using 'SIERRA' as NAME (l. 5)
[ Info: Using 'OBJ' as objective (l. 1247)
[ Info: Using 'BB1R' as RHS (l. 6566)
ERROR: ArgumentError: cannot parse "BB2R" as Float64
Stacktrace:
 [1] _parse_failure(::Type{T} where T, ::String, ::Int64, ::Int64) at ./parse.jl:370 (repeats 2 times)
 [2] #tryparse_internal#347 at ./parse.jl:366 [inlined]
 [3] tryparse_internal at ./parse.jl:364 [inlined]
 [4] #parse#348 at ./parse.jl:376 [inlined]
 [5] parse at ./parse.jl:376 [inlined]
 [6] read_rhs_line!(::QPSData, ::QPSReader.MPSCard{QPSReader.FreeMPS}) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:478
 [7] readqps(::String; mpsformat::Symbol) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:800
 [8] readqps(::String) at /Users/dpo/dev/julia/JSO/QPSReader.jl/src/readqps.jl:703
 [9] top-level scope at REPL[9]:1
 [10] eval(::Module, ::Any) at ./boot.jl:331
 [11] eval_user_input(::Any, ::REPL.REPLBackend) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
 [12] run_backend(::REPL.REPLBackend) at /Users/dpo/.julia/packages/Revise/Pcs5V/src/Revise.jl:1073
 [13] top-level scope at none:0

cc @geoffroyleconte

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

Release and register as Julia package?

Several Julia packages need to read MPS files, so having a stand-alone Julia reader for MPS files would avoid duplicating code.
For instance:

  • MathOptInterface.jl has an MPS reader/writer
  • Tulip.jl has its own MPS reader (that handles free MPS format)
  • SDDP.jl needs to parse MPS files when reading stochastic mps problem (I'm currently writing a parser for smps files and I'd like to avoid re-writing an MPS reader for the 3rd time)

Couple of questions:

  • Would there be license restrictions when using QPSReader within another Julia package? (e.g., is it OK to use QPSReader within an MIT-licensed package?)
  • For various reasons (especially in Tulip), I need constraint/objective matrices in COO format, not SparseCSC, so I would very much like to remove the COO -> SparseCSC conversion after parsing
  • Performance is not (yet) an issue, but the reader in Tulip is ~2-3x faster than QPSReader

(obviously, I can PR all this, just want the go-ahead before spending time on it)

TODO

  • Use COO format for matrices (#12)
  • Rim data
    • Choose conventions (#14)
    • Implement & update documentation (e.g. in README) (#18)
  • Performance evaluation (#15, #17, #20)
  • Free MPS format support (#21)

Fails to read neos-5044663-wairoa

The neos-5044663-wairoa instance from MIPLIB 2017 fails to read.

julia> QPSReader.readqps(GZip.gzopen("neos-5044663-wairoa.mps.gz"), mpsformat=:fixed)
[ Info: Using 'neos-5044663-wairoa' as NAME (l. 8)
[ Info: Using 'R0000000' as objective (l. 10)
┌ Error: Ignoring marker  at line 230060
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 301671
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 301674
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 301707
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 301712
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 302575
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 302578
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 302793
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 302796
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 303257
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 303260
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 303353
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 303358
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304105
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304108
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304155
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304158
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304469
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304472
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304565
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304568
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304601
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304606
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304699
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304704
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304797
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304800
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304881
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 304888
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 305027
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 305030
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 305485
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 305490
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 306351
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 306354
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 306593
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 306596
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 307447
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 307450
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 307635
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 307638
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 308283
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 308286
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 309055
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 309058
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 309275
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 309280
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 310407
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 310410
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 310543
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 310546
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 310731
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 310736
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 311137
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 311140
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 311315
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 311318
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 311365
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 311368
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 312335
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 312338
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 312523
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 312526
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 312849
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 312852
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 313155
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 313158
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 313481
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 313486
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 314337
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 314340
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 314479
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 314482
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 314979
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 314982
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 315477
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 315480
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 315619
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 315764
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
┌ Error: Ignoring marker  at line 319405
└ @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:852
ERROR: ArgumentError: cannot parse "lumn" as Float64
Stacktrace:
 [1] _parse_failure(T::Type, s::String, startpos::Int64, endpos::Int64) (repeats 2 times)
   @ Base ./parse.jl:373
 [2] #tryparse_internal#403
   @ ./parse.jl:369 [inlined]
 [3] tryparse_internal
   @ ./parse.jl:367 [inlined]
 [4] #parse#404
   @ ./parse.jl:379 [inlined]
 [5] parse
   @ ./parse.jl:379 [inlined]
 [6] read_columns_line!(qps::QPSReader.QPSData, card::QPSReader.MPSCard{QPSReader.FixedMPS}; integer_section::Bool)
   @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:487
 [7] readqps(qps::GZip.GZipStream; mpsformat::Symbol)
   @ QPSReader ~/.julia/packages/QPSReader/panNr/src/readqps.jl:856
 [8] top-level scope
   @ REPL[5]:1

The problematic line in the file is likely:

    C0063540  LB_full              0   $ empty column

I had never seen "$" in an MPS file before, but apparently it's valid comment in fixed format. IBM docs say:

If the first character in Field 3 or 5 is a dollar sign ($), the remaining characters in the record are treated as a comment. Another method for inserting comments is to place an asterisk (*) in column 1. Everything on such a line is treated as a comment.

Convention for rim data?

MPS files may have multiple objective rows, right-hand sides, etc... which is currently not handled in the code.

  • The objective name is reset every time a N row is encountered, so only the last such row is recorded.
  • Names for right-hand side and bounds are ignored, which means that
RHS
    rhs1      r1                2.0    r2                6.0
    rhs2      r1               -2.0    r2               -6.0

would yield right-hand sides of -2 and -6 for rows r1 and r2, respectively.

Obviously, nobody follows the same convention, so I would propose to do as follows:

  • The first N row is selected as the objective. Other N rows are ignored.
    Consequently, entries in subsequent sections that correspond to unregistered rows should be ignored, not raise an error. If this sounds bad or if you really want to raise an error, then one should keep track of these extra N rows.
  • The first name encountered in RHS, BOUNDS, RANGES is selected; others (if any) are ignored
  • Duplicate coefficients in the COLUMNS and QUADOBJ sections are added together. This follows the default behavior of creating a sparse matrix from the coefficients list: duplicate entries are added.
  • Duplicate entries in RHS, BOUNDS, RANGES sections over-write previous entries.

Here's a quick and non-exhaustive overview of what others do:

  • lpsolve:

    The RHS section allows one or more right-hand-side vectors to be
    defined; most people don't bother having more than one.

  • CPLEX docs:

    The MPS format allows multiple righthand sides (RHSs), multiple bounds, and multiple range vectors. It also allows extra free rows. Together, these features are known as extra rim vectors. By default, the CPLEX MPS reader selects the first RHS, bound, and range definitions that it finds. The first free row (that is, N-type row) becomes the objective function, and the remaining free rows are discarded. The extra rim data are also discarded.

  • The Gurobi docs says

    The name of the RHS is specified in the first field (column 5 in fixed format), but this name is ignored by the Gurobi reader
    and when I test with Gurobi 9.0, duplicate rhs entries for a given row are ignored (i.e., only the first occurrence of each row is recorded).
    bound name (ignored)

  • Mosek docs do not mention how multiple entries are handled, however in practice it looks like the first occurrence of RHS is recorded, so in the example above, the line rhs2 ... would be ignored.
    If there are duplicate entries, only the last one is recorded, i.e.,

        rhs1      r1                2.0    r1                6.0
    

    would yield a right-hand side value of 6.0 for row r1.

Drop Julia 1.1, 1.2 from CI

I think it would be enough to have

# .travis.yml
julia:
  - 1.0
  - 1
  - nightly

and

# .appveyor.yml
environment:
  matrix:
  - julia_version: 1.0
  - julia_version: 1
  - julia_version: nightly

since 1 should automatically point to the newest stable 1.Y.Z release.

Incorrect bounds on binary variables

While integer variables are not supported, the code claims to at least set their bounds. However, the reader can silently give incorrect bounds.

The CPLEX MPS documentation says:

ILOG CPLEX accepts two commonly used ways of extending
the MPS file format to include integer variables: in the COLUMNS section or in the BOUNDS
section.
In the first way, integer variables are identified within the COLUMNS section of the MPS file
by marker lines.
...
If no bounds are specified for the variables within markers, bounds of 0 (zero) and 1 (one)
are assumed.

GLPK follows the CPLEX behavior.

However, QPSReader ignores markers, so it can't can't enforce this rule to set the correct variable bounds (it sets an upper bound of infinity in this case).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.