[FEATURE]: Add support for HiGHS
Feature Request
Add support for HiGHS solver. Looking at HiGHS documentation, and think it will be fairly straightforward as HiGHS will print out data in similar (or same!) format as other solvers!
I have supplied the the formats I think will be useful below, but dont really suggest a path forward. Originally I was thinking that the GLPK format would be best, since we have logic to process it currently. But having to supply the .lp file for this as an additional argument is a pain. So maybe just using the raw HiGHS format (last option) would be best.
Is your feature related to a bug?
No response
Suggested Solution
setup
I will assume that the user has a generic .lp file to start with. If you run this code, making sure to specify the integer value in the writeSolution call (see here for options)
import highspy
h = highspy.Highs()
filename = 'model.lp'
h.readModel(filename)
h.run()
h.writeSolution("highs.sol", 0)
GLPK Format
if the user specifies a 2 (ie. h.writeSolution("highs.sol", 2)) the output format will be identical to GLPK. While otoole can currently process GLPK, the user does also have to pass in the .lp file, which is a bit of a pain.
GLPK Output
c Problem: OSeMOSYS
c Rows: 293715
c Columns: 366745
c Non-zeros: 794822
c Status: OPTIMAL
c Objective: cost = 4497.31967 (MINimum)
c
s bas 293715 366745 f f 4497.31967015205
i 1 b 4497.31967015205 0
i 2 s -1.59376124775045 -2.68631688302325
i 3 s -1.60167966406719 -2.55839703145071
i 4 s -1.6369526094781 -2.43656860138163
i 5 s -1.68590281943611 -2.32054152512536
HiGHS Output
(Identical to GLPK!)
c Problem: model
c Rows: 293715
c Columns: 366745
c Non-zeros: 794822
c Status: OPTIMAL
c Objective: cost = 4497.31967 (MINimum)
c
s bas 293715 366745 f f 4497.319670152045
i 1 s -1.5937612477504 -2.6863168830232
i 2 s -1.6016796640672 -2.5583970314507
i 3 s -1.6369526094781 -2.4365686013816
i 4 s -1.6859028194361 -2.3205415251254
i 5 s -1.7463707258548 -2.2100395477384
CBC Format
if the user specifies a 0 (ie. h.writeSolution("highs.sol", 0)) the output format will be very similar to CBC. HiGHS does write out all the zeros if using the 0, else if you supply a 4, the zeros are removed.
HiGHS output
Model status
Optimal
# Primal solution values
Feasible
Objective 4497.319670152045
# Columns 366745
TotalDiscountedCost(SIMPLICITY,2014) 193.6038541621821
TotalDiscountedCost(SIMPLICITY,2015) 187.7238605093666
TotalDiscountedCost(SIMPLICITY,2016) 183.997629568643
TotalDiscountedCost(SIMPLICITY,2017) 181.7275229818637
TotalDiscountedCost(SIMPLICITY,2018) 218.7360421598646
CBC output
Optimal - objective value 4497.31967015
0 TotalDiscountedCost(SIMPLICITY,2014) 193.60385 0
1 TotalDiscountedCost(SIMPLICITY,2015) 187.72386 0
2 TotalDiscountedCost(SIMPLICITY,2016) 183.99763 0
3 TotalDiscountedCost(SIMPLICITY,2017) 181.72752 0
4 TotalDiscountedCost(SIMPLICITY,2018) 218.73604 0
HiGHS Format
Alternatively, if the user specifies a 1, (ie. h.writeSolution("highs.sol", 1)), the format provided below can allow us to easily extract out dual values and similar (see issue #191). We could just add logic to process this and then use the existing ReadWideResults class methods to finalize processing.
Columns
Index Status Lower Upper Primal Dual Type Name
0 BS 0 inf 193.604 0 Continuous TotalDiscountedCost(SIMPLICITY,2014)
1 BS 0 inf 187.724 0 Continuous TotalDiscountedCost(SIMPLICITY,2015)
2 BS 0 inf 183.998 0 Continuous TotalDiscountedCost(SIMPLICITY,2016)
3 BS 0 inf 181.728 0 Continuous TotalDiscountedCost(SIMPLICITY,2017)
4 BS 0 inf 218.736 0 Continuous TotalDiscountedCost(SIMPLICITY,2018)
Additional Info
No response