opencobra / optlang

optlang - sympy based mathematical programming language
http://optlang.readthedocs.org/
Apache License 2.0
244 stars 51 forks source link

Replace OSQP with a hybrid HIGHS/OSQP solver interface #256

Closed cdiener closed 11 months ago

cdiener commented 1 year ago

This is a proposal for a new interface that leverages the matrix interface to combine HIGHS and OSQP in a general purpose large problem solver. This was designed with MICOM in mind, so I am not completely sure whether it's in scope here (see pro-con below). It passes all the generic tests in optlang and also the full COBRAPY suite.

Pro

Cons

So let me know what you think.

COBRAPY tests and benchmarks

``` ==================================================================== test session starts ==================================================================== platform linux -- Python 3.11.5, pytest-7.3.0, pluggy-1.0.0 benchmark: 4.0.0 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000) rootdir: /home/cdiener/code/cobrapy configfile: tox.ini testpaths: tests plugins: cov-4.0.0, mock-3.10.0, anyio-3.6.2, benchmark-4.0.0 collected 670 items tests/test_core/test_configuration.py ...... [ 0%] tests/test_core/test_core_reaction.py ...........s.........................................x....... [ 10%] tests/test_core/test_dictlist.py ...................... [ 13%] tests/test_core/test_formula.py ..... [ 14%] tests/test_core/test_gene.py . [ 14%] tests/test_core/test_gpr.py .....................x..x............................................. [ 24%] tests/test_core/test_group.py .. [ 24%] tests/test_core/test_metabolite.py ....s..s. [ 26%] tests/test_core/test_model.py ...............................................................s. [ 35%] tests/test_core/test_solution.py ..s [ 36%] tests/test_flux_analysis/test_deletion.py ....s..... [ 37%] tests/test_flux_analysis/test_fastcc.py .... [ 38%] tests/test_flux_analysis/test_geometric.py .. [ 38%] tests/test_flux_analysis/test_moma.py . [ 38%] tests/test_flux_analysis/test_parsimonious.py .. [ 39%] tests/test_flux_analysis/test_reaction.py . [ 39%] tests/test_flux_analysis/test_room.py .... [ 40%] tests/test_flux_analysis/test_variability.py ....... [ 41%] tests/test_flux_analysis/test_deletion.py .......... [ 42%] tests/test_flux_analysis/test_fastcc.py .... [ 43%] tests/test_flux_analysis/test_geometric.py .. [ 43%] tests/test_flux_analysis/test_moma.py . [ 43%] tests/test_flux_analysis/test_parsimonious.py .. [ 43%] tests/test_flux_analysis/test_reaction.py . [ 44%] tests/test_flux_analysis/test_room.py .... [ 44%] tests/test_flux_analysis/test_variability.py ....... [ 45%] tests/test_flux_analysis/test_deletion.py .......... [ 47%] tests/test_flux_analysis/test_fastcc.py .... [ 47%] tests/test_flux_analysis/test_geometric.py .. [ 48%] tests/test_flux_analysis/test_moma.py . [ 48%] tests/test_flux_analysis/test_parsimonious.py .. [ 48%] tests/test_flux_analysis/test_reaction.py . [ 48%] tests/test_flux_analysis/test_room.py .... [ 49%] tests/test_flux_analysis/test_variability.py ....... [ 50%] tests/test_flux_analysis/test_deletion.py ... [ 50%] tests/test_flux_analysis/test_moma.py . [ 50%] tests/test_flux_analysis/test_deletion.py ... [ 51%] tests/test_flux_analysis/test_moma.py . [ 51%] tests/test_flux_analysis/test_deletion.py ...... [ 52%] tests/test_flux_analysis/test_gapfilling.py . [ 52%] tests/test_flux_analysis/test_helpers.py ... [ 52%] tests/test_flux_analysis/test_loopless.py ....... [ 54%] tests/test_flux_analysis/test_phenotype_phase_plane.py ...... [ 54%] tests/test_flux_analysis/test_variability.py ....... [ 55%] tests/test_io/test_annotation.py .. [ 56%] tests/test_io/test_annotation_format.py .. [ 56%] tests/test_io/test_io_order.py ........................... [ 60%] tests/test_io/test_json.py .... [ 61%] tests/test_io/test_mat.py ............... [ 63%] tests/test_io/test_notes.py . [ 63%] tests/test_io/test_pickle.py .. [ 63%] tests/test_io/test_sbml.py .ssss............xxxx.x.x..s............. [ 70%] tests/test_io/test_yaml.py .x [ 70%] tests/test_io/test_web/test_load.py ....... [ 71%] tests/test_manipulation/test_annotate.py . [ 71%] tests/test_manipulation/test_delete.py ....... [ 72%] tests/test_manipulation/test_modify.py ... [ 72%] tests/test_manipulation/test_validate.py .. [ 73%] tests/test_medium/test_boundary_types.py ......... [ 74%] tests/test_medium/test_minimal_medium.py .......... [ 76%] tests/test_sampling/test_achr.py ...... [ 77%] tests/test_sampling/test_optgp.py ...... [ 77%] tests/test_sampling/test_sampling.py .......... [ 79%] tests/test_summary/test_metabolite_summary.py ................. [ 81%] tests/test_summary/test_model_summary.py ............... [ 84%] tests/test_summary/test_reaction_summary.py ........... [ 85%] tests/test_summary/test_metabolite_summary.py ................. [ 88%] tests/test_summary/test_model_summary.py ............... [ 90%] tests/test_summary/test_reaction_summary.py .................... [ 93%] tests/test_util/test_array.py .. [ 93%] tests/test_util/test_context.py ... [ 94%] tests/test_util/test_process_pool.py ............... [ 96%] tests/test_util/test_solver.py ................... [ 99%] tests/test_util/test_util.py .... [100%] ===================================================================== warnings summary ====================================================================== ../optlang/src/optlang/matrix_interface.py:60 /home/cdiener/code/optlang/src/optlang/matrix_interface.py:60: DeprecationWarning: invalid escape sequence '\m' """A representation of the convex optimizatgion problem in standard form. tests/test_core/test_gpr.py::test_and_gpr[a AND b-2-gpr_genes2-a and b] tests/test_core/test_gpr.py::test_gpr_equality_with_bolean_logic[a_and_b_strs] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists0] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists1] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists2] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists3] /home/cdiener/code/cobrapy/src/cobra/core/gene.py:358: SyntaxWarning: Uppercase AND/OR found in rule 'a AND b'. warn( tests/test_core/test_gpr.py::test_or_gpr[a OR b-2-gpr_genes2-a or b] tests/test_core/test_gpr.py::test_gpr_as_symbolic_boolean[a OR b-symbolic_gpr2] tests/test_core/test_gpr.py::test_gpr_equality_with_bolean_logic[a_or_b_strs] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists0] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists4] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists5] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists6] tests/test_core/test_gpr.py::test_gpr_from_symbolic[a OR b-symbolic_gpr5] /home/cdiener/code/cobrapy/src/cobra/core/gene.py:358: SyntaxWarning: Uppercase AND/OR found in rule 'a OR b'. warn( tests/test_core/test_gpr.py::test_complicated_gpr[(a OR b) AND c] tests/test_core/test_gpr.py::test_gpr_as_symbolic_boolean[(a OR b) AND c-symbolic_gpr6] tests/test_core/test_gpr.py::test_gpr_equality_with_bolean_logic[a_b_c_or_and_strs] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists3] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists6] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists8] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists9] tests/test_core/test_gpr.py::test_gpr_from_symbolic[(a OR b) AND c-symbolic_gpr9] /home/cdiener/code/cobrapy/src/cobra/core/gene.py:358: SyntaxWarning: Uppercase AND/OR found in rule '(a OR b) AND c'. warn( tests/test_core/test_gpr.py::test_gpr_that_needs_two_replacements /home/cdiener/code/cobrapy/src/cobra/core/gene.py:358: SyntaxWarning: Uppercase AND/OR found in rule '(591001.3.peg.1891 AND 591001.3.peg.1892 AND 591001.3.peg.1893)'. warn( tests/test_core/test_gpr.py::test_gpr_equality_with_bolean_logic[a_and_b_strs] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists0] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists1] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists2] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists3] /home/cdiener/code/cobrapy/src/cobra/core/gene.py:358: SyntaxWarning: Uppercase AND/OR found in rule 'b AND a'. warn( tests/test_core/test_gpr.py::test_gpr_equality_with_bolean_logic[a_or_b_strs] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists0] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists4] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists5] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists6] /home/cdiener/code/cobrapy/src/cobra/core/gene.py:358: SyntaxWarning: Uppercase AND/OR found in rule 'b OR a'. warn( tests/test_core/test_gpr.py::test_gpr_equality_with_bolean_logic[a_b_c_or_strs] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists1] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists4] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists7] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists8] /home/cdiener/code/cobrapy/src/cobra/core/gene.py:358: SyntaxWarning: Uppercase AND/OR found in rule 'a OR b or c'. warn( tests/test_core/test_gpr.py::test_gpr_equality_with_bolean_logic[a_b_c_and_strs] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists2] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists5] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists7] tests/test_core/test_gpr.py::test_gpr_inequality_boolean[gpr_lists9] /home/cdiener/code/cobrapy/src/cobra/core/gene.py:358: SyntaxWarning: Uppercase AND/OR found in rule 'a AND b and c'. warn( tests/test_core/test_model.py::test_reaction_delete tests/test_core/test_model.py::test_reaction_delete /home/cdiener/code/cobrapy/src/cobra/core/reaction.py:879: DeprecationWarning: delete is deprecated. Use reaction.remove_from_model instead warn( tests/test_core/test_model.py::test_group_loss_of_elements tests/test_flux_analysis/test_gapfilling.py::test_gapfilling /home/cdiener/code/cobrapy/src/cobra/core/group.py:147: UserWarning: need to pass in a list warn("need to pass in a list") tests/test_core/test_model.py::test_change_objective tests/test_core/test_model.py::test_change_objective tests/test_core/test_model.py::test_change_objective /home/cdiener/code/cobrapy/src/cobra/core/reaction.py:761: DeprecationWarning: Please use reaction.flux instead. warn("Please use reaction.flux instead.", DeprecationWarning) tests/test_io/test_json.py: 6 warnings tests/test_io/test_mat.py: 14 warnings tests/test_io/test_pickle.py: 2 warnings tests/test_io/test_sbml.py: 18 warnings tests/test_io/test_yaml.py: 2 warnings /home/cdiener/code/cobrapy/src/cobra/util/solver.py:554: UserWarning: Solver status is 'infeasible'. warn(f"Solver status is '{status}'.", UserWarning) tests/test_medium/test_minimal_medium.py: 338 warnings /home/cdiener/code/cobrapy/src/cobra/medium/minimal_medium.py:112: FutureWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning. medium = pd.Series() tests/test_util/test_process_pool.py::test_with_context /home/cdiener/code/cobrapy/src/cobra/util/process_pool.py:72: PytestMockWarning: Mocks returned by pytest-mock do not need to be used as context managers. The mocker fixture automatically undoes mocking at the end of a test. This warning can be ignored if it was triggered by mocking a context manager. https://pytest-mock.readthedocs.io/en/latest/remarks.html#usage-as-context-manager self._pool.__enter__() -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html ------------------------------------------------------------------------------------------------------------------------------ benchmark: 56 tests ------------------------------------------------------------------------------------------------------------------------------- Name (time in us) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- test_subtract_metabolite_benchmark[glpk] 2.2940 (1.0) 41.6790 (1.75) 2.7088 (1.0) 1.6004 (1.36) 2.5470 (1.0) 0.2420 (1.0) 62;217 369,171.1731 (1.0) 5147 1 test_subtract_metabolite_benchmark[gurobi] 2.3040 (1.00) 23.8300 (1.0) 3.1370 (1.16) 1.2766 (1.08) 2.7490 (1.08) 0.3728 (1.54) 547;745 318,776.9995 (0.86) 5171 1 test_subtract_metabolite_benchmark[cplex] 2.3270 (1.01) 29.6590 (1.24) 3.0719 (1.13) 1.1784 (1.0) 2.8710 (1.13) 0.4440 (1.83) 161;264 325,527.3538 (0.88) 4861 1 test_change_objective_benchmark[optlang-glpk] 93.7590 (40.87) 1,045.8220 (43.89) 115.6829 (42.71) 40.7843 (34.61) 105.6195 (41.47) 17.7575 (73.38) 393;602 8,644.3185 (0.02) 6488 1 test_change_objective_benchmark[optlang-cplex] 167.4180 (72.98) 664.0410 (27.87) 198.0228 (73.10) 68.6797 (58.28) 172.5510 (67.75) 31.7868 (131.35) 5;7 5,049.9224 (0.01) 71 1 test_achr_sample_benchmark 285.6440 (124.52) 12,066.5810 (506.36) 613.6580 (226.54) 1,518.5459 (>1000.0) 417.2535 (163.82) 136.0595 (562.23) 8;9 1,629.5722 (0.00) 336 1 test_optgp_sample_benchmark 318.7220 (138.94) 1,453.9940 (61.02) 439.3567 (162.20) 123.3586 (104.68) 380.6855 (149.46) 252.9545 (>1000.0) 292;1 2,276.0552 (0.01) 1028 1 test_loopless_benchmark_after 856.9130 (373.55) 1,914.0690 (80.32) 932.6770 (344.32) 89.8059 (76.21) 912.2280 (358.16) 57.6123 (238.07) 48;42 1,072.1825 (0.00) 835 1 test_loopless_benchmark_before 982.1810 (428.15) 2,895.7210 (121.52) 1,125.2880 (415.42) 148.0538 (125.64) 1,084.9300 (425.96) 71.4895 (295.41) 46;50 888.6614 (0.00) 543 1 test_minimal_medium_mip_benchmark 5,000.9720 (>1000.0) 11,344.0710 (476.04) 5,979.3052 (>1000.0) 1,010.8075 (857.75) 5,577.5295 (>1000.0) 605.6295 (>1000.0) 16;16 167.2435 (0.00) 152 1 test_minimal_medium_linear_benchmark 5,014.5100 (>1000.0) 13,586.2740 (570.13) 6,196.1172 (>1000.0) 1,249.0836 (>1000.0) 5,673.4300 (>1000.0) 1,269.3137 (>1000.0) 22;10 161.3914 (0.00) 171 1 test_copy_benchmark[optlang-glpk] 7,775.1690 (>1000.0) 233,973.5810 (>1000.0) 12,314.2383 (>1000.0) 22,097.1067 (>1000.0) 10,021.4950 (>1000.0) 1,900.2120 (>1000.0) 1;1 81.2068 (0.00) 103 1 test_copy_benchmark[optlang-cplex] 8,192.3830 (>1000.0) 188,663.0290 (>1000.0) 14,563.4414 (>1000.0) 27,913.1416 (>1000.0) 10,097.4170 (>1000.0) 1,617.4582 (>1000.0) 1;3 68.6651 (0.00) 41 1 test_deepcopy_benchmark 14,818.1790 (>1000.0) 341,512.8770 (>1000.0) 22,460.2896 (>1000.0) 40,571.6102 (>1000.0) 17,043.4845 (>1000.0) 1,779.8940 (>1000.0) 1;5 44.5230 (0.00) 64 1 test_gpr_equality_benchmark 19,512.2750 (>1000.0) 27,561.2190 (>1000.0) 20,760.3585 (>1000.0) 1,596.3958 (>1000.0) 20,329.4905 (>1000.0) 1,003.6905 (>1000.0) 5;5 48.1687 (0.00) 44 1 test_single_reaction_deletion_benchmark[glpk] 24,949.6810 (>1000.0) 39,783.2670 (>1000.0) 28,757.6977 (>1000.0) 4,220.5987 (>1000.0) 26,283.3280 (>1000.0) 6,584.3122 (>1000.0) 7;0 34.7733 (0.00) 35 1 test_fastcc_benchmark[cplex] 26,375.8290 (>1000.0) 29,994.9120 (>1000.0) 27,830.2230 (>1000.0) 960.0516 (814.68) 27,425.7610 (>1000.0) 1,428.6313 (>1000.0) 8;0 35.9322 (0.00) 31 1 test_fastcc_benchmark[glpk] 27,192.8950 (>1000.0) 36,070.9660 (>1000.0) 30,657.0597 (>1000.0) 2,188.4312 (>1000.0) 30,429.1620 (>1000.0) 3,345.3580 (>1000.0) 13;0 32.6189 (0.00) 32 1 test_single_gene_deletion_moma_benchmark[cplex] 27,316.7860 (>1000.0) 40,653.3360 (>1000.0) 29,405.6284 (>1000.0) 2,388.0167 (>1000.0) 28,958.4930 (>1000.0) 1,984.2020 (>1000.0) 2;1 34.0071 (0.00) 32 1 test_single_gene_deletion_linear_moma_benchmark[glpk] 29,020.0350 (>1000.0) 42,259.8270 (>1000.0) 32,428.5570 (>1000.0) 2,789.7775 (>1000.0) 31,926.0450 (>1000.0) 3,058.6935 (>1000.0) 9;1 30.8370 (0.00) 29 1 test_single_gene_deletion_linear_room_benchmark[cplex] 29,797.8000 (>1000.0) 36,418.9160 (>1000.0) 31,571.9718 (>1000.0) 1,871.9644 (>1000.0) 30,884.4510 (>1000.0) 1,969.3680 (>1000.0) 4;2 31.6737 (0.00) 26 1 test_single_gene_deletion_linear_room_benchmark[glpk] 30,084.9770 (>1000.0) 40,439.0320 (>1000.0) 31,899.7990 (>1000.0) 2,381.5916 (>1000.0) 31,442.5100 (>1000.0) 1,983.5260 (>1000.0) 2;2 31.3482 (0.00) 34 1 test_single_gene_deletion_linear_moma_benchmark[cplex] 30,318.9700 (>1000.0) 47,109.7660 (>1000.0) 34,200.8932 (>1000.0) 4,610.8317 (>1000.0) 32,318.3530 (>1000.0) 4,807.6578 (>1000.0) 2;2 29.2390 (0.00) 25 1 test_single_reaction_deletion_benchmark[cplex] 39,403.7990 (>1000.0) 42,882.9550 (>1000.0) 40,963.0930 (>1000.0) 860.1422 (729.90) 40,812.3240 (>1000.0) 989.7122 (>1000.0) 5;0 24.4122 (0.00) 23 1 test_fastcc_benchmark[hybrid] 45,097.8010 (>1000.0) 48,174.6180 (>1000.0) 46,268.7677 (>1000.0) 844.4191 (716.55) 46,235.3120 (>1000.0) 1,249.0205 (>1000.0) 7;0 21.6129 (0.00) 19 1 test_add_metabolite_benchmark[glpk] 47,883.7340 (>1000.0) 52,183.0690 (>1000.0) 49,432.3566 (>1000.0) 1,124.5969 (954.31) 49,502.9490 (>1000.0) 1,613.4523 (>1000.0) 8;0 20.2297 (0.00) 21 1 test_add_metabolite_benchmark[cplex] 47,917.3350 (>1000.0) 54,370.6840 (>1000.0) 49,333.9763 (>1000.0) 1,511.0800 (>1000.0) 48,942.5195 (>1000.0) 969.4290 (>1000.0) 2;2 20.2700 (0.00) 18 1 test_add_metabolite_benchmark[gurobi] 48,237.0580 (>1000.0) 52,046.7320 (>1000.0) 49,559.0800 (>1000.0) 1,070.3856 (908.30) 49,126.7300 (>1000.0) 1,229.6935 (>1000.0) 5;1 20.1779 (0.00) 20 1 test_flux_variability_benchmark[cplex] 62,572.2430 (>1000.0) 67,038.3950 (>1000.0) 63,772.4243 (>1000.0) 1,536.4200 (>1000.0) 63,433.0310 (>1000.0) 1,197.2452 (>1000.0) 1;1 15.6808 (0.00) 7 1 test_pfba_benchmark[cplex] 69,373.4100 (>1000.0) 72,500.4950 (>1000.0) 70,726.8981 (>1000.0) 1,150.6451 (976.41) 70,255.0820 (>1000.0) 1,765.2030 (>1000.0) 3;0 14.1389 (0.00) 7 1 test_single_gene_deletion_fba_benchmark[glpk] 71,984.7330 (>1000.0) 101,895.6180 (>1000.0) 84,120.6408 (>1000.0) 10,542.5950 (>1000.0) 81,724.0980 (>1000.0) 17,880.6290 (>1000.0) 5;0 11.8877 (0.00) 13 1 test_flux_variability_loopless_benchmark[glpk] 87,341.3150 (>1000.0) 98,250.1150 (>1000.0) 92,035.9655 (>1000.0) 3,734.7568 (>1000.0) 92,681.6800 (>1000.0) 6,607.9350 (>1000.0) 4;0 10.8653 (0.00) 10 1 test_single_gene_deletion_linear_moma_benchmark[hybrid] 89,488.5290 (>1000.0) 98,569.1990 (>1000.0) 93,464.3613 (>1000.0) 3,368.9686 (>1000.0) 92,577.7580 (>1000.0) 6,140.8090 (>1000.0) 4;0 10.6993 (0.00) 10 1 test_single_gene_deletion_linear_room_benchmark[hybrid] 89,873.4130 (>1000.0) 111,261.5240 (>1000.0) 99,264.7753 (>1000.0) 7,729.0775 (>1000.0) 96,084.0400 (>1000.0) 11,888.2920 (>1000.0) 3;0 10.0741 (0.00) 9 1 test_single_gene_deletion_fba_benchmark[cplex] 94,007.7240 (>1000.0) 125,803.0550 (>1000.0) 109,609.7511 (>1000.0) 9,708.6572 (>1000.0) 109,267.7025 (>1000.0) 10,994.1460 (>1000.0) 4;0 9.1233 (0.00) 10 1 test_flux_variability_loopless_benchmark[cplex] 101,279.8200 (>1000.0) 127,426.1190 (>1000.0) 115,119.6169 (>1000.0) 8,934.3517 (>1000.0) 115,994.7180 (>1000.0) 15,209.3568 (>1000.0) 5;0 8.6866 (0.00) 11 1 test_single_gene_deletion_fba_benchmark[hybrid] 108,592.5740 (>1000.0) 128,052.1530 (>1000.0) 114,276.8117 (>1000.0) 6,564.1222 (>1000.0) 112,137.3330 (>1000.0) 6,858.0570 (>1000.0) 2;1 8.7507 (0.00) 9 1 test_achr_init_benchmark 111,644.4430 (>1000.0) 259,542.5750 (>1000.0) 189,091.9971 (>1000.0) 40,641.7804 (>1000.0) 188,813.5120 (>1000.0) 28,185.8560 (>1000.0) 3;2 5.2884 (0.00) 10 1 test_flux_variability_loopless_benchmark[hybrid] 137,303.4070 (>1000.0) 172,634.0580 (>1000.0) 144,482.7328 (>1000.0) 11,939.1357 (>1000.0) 138,924.5685 (>1000.0) 7,516.0970 (>1000.0) 1;1 6.9212 (0.00) 8 1 test_geometric_fba_benchmark[cplex] 159,985.5510 (>1000.0) 177,495.7960 (>1000.0) 164,643.3833 (>1000.0) 6,773.4833 (>1000.0) 162,194.5010 (>1000.0) 5,778.3530 (>1000.0) 1;1 6.0737 (0.00) 6 1 test_gpr_symbolism_benchmark 160,644.6840 (>1000.0) 167,942.6390 (>1000.0) 164,815.3687 (>1000.0) 2,588.9621 (>1000.0) 164,865.6390 (>1000.0) 3,398.7670 (>1000.0) 2;0 6.0674 (0.00) 6 1 test_double_gene_deletion_benchmark 167,696.1570 (>1000.0) 175,797.2720 (>1000.0) 172,594.0390 (>1000.0) 3,088.6810 (>1000.0) 173,200.2620 (>1000.0) 3,847.0258 (>1000.0) 2;0 5.7939 (0.00) 5 1 test_pfba_benchmark[glpk] 172,922.4480 (>1000.0) 183,506.8040 (>1000.0) 178,845.3286 (>1000.0) 3,971.8920 (>1000.0) 179,071.5260 (>1000.0) 5,179.9003 (>1000.0) 2;0 5.5914 (0.00) 5 1 test_optgp_init_benchmark 181,274.1330 (>1000.0) 295,439.2900 (>1000.0) 248,008.1180 (>1000.0) 47,964.6059 (>1000.0) 257,072.5880 (>1000.0) 80,119.2250 (>1000.0) 1;0 4.0321 (0.00) 5 1 test_geometric_fba_benchmark[glpk] 190,243.9940 (>1000.0) 205,950.4770 (>1000.0) 198,127.5766 (>1000.0) 7,351.6281 (>1000.0) 199,338.0600 (>1000.0) 14,028.5838 (>1000.0) 2;0 5.0473 (0.00) 5 1 test_copy_benchmark_large_model[optlang-cplex] 200,014.1030 (>1000.0) 479,692.8340 (>1000.0) 260,174.3876 (>1000.0) 122,820.0532 (>1000.0) 209,061.5160 (>1000.0) 78,163.3175 (>1000.0) 1;1 3.8436 (0.00) 5 1 test_copy_benchmark_large_model[optlang-glpk] 201,319.6950 (>1000.0) 431,441.0280 (>1000.0) 261,893.3830 (>1000.0) 96,839.3568 (>1000.0) 217,140.3780 (>1000.0) 91,585.1513 (>1000.0) 1;0 3.8183 (0.00) 5 1 test_pfba_benchmark[hybrid] 203,952.2130 (>1000.0) 569,494.7990 (>1000.0) 288,143.9220 (>1000.0) 157,503.4885 (>1000.0) 223,132.0900 (>1000.0) 96,671.7515 (>1000.0) 1;1 3.4705 (0.00) 5 1 test_single_reaction_deletion_benchmark[hybrid] 221,182.8530 (>1000.0) 244,393.6030 (>1000.0) 230,863.3204 (>1000.0) 8,749.2173 (>1000.0) 231,146.5540 (>1000.0) 10,639.3385 (>1000.0) 2;0 4.3316 (0.00) 5 1 test_single_gene_deletion_moma_benchmark[hybrid] 299,807.7240 (>1000.0) 307,206.4760 (>1000.0) 303,496.1998 (>1000.0) 2,679.2733 (>1000.0) 303,887.6140 (>1000.0) 2,964.3612 (>1000.0) 2;0 3.2949 (0.00) 5 1 test_flux_variability_benchmark[glpk] 346,637.4510 (>1000.0) 362,749.8540 (>1000.0) 356,306.9624 (>1000.0) 6,185.9668 (>1000.0) 356,477.0300 (>1000.0) 7,904.1225 (>1000.0) 2;0 2.8066 (0.00) 5 1 test_double_reaction_deletion_benchmark 539,117.0300 (>1000.0) 560,762.3910 (>1000.0) 550,230.1016 (>1000.0) 8,060.1946 (>1000.0) 551,997.7410 (>1000.0) 10,341.8253 (>1000.0) 2;0 1.8174 (0.00) 5 1 test_geometric_fba_benchmark[hybrid] 1,105,175.6980 (>1000.0) 1,346,059.5970 (>1000.0) 1,254,707.5488 (>1000.0) 93,848.3047 (>1000.0) 1,252,914.2670 (>1000.0) 115,573.2593 (>1000.0) 1;0 0.7970 (0.00) 5 1 test_flux_variability_benchmark[hybrid] 4,693,848.6870 (>1000.0) 5,364,513.7700 (>1000.0) 5,148,930.4578 (>1000.0) 280,675.3526 (>1000.0) 5,292,484.2370 (>1000.0) 369,828.9155 (>1000.0) 1;0 0.1942 (0.00) 5 1 test_single_gene_deletion_room_benchmark[cplex] 7,970,187.0850 (>1000.0) 8,966,477.0290 (>1000.0) 8,280,201.4938 (>1000.0) 422,268.7731 (>1000.0) 8,078,233.4040 (>1000.0) 567,589.4288 (>1000.0) 1;0 0.1208 (0.00) 5 1 test_single_gene_deletion_room_benchmark[hybrid] 39,582,174.2460 (>1000.0) 95,114,824.2720 (>1000.0) 69,713,440.2258 (>1000.0) 20,431,416.8946 (>1000.0) 73,131,111.6930 (>1000.0) 24,705,340.6650 (>1000.0) 2;0 0.0143 (0.00) 5 1 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Legend: Outliers: 1 Standard Deviation from Mean; 1.5 IQR (InterQuartile Range) from 1st Quartile and 3rd Quartile. OPS: Operations Per Second, computed as 1 / Mean =========================================== 649 passed, 11 skipped, 10 xfailed, 432 warnings in 699.26s (0:11:39) =========================================== ```
Midnighter commented 1 year ago

