Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does scipy support OpenMP #13372

Closed
touqir14 opened this issue Jan 9, 2021 · 18 comments
Closed

Does scipy support OpenMP #13372

touqir14 opened this issue Jan 9, 2021 · 18 comments
Labels
query A question or suggestion that requires further information

Comments

@touqir14
Copy link

touqir14 commented Jan 9, 2021

So, a bunch of Scipy functionalities have been cythonized for performance. Will it be possible to include OpenMP and parallelize some of them?

@rgommers rgommers added the query A question or suggestion that requires further information label Jan 9, 2021
@rgommers
Copy link
Member

rgommers commented Jan 9, 2021

In short, no not with OpenMP - see gh-10239.

We do have parallel algorithms do, through the workers keyword. See http://scipy.github.io/devdocs/roadmap.html#performance-improvements. More parallelization is welcome.

@rgommers rgommers closed this as completed Jan 9, 2021
@denis-bz
Copy link

Another program that tries to use OpenMP is optimize.linprog HiGHS.
Has anyone tested this on a Mac ?
From SO enable-openmp-support-in-clang-in-mac-os-x-sierra-mojave
it looks like versionitis (the dreaded version disease).
With numpy 1.19.5 scipy 1.6.0 python 3.7.6 mac 10.10.5 (old) I get

WARNING: Number of OMP threads available = 0 < 1 = Number of HiGHS threads to be used:
Parallel performance will be less than anticipated

on my 4-core Mac, OMP_NUM_THREADS=4, any LP at all.

This is just a comment -- over to you

@rgommers
Copy link
Member

Pretty sure OpenMP was disabled in the HiGHS PR; this warning may be an unintended side effect of disabling OpenMP. Can you give a reproducible example that triggers this warning @denis-bz?

Cc @mckib2 who can correct me on the implementation details if I'm misremembering.

@mckib2
Copy link
Contributor

mckib2 commented Jan 14, 2021

