Skip to content

Commit e2a7e4c

Browse files
authored
Add pyoptinterface_based_impl.py and integrate it (#104)
* Add pyoptInterface_based_impl.py and integrate it * Rename and improve pyoptinterface_based_impl.py
1 parent 4a961e7 commit e2a7e4c

21 files changed

+1731
-2344
lines changed

dingo/MetabolicNetwork.py

Lines changed: 15 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
# Copyright (c) 2021 Apostolos Chalkis
55
# Copyright (c) 2021 Vissarion Fisikopoulos
6+
# Copyright (c) 2024 Ke Shi
67

78
# Licensed under GNU LGPL.3, see LICENCE file
89

@@ -11,15 +12,7 @@
1112
from typing import Dict
1213
import cobra
1314
from dingo.loading_models import read_json_file, read_mat_file, read_sbml_file, parse_cobra_model
14-
from dingo.fva import slow_fva
15-
from dingo.fba import slow_fba
16-
17-
try:
18-
import gurobipy
19-
from dingo.gurobi_based_implementations import fast_fba, fast_fva, fast_inner_ball
20-
except ImportError as e:
21-
pass
22-
15+
from dingo.pyoptinterface_based_impl import fba,fva,inner_ball,remove_redundant_facets
2316

2417
class MetabolicNetwork:
2518
def __init__(self, tuple_args):
@@ -28,13 +21,7 @@ def __init__(self, tuple_args):
2821
self._parameters["opt_percentage"] = 100
2922
self._parameters["distribution"] = "uniform"
3023
self._parameters["nullspace_method"] = "sparseQR"
31-
32-
try:
33-
import gurobipy
34-
35-
self._parameters["fast_computations"] = True
36-
except ImportError as e:
37-
self._parameters["fast_computations"] = False
24+
self._parameters["solver"] = None
3825

3926
if len(tuple_args) != 10:
4027
raise Exception(
@@ -107,30 +94,18 @@ def from_cobra_model(cls, arg):
10794
def fva(self):
10895
"""A member function to apply the FVA method on the metabolic network."""
10996

110-
if self._parameters["fast_computations"]:
111-
return fast_fva(
112-
self._lb,
113-
self._ub,
114-
self._S,
115-
self._objective_function,
116-
self._parameters["opt_percentage"],
117-
)
118-
else:
119-
return slow_fva(
120-
self._lb,
121-
self._ub,
122-
self._S,
123-
self._objective_function,
124-
self._parameters["opt_percentage"],
125-
)
97+
return fva(
98+
self._lb,
99+
self._ub,
100+
self._S,
101+
self._objective_function,
102+
self._parameters["opt_percentage"],
103+
self._parameters["solver"]
104+
)
126105

127106
def fba(self):
128107
"""A member function to apply the FBA method on the metabolic network."""
129-
130-
if self._parameters["fast_computations"]:
131-
return fast_fba(self._lb, self._ub, self._S, self._objective_function)
132-
else:
133-
return slow_fba(self._lb, self._ub, self._S, self._objective_function)
108+
return fba(self._lb, self._ub, self._S, self._objective_function, self._parameters["solver"])
134109

135110
@property
136111
def lb(self):
@@ -286,20 +261,9 @@ def set_active_bound(reaction: str, reac_index: int, bound: float) -> None:
286261
set_active_bound(
287262
rxn_id, reac_index, min(0.0, -self._lb[reac_index] if is_export else self._ub[reac_index])
288263
)
289-
290-
def set_fast_mode(self):
291-
292-
try:
293-
import gurobipy
294-
295-
self._parameters["fast_computations"] = True
296-
except ImportError as e:
297-
print("You have to install gurobi to use the fast computations.")
298-
self._parameters["fast_computations"] = False
299-
300-
def set_slow_mode(self):
301-
302-
self._parameters["fast_computations"] = False
264+
265+
def set_solver(self, solver: str):
266+
self._parameters["solver"] = solver
303267

304268
def set_nullspace_method(self, value):
305269

dingo/PolytopeSampler.py

Lines changed: 25 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# dingo is part of GeomScale project
33

44
# Copyright (c) 2021 Apostolos Chalkis
5+
# Copyright (c) 2024 Ke Shi
56

67
# Licensed under GNU LGPL.3, see LICENCE file
78

@@ -10,23 +11,13 @@
1011
import warnings
1112
import math
1213
from dingo.MetabolicNetwork import MetabolicNetwork
13-
from dingo.fva import slow_fva
1414
from dingo.utils import (
1515
map_samples_to_steady_states,
1616
get_matrices_of_low_dim_polytope,
1717
get_matrices_of_full_dim_polytope,
1818
)
1919

20-
try:
21-
import gurobipy
22-
from dingo.gurobi_based_implementations import (
23-
fast_fba,
24-
fast_fva,
25-
fast_inner_ball,
26-
fast_remove_redundant_facets,
27-
)
28-
except ImportError as e:
29-
pass
20+
from dingo.pyoptinterface_based_impl import fba,fva,inner_ball,remove_redundant_facets
3021

3122
from volestipy import HPolytope
3223

@@ -53,14 +44,8 @@ def __init__(self, metabol_net):
5344
self._parameters["first_run_of_mmcs"] = True
5445
self._parameters["remove_redundant_facets"] = True
5546

56-
try:
57-
import gurobipy
58-
59-
self._parameters["fast_computations"] = True
60-
self._parameters["tol"] = 1e-06
61-
except ImportError as e:
62-
self._parameters["fast_computations"] = False
63-
self._parameters["tol"] = 1e-03
47+
self._parameters["tol"] = 1e-06
48+
self._parameters["solver"] = None
6449

6550
def get_polytope(self):
6651
"""A member function to derive the corresponding full dimensional polytope
@@ -82,24 +67,18 @@ def get_polytope(self):
8267
) = self._metabolic_network.fba()
8368

8469
if (
85-
self._parameters["fast_computations"]
86-
and self._parameters["remove_redundant_facets"]
70+
self._parameters["remove_redundant_facets"]
8771
):
8872

89-
A, b, Aeq, beq = fast_remove_redundant_facets(
73+
A, b, Aeq, beq = remove_redundant_facets(
9074
self._metabolic_network.lb,
9175
self._metabolic_network.ub,
9276
self._metabolic_network.S,
9377
self._metabolic_network.objective_function,
9478
self._parameters["opt_percentage"],
79+
self._parameters["solver"],
9580
)
9681
else:
97-
if (not self._parameters["fast_computations"]) and self._parameters[
98-
"remove_redundant_facets"
99-
]:
100-
warnings.warn(
101-
"We continue without redundancy removal (slow mode is ON)"
102-
)
10382

10483
(
10584
min_fluxes,
@@ -162,14 +141,9 @@ def generate_steady_states(
162141

163142
P = HPolytope(self._A, self._b)
164143

165-
if self._parameters["fast_computations"]:
166-
self._A, self._b, Tr, Tr_shift, samples = P.fast_mmcs(
167-
ess, psrf, parallel_mmcs, num_threads
168-
)
169-
else:
170-
self._A, self._b, Tr, Tr_shift, samples = P.slow_mmcs(
171-
ess, psrf, parallel_mmcs, num_threads
172-
)
144+
self._A, self._b, Tr, Tr_shift, samples = P.mmcs(
145+
ess, psrf, parallel_mmcs, num_threads, self._parameters["solver"]
146+
)
173147

174148
if self._parameters["first_run_of_mmcs"]:
175149
steady_states = map_samples_to_steady_states(
@@ -207,7 +181,7 @@ def generate_steady_states_no_multiphase(
207181
else:
208182
bias_vector = bias_vector.astype('float64')
209183

210-
samples = P.generate_samples(method, n, burn_in, thinning, self._parameters["fast_computations"], variance, bias_vector)
184+
samples = P.generate_samples(method, n, burn_in, thinning, variance, bias_vector, self._parameters["solver"])
211185
samples_T = samples.T
212186

213187
steady_states = map_samples_to_steady_states(
@@ -218,7 +192,7 @@ def generate_steady_states_no_multiphase(
218192

219193
@staticmethod
220194
def sample_from_polytope(
221-
A, b, ess=1000, psrf=False, parallel_mmcs=False, num_threads=1
195+
A, b, ess=1000, psrf=False, parallel_mmcs=False, num_threads=1, solver=None
222196
):
223197
"""A static function to sample from a full dimensional polytope.
224198
@@ -233,22 +207,16 @@ def sample_from_polytope(
233207

234208
P = HPolytope(A, b)
235209

236-
try:
237-
import gurobipy
210+
A, b, Tr, Tr_shift, samples = P.mmcs(
211+
ess, psrf, parallel_mmcs, num_threads, solver
212+
)
238213

239-
A, b, Tr, Tr_shift, samples = P.fast_mmcs(
240-
ess, psrf, parallel_mmcs, num_threads
241-
)
242-
except ImportError as e:
243-
A, b, Tr, Tr_shift, samples = P.slow_mmcs(
244-
ess, psrf, parallel_mmcs, num_threads
245-
)
246214

247215
return samples
248216

249217
@staticmethod
250218
def sample_from_polytope_no_multiphase(
251-
A, b, method = 'billiard_walk', n=1000, burn_in=0, thinning=1, variance=1.0, bias_vector=None
219+
A, b, method = 'billiard_walk', n=1000, burn_in=0, thinning=1, variance=1.0, bias_vector=None, solver=None
252220
):
253221
"""A static function to sample from a full dimensional polytope with an MCMC method.
254222
@@ -267,25 +235,17 @@ def sample_from_polytope_no_multiphase(
267235

268236
P = HPolytope(A, b)
269237

270-
try:
271-
import gurobipy
272-
samples = P.generate_samples(method, n, burn_in, thinning, True, variance, bias_vector)
273-
except ImportError as e:
274-
samples = P.generate_samples(method, n, burn_in, thinning, False, variance, bias_vector)
238+
samples = P.generate_samples(method, n, burn_in, thinning, variance, bias_vector, solver)
275239

276240
samples_T = samples.T
277241
return samples_T
278242

279243
@staticmethod
280244
def round_polytope(
281-
A, b, method = "john_position"
245+
A, b, method = "john_position", solver = None
282246
):
283247
P = HPolytope(A, b)
284-
try:
285-
import gurobipy
286-
A, b, Tr, Tr_shift, round_value = P.rounding(method, True)
287-
except ImportError as e:
288-
A, b, Tr, Tr_shift, round_value = P.rounding(method, False)
248+
A, b, Tr, Tr_shift, round_value = P.rounding(method, solver)
289249

290250
return A, b, Tr, Tr_shift
291251

@@ -301,6 +261,7 @@ def sample_from_fva_output(
301261
psrf=False,
302262
parallel_mmcs=False,
303263
num_threads=1,
264+
solver = None
304265
):
305266
"""A static function to sample steady states when the output of FVA is given.
306267
@@ -335,16 +296,9 @@ def sample_from_fva_output(
335296

336297
P = HPolytope(A, b)
337298

338-
try:
339-
import gurobipy
340-
341-
A, b, Tr, Tr_shift, samples = P.fast_mmcs(
342-
ess, psrf, parallel_mmcs, num_threads
343-
)
344-
except ImportError as e:
345-
A, b, Tr, Tr_shift, samples = P.slow_mmcs(
346-
ess, psrf, parallel_mmcs, num_threads
347-
)
299+
A, b, Tr, Tr_shift, samples = P.mmcs(
300+
ess, psrf, parallel_mmcs, num_threads, solver
301+
)
348302

349303
steady_states = map_samples_to_steady_states(samples, N, N_shift)
350304

@@ -381,20 +335,8 @@ def metabolic_network(self):
381335
def facet_redundancy_removal(self, value):
382336
self._parameters["remove_redundant_facets"] = value
383337

384-
if (not self._parameters["fast_computations"]) and value:
385-
warnings.warn(
386-
"Since you are in slow mode the redundancy removal step is skipped (dingo does not currently support this functionality in slow mode)"
387-
)
388-
389-
def set_fast_mode(self):
390-
391-
self._parameters["fast_computations"] = True
392-
self._parameters["tol"] = 1e-06
393-
394-
def set_slow_mode(self):
395-
396-
self._parameters["fast_computations"] = False
397-
self._parameters["tol"] = 1e-03
338+
def set_solver(self, solver):
339+
self._parameters["solver"] = solver
398340

399341
def set_distribution(self, value):
400342

0 commit comments

Comments
 (0)