Could you elaborate a little on the pros/cons of creating a separate HIGHS interface compared to a combined one? I don't find the fact that it is not suitable for very large problems concerning, since presumably MICOM users would know to use the OSQP interface?

I don't think that the fact that this interface is slower than CPLEX & Gurobi is a problem. It would still be the only open source MILP solver that we have available in optlang. This would be extremely helpful for the memote webservice, for example, where we had to disable the MILPs.

In summary, I'm not sure about splitting the interfaces but I definitely would like to have them ❤️.

cdiener commented 1 year ago

Could you elaborate a little on the pros/cons of creating a separate HIGHS interface compared to a combined one? I don't find the fact that it is not suitable for very large problems concerning, since presumably MICOM users would know to use the OSQP interface?

Sorry I wasn't clear here. I think there should be a HIGHS interface in optlang regardless. HIGHS is a great solver and it has another API (somewhat reminiscent of the GLPK API) that would fit well with optlang and be more efficient in terms of basis reuse and getting solution values. The QP solver in HIGHS is also pretty good for decent size problem (thousands of vars).

OSQP is great for QPs but can't solve LPs well, which leads to issues in settings where you need to do both within the same interface. That applies to MICOM but also other examples (MOMA in COBRAPY is another example). So this combines OSQP with HIGHS to cover all bases. Maybe it should even replace the OSQP interface since it would still retain all functionality but would provide an excellent LP/MILP fallback in the same interface as well... :thinking: If that is not a good fit I cold also just add it to MICOM though.

