seed2lp 2.0.0__py3-none-any.whl → 2.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- seed2lp/__main__.py +124 -70
- seed2lp/_version.py +1 -1
- seed2lp/argument.py +6 -6
- seed2lp/asp/enum-cc.lp +3 -3
- seed2lp/clingo_lpx.py +14 -6
- seed2lp/description.py +44 -33
- seed2lp/file.py +6 -3
- seed2lp/flux.py +23 -17
- seed2lp/linear.py +37 -36
- seed2lp/log_conf.yaml +4 -4
- seed2lp/logger.py +83 -39
- seed2lp/network.py +55 -68
- seed2lp/reaction.py +4 -2
- seed2lp/reasoning.py +29 -26
- seed2lp/reasoningcom.py +27 -20
- seed2lp/reasoninghybrid.py +30 -25
- seed2lp/sbml.py +4 -2
- seed2lp/scope.py +14 -12
- seed2lp/solver.py +44 -41
- seed2lp/utils.py +7 -3
- seed2lp-2.1.0.dist-info/METADATA +621 -0
- {seed2lp-2.0.0.dist-info → seed2lp-2.1.0.dist-info}/RECORD +28 -28
- {seed2lp-2.0.0.dist-info → seed2lp-2.1.0.dist-info}/WHEEL +1 -1
- tests/normalization.py +8 -8
- tests/utils.py +18 -10
- seed2lp-2.0.0.dist-info/METADATA +0 -404
- {seed2lp-2.0.0.dist-info → seed2lp-2.1.0.dist-info}/entry_points.txt +0 -0
- {seed2lp-2.0.0.dist-info → seed2lp-2.1.0.dist-info}/licenses/LICENCE.txt +0 -0
- {seed2lp-2.0.0.dist-info → seed2lp-2.1.0.dist-info}/top_level.txt +0 -0
seed2lp/description.py
CHANGED
|
@@ -7,7 +7,7 @@ import pandas as pd
|
|
|
7
7
|
import re
|
|
8
8
|
from os import path
|
|
9
9
|
from seed2lp.network import Network
|
|
10
|
-
from . import flux, logger,
|
|
10
|
+
from . import flux, color # logger,
|
|
11
11
|
import warnings
|
|
12
12
|
import difflib
|
|
13
13
|
import seed2lp.sbml as SBML
|
|
@@ -21,15 +21,15 @@ BISEAU_VIZ = """
|
|
|
21
21
|
#defined reactant/4.
|
|
22
22
|
#defined product/4.
|
|
23
23
|
#defined reaction/1.
|
|
24
|
-
link(T,R) :- reactant(T,_,R,_).
|
|
25
|
-
link(R,P) :- product(P,_,R,_).
|
|
24
|
+
link(T,R) :- reactant(T,_,R,_,_,_).
|
|
25
|
+
link(R,P) :- product(P,_,R,_,_,_).
|
|
26
26
|
shape(R,rectangle) :- reaction(R).
|
|
27
27
|
obj_property(edge,arrowhead,vee).
|
|
28
28
|
"""
|
|
29
29
|
BISEAU_VIZ_NOREACTION = """
|
|
30
|
-
link(M,P) :- product(P,_,R,_) ; reactant(M,_,R,_).
|
|
31
|
-
link(P,P) :- product(P,_,R,_) ; not reactant(_,_,R,_).
|
|
32
|
-
link(M,M) :- reactant(M,_,R,_), not product(_,_,R,_).
|
|
30
|
+
link(M,P) :- product(P,_,R,_,_,_) ; reactant(M,_,R,_,_,_).
|
|
31
|
+
link(P,P) :- product(P,_,R,_,_,_) ; not reactant(_,_,R,_,_,_).
|
|
32
|
+
link(M,M) :- reactant(M,_,R,_,_,_), not product(_,_,R,_,_,_).
|
|
33
33
|
obj_property(edge,arrowhead,vee).
|
|
34
34
|
"""
|
|
35
35
|
|
|
@@ -102,7 +102,7 @@ class Description(Network):
|
|
|
102
102
|
def details_from_lp(self):
|
|
103
103
|
"""Get the network description from lp facts and save it
|
|
104
104
|
"""
|
|
105
|
-
logger.
|
|
105
|
+
self.logger.info("Start Getting Details from LP file")
|
|
106
106
|
reactions_composition_df = pd.DataFrame(columns=['reaction', 'metabolite', 'type_metabolite', 'stoichiometry'])
|
|
107
107
|
reaction_df = pd.DataFrame(columns=['reaction', 'low_bound', 'up_bound','is_forward', 'is_reverse', 'is_low_set'])
|
|
108
108
|
only_forward=list()
|
|
@@ -251,13 +251,13 @@ class Description(Network):
|
|
|
251
251
|
#print(reaction_without_reactant)
|
|
252
252
|
#print("REACTION WITHOUT PRODUCT")
|
|
253
253
|
#print(reaction_without_product)
|
|
254
|
-
save(self.lp_details , full_details)
|
|
254
|
+
self.save(self.lp_details , full_details)
|
|
255
255
|
|
|
256
256
|
|
|
257
257
|
def details_from_cobra(self):
|
|
258
258
|
"""Get the network description from sbml file by using cobra and save it
|
|
259
259
|
"""
|
|
260
|
-
logger.
|
|
260
|
+
self.logger.info("Start Getting Details from Cobra file")
|
|
261
261
|
warnings.filterwarnings("error")
|
|
262
262
|
model = flux.get_model(self.file)
|
|
263
263
|
if not self.keep_import_reactions:
|
|
@@ -267,14 +267,14 @@ class Description(Network):
|
|
|
267
267
|
full_details += f"{reaction}\t[{reaction.lower_bound}, {reaction.upper_bound}]\n"
|
|
268
268
|
|
|
269
269
|
self.cobra_details = path.join(self.out_dir, f"{self.name}_{self.short_option}_details_from_cobra.txt")
|
|
270
|
-
save(self.cobra_details, full_details)
|
|
270
|
+
self.save(self.cobra_details, full_details)
|
|
271
271
|
|
|
272
272
|
|
|
273
273
|
def details_diff(self):
|
|
274
274
|
"""Compare the Network description from cobra and lp facts
|
|
275
275
|
save the diff information into file
|
|
276
276
|
"""
|
|
277
|
-
logger.
|
|
277
|
+
self.logger.info("Start checking diff between Cobra and LP Network")
|
|
278
278
|
diff = ""
|
|
279
279
|
with open(self.cobra_details) as cobra_details:
|
|
280
280
|
cobra_details_text = cobra_details.readlines()
|
|
@@ -292,12 +292,13 @@ class Description(Network):
|
|
|
292
292
|
lp_details.close()
|
|
293
293
|
|
|
294
294
|
diff_path = path.join(self.out_dir, f"{self.name}_{self.short_option}_details_diff.txt")
|
|
295
|
-
save(diff_path, diff)
|
|
295
|
+
self.save(diff_path, diff)
|
|
296
296
|
|
|
297
297
|
def render_network(self):
|
|
298
298
|
"""From lp facts render the network graph with or without reaction
|
|
299
299
|
"""
|
|
300
300
|
import biseau
|
|
301
|
+
check_graphviz()
|
|
301
302
|
out_file = path.join(self.out_dir, f"{self.name}_{self.short_option}_visu")
|
|
302
303
|
|
|
303
304
|
print(f"\n\n{color.cyan_dark}############################################")
|
|
@@ -343,10 +344,10 @@ class Description(Network):
|
|
|
343
344
|
print(f"############################################\n{color.reset}")
|
|
344
345
|
|
|
345
346
|
if self.keep_import_reactions:
|
|
346
|
-
logger.
|
|
347
|
+
self.logger.warning("IMPORT REACTION KEPT")
|
|
347
348
|
else:
|
|
348
|
-
logger.
|
|
349
|
-
logger.
|
|
349
|
+
self.logger.warning("IMPORT REACTION REMOVED BY DEFAULT")
|
|
350
|
+
self.logger.warning("If you want to keep import reaction\nuse option -kir / --keep-import-reactions")
|
|
350
351
|
species=self.name
|
|
351
352
|
original_reactions = SBML.get_listOfReactions(self.model[species])
|
|
352
353
|
|
|
@@ -366,7 +367,7 @@ class Description(Network):
|
|
|
366
367
|
if reaction_name in self.deleted_reactions:
|
|
367
368
|
self.sbml_remove_reaction(reaction, species)
|
|
368
369
|
rm_reac_message+=f"\n\t- {reaction_name}"
|
|
369
|
-
logger.
|
|
370
|
+
self.logger.info(rm_reac_message)
|
|
370
371
|
else:
|
|
371
372
|
# Change the reversibility
|
|
372
373
|
is_modif_rev = self.sbml_review_reversibilty(reaction_name, reaction)
|
|
@@ -389,11 +390,11 @@ class Description(Network):
|
|
|
389
390
|
|
|
390
391
|
#print and log
|
|
391
392
|
if is_modif_rev_log:
|
|
392
|
-
logger.
|
|
393
|
+
self.logger.warning(modif_rev_message)
|
|
393
394
|
if is_switch_meta_log:
|
|
394
|
-
logger.
|
|
395
|
+
self.logger.warning(switch_meta_message)
|
|
395
396
|
if is_rm_import_log:
|
|
396
|
-
logger.
|
|
397
|
+
self.logger.warning(rm_import_message)
|
|
397
398
|
|
|
398
399
|
# Replace list of parameters because we added new specific parameters for the exchange reactions
|
|
399
400
|
self.sbml_review_parameters(species)
|
|
@@ -405,20 +406,30 @@ class Description(Network):
|
|
|
405
406
|
file_path = path.join(self.out_dir, self.name+".xml")
|
|
406
407
|
str_model = self.sbml_first_line+SBML.etree_to_string(self.sbml[species])
|
|
407
408
|
print(f"File saved at: {file_path}")
|
|
408
|
-
save(file_path, str_model)
|
|
409
|
+
self.save(file_path, str_model)
|
|
409
410
|
|
|
410
|
-
########################################################
|
|
411
411
|
|
|
412
|
+
def save(self, out_file:str, data):
|
|
413
|
+
"""Save file of Network description or graphs
|
|
412
414
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
415
|
+
Args:
|
|
416
|
+
out_file (str): Output file path
|
|
417
|
+
data: Graph or Network details data
|
|
418
|
+
"""
|
|
419
|
+
with open(out_file, 'w') as f:
|
|
420
|
+
f.write(data)
|
|
421
|
+
f.close()
|
|
422
|
+
self.logger.info(f"File saved at: {out_file}")
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def check_graphviz():
|
|
426
|
+
import shutil
|
|
427
|
+
if shutil.which("dot") is None:
|
|
428
|
+
raise RuntimeError(
|
|
429
|
+
f"\n\n{color.red_bright}Graphviz is required and missing from your environment.{color.reset}\n"
|
|
430
|
+
f"First install it with:\n"
|
|
431
|
+
f" {color.cyan_dark}conda install -c conda-forge graphviz{color.reset}\n"
|
|
432
|
+
f"or\n"
|
|
433
|
+
f" {color.cyan_dark}sudo apt install graphviz{color.reset}\n"
|
|
434
|
+
f"Then retry.\n"
|
|
435
|
+
)
|
seed2lp/file.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from os import path, makedirs, stat, remove
|
|
2
3
|
from json import dump, load
|
|
3
4
|
from csv import writer, reader
|
|
4
|
-
from . import logger
|
|
5
|
+
#from . import logger
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
def existant_path(inpath:str) -> str:
|
|
@@ -29,12 +30,13 @@ def is_valid_dir(dirpath):
|
|
|
29
30
|
Returns:
|
|
30
31
|
bool: True if dir exists, False otherwise
|
|
31
32
|
"""
|
|
33
|
+
logger = logging.getLogger("s2lp")
|
|
32
34
|
if not path.isdir(dirpath):
|
|
33
35
|
try:
|
|
34
36
|
makedirs(dirpath)
|
|
35
37
|
return dirpath
|
|
36
38
|
except OSError as e:
|
|
37
|
-
logger.
|
|
39
|
+
logger.error(e)
|
|
38
40
|
return None
|
|
39
41
|
else:
|
|
40
42
|
return dirpath
|
|
@@ -64,6 +66,7 @@ def save(filename:str, directory:str, results, type:str, is_result_temp=False):
|
|
|
64
66
|
type (str): Type of output fils (json or tsv or txt)
|
|
65
67
|
"""
|
|
66
68
|
|
|
69
|
+
logger = logging.getLogger("s2lp")
|
|
67
70
|
out_file_path = path.join(directory,filename)
|
|
68
71
|
try:
|
|
69
72
|
match type:
|
|
@@ -91,7 +94,7 @@ def save(filename:str, directory:str, results, type:str, is_result_temp=False):
|
|
|
91
94
|
with open(out_file_path, "w") as f:
|
|
92
95
|
f.write("\n".join(results))
|
|
93
96
|
except Exception as e:
|
|
94
|
-
logger.
|
|
97
|
+
logger.error(f"while saving file: {e}")
|
|
95
98
|
|
|
96
99
|
|
|
97
100
|
|
seed2lp/flux.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import cobra
|
|
1
|
+
import cobra, logging
|
|
2
2
|
from re import sub
|
|
3
3
|
from cobra.core import Model
|
|
4
4
|
import warnings
|
|
5
|
-
from . import logger
|
|
5
|
+
from . import color #,logger
|
|
6
|
+
from .logger import print_log
|
|
6
7
|
|
|
7
8
|
def get_model(model_file:str):
|
|
8
9
|
"""Get cobra model
|
|
@@ -41,7 +42,8 @@ def get_list_fluxes(model:Model, list_objective:list, show_messages:bool=True):
|
|
|
41
42
|
objective_flux = 0.0
|
|
42
43
|
fluxes_dict[objective_reaction]=objective_flux
|
|
43
44
|
if show_messages:
|
|
44
|
-
|
|
45
|
+
for reaction, flux in fluxes_dict.items():
|
|
46
|
+
print(f"'{reaction}': {float(flux)}")
|
|
45
47
|
print('\n')
|
|
46
48
|
return fluxes_dict
|
|
47
49
|
|
|
@@ -79,6 +81,7 @@ def get_flux(model:Model, objective_reaction:str, list_objective:list,
|
|
|
79
81
|
Returns:
|
|
80
82
|
float, bool: The value of the objective flux, if the model is infeasible or not
|
|
81
83
|
"""
|
|
84
|
+
logger = logging.getLogger("s2lp")
|
|
82
85
|
warnings.filterwarnings("error")
|
|
83
86
|
objective_flux=dict()
|
|
84
87
|
try:
|
|
@@ -157,12 +160,12 @@ def get_flux(model:Model, objective_reaction:str, list_objective:list,
|
|
|
157
160
|
objective = remove_prefix_reaction(obj)
|
|
158
161
|
objective_flux[objective]=0
|
|
159
162
|
infeasible = True
|
|
160
|
-
logger.
|
|
163
|
+
logger.info("Model infeasible")
|
|
161
164
|
|
|
162
165
|
return objective_flux, infeasible
|
|
163
166
|
|
|
164
167
|
|
|
165
|
-
def get_init(model:Model, list_objective:list, show_messages:bool=True):
|
|
168
|
+
def get_init(model:Model, list_objective:list, logger:logging, show_messages:bool=True):
|
|
166
169
|
"""Get initial flux of all objective reactions using cobra
|
|
167
170
|
|
|
168
171
|
Args:
|
|
@@ -179,7 +182,7 @@ def get_init(model:Model, list_objective:list, show_messages:bool=True):
|
|
|
179
182
|
f" {color.bold}CHECK FLUX{color.cyan_light}\n"\
|
|
180
183
|
"############################################\n" \
|
|
181
184
|
"############################################\n"
|
|
182
|
-
|
|
185
|
+
print_log(logger, title_mess, "info", color.cyan_light)
|
|
183
186
|
|
|
184
187
|
|
|
185
188
|
print("---------------- FLUX INIT -----------------\n")
|
|
@@ -204,9 +207,11 @@ def stop_flux(model:Model, list_objective:list=None, show_messages:bool=True):
|
|
|
204
207
|
Returns:
|
|
205
208
|
dic: Dictionnary of objective reaction and their respective fluxes
|
|
206
209
|
"""
|
|
210
|
+
logger = logging.getLogger("s2lp")
|
|
211
|
+
|
|
207
212
|
if show_messages:
|
|
208
213
|
print("---------- STOP IMPORT FLUX -------------\n")
|
|
209
|
-
logger.
|
|
214
|
+
logger.info("Shutting down import flux ...")
|
|
210
215
|
|
|
211
216
|
for elem in model.boundary:
|
|
212
217
|
if not elem.reactants and elem.upper_bound > 0:
|
|
@@ -218,7 +223,7 @@ def stop_flux(model:Model, list_objective:list=None, show_messages:bool=True):
|
|
|
218
223
|
elem.upper_bound = 0
|
|
219
224
|
elem.lower_bound = 0.0
|
|
220
225
|
|
|
221
|
-
logger.
|
|
226
|
+
logger.info("... DONE")
|
|
222
227
|
|
|
223
228
|
if list_objective is not None:
|
|
224
229
|
fluxes_no_import = get_list_fluxes(model, list_objective, show_messages)
|
|
@@ -242,10 +247,11 @@ def calculate(model:Model, list_objective:list, list_seeds:list,
|
|
|
242
247
|
Returns:
|
|
243
248
|
dict, str: result (containing the data), objective_reaction (chosen, the first having flux)
|
|
244
249
|
"""
|
|
250
|
+
logger = logging.getLogger("s2lp")
|
|
245
251
|
warnings.filterwarnings("error")
|
|
246
|
-
logger.
|
|
252
|
+
logger.info("Starting calculate Flux...")
|
|
247
253
|
if not list_objective:
|
|
248
|
-
logger.
|
|
254
|
+
logger.error("No objective found, abort")
|
|
249
255
|
return None, None
|
|
250
256
|
|
|
251
257
|
#cobra.flux_analysis.add_loopless(model)
|
|
@@ -266,7 +272,7 @@ def calculate(model:Model, list_objective:list, list_seeds:list,
|
|
|
266
272
|
meta_exchange_list[str(key)]=reaction.id
|
|
267
273
|
|
|
268
274
|
created_sinks = []
|
|
269
|
-
logger.
|
|
275
|
+
logger.info("Opening Import flux from seeds (Exchange) or add Sinks ...")
|
|
270
276
|
objective_reaction = set_objective(model, list_objective[0])
|
|
271
277
|
|
|
272
278
|
for seed in list_seeds:
|
|
@@ -300,9 +306,9 @@ def calculate(model:Model, list_objective:list, list_seeds:list,
|
|
|
300
306
|
lb=float(-1000))
|
|
301
307
|
created_sinks.append(f"SK_{seed}")
|
|
302
308
|
|
|
303
|
-
logger.
|
|
309
|
+
logger.info("Opening Import flux: Done")
|
|
304
310
|
|
|
305
|
-
logger.
|
|
311
|
+
logger.info("Checking objective flux on seeds ...")
|
|
306
312
|
|
|
307
313
|
lp_flux=None
|
|
308
314
|
if not is_community:
|
|
@@ -322,9 +328,9 @@ def calculate(model:Model, list_objective:list, list_seeds:list,
|
|
|
322
328
|
infeasible_demands=None
|
|
323
329
|
if ok_seeds:
|
|
324
330
|
ok_result = True
|
|
325
|
-
logger.
|
|
331
|
+
logger.info("... OK")
|
|
326
332
|
elif try_demands:
|
|
327
|
-
logger.
|
|
333
|
+
logger.info("... KO - Checking objective flux on demands ...")
|
|
328
334
|
# create a demand reaction for all products of the biomass reaction
|
|
329
335
|
products = [m.id for m in model.reactions.get_by_id(objective_reaction).products]
|
|
330
336
|
for m in products:
|
|
@@ -349,9 +355,9 @@ def calculate(model:Model, list_objective:list, list_seeds:list,
|
|
|
349
355
|
|
|
350
356
|
if ok_demands:
|
|
351
357
|
ok_result = True
|
|
352
|
-
logger.
|
|
358
|
+
logger.info("... OK")
|
|
353
359
|
else:
|
|
354
|
-
logger.
|
|
360
|
+
logger.info("... KO")
|
|
355
361
|
|
|
356
362
|
result = {'id' : species,
|
|
357
363
|
'objective_flux_seeds': objective_flux_seeds,
|
seed2lp/linear.py
CHANGED
|
@@ -8,14 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
from seed2lp.network import Network
|
|
10
10
|
from seed2lp.solver import Solver
|
|
11
|
-
from . import clingo_lpx, color
|
|
11
|
+
from . import clingo_lpx, color
|
|
12
|
+
from .logger import print_log
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
###################################################################
|
|
15
16
|
################### Class Hybrid : herit Solver ###################
|
|
16
17
|
###################################################################
|
|
17
18
|
class Hybrid(Solver):
|
|
18
|
-
def __init__(self, run_mode:str, run_solve:str, network:Network,
|
|
19
|
+
def __init__(self, run_mode:str, run_solve:str, network:Network, log_path:str,
|
|
19
20
|
time_limit_minute:float=None, number_solution:int=None,
|
|
20
21
|
clingo_configuration:str=None, clingo_strategy:str=None,
|
|
21
22
|
intersection:bool=False, union:bool=False,
|
|
@@ -43,7 +44,7 @@ class Hybrid(Solver):
|
|
|
43
44
|
short_option (str, optional): Short way to write option on filename. Defaults to None.
|
|
44
45
|
verbose (bool, optional): Set debug mode. Defaults to False.
|
|
45
46
|
"""
|
|
46
|
-
super().__init__(run_mode, network, time_limit_minute, number_solution, clingo_configuration,
|
|
47
|
+
super().__init__(run_mode, network, log_path, time_limit_minute, number_solution, clingo_configuration,
|
|
47
48
|
clingo_strategy, intersection, union, minimize, subset_minimal, temp_dir, short_option, run_solve, verbose)
|
|
48
49
|
|
|
49
50
|
self.is_linear = True
|
|
@@ -65,7 +66,7 @@ class Hybrid(Solver):
|
|
|
65
66
|
f" {color.bold}HYBRID{color.cyan_light}\n"\
|
|
66
67
|
"############################################\n" \
|
|
67
68
|
"############################################\n"
|
|
68
|
-
|
|
69
|
+
print_log(self.logger, title_mess, "info", color.cyan_light)
|
|
69
70
|
|
|
70
71
|
|
|
71
72
|
def _init_clingo_constant(self):
|
|
@@ -74,11 +75,11 @@ class Hybrid(Solver):
|
|
|
74
75
|
self.init_const()
|
|
75
76
|
|
|
76
77
|
if self.maximize_flux:
|
|
77
|
-
|
|
78
|
+
print_log(self.logger, 'Flux: MAXIMIZATION', "info", verbose=self.verbose)
|
|
78
79
|
else:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
print_log(self.logger, 'Flux: NO MAXIMIZATION', "info")
|
|
81
|
+
print_log(self.logger, f"Time limit: {self.time_limit_minute} minutes", 'info', verbose=self.verbose)
|
|
82
|
+
print_log(self.logger, f"Solution number limit: {self.number_solution}", 'info', verbose=self.verbose)
|
|
82
83
|
|
|
83
84
|
|
|
84
85
|
def search_seed(self):
|
|
@@ -94,19 +95,19 @@ class Hybrid(Solver):
|
|
|
94
95
|
files.append(self.asp.ASP_SRC_MAXIMIZE_FLUX)
|
|
95
96
|
if self.subset_minimal:
|
|
96
97
|
self.get_message('subsetmin')
|
|
97
|
-
#
|
|
98
|
+
#print_log(self.logger, "GROUNDING...", "info")
|
|
98
99
|
#self.grounded, timer, err_output, error_code, memory = self.ground(files, self.clingo_constant, self.is_linear, self.verbose)
|
|
99
100
|
self.search_subsetmin(files)
|
|
100
101
|
if self.minimize:
|
|
101
102
|
self.get_message('minimize')
|
|
102
103
|
if self.network.is_subseed:
|
|
103
104
|
files.append(self.asp.ASP_SRC_MAXIMIZE_PRODUCED_TARGET)
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
print_log(self.logger, 'POSSIBLE SEED: Given', "info", verbose=self.verbose)
|
|
106
|
+
print_log(self.logger, ' A subset of possible seed is search \n maximising the number of produced target', "info", verbose=self.verbose)
|
|
106
107
|
self.clingo_constant.append('-c')
|
|
107
108
|
self.clingo_constant.append('subseed=1')
|
|
108
109
|
files.append(self.asp.ASP_SRC_MINIMIZE)
|
|
109
|
-
#
|
|
110
|
+
#print_log(self.logger, "GROUNDING...", "info")
|
|
110
111
|
#self.grounded, timer, err_output, error_code, memory = self.ground(files, self.clingo_constant, self.is_linear, self.verbose)
|
|
111
112
|
self.search_minimize(files)
|
|
112
113
|
self.get_message('end')
|
|
@@ -115,7 +116,7 @@ class Hybrid(Solver):
|
|
|
115
116
|
def search_minimize(self, asp_files):
|
|
116
117
|
"""Launch seed searching with minimze options
|
|
117
118
|
"""
|
|
118
|
-
|
|
119
|
+
print_log(self.logger, "Finding optimum...", "info", verbose=self.verbose)
|
|
119
120
|
self.solve(asp_files, "minimize-one-model")
|
|
120
121
|
|
|
121
122
|
if self.one_model_unsat:
|
|
@@ -134,7 +135,7 @@ class Hybrid(Solver):
|
|
|
134
135
|
self.solve(asp_files, "minimize-enumeration")
|
|
135
136
|
else:
|
|
136
137
|
self.get_message('enumeration')
|
|
137
|
-
|
|
138
|
+
print_log(self.logger, f"\nNot computed: {opti_message}", "info", verbose=self.verbose)
|
|
138
139
|
|
|
139
140
|
if self.intersection:
|
|
140
141
|
if ok_opti:
|
|
@@ -142,7 +143,7 @@ class Hybrid(Solver):
|
|
|
142
143
|
self.solve(asp_files, "minimize-intersection")
|
|
143
144
|
else:
|
|
144
145
|
self.get_message('intersection')
|
|
145
|
-
|
|
146
|
+
print_log(self.logger, f"\nNot computed: {opti_message}", "info", verbose=self.verbose)
|
|
146
147
|
|
|
147
148
|
|
|
148
149
|
def search_subsetmin(self, asp_files):
|
|
@@ -153,7 +154,7 @@ class Hybrid(Solver):
|
|
|
153
154
|
self.solve(asp_files, "submin-enumeration")
|
|
154
155
|
else:
|
|
155
156
|
self.number_solution = 1
|
|
156
|
-
|
|
157
|
+
print_log(self.logger, "\n--------------- One solution ---------------", "info", verbose=self.verbose)
|
|
157
158
|
self.solve(asp_files, "submin-enumeration")
|
|
158
159
|
|
|
159
160
|
|
|
@@ -201,7 +202,7 @@ class Hybrid(Solver):
|
|
|
201
202
|
asp_files (list, optional): List of ASP files used for sovling. Defaults to [].
|
|
202
203
|
search_mode (str, optional): Describe the launch mode. . Defaults to "".
|
|
203
204
|
"""
|
|
204
|
-
|
|
205
|
+
print_log(self.logger, "SOLVING...\n", "info", verbose=self.verbose)
|
|
205
206
|
results = dict()
|
|
206
207
|
solution_list = dict()
|
|
207
208
|
timer = dict()
|
|
@@ -224,35 +225,35 @@ class Hybrid(Solver):
|
|
|
224
225
|
proc_output, err, error_code, \
|
|
225
226
|
memory, is_killed = clingo_lpx.solve(cmd, self.time_limit)
|
|
226
227
|
self.get_message("command")
|
|
227
|
-
|
|
228
|
+
print_log(self.logger, f'{cmd_str}', 'debug', verbose=self.verbose)
|
|
228
229
|
|
|
229
230
|
self.get_error(error_code, err)
|
|
230
231
|
output_full_list, unsatisfiable, self.optimum_found, full_timers, opt = clingo_lpx.result_convert(proc_output,
|
|
231
232
|
self.network.objectives,
|
|
232
233
|
"", is_killed, False)
|
|
233
234
|
if unsatisfiable:
|
|
234
|
-
|
|
235
|
+
print_log(self.logger, 'Unsatisfiable problem', "error", verbose=self.verbose)
|
|
235
236
|
|
|
236
237
|
elif self.optimum_found:
|
|
237
|
-
|
|
238
|
+
print_log(self.logger, "Optimum Found", "info", verbose=self.verbose)
|
|
238
239
|
self.one_model_unsat = False
|
|
239
240
|
one_model_list=output_full_list[list(output_full_list.keys())[-1]]
|
|
240
241
|
self.optimum=opt
|
|
241
242
|
self.get_separate_optimum()
|
|
242
243
|
#TODO Corrects the producible targets count
|
|
243
244
|
#if self.network.is_subseed:
|
|
244
|
-
#
|
|
245
|
+
# print_log(self.logger, (f"Number of producible targets: {- self.opt_prod_tgt}"), 'info')
|
|
245
246
|
#TODO END
|
|
246
|
-
|
|
247
|
+
print_log(self.logger, f"Minimal size of seed set is {self.opt_size}\n", 'info', verbose=self.verbose)
|
|
247
248
|
if self.optimum is not None and self.network.keep_import_reactions:
|
|
248
|
-
|
|
249
|
+
print_log(self.logger, "Try with the option remove import reactions.", "info", verbose=self.verbose)
|
|
249
250
|
solution_list[model_type] = one_model_list
|
|
250
251
|
#Get obejctives fluxes and add results seeds to network object
|
|
251
252
|
obj_flux_dict = self.get_objectives_flux(one_model_list[5])
|
|
252
253
|
self.add_result_seeds(search_mode, model_type, one_model_list[1], one_model_list[3], obj_flux_dict)
|
|
253
254
|
# Satisfiable probleme but optimum not found in given time
|
|
254
255
|
else:
|
|
255
|
-
|
|
256
|
+
print_log(self.logger, 'Optimum not found', "error", verbose=self.verbose)
|
|
256
257
|
|
|
257
258
|
case "minimize-enumeration":
|
|
258
259
|
cmd = clingo_lpx.command(files=asp_files, options=full_option, nb_model= self.number_solution,
|
|
@@ -261,12 +262,12 @@ class Hybrid(Solver):
|
|
|
261
262
|
proc_output, err, error_code, \
|
|
262
263
|
memory, is_killed = clingo_lpx.solve(cmd, self.time_limit)
|
|
263
264
|
self.get_message("command")
|
|
264
|
-
|
|
265
|
+
print_log(self.logger, f'{cmd_str}', 'debug', verbose=self.verbose)
|
|
265
266
|
self.get_error(error_code, err)
|
|
266
267
|
solution_list, unsatisfiable, _, full_timers, _ = clingo_lpx.result_convert(proc_output,
|
|
267
268
|
self.network.objectives, "enumeration", is_killed)
|
|
268
269
|
if unsatisfiable:
|
|
269
|
-
|
|
270
|
+
print_log(self.logger, 'Unsatisfiable problem', "error", verbose=self.verbose)
|
|
270
271
|
else:
|
|
271
272
|
for model_name, solution in solution_list.items():
|
|
272
273
|
#Get obejctives fluxes and add results seeds to network object
|
|
@@ -280,12 +281,12 @@ class Hybrid(Solver):
|
|
|
280
281
|
proc_output, err, error_code, \
|
|
281
282
|
memory, is_killed = clingo_lpx.solve(cmd, self.time_limit)
|
|
282
283
|
self.get_message("command")
|
|
283
|
-
|
|
284
|
+
print_log(self.logger, f'{cmd_str}', 'debug', verbose=self.verbose)
|
|
284
285
|
self.get_error(error_code, err)
|
|
285
286
|
solution_list, unsatisfiable, _, full_timers,_ = clingo_lpx.result_convert(proc_output,
|
|
286
287
|
self.network.objectives, "enumeration", is_killed)
|
|
287
288
|
if unsatisfiable:
|
|
288
|
-
|
|
289
|
+
print_log(self.logger, 'Unsatisfiable problem', "error", verbose=self.verbose)
|
|
289
290
|
else:
|
|
290
291
|
for model_name, solution in solution_list.items():
|
|
291
292
|
#Get obejctives fluxes and add results seeds to network object
|
|
@@ -299,12 +300,12 @@ class Hybrid(Solver):
|
|
|
299
300
|
proc_output, err, error_code, \
|
|
300
301
|
memory, is_killed = clingo_lpx.solve(cmd, self.time_limit)
|
|
301
302
|
self.get_message("command")
|
|
302
|
-
|
|
303
|
+
print_log(self.logger, f'{cmd_str}', 'debug', verbose=self.verbose)
|
|
303
304
|
self.get_error(error_code, err)
|
|
304
305
|
output_full_list, unsatisfiable, _, full_timers = clingo_lpx.result_convert(proc_output,
|
|
305
306
|
self.network.objectives, 'cautious', is_killed)
|
|
306
307
|
if unsatisfiable:
|
|
307
|
-
|
|
308
|
+
print_log(self.logger, 'Unsatisfiable problem', "error", verbose=self.verbose)
|
|
308
309
|
elif output_full_list:
|
|
309
310
|
model = output_full_list[list(output_full_list.keys())[-1]]
|
|
310
311
|
solution_list[model_type ] = model
|
|
@@ -321,12 +322,12 @@ class Hybrid(Solver):
|
|
|
321
322
|
memory, is_killed = clingo_lpx.solve(files=asp_files, options=full_option,
|
|
322
323
|
time_limit=self.time_limit)
|
|
323
324
|
self.get_message("command")
|
|
324
|
-
|
|
325
|
+
print_log(self.logger, f'{cmd_str}', 'debug', verbose=self.verbose)
|
|
325
326
|
self.get_error(error_code, err)
|
|
326
327
|
output_full_list, unsatisfiable, _, full_timers = clingo_lpx.result_convert(proc_output,
|
|
327
328
|
self.network.objectives, 'cautious', is_killed)
|
|
328
329
|
if unsatisfiable:
|
|
329
|
-
|
|
330
|
+
print_log(self.logger, 'Unsatisfiable problem', "error", verbose=self.verbose)
|
|
330
331
|
elif output_full_list:
|
|
331
332
|
model = output_full_list[list(output_full_list.keys())[-1]]
|
|
332
333
|
solution_list[model_type] = model
|
|
@@ -359,7 +360,7 @@ class Hybrid(Solver):
|
|
|
359
360
|
print(f'error_code = {error_code}')
|
|
360
361
|
raise ValueError(err.decode())
|
|
361
362
|
elif err:
|
|
362
|
-
|
|
363
|
+
print_log(self.logger, err.decode(), 'debug', verbose=self.verbose)
|
|
363
364
|
|
|
364
365
|
########################################################
|
|
365
366
|
|
|
@@ -368,7 +369,7 @@ class Hybrid(Solver):
|
|
|
368
369
|
##################### Class FBA : herit Hybrid ####################
|
|
369
370
|
###################################################################
|
|
370
371
|
class FBA(Hybrid):
|
|
371
|
-
def __init__(self, run_mode:str, network:Network,
|
|
372
|
+
def __init__(self, run_mode:str, network:Network, log_path:str,
|
|
372
373
|
time_limit_minute:float=None, number_solution:int=None,
|
|
373
374
|
clingo_configuration:str=None, clingo_strategy:str=None,
|
|
374
375
|
intersection:bool=False, union:bool=False,
|
|
@@ -395,7 +396,7 @@ class FBA(Hybrid):
|
|
|
395
396
|
short_option (str, optional): Short way to write option on filename. Defaults to None.
|
|
396
397
|
verbose (bool, optional): Set debug mode. Defaults to False.
|
|
397
398
|
"""
|
|
398
|
-
super().__init__(run_mode, None, network,
|
|
399
|
+
super().__init__(run_mode, None, network, log_path,
|
|
399
400
|
time_limit_minute, number_solution,
|
|
400
401
|
clingo_configuration, clingo_strategy,
|
|
401
402
|
intersection, union, minimize,
|
|
@@ -413,7 +414,7 @@ class FBA(Hybrid):
|
|
|
413
414
|
f" {color.bold}FBA{color.cyan_light}\n"\
|
|
414
415
|
"############################################\n" \
|
|
415
416
|
"############################################\n"
|
|
416
|
-
|
|
417
|
+
print_log(self.logger, title_mess, "info", color.cyan_light, self.verbose)
|
|
417
418
|
|
|
418
419
|
def add_result_seeds(self, search_mode:str, model_name:str, len:int, seeds:list, flux_list:list):
|
|
419
420
|
"""Add a formated resulted set of seeds into the network object
|
seed2lp/log_conf.yaml
CHANGED
|
@@ -4,22 +4,22 @@
|
|
|
4
4
|
|
|
5
5
|
version: 1
|
|
6
6
|
disable_existing_loggers: False
|
|
7
|
+
|
|
7
8
|
formatters:
|
|
8
9
|
simple:
|
|
9
10
|
format: '%(levelname)s : %(message)s'
|
|
10
11
|
() : seed2lp.logger.ColoredFormatter
|
|
11
12
|
use_color: true
|
|
13
|
+
|
|
12
14
|
handlers:
|
|
13
15
|
console:
|
|
14
16
|
class: logging.StreamHandler
|
|
15
17
|
level: WARNING
|
|
16
18
|
formatter: simple
|
|
17
19
|
stream: ext://sys.stdout
|
|
20
|
+
|
|
18
21
|
loggers:
|
|
19
22
|
s2lp:
|
|
20
23
|
level: DEBUG
|
|
21
24
|
handlers: [console]
|
|
22
|
-
propagate:
|
|
23
|
-
root:
|
|
24
|
-
level: DEBUG
|
|
25
|
-
handlers: [console]
|
|
25
|
+
propagate: false
|