coin-or / pulp

A python Linear Programming API
http://coin-or.github.io/pulp/
Other
2.04k stars 381 forks source link

LpMaximize and writeMPS #697

Open fuglede opened 10 months ago

fuglede commented 10 months ago

Details for the issue

What did you do?

Consider writing the following simple LP to an MPS file:

model = LpProblem("Test problem", LpMaximize)
x = LpVariable("x")
model += x
model += x <= 60
model += x >= -30
model.writeMPS('test.mps')

The resulting file looks as follows:

*SENSE:Maximize
NAME          Test_problem
ROWS
 N  OBJ
 L  _C1
 G  _C2
COLUMNS
    x         _C1        1.000000000000e+00
    x         _C2        1.000000000000e+00
    x         OBJ        1.000000000000e+00
RHS
    RHS       _C1        6.000000000000e+01
    RHS       _C2       -3.000000000000e+01
BOUNDS
 FR BND       x       
ENDATA

In particular, the first line, *SENSE:Maximize indicates that we are indeed dealing with a maximization problem. I can't seem to be able to figure out where that's specified though. And I tried passing the MPS to HiGHS and MOSEK, both of which assume that we are dealing with a minimization problem instead.

Wikipedia mentions the following syntax for specifying that a problem is a maximization problem, and e.g. HiGHS does manage to parse that:

OBJSENSE
 MAX

Should I have expected *SENSE:Maximize to be something that solvers can parse, so that I can go on to blame the other solvers, should I maybe have realized that MPS isn't good for maximization problems altogether? If this syntax is PuLP-specific, might it make sense to switch to the possibly-supported syntax from Wikipedia?

Useful extra information

The info below often helps, please fill it out if you're able to. :)

What operating system are you using?

I'm using python version:

I installed PuLP via:

Did you also

fuglede commented 10 months ago

So indeed, someone did think of this discrepancy at some point; there's a parameter for deciding which syntax to use: https://github.com/coin-or/pulp/blob/c0c391acaf75edd330bb81bc4ab0de7f0ee21b42/pulp/mps_lp.py#L252-L256 It looks like(?) it's undocumented though, so explaining (e.g. in the documentation for LpProblem.writeMPS itself) that that's something to be aware of, what the caveats are and what one might want to use when.

tkralphs commented 10 months ago

Just for background, the original specification for the MPS format goes back decades, literally to the time when punch cards were used for input, and only allowed for minimization (which was just the silent default and could not be specified explicitly one way or the other). All MPS files that strictly adhere to that original specification thus describe minimization problems. Over time, the MPS format has been relaxed in various ways to get rid of restrictions that are now not really useful, including the prohibition on describing maximization problems. The OBJSENSE keyword was added informally, but this and other additions has lead to minor incompatibilities between different writers and readers and it is generally safer even today to convert to minimization before writing out an MPS file. On the other hand, if you are aware of the issue, then it is easy to test whether any given reader or writer knows about this keyword.