OpenMP is disabled, but HiGHS will still tell you about it because it agrees you might be leaving performance on the table. I think this warning should only be displayed in verbose modes -- please do send a reproducible example if this is not the case. The performance boost of parallelizing any simplex solver is minimal (as it's difficult to do), so this warning can safely be ignored.

If you're experimenting, you can enable OpenMP for HiGHS by commenting out this line, but you have no guarantees about what happens after from us

@denis-bz
Copy link

Folks,
a trivial test, and some suggestions
(a German saying: "don't give unasked-for advice")

#!/usr/bin/env python3
""" test scipy.optimize.linprog highs* lpgen_2d """
# suggestions / questions:
#   default should be IPM -- faster on problems > a minute
#   highs == highs-ds, not IPM, disp=True:
#       WARNING: Number of OMP threads available = 0 < 1 = Number of HiGHS threads to be used:
# timelimit hit: -> f, x None ?!
# tol is murky -- scaled ?

import sys
import numpy as np
from scipy import sparse
from scipy.optimize import linprog  # $scopt/_linprog_doc.py
from scipy.optimize.tests.test_linprog import lpgen_2d  # cf. lpgen34.py

__version__ = "2021-01-16"  # denis-bz-py t-online.de
np.set_printoptions( threshold=20, edgeitems=10, linewidth=120,
        formatter = dict( float = lambda x: "%.2g" % x ))  # float arrays %.2g
# print( nu.versionstr() )  # numpy 1.19.5  scipy 1.6.0  python 3.7.6

#...............................................................................
n = 10
solvers = "highs highs-ds highs-ipm "  # highs == ds
disp = True
timelimit = 0.1  # n=200: -> f, x None
tol = 0.1  # IPM should quit when mu < this

    # to change these params, run this.py  a=1  b=None  'c = expr' ... in sh or ipython --
for arg in sys.argv[1:]:
    exec( arg )

A, b, c = lpgen_2d( n, n )  # m+n, m*n
A = sparse.csr_matrix( A )
print( "lpgen_2d: A sparse %s \nb %s \n%s " % (
        A.shape, b, c ))
options = dict(
    disp=disp, time_limit=timelimit,
    dual_feasibility_tolerance=tol,
    primal_feasibility_tolerance=tol,
    ipm_optimality_tolerance=tol )

#...............................................................................
for solver in solvers.split():
    print( "\n" + 80 * "-" )
    print( "--", solver )
    res = linprog( c, A_eq=A, b_eq=b, method=solver, options=options )
    print( "res: \n", res )

@mckib2
Copy link
Contributor

mckib2 commented Jan 17, 2021

default should be IPM -- faster on problems > a minute

The default is chosen to be the default solver that HiGHS chooses (currently hard-coded to be dual simplex, but will probably change in the future to use some more intelligent decision logic). I think we don't want to make promises about which solver is chosen when the user doesn't specify, but we might want to change scipy over to using IPM by default if there's enough of a performance improvement. @mdhaber any thoughts about switching to use IPM as HiGHS default?

highs == highs-ds, not IPM, disp=True:
WARNING: Number of OMP threads available = 0 < 1 = Number of HiGHS threads to be used:

Yes, this warning is produced in the C++ source code. It is a harmless warning, but we might think about asking the upstream HiGHS developers about removing it to not bother users who opt out of OpenMP. You can try creating a PR to comment it out, I see no reason we wouldn't accept a PR like that, but it doesn't bother me personally.

timelimit hit: -> f, x None ?!

There is currently no mechanism in HiGHS to retrieve a partial solution, so if HiGHS does not report a solution then None is returned. This is something we've asked them about before, but it doesn't seem high on their list of priorities. I'm sure if they got enough interest in this feature (partial solution recovery) they might consider it.

For more context you can see this comment: "The only useful "partial solution" I can think of offering is in the case where an LP is primal unbounded. HiGHS could return the point at which primal unboundedness is detected. Quite how valuable this is to a user is another question."

tol is murky -- scaled ?

There was a lot of discussion and testing to determine how tolerances worked (and several fixes that I don't believe have made it into scipy yet). We hope that the tolerances are working in a reasonable way -- is it unclear from the documentation how tolerances are used? This comment clarifies that IPM tolerances may not be working as expected: "The reason why playing with the feasiblity and optimality tolerances - esp setting them to large values - doesn't have much effect on behaviour of IPX is that there is another tolerance, "crossover_start", that determines when crossover starts." The new start_crossover_tolerance will be available when upstream sync PRs go through (e.g. gh-13197).

If there's a particular failure with dual simplex tolerances that you can produce, please do open a ticket so we can investigate!

@denis-bz
Copy link

@mckib2, Thanks for looking this over.
Don't mean to nitpick, want to improve the doc and to testbench biggish sparse problems.
(I don't know of ANY real ones at all, do you --
how can we get anywhere near Gurobi or maybe SCIPopt without real testcases ?
The netlib ones run in seconds in GLPK, as you know Klee-Minty too.)

Fwiw lpgen34.py under my gists generates A 4n^3 x n^4 with 4n^4 nnz, with runtimes

n10-d4-highs-ipm.log:   4.17 real time
n10-d4-highs-ds.log:    38.43 real time

n11-d4-highs-ipm.log:   7.69 real time
n11-d4-highs-ds.log:    126.91 real time

n22-d4-highs-ipm.log:   8590.30 real time

What do you think ?

@mckib2
Copy link
Contributor

mckib2 commented Jan 17, 2021

@denis-bz These are really interesting results that show a big difference between dual simplex and IPM. Do you mind if we share the gist with the HiGHS developers? I think they would be interested to see and might have comments on the disparity

@mdhaber
Copy link
Contributor

mdhaber commented Jan 18, 2021

@mdhaber any thoughts about switching to use IPM as HiGHS default?

Since IPM has crossover (and therefore is just as accurate as DS), that's fine with me if it tends to be faster on all major platforms. If it's platform-dependent, we would need to figure out what causes the difference between them and decide which way to go from there.

BTW, almost all of the Netlib problems are available as benchmarks in optimize_linprog.py, and they'll all run if you have an environment variable SCIPY_XSLOW=1. Maybe I'll try running them tonight.

@mdhaber
Copy link
Contributor

mdhaber commented Jan 18, 2021

I can confirm that DS tends to be slower for larger and more difficult problems. ("Failed" occurs when the benchmark takes longer than 60s, I think.)
image

but it is basically always faster for the smaller problems - that is, all ~70 of the feaibly Netlib problems included in SciPy that are not shown above.

DS is clearly better at identifying infeasibility correctly. There are 28 infeasible problems (separate from the ones above) ; DS identifies all of them correctly, but IPM doesn't give the right status code for box1, chemcom, cplex2, ex72a, ex73a.

There is no difference in accuracy. (However, I suspect that the "correct" values listed along with the Netlib problems are incorrect in some places, or there is something slightly wrong with the MPS files or my conversion code. There are some problems for which IPM and DS agree with one another on the optimal objective but disagree with the listed value - e.g. GREENBEA, GREENBEB relative differences are > 1e-5.)

@mckib2 could you run HiGHS directly (not via SciPy) on some of these to see if the results hold?

@mckib2
Copy link
Contributor

mckib2 commented Jan 19, 2021

I did a quick run for 106 feasible and 23 infeasible NETLIB problems (some of the feasible problems crashed on HiGHS master, so omitted those from the results).

For the set of feasible problems, status codes only disagreed in 1 instance: GREENBEA. I only ran each problem once, so there's no error bars here -- just a single sampling. Broadly I would say IPM seems like it runs faster than simplex on this problem set.

@mdhaber For the infeasible problems, IPM fails much more often than simplex as you said. The only real "failure" seems to be cplex2 where IPM reports unbounded and simplex reports infeasible (we've seen a failure like this before where it got it wrong the other way). The others are just HiGHS errors -- meaning the solver couldn't handle the problem. That's probably where the different return codes come from. Dual simplex has only one such error with vol1.

Pinging @jajhall in case he wants to listen in to our discussion

Feasible NETLIB Problems
PROBLEM IPM_TIME SIMPLEX_TIME IPM_STATUS SIMPLEX_STATUS IPM_FUN SIMPLEX_FUN DS/IPM - 1 STATUS DIFF FUN DIFF
25fv47 0.1397430897 0.2058658600 Optimal Optimal 5.5018458883 5.5018458883 47.3174% True True
80bau3b 0.3499679565 0.0987069607 Optimal Optimal 9.8722419241 9.8722419241 -71.7954% True True
adlittle 0.0048902035 0.0012917519 Optimal Optimal 2.2549496316 2.2549496316 -73.5849% True True
afiro 0.0027146339 0.0008461475 Optimal Optimal -4.6475314286 -4.6475314286 -68.8301% True True
agg2 0.0253405571 0.0050559044 Optimal Optimal -2.0239252356 -2.0239252356 -80.0482% True True
agg3 0.0194561481 0.0069298744 Optimal Optimal 1.0312115935 1.0312115935 -64.3821% True True
agg 0.0092253685 0.0037322044 Optimal Optimal -3.5991767287 -3.5991767287 -59.5441% True True
bandm 0.0140182972 0.0102214813 Optimal Optimal -1.5862801845 -1.5862801845 -27.0847% True True
beaconfd 0.0036039352 0.0017199516 Optimal Optimal 3.3592485807 3.3592485807 -52.2757% True True
bnl1 0.0564663410 0.0359139442 Optimal Optimal 1.9776295615 1.9776295615 -36.3976% True True
bnl2 0.1359958649 0.0465247631 Optimal Optimal 1.8112365404 1.8112365404 -65.7896% True True
boeing1 0.0209162235 0.0112266541 Optimal Optimal -3.3521356751 -3.3521356751 -46.3256% True True
boeing2 0.0119757652 0.0023574829 Optimal Optimal -3.1501872802 -3.1501872802 -80.3146% True True
bore3d 0.0050337315 0.0026893616 Optimal Optimal 1.3730803942 1.3730803942 -46.5732% True True
brandy 0.0119688511 0.0062158108 Optimal Optimal 1.5185098965 1.5185098965 -48.0668% True True
capri 0.0125567913 0.0031185150 Optimal Optimal 2.6900129138 2.6900129138 -75.1647% True True
cre-a 0.3287925720 0.0887901783 Optimal Optimal 2.3595407061 2.3595407061 -72.9951% True True
cre-b 2.7204642296 1.9375388622 Optimal Optimal 2.3129639887 2.3129639887 -28.7791% True True
cre-c 0.2128822803 0.0654697418 Optimal Optimal 2.5275116141 2.5275116141 -69.246% True True
cre-d 1.9300870895 0.8739824295 Optimal Optimal 2.4454969765 2.4454969765 -54.718% True True
cycle 0.1531128883 0.0334155560 Optimal Optimal -5.2263930249 -5.2263930249 -78.1759% True True
czprob 0.0423440933 0.0112936497 Optimal Optimal 2.1851966989 2.1851966989 -73.3289% True True
d2q06c 0.5033462048 0.8549218178 Optimal Optimal 1.2278421081 1.2278421081 69.8477% True True
d6cube 0.3660383224 0.0908024311 Optimal Optimal 3.1549166667 3.1549166667 -75.1932% True True
degen2 0.0341401100 0.0349512100 Optimal Optimal -1.4351780000 -1.4351780000 2.3758% True True
degen3 0.2157137394 0.1188237667 Optimal Optimal -9.8729400000 -9.8729400000 -44.916% True True
e226 0.0163307190 0.0065047741 Optimal Optimal -1.1638929066 -1.1638929066 -60.1685% True True
etamacro 0.0241317749 0.0229272842 Optimal Optimal -7.5571523337 -7.5571523130 -4.99131% True True
fffff800 0.0355825424 0.0226507187 Optimal Optimal 5.5567956482 5.5567956482 -36.3432% True True
finnis 0.0297529697 0.0161807537 Optimal Optimal 1.7279106560 1.7279106560 -45.6163% True True
fit1d 0.0246403217 0.0144109726 Optimal Optimal -9.1463780924 -9.1463780924 -41.5147% True True
fit1p 0.0355720520 0.0466125011 Optimal Optimal 9.1463780924 9.1463780924 31.0369% True True
fit2d 0.3086652756 0.0957748890 Optimal Optimal -6.8464293294 -6.8464293294 -68.9713% True True
fit2p 0.3481917381 1.0974757671 Optimal Optimal 6.8464293294 6.8464293294 215.193% True True
forplan 0.0248925686 0.0060803890 Optimal Optimal -6.6421896127 -6.6421896127 -75.5735% True True
ganges 0.0258698463 0.0117228031 Optimal Optimal -1.0958573613 -1.0958573613 -54.6855% True True
greenbea 0.2421672344 0.1618537903 Infeasible Optimal None -7.2555248130 -33.1645% False None
greenbeb 0.3260898590 0.4249796867 Optimal Optimal -4.3022602612 -4.3022602612 30.3259% True True
grow15 0.0464403629 0.0650818348 Optimal Optimal -1.0687094129 -1.0687094129 40.1407% True True
grow22 0.0721240044 0.0970196724 Optimal Optimal -1.6083433648 -1.6083433648 34.5179% True True
grow7 0.0220956802 0.0091850758 Optimal Optimal -4.7787811815 -4.7787811815 -58.4304% True True
israel 0.0140705109 0.0039536953 Optimal Optimal -8.9664482186 -8.9664482186 -71.9008% True True
kb2 0.0024373531 0.0009021759 Optimal Optimal -1.7499001299 -1.7499001299 -62.9854% True True
ken-07 0.0292353630 0.0171158314 Optimal Optimal -6.7952044338 -6.7952044338 -41.455% True True
ken-11 0.3364188671 0.1399352551 Optimal Optimal -6.9723822625 -6.9723822625 -58.4045% True True
ken-13 1.2613356113 0.4297754765 Optimal Optimal -1.0257394789 -1.0257394789 -65.927% True True
ken-18 9.1149294376 3.3734877110 Optimal Optimal -5.2217025287 -5.2217025287 -62.9894% True True
lotfi 0.0231647491 0.0064330101 Optimal Optimal -2.5264706062 -2.5264706062 -72.2293% True True
maros 0.0497906208 0.0438647270 Optimal Optimal -5.8063743701 -5.8063743701 -11.9016% True True
maros-r7 0.5852227211 0.7210648060 Optimal Optimal 1.4971851665 1.4971851665 23.212% True True
modszk1 0.0339152813 0.0138957500 Optimal Optimal 3.2061972906 3.2061972906 -59.0281% True True
nesm 0.0942192078 0.0865945816 Optimal Optimal 1.4076036488 1.4076036488 -8.09243% True True
osa-07 0.4720487595 0.2107739449 Optimal Optimal 5.3572251730 5.3572251730 -55.3491% True True
osa-14 1.6876394749 0.8950397968 Optimal Optimal 1.1064628447 1.1064628447 -46.965% True True
osa-30 3.1959226131 4.5480649471 Optimal Optimal 2.1421398732 2.1421398732 42.3084% True True
osa-60 8.4879646301 24.2191154957 Optimal Optimal 4.0440725032 4.0440725032 185.335% True True
pds-02 0.1200804710 0.0350420475 Optimal Optimal 2.8857862010 2.8857862010 -70.8179% True True
pds-06 0.8370428085 0.1551849842 Optimal Optimal 2.7761037600 2.7761037600 -81.4603% True True
pds-10 2.0220077038 0.3633828163 Optimal Optimal 2.6727094976 2.6727094976 -82.0286% True True
pds-20 7.2958815098 1.2818229198 Optimal Optimal 2.3821658640 2.3821658640 -82.4309% True True
perold 0.0864934921 0.0685126781 Optimal Optimal -9.3807552782 -9.3807552782 -20.7886% True True
pilot4 0.0580520630 0.0299544334 Optimal Optimal -2.5811392589 -2.5811392589 -48.4007% True True
pilot87 2.3749861717 4.7522900105 Optimal Optimal 3.0171034733 3.0171034733 100.098% True True
pilot.ja 0.1341872215 0.0993723869 Optimal Optimal -6.1131364656 -6.1131364656 -25.945% True True
pilot 0.7900209427 1.1153838634 Optimal Optimal -5.5748972928 -5.5748972928 41.1841% True True
pilotnov 0.1340510845 0.1099405289 Optimal Optimal -4.4972761882 -4.4972761882 -17.9861% True True
pilot.we 0.1187598705 0.1725435257 Optimal Optimal -2.7201075328 -2.7201075328 45.2877% True True
qap08 0.0931069851 0.3473794460 Optimal Optimal 2.0350000000 2.0350000000 273.097% True True
recipe 0.0039203167 0.0009629726 Optimal Optimal -2.6661600000 -2.6661600000 -75.4364% True True
sc105 0.0038139820 0.0016827583 Optimal Optimal -5.2202061212 -5.2202061212 -55.8792% True True
sc205 0.0067875385 0.0024046898 Optimal Optimal -5.2202061212 -5.2202061212 -64.572% True True
sc50a 0.0021998882 0.0008194447 Optimal Optimal -6.4575077059 -6.4575077059 -62.7506% True True
sc50b 0.0012402534 0.0006566048 Optimal Optimal -7.0000000000 -7.0000000000 -47.0588% True True
scagr25 0.0133976936 0.0056357384 Optimal Optimal -1.4753433061 -1.4753433061 -57.935% True True
scagr7 0.0033504963 0.0019857883 Optimal Optimal -2.3313898243 -2.3313898243 -40.7315% True True
scfxm1 0.0191004276 0.0061655045 Optimal Optimal 1.8416759028 1.8416759028 -67.7206% True True
scfxm2 0.0408864021 0.0130627155 Optimal Optimal 3.6660261565 3.6660261565 -68.0512% True True
scfxm3 0.0572094917 0.0259768963 Optimal Optimal 5.4901254550 5.4901254550 -54.5934% True True
scorpion 0.0034079552 0.0019710064 Optimal Optimal 1.8781248227 1.8781248227 -42.1645% True True
scrs8 0.0173482895 0.0086598396 Optimal Optimal 9.0429695380 9.0429695380 -50.0825% True True
scsd1 0.0073449612 0.0027372837 Optimal Optimal 8.6666666743 8.6666666743 -62.7325% True True
scsd6 0.0177228451 0.0071759224 Optimal Optimal 5.0500000077 5.0500000078 -59.5103% True True
scsd8 0.0415987968 0.0406723022 Optimal Optimal 9.0499999993 9.0499999993 -2.22721% True True
sctap1 0.0214285851 0.0048112869 Optimal Optimal 1.4122500000 1.4122500000 -77.5473% True True
sctap2 0.0538339615 0.0117197037 Optimal Optimal 1.7248071429 1.7248071429 -78.2299% True True
sctap3 0.0661859512 0.0151095390 Optimal Optimal 1.4240000000 1.4240000000 -77.1711% True True
seba 0.0268239975 0.0147471428 Optimal Optimal 1.5711600000 1.5711600000 -45.0226% True True
share1b 0.0122029781 0.0023732185 Optimal Optimal -7.6589318579 -7.6589318579 -80.5521% True True
share2b 0.0052118301 0.0014970303 Optimal Optimal -4.1573224074 -4.1573224074 -71.2763% True True
shell 0.0183289051 0.0048310757 Optimal Optimal 1.2088253460 1.2088253460 -73.6423% True True
ship04l 0.0175602436 0.0086758137 Optimal Optimal 1.7933245380 1.7933245380 -50.594% True True
ship04s 0.0120244026 0.0043787956 Optimal Optimal 1.7987147004 1.7987147004 -63.5841% True True
ship08l 0.0432233810 0.0155656338 Optimal Optimal 1.9090552114 1.9090552114 -63.9879% True True
ship08s 0.0177967548 0.0068600178 Optimal Optimal 1.9200982105 1.9200982105 -61.4535% True True
ship12l 0.0483725071 0.0163819790 Optimal Optimal 1.4701879193 1.4701879193 -66.1337% True True
ship12s 0.0272397995 0.0087308884 Optimal Optimal 1.4892361344 1.4892361344 -67.948% True True
stair 0.0295102596 0.0139555931 Optimal Optimal -2.5126695119 -2.5126695119 -52.7094% True True
standata 0.0128819942 0.0042891502 Optimal Optimal 1.2576995000 1.2576995000 -66.7043% True True
standgub 0.0188145638 0.0029911995 Optimal Optimal 1.2576995000 1.2576995000 -84.1017% True True
standmps 0.0221896172 0.0047333241 Optimal Optimal 1.4060175000 1.4060175000 -78.6687% True True
stocfor1 0.0028178692 0.0014157295 Optimal Optimal -4.1131976219 -4.1131976219 -49.7589% True True
stocfor2 0.0544986725 0.0250179768 Optimal Optimal -3.9024408538 -3.9024408538 -54.0943% True True
tuff 0.0203638077 0.0074510574 Optimal Optimal 2.9214776509 2.9214776509 -63.4103% True True
vtp_base 0.0027258396 0.0011315346 Optimal Optimal 1.2983146246 1.2983146246 -58.4886% True True
wood1p 0.1774775982 0.0304467678 Optimal Optimal 1.4429024116 1.4429024116 -82.8447% True True
woodw 0.1917996407 0.0636851788 Optimal Optimal 1.3044763331 1.3044763331 -66.796% True True
Infeasible NETLIB Problems
PROBLEM IPM_TIME SIMPLEX_TIME IPM_STATUS SIMPLEX_STATUS IPM_FUN SIMPLEX_FUN DS/IPM - 1 STATUS DIFF FUN DIFF
bgdbg1 0.000412941 0.0004189014 Infeasible Infeasible None None 1.4434% True None
bgetam 0.0029866695 0.002076149 Infeasible Infeasible None None -30.4861% True None
bgindy 0.0109028816 0.0206785202 Infeasible Infeasible None None 89.6611% True None
bgprtr 0.0036225319 0.0016944408 Infeasible Infeasible None None -53.225% True None
box1 None 0.0013058186 Error Infeasible None None 0% False None
ceria3d 0.0009899139 0.0020847321 Infeasible Infeasible None None 110.597% True None
chemcom 0.0065031052 0.0013661385 Infeasible Infeasible None None -78.9925% True None
cplex2 0.0272738934 0.019302845 Unbounded Infeasible None None -29.2259% False None
ex72a None 0.0019464493 Error Infeasible None None 0% False None
ex73a None 0.0022170544 Error Infeasible None None 0% False None
forest6 0.0062012672 0.0022940636 Infeasible Infeasible None None -63.0065% True None
galenet 0.0002186298 0.000223875 Infeasible Infeasible None None 2.39912% True None
gosh 0.0169422626 0.0176627636 Infeasible Infeasible None None 4.25268% True None
gran 0.0006511211 0.000795126 Infeasible Infeasible None None 22.1165% True None
greenbea 0.0009961128 0.0008280277 Infeasible Infeasible None None -16.8741% True None
itest2 0.0001220703 0.0001382828 Infeasible Infeasible None None 13.2813% True None
itest6 0.0003955364 0.0002739429 Infeasible Infeasible None None -30.7414% True None
klein1 0.0135667324 0.0071876049 Infeasible Infeasible None None -47.0204% True None
klein2 0.0142154694 0.0246012211 Infeasible Infeasible None None 73.0595% True None
klein3 0.0251629353 0.0241458416 Infeasible Infeasible None None -4.04203% True None
mondou2 0.0026745796 0.0022149086 Infeasible Infeasible None None -17.1867% True None
pang 0.0143818855 0.0259618759 Infeasible Infeasible None None 80.5179% True None
pilot4i 0.0001904964 0.0003423691 Infeasible Infeasible None None 79.7247% True None
qual 0.0098567009 0.0050554276 Infeasible Infeasible None None -48.7108% True None
reactor 0.0008440018 0.0006542206 Infeasible Infeasible None None -22.4859% True None
refinery 0.0084352493 0.0056781769 Infeasible Infeasible None None -32.6851% True None
vol1 0.0100765228 None Infeasible Error None None 0% False None
woodinfe 0.0001683235 9.01222e-05 Infeasible Infeasible None None -46.4589% True None
Scripts for those who want to follow along
# run_probs.sh
# HiGHS master, Release build, commit b8f0bb9
solvers='simplex ipm'
dirs='netlib infeas'
for d in $dirs; do
    echo "" > results.txt
    for problem in $d/*; do
        echo "====================== Problem $d/$problem ======================" >> results.txt
        for solver in $solvers; do
            echo "Solver = $solver" >> results.txt
            echo "solver = $solver" > myopts
            echo "time_limit = 60" >> myopts
            ./highs --options_file myopts $problem | grep 'Objective value\|HiGHS run time\|Model   status\|HiGHS status' >> results.txt
        done
    done
    python analyze.py
done
'''analyze.py -- rough n ready analysis of HiGHS LP runs'''

import re
import numpy as np


if __name__ == '__main__':
    regex = re.compile(r'====================== Problem (?P<DIR>\w+)\/(?P<PROBLEM>.+).mps ======================\nSolver = simplex\n((Model\s+status\s+:\s+(?P<SIMPLEX_STATUS>\w+)\n(Objective value\s+:\s+(?P<SIMPLEX_FUN>-?\d+\.\d+)e[+|-]\d+\n)?HiGHS run time\s+:\s+(?P<SIMPLEX_TIME>\d+\.\d+)\n)|(HiGHS status: (?P<SIMPLEX_HIGHS_STATUS>\w+)\n))Solver = ipm\n(Model\s+status\s+:\s+(?P<IPM_STATUS>\w+)\n((Objective value\s+:\s+(?P<IPM_FUN>-?\d+\.\d+)e[+|-]\d+\n)?HiGHS run time\s+:\s+(?P<IPM_TIME>\d+\.\d+))|(HiGHS status: (?P<IPM_HIGHS_STATUS>\w+)\n))', flags=re.MULTILINE)

    with open('results.txt', 'r') as fp:
        results = fp.read()

    matches = re.finditer(regex, results)
    print('PROBLEM | IPM_TIME | SIMPLEX_TIME | IPM_STATUS | SIMPLEX_STATUS | IPM_FUN | SIMPLEX_FUN | DS/IPM - 1 | STATUS DIFF | FUN DIFF')
    print('-- | -- | -- | -- | -- | -- | -- | -- | -- | --')
    for m in matches:
        try:
            fun_diff = np.allclose(float(m.group('SIMPLEX_FUN')), float(m.group('IPM_FUN')))
        except (IndexError, TypeError):
            fun_diff = 'None'
        try:
            ipm_status = m.group("IPM_STATUS")
            ipm_time = float(m.group('IPM_TIME'))
        except (IndexError, TypeError):
            ipm_status = m.group('IPM_HIGHS_STATUS')
            ipm_time = None
        try:
            simplex_status = m.group("SIMPLEX_STATUS")
            simplex_time = float(m.group('SIMPLEX_TIME'))
        except (IndexError, TypeError):
            simplex_status = m.group('SIMPLEX_HIGHS_STATUS')
            simplex_time = None

        if simplex_time and ipm_time:
            perc = (simplex_time / ipm_time - 1)*100
        else:
            perc = 0

        # it ain't pretty, but it gets it done
        print('%s' % m.group('PROBLEM') + ' | '
              '%s' % ipm_time + ' | '
              '%s' % simplex_time + ' | '
              '%s | %s' % (ipm_status, simplex_status) + ' | '
              '%s | %s' % (m.group("IPM_FUN"), m.group("SIMPLEX_FUN")) + ' | '
              '%g%%' % perc + ' | '
              '%s' % (ipm_status == simplex_status) + ' | '
              '%s' %  fun_diff)

@mdhaber
Copy link
Contributor

mdhaber commented Jan 19, 2021

Broadly I would say IPM seems like it runs faster than simplex on this problem set.

I think we need some of the more challenging problems to know for sure, because currently in your data DS/IPM - 1 is almost always negative, indicating that DS time < IPM time. Can you run these for some of the top problems in my list - QAP12/QAP15, STOCFOR3, DFL001, TRUSS, etc.?

@denis-bz
Copy link

Fwiw, I've run some of the Mittelmann benchmarks through HiGHS-ipm, with runtimes 5 .. 30 minutes or so:
see LP-benchmarks-Mittelmann-HiGHS with logfiles under my gists.

Which way is up ?

@jajhall
Copy link

jajhall commented Jan 19, 2021

Thanks for all this. Here are a few observations.

  • (Dual) simplex is fundamentally more reliable than Interior Point, particularly if LPs are infeasible or unbounded.
  • If users want bugs fixing in the Interior Point solver, it's very much harder since its author is no longer in the team.
  • My advice would be that the default should be simplex, but users should be told that if their problems take a long time to solve then they it might be good to try interior point.
  • HiGHS isn't going to run as fast as Gurobi for a long time, if ever.
  • SCIPopt is a MIP solver. It's native (simplex) LP solver is Soplex, and HiGHS simplex is faster than Soplex. Of open-source solvers, only Clp is faster than HiGHS. And we expect to close the gap
  • From my exchanges with denis-bz, I know about his distaste for the null-return after time-out, and accept that HiGHS produces a little too much output. The latter can soon be fixed, but the former is more time-consuming to do

Not a lot will happen with HiGHS simplex in the next couple of months, as I'm now teaching my course. The real action with HiGHS at the moment is the growing power of its MIP solver!

@mckib2
Copy link
Contributor

mckib2 commented Jan 20, 2021

Broadly I would say IPM seems like it runs faster than simplex on this problem set.

I think we need some of the more challenging problems to know for sure, because currently in your data DS/IPM - 1 is almost always negative, indicating that DS time < IPM time. Can you run these for some of the top problems in my list - QAP12/QAP15, STOCFOR3, DFL001, TRUSS, etc.?

There must be a problem with my scripts, the negative in the tables I provide indicate that IPM time < DS time.

  • QAP12 times out (>60sec) with DS but runs in 2.3033 seconds with IPM
  • QAP15 times out with DS but runs in 14.995 seconds with IPM
  • DFL001 throws an exception on current master (see BUG: Simplex/IPM crash ERGO-Code/HiGHS#442)
  • I can't for the life of me figure out how to compile the Fortran sources to generate MPS files for STOCFOR3 or TRUSS... Any pointers?

@mdhaber
Copy link
Contributor

mdhaber commented Jan 20, 2021

They are available here: http://www.numerical.rl.ac.uk/cute/netlib.html

Although the extension is SIF, i believe they're regular MPS format.

@mckib2
Copy link
Contributor

mckib2 commented Jan 20, 2021

Thanks @mdhaber , here are results from all the programs on that site:

AGG, BLEND, DFL001, GFRD-PNC, SIERRA all throw exceptions and are omitted from the table. Simplex seems a lot more competitive on this set.

PROBLEM IPM_TIME SIMPLEX_TIME IPM_STATUS SIMPLEX_STATUS IPM_FUN SIMPLEX_FUN DS/IPM - 1 STATUS DIFF FUN DIFF
netlib2/25FV47 0.1470820904 0.1837844849 Optimal Optimal 5.5018458883 5.5018458883 24.9537% True True
netlib2/80BAU3B 0.3827693462 0.1004018784 Optimal Optimal 9.8722419241 9.8722419241 -73.7696% True True
netlib2/ADLITTLE 0.0062909126 0.0031583309 Optimal Optimal 2.2549496316 2.2549496316 -49.7953% True True
netlib2/AFIRO 0.0018546581 0.0006144047 Optimal Optimal -4.6475314286 -4.6475314286 -66.8723% True True
netlib2/AGG2 0.0288982391 0.0053567886 Optimal Optimal -2.0239252356 -2.0239252356 -81.4633% True True
netlib2/AGG3 0.022115469 0.0092036724 Optimal Optimal 1.0312115935 1.0312115935 -58.3836% True True
netlib2/BANDM 0.0215656757 0.0132987499 Optimal Optimal -1.5862801845 -1.5862801845 -38.3337% True True
netlib2/BEACONFD 0.004617691 0.0034310818 Optimal Optimal 3.3592485807 3.3592485807 -25.697% True True
netlib2/BNL1 0.0552103519 0.0341472626 Optimal Optimal 1.9776295615 1.9776295615 -38.1506% True True
netlib2/BNL2 0.1334242821 0.0615165234 Optimal Optimal 1.8112365404 1.8112365404 -53.8941% True True
netlib2/BOEING1 0.0230183601 0.0098044872 Optimal Optimal -3.3521356751 -3.3521356751 -57.4058% True True
netlib2/BOEING2 0.010822773 0.0028347969 Optimal Optimal -3.1501872802 -3.1501872802 -73.8071% True True
netlib2/BORE3D 0.0065853596 0.0031967163 Optimal Optimal 1.3730803942 1.3730803942 -51.4572% True True
netlib2/BRANDY 0.0164489746 0.0063705444 Optimal Optimal 1.5185098965 1.5185098965 -61.2709% True True
netlib2/CAPRI 0.0136566162 0.0047326088 Optimal Optimal 2.6900129138 2.6900129138 -65.3457% True True
netlib2/CRE-A 0.3202803135 0.0762884617 Optimal Optimal 2.3595407061 2.3595407061 -76.1807% True True
netlib2/CRE-B 3.5974531174 2.0943713188 Optimal Optimal 2.3129639887 2.3129639887 -41.7818% True True
netlib2/CRE-C 0.2528235912 0.0636856556 Optimal Optimal 2.5275116141 2.5275116141 -74.8102% True True
netlib2/CRE-D 2.6680419445 1.205368042 Optimal Optimal 2.4454969765 2.4454969765 -54.822% True True
netlib2/CYCLE 0.2265508175 0.0458631516 Optimal Optimal -5.2263930249 -5.2263930249 -79.7559% True True
netlib2/CZPROB 0.0703005791 0.0170443058 Optimal Optimal 2.1851966989 2.1851966989 -75.7551% True True
netlib2/D2Q06C 0.6433255672 1.3775911331 Optimal Optimal 1.2278421081 1.2278421081 114.136% True True
netlib2/D6CUBE 0.4403264523 0.0964045525 Optimal Optimal 3.1549166667 3.1549166667 -78.1061% True True
netlib2/DEGEN2 0.0349373817 0.013119936 Optimal Optimal -1.4351780000 -1.4351780000 -62.4473% True True
netlib2/DEGEN3 0.2311573029 0.1208825111 Optimal Optimal -9.8729400000 -9.8729400000 -47.7055% True True
netlib2/E226 0.0167238712 0.0059974194 Optimal Optimal -1.1638929066 -1.1638929066 -64.1386% True True
netlib2/ETAMACRO 0.0212612152 0.0068535805 Optimal Optimal -7.5571523337 -7.5571523130 -67.7649% True True
netlib2/FFFFF800 0.0330922604 0.0071618557 Optimal Optimal 5.5567956482 5.5567956482 -78.3579% True True
netlib2/FINNIS 0.0214238167 0.0039961338 Optimal Optimal 1.7279106560 1.7279106560 -81.3472% True True
netlib2/FIT1D 0.0235753059 0.0069038868 Optimal Optimal -9.1463780924 -9.1463780924 -70.7156% True True
netlib2/FIT1P 0.0456521511 0.0442545414 Optimal Optimal 9.1463780924 9.1463780924 -3.06143% True True
netlib2/FIT2D 0.3182651997 0.0910618305 Optimal Optimal -6.8464293294 -6.8464293294 -71.3881% True True
netlib2/FIT2P 0.4003190994 1.3867065907 Optimal Optimal 6.8464293294 6.8464293294 246.4% True True
netlib2/FORPLAN 0.0248043537 0.0100970268 Optimal Optimal -6.6421896127 -6.6421896127 -59.2933% True True
netlib2/GANGES 0.0317771435 0.0129628181 Optimal Optimal -1.0958573613 -1.0958573613 -59.2071% True True
netlib2/GREENBEA 0.2575826645 0.1591598988 Infeasible Optimal None -7.2555248130 -38.2102% False None
netlib2/GREENBEB 0.3870840073 0.4439024925 Optimal Optimal -4.3022602612 -4.3022602612 14.6786% True True
netlib2/GROW15 0.0529303551 0.0597867966 Optimal Optimal -1.0687094129 -1.0687094129 12.9537% True True
netlib2/GROW22 0.0928366184 0.1078822613 Optimal Optimal -1.6083433648 -1.6083433648 16.2066% True True
netlib2/GROW7 0.0217726231 0.0133624077 Optimal Optimal -4.7787811815 -4.7787811815 -38.6275% True True
netlib2/ISRAEL 0.0188548565 0.0053124428 Optimal Optimal -8.9664482186 -8.9664482186 -71.8245% True True
netlib2/KB2 0.0040252209 0.0026240349 Optimal Optimal -1.7499001299 -1.7499001299 -34.8102% True True
netlib2/KEN-07 0.0345678329 0.0206410885 Optimal Optimal -6.7952044338 -6.7952044338 -40.2882% True True
netlib2/KEN-11 0.5569889545 0.1969752312 Optimal Optimal -6.9723822625 -6.9723822625 -64.6357% True True
netlib2/KEN-13 1.7041401863 0.6251370907 Optimal Optimal -1.0257394789 -1.0257394789 -63.3166% True True
netlib2/KEN-18 10.6808400154 5.0693204403 Optimal Optimal -5.2217025287 -5.2217025287 -52.5382% True True
netlib2/LOTFI 0.0108823776 0.0018007755 Optimal Optimal -2.5264706062 -2.5264706062 -83.4524% True True
netlib2/MAROS 0.0725240707 0.0331566334 Optimal Optimal -5.8063743701 -5.8063743701 -54.2819% True True
netlib2/MAROS-R7 0.7430620193 0.9961662292 Optimal Optimal 1.4971851665 1.4971851665 34.0623% True True
netlib2/MODSZK1 0.0486576557 0.0183568001 Optimal Optimal 3.2061972906 3.2061972906 -62.2736% True True
netlib2/NESM 0.1573624611 0.1132991314 Optimal Optimal 1.4076036488 1.4076036488 -28.0012% True True
netlib2/OSA-07 0.6857624054 0.3761591911 Optimal Optimal 5.3572251730 5.3572251730 -45.1473% True True
netlib2/OSA-14 2.0755908489 1.1563892365 Optimal Optimal 1.1064628447 1.1064628447 -44.2863% True True
netlib2/OSA-30 4.7951984406 5.5958559513 Optimal Optimal 2.1421398732 2.1421398732 16.6971% True True
netlib2/OSA-60 8.8828349113 28.1863703728 Optimal Optimal 4.0440725032 4.0440725032 217.313% True True
netlib2/PDS-02 0.1202168465 0.0261251926 Optimal Optimal 2.8857862010 2.8857862010 -78.2683% True True
netlib2/PDS-06 0.793582201 0.1704893112 Optimal Optimal 2.7761037600 2.7761037600 -78.5165% True True
netlib2/PDS-10 2.5077772141 0.4110636711 Optimal Optimal 2.6727094976 2.6727094976 -83.6084% True True
netlib2/PDS-20 7.7578623295 1.4728662968 Optimal Optimal 2.3821658640 2.3821658640 -81.0145% True True
netlib2/PEROLD 0.0833134651 0.076833725 Optimal Optimal -9.3807552782 -9.3807552782 -7.77754% True True
netlib2/PILOT4 0.0545151234 0.0507054329 Optimal Optimal -2.5811392589 -2.5811392589 -6.98832% True True
netlib2/PILOT87 2.5448973179 4.6683428288 Optimal Optimal 3.0171034733 3.0171034733 83.4393% True True
netlib2/PILOT-JA 0.1362094879 0.1058752537 Optimal Optimal -6.1131364656 -6.1131364656 -22.2703% True True
netlib2/PILOT 0.8683264256 1.169883728 Optimal Optimal -5.5748972928 -5.5748972928 34.7286% True True
netlib2/PILOTNOV 0.1352808475 0.122774601 Optimal Optimal -4.4972761882 -4.4972761882 -9.24465% True True
netlib2/PILOT-WE 0.1215929985 0.1602721214 Optimal Optimal -2.7201075328 -2.7201075328 31.8103% True True
netlib2/QAP8 0.1070311069 0.3941118717 Optimal Optimal 2.0350000000 2.0350000000 268.222% True True
netlib2/RECIPELP 0.0068964958 0.0013604164 Optimal Optimal -2.6661600000 -2.6661600000 -80.2738% True True
netlib2/SC105 0.008759737 0.0047972202 Optimal Optimal -5.2202061212 -5.2202061212 -45.2356% True True
netlib2/SC205 0.015556097 0.0064382553 Optimal Optimal -5.2202061212 -5.2202061212 -58.6127% True True
netlib2/SC50A 0.0026831627 0.0013017654 Optimal Optimal -6.4575077059 -6.4575077059 -51.4839% True True
netlib2/SC50B 0.004206419 0.0023927689 Optimal Optimal -7.0000000000 -7.0000000000 -43.1162% True True
netlib2/SCAGR25 0.0280942917 0.017087698 Optimal Optimal -1.4753433061 -1.4753433061 -39.1773% True True
netlib2/SCAGR7 0.0116407871 0.0048620701 Optimal Optimal -2.3313898243 -2.3313898243 -58.2325% True True
netlib2/SCFXM1 0.0357644558 0.0151097775 Optimal Optimal 1.8416759028 1.8416759028 -57.752% True True
netlib2/SCFXM2 0.0390408039 0.043596983 Optimal Optimal 3.6660261565 3.6660261565 11.6703% True True
netlib2/SCFXM3 0.055290699 0.0425653458 Optimal Optimal 5.4901254550 5.4901254550 -23.0154% True True
netlib2/SCORPION 0.0073137283 0.0072283745 Optimal Optimal 1.8781248227 1.8781248227 -1.16704% True True
netlib2/SCRS8 0.022295475 0.0228662491 Optimal Optimal 9.0429695380 9.0429695380 2.56004% True True
netlib2/SCSD1 0.0156433582 0.0101511478 Optimal Optimal 8.6666666743 8.6666666743 -35.1089% True True
netlib2/SCSD6 0.0202934742 0.022289753 Optimal Optimal 5.0500000077 5.0500000078 9.83705% True True
netlib2/SCSD8 0.046271801 0.0510308743 Optimal Optimal 9.0499999993 9.0499999993 10.285% True True
netlib2/SCTAP1 0.0205540657 0.0185205936 Optimal Optimal 1.4122500000 1.4122500000 -9.89328% True True
netlib2/SCTAP2 0.0503768921 0.0273611546 Optimal Optimal 1.7248071429 1.7248071429 -45.6871% True True
netlib2/SCTAP3 0.0632100105 0.0160081387 Optimal Optimal 1.4240000000 1.4240000000 -74.6747% True True
netlib2/SEBA 0.0301721096 0.0297825336 Optimal Optimal 1.5711600000 1.5711600000 -1.29118% True True
netlib2/SHARE1B 0.0179543495 0.0100047588 Optimal Optimal -7.6589318579 -7.6589318579 -44.2767% True True
netlib2/SHARE2B 0.0151331425 0.0074601173 Optimal Optimal -4.1573224074 -4.1573224074 -50.7034% True True
netlib2/SHELL 0.0211365223 0.00558424 Optimal Optimal 1.2088253460 1.2088253460 -73.5801% True True
netlib2/SHIP04L 0.0233538151 0.0162642002 Optimal Optimal 1.7933245380 1.7933245380 -30.3574% True True
netlib2/SHIP04S 0.0139832497 0.004327774 Optimal Optimal 1.7987147004 1.7987147004 -69.0503% True True
netlib2/SHIP08L 0.0363335609 0.019598484 Optimal Optimal 1.9090552114 1.9090552114 -46.0596% True True
netlib2/SHIP08S 0.0191073418 0.0160377026 Optimal Optimal 1.9200982105 1.9200982105 -16.0652% True True
netlib2/SHIP12L 0.0451352596 0.021394968 Optimal Optimal 1.4701879193 1.4701879193 -52.5981% True True
netlib2/SHIP12S 0.0218532085 0.0105743408 Optimal Optimal 1.4892361344 1.4892361344 -51.612% True True
netlib2/STAIR 0.0351769924 0.0246686935 Optimal Optimal -2.5126695119 -2.5126695119 -29.8726% True True
netlib2/STANDATA 0.0404434204 0.0129902363 Optimal Optimal 1.2576995000 1.2576995000 -67.8805% True True
netlib2/STANDGUB 0.0601873398 0.0112917423 Optimal Optimal 1.2576995000 1.2576995000 -81.239% True True
netlib2/STANDMPS 0.0236985683 0.0073950291 Optimal Optimal 1.4060175000 1.4060175000 -68.7955% True True
netlib2/STOCFOR1 0.0129446983 0.0054383278 Optimal Optimal -4.1131976219 -4.1131976219 -57.988% True True
netlib2/STOCFOR2 0.0545976162 0.0551199913 Optimal Optimal -3.9024408538 -3.9024408538 0.956773% True True
netlib2/STOCFOR3 1.3277184963 0.3356781006 Optimal Optimal -3.9976783944 -3.9976783944 -74.7177% True True
netlib2/TRUSS 0.132188797 3.3362779617 Infeasible Optimal None 4.5881584719 2423.87% False None
netlib2/TUFF 0.026761055 0.0108594894 Optimal Optimal 2.9214776509 2.9214776509 -59.4205% True True
netlib2/VTP-BASE 0.0035638809 0.0016112328 Optimal Optimal 1.2983146246 1.2983146246 -54.7899% True True
netlib2/WOOD1P 0.2469174862 0.030287981 Optimal Optimal 1.4429024116 1.4429024116 -87.7336% True True
netlib2/WOODW 0.2298738956 0.0663883686 Optimal Optimal 1.3044763331 1.3044763331 -71.1197% True True

@mdhaber
Copy link
Contributor

mdhaber commented Jan 20, 2021

Yup. Definitely more reliable. I think we should leave the behavior of method='highs' alone, and the documentation already mentions that which is faster is problem-dependent. Let's just remember to consider making method='highs' the default before the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
query A question or suggestion that requires further information
Projects
None yet
Development

No branches or pull requests

6 participants