I don't think that the fact that this interface is slower than CPLEX & Gurobi is a problem. It would still be the only open source MILP solver that we have available in optlang. This would be extremely helpful for the memote webservice, for example, where we had to disable the MILPs.

I mean GLPK has a MILP solver, it just struggles with certain types of problems. Which specific MILPs are you running in MEMOTE? I could benchmark some with my COBRAPY branch that has the interface enabled to see if it would be helpful there.

In summary, I'm not sure about splitting the interfaces but I definitely would like to have them ❤️.

Yeah they will definitely both be in optlang eventually. I do want to get on the HIGHS interface as well but it might take a bit longer since it would have to be coded from the ground up and there are more methods to overwrite.

Midnighter commented 1 year ago

Okay, from my understanding of your description, it sounds like it might be best to have one combined HIGHS-OSQP interface and a separate HIGHS interface.

With regard to MEMOTE, there are a couple of MILP in the test_stoichiometry module. There is also the paper reference in the docstrings if you want to read the source. GLPK does very poorly at those. Can easily take hours whereas CPLEX/Gurobi finish in about a minute.

cdiener commented 1 year ago

Okay perfect, I'll change it into that then.

cdiener commented 1 year ago

The only MIPs I found in memote for now where find_unconserved_metabolites and find_inconsistent_min_stoichiometry. Running those on iJO1366 cplex and highs were pretty much equally fast. Though, all returned empty sets so maybe should be benchmarked with a problem that has some inconsistencies.

In [10]: mod = load_model("iJO1366")

In [11]: modhy = mod.copy()

In [12]: modhy.solver.configuration.qp_method = "auto"

In [13]: modhy.solver.configuration.lp_method = "auto"

In [14]: modhy.solver = "hybrid"

In [15]: %time find_unconserved_metabolites(mod)
CPU times: user 2.06 s, sys: 6.33 ms, total: 2.06 s
Wall time: 1.99 s
Out[15]: set()

In [16]: %time find_unconserved_metabolites(modhy)
CPU times: user 2.24 s, sys: 7.73 ms, total: 2.25 s
Wall time: 2.25 s
Out[16]: set()

In [17]: from memote.support.consistency import *

In [18]: %time find_inconsistent_min_stoichiometry(mod)
CPU times: user 1.81 s, sys: 0 ns, total: 1.81 s
Wall time: 1.81 s
Out[18]: set()

In [19]: %time find_inconsistent_min_stoichiometry(modhy)
CPU times: user 1.65 s, sys: 3.24 ms, total: 1.65 s
Wall time: 1.65 s
Out[19]: set()
Midnighter commented 1 year ago

Something like Recon3D is probably the biggest that we have. Super cool to hear about the comparable speed ✌🏼

cdiener commented 1 year ago

Something like Recon3D is probably the biggest that we have. Super cool to hear about the comparable speed ✌🏼

Same for Recon3, just takes around 9s for either, but again there are no violations, so I could imagine that it is different for models with actual inconsistencies.

Midnighter commented 1 year ago

Oh yeah, if there are none, then it is a very fast MILP.

cdiener commented 11 months ago

I would probably be inclined to pull this by November 14 (2 month wait) if I get no reviews because it is high priority for us. It is tested pretty extensively now and avoids returning astonishingly wrong/non-optimal LP solutions in the OSQP interface.

Midnighter commented 11 months ago

By pull, you mean merge? I'm sorry, I didn't realize you were waiting on me. I thought you were still making modifications.

cdiener commented 11 months ago

Yep I meant merge. It has been done for a while. I fixed some edge cases that came up testing some larger models, but it has been done for a while .

cdiener commented 11 months ago

Thank you!