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/reasoning.py
CHANGED
|
@@ -5,14 +5,15 @@ import clyngor
|
|
|
5
5
|
from time import time
|
|
6
6
|
from .network import Network
|
|
7
7
|
from .reasoninghybrid import HybridReasoning
|
|
8
|
-
from . import color
|
|
8
|
+
from . import color
|
|
9
|
+
from .logger import print_log
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
###################################################################
|
|
12
13
|
############ Class Reasoning : herit HybridReasoning ##############
|
|
13
14
|
###################################################################
|
|
14
15
|
class Reasoning(HybridReasoning):
|
|
15
|
-
def __init__(self, run_mode:str, run_solve:str, network:Network,
|
|
16
|
+
def __init__(self, run_mode:str, run_solve:str, network:Network, log_path:str,
|
|
16
17
|
time_limit_minute:float=None, number_solution:int=None,
|
|
17
18
|
clingo_configuration:str=None, clingo_strategy:str=None,
|
|
18
19
|
intersection:bool=False, union:bool=False,
|
|
@@ -37,7 +38,7 @@ class Reasoning(HybridReasoning):
|
|
|
37
38
|
short_option (str, optional): Short way to write option on filename. Defaults to None.
|
|
38
39
|
verbose (bool, optional): Set debug mode. Defaults to False.
|
|
39
40
|
"""
|
|
40
|
-
super().__init__(run_mode, network, time_limit_minute, number_solution, clingo_configuration,
|
|
41
|
+
super().__init__(run_mode, network, log_path, time_limit_minute, number_solution, clingo_configuration,
|
|
41
42
|
clingo_strategy, intersection, union, minimize, subset_minimal,
|
|
42
43
|
temp_dir, short_option, run_solve, verbose, community_mode, all_transfers)
|
|
43
44
|
|
|
@@ -47,7 +48,7 @@ class Reasoning(HybridReasoning):
|
|
|
47
48
|
f" {color.bold}REASONING{color.cyan_light}\n"\
|
|
48
49
|
"############################################\n" \
|
|
49
50
|
"############################################\n"
|
|
50
|
-
|
|
51
|
+
print_log(self.logger, title_mess, "info", color.cyan_light)
|
|
51
52
|
self._set_clingo_constant()
|
|
52
53
|
self._set_temp_result_file()
|
|
53
54
|
|
|
@@ -58,8 +59,8 @@ class Reasoning(HybridReasoning):
|
|
|
58
59
|
"""Prepare ASP constant command for resolution
|
|
59
60
|
"""
|
|
60
61
|
self.init_const()
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
print_log(self.logger, f"Time limit: {self.time_limit_minute} minutes", "info")
|
|
63
|
+
print_log(self.logger, f"Solution number limit: {self.number_solution}", "info")
|
|
63
64
|
########################################################
|
|
64
65
|
|
|
65
66
|
|
|
@@ -92,10 +93,12 @@ class Reasoning(HybridReasoning):
|
|
|
92
93
|
self.search_subsetmin(timer, 'filter')
|
|
93
94
|
|
|
94
95
|
if self.run_solve == "guess_check" or self.run_solve == "all":
|
|
96
|
+
self.diversity=False
|
|
95
97
|
self.get_message('guess_check')
|
|
96
98
|
self.search_subsetmin(timer, 'guess_check')
|
|
97
99
|
|
|
98
100
|
if self.run_solve == "guess_check_div" or self.run_solve == "all":
|
|
101
|
+
self.diversity=True
|
|
99
102
|
self.get_message('guess_check_div')
|
|
100
103
|
self.search_subsetmin(timer, 'guess_check_div')
|
|
101
104
|
|
|
@@ -104,7 +107,7 @@ class Reasoning(HybridReasoning):
|
|
|
104
107
|
self.get_message('minimize')
|
|
105
108
|
if self.network.is_subseed:
|
|
106
109
|
self.asp_files.append(self.asp.ASP_SRC_MAXIMIZE_PRODUCED_TARGET)
|
|
107
|
-
|
|
110
|
+
print_log(self.logger, 'POSSIBLE SEED: Given\n A subset of possible seed is search \n maximising the number of produced target', 'info')
|
|
108
111
|
self.clingo_constant.append('-c')
|
|
109
112
|
self.clingo_constant.append('subseed=1')
|
|
110
113
|
self.asp_files.append(self.asp.ASP_SRC_MINIMIZE)
|
|
@@ -143,7 +146,7 @@ class Reasoning(HybridReasoning):
|
|
|
143
146
|
asp_files (list): List of ASP files, included th network asp file saved in temp directory
|
|
144
147
|
"""
|
|
145
148
|
timer = dict()
|
|
146
|
-
|
|
149
|
+
print_log(self.logger, 'GROUNDING...', 'info')
|
|
147
150
|
time_ground = time()
|
|
148
151
|
const_option = ""
|
|
149
152
|
const_option = ' '.join(self.clingo_constant)
|
|
@@ -167,21 +170,21 @@ class Reasoning(HybridReasoning):
|
|
|
167
170
|
seeds = list()
|
|
168
171
|
|
|
169
172
|
if self.optimum is None:
|
|
170
|
-
|
|
173
|
+
print_log(self.logger, '\tNo seed found', 'info')
|
|
171
174
|
else:
|
|
172
175
|
self.get_separate_optimum()
|
|
173
|
-
|
|
176
|
+
print_log(self.logger, f"Optimum found.", "info")
|
|
174
177
|
if self.network.is_subseed:
|
|
175
|
-
|
|
176
|
-
|
|
178
|
+
print_log(self.logger, (f"Number of producible targets: {- self.opt_prod_tgt}"), 'info', self.verbose)
|
|
179
|
+
print_log(self.logger, f"Minimal size of seed set is {self.opt_size}\n", 'info', self.verbose)
|
|
177
180
|
if self.opt_size > 0:
|
|
178
181
|
seeds = [args[0] for args in one_model.get('seed', ())]
|
|
179
182
|
seeds=list(sorted(seeds))
|
|
180
183
|
else:
|
|
181
184
|
seeds = []
|
|
182
185
|
if self.network.keep_import_reactions:
|
|
183
|
-
|
|
184
|
-
#
|
|
186
|
+
print_log(self.logger, "Try with the option remove import reactions.", 'info', self.verbose)
|
|
187
|
+
#print_log(self.logger, f"\nOne solution:\n{', '.join(map(str, seeds))}\n", 'info')
|
|
185
188
|
solution_list['model_one_solution'] = ["size", self.opt_size] + \
|
|
186
189
|
["Set of seeds", seeds]
|
|
187
190
|
|
|
@@ -195,7 +198,7 @@ class Reasoning(HybridReasoning):
|
|
|
195
198
|
timer (dict): Timer dictionnary containing grouding time
|
|
196
199
|
step (str, optional): step solving mode (classic, filter, guess_check, guess_check_div). Defaults to "classic".
|
|
197
200
|
"""
|
|
198
|
-
|
|
201
|
+
print_log(self.logger, "Finding optimum...", "info")
|
|
199
202
|
self.solve("minimize-one-model", timer, self.asp_files, step, True)
|
|
200
203
|
|
|
201
204
|
if not self.optimum_found:
|
|
@@ -211,7 +214,7 @@ class Reasoning(HybridReasoning):
|
|
|
211
214
|
self.solve("minimize-intersection", timer, self.asp_files, step)
|
|
212
215
|
else:
|
|
213
216
|
self.get_message('intersection')
|
|
214
|
-
|
|
217
|
+
print_log(self.logger, f"\nNot computed: {opti_message}", "error")
|
|
215
218
|
|
|
216
219
|
if self.union:
|
|
217
220
|
if ok_opti:
|
|
@@ -219,7 +222,7 @@ class Reasoning(HybridReasoning):
|
|
|
219
222
|
self.solve("minimize-union", timer, self.asp_files, step)
|
|
220
223
|
else:
|
|
221
224
|
self.get_message('union')
|
|
222
|
-
|
|
225
|
+
print_log(self.logger, f"\nNot computed: {opti_message}", "error")
|
|
223
226
|
|
|
224
227
|
if self.enumeration:
|
|
225
228
|
if ok_opti:
|
|
@@ -227,7 +230,7 @@ class Reasoning(HybridReasoning):
|
|
|
227
230
|
self.solve("minimize-enumeration", timer, self.asp_files, step)
|
|
228
231
|
else:
|
|
229
232
|
self.get_message('enumeration')
|
|
230
|
-
|
|
233
|
+
print_log(self.logger, f"\nNot computed: {opti_message}", "error")
|
|
231
234
|
|
|
232
235
|
|
|
233
236
|
def search_subsetmin(self, timer:dict, step:str="classic"):
|
|
@@ -247,7 +250,7 @@ class Reasoning(HybridReasoning):
|
|
|
247
250
|
|
|
248
251
|
if self.intersection:
|
|
249
252
|
self.get_message('intersection')
|
|
250
|
-
|
|
253
|
+
print_log(self.logger, "SOLVING...\n", "info")
|
|
251
254
|
self.solve("submin-intersection", timer, self.asp_files, step)
|
|
252
255
|
|
|
253
256
|
|
|
@@ -282,7 +285,7 @@ class Reasoning(HybridReasoning):
|
|
|
282
285
|
is_one_model (bool, optional): Define if it is the minimizing one model we are searching. Defaults to False.
|
|
283
286
|
"""
|
|
284
287
|
|
|
285
|
-
|
|
288
|
+
print_log(self.logger, "SOLVING...\n", "info")
|
|
286
289
|
results = dict()
|
|
287
290
|
one_model = None
|
|
288
291
|
number_rejected = None
|
|
@@ -305,7 +308,7 @@ class Reasoning(HybridReasoning):
|
|
|
305
308
|
time_limit=self.time_limit).discard_quotes.by_predicate
|
|
306
309
|
time_solve = time() - time_solve
|
|
307
310
|
self.get_message("command")
|
|
308
|
-
|
|
311
|
+
print_log(self.logger, f'{models.command}', 'debug')
|
|
309
312
|
for model, opt, optimum_found in models.by_arity.with_optimality:
|
|
310
313
|
if optimum_found:
|
|
311
314
|
self.optimum_found = True
|
|
@@ -318,7 +321,7 @@ class Reasoning(HybridReasoning):
|
|
|
318
321
|
else:
|
|
319
322
|
self.optimum = 0
|
|
320
323
|
if not self.optimum_found:
|
|
321
|
-
|
|
324
|
+
print_log(self.logger, 'Optimum not found', "error")
|
|
322
325
|
else:
|
|
323
326
|
solution_list, seeds = self.write_one_model_solution(one_model)
|
|
324
327
|
self.network.add_result_seeds('REASONING', search_mode, model_type, len(seeds), seeds)
|
|
@@ -340,7 +343,7 @@ class Reasoning(HybridReasoning):
|
|
|
340
343
|
time_limit=self.time_limit).discard_quotes.by_predicate
|
|
341
344
|
time_solve = time() - time_solve
|
|
342
345
|
self.get_message("command")
|
|
343
|
-
|
|
346
|
+
print_log(self.logger, f'{models.command}', 'debug')
|
|
344
347
|
has_solution=False
|
|
345
348
|
for model in models:
|
|
346
349
|
has_solution=True
|
|
@@ -357,7 +360,7 @@ class Reasoning(HybridReasoning):
|
|
|
357
360
|
solution_list, _ = self.complete_solutions(solution_list, 'model_'+ model_type, len(seeds), seeds)
|
|
358
361
|
self.network.add_result_seeds('REASONING', search_mode, model_type, len(seeds), seeds)
|
|
359
362
|
else:
|
|
360
|
-
|
|
363
|
+
print_log(self.logger, 'Unsatisfiable problem', "error")
|
|
361
364
|
|
|
362
365
|
# FILTER OR GUESS-CHECK mode
|
|
363
366
|
#TODO redo intersection and union mode
|
|
@@ -401,7 +404,7 @@ class Reasoning(HybridReasoning):
|
|
|
401
404
|
models = clyngor.solve(files=asp_files, options=construct_option,
|
|
402
405
|
time_limit=self.time_limit, nb_model=self.number_solution).discard_quotes.by_predicate
|
|
403
406
|
self.get_message("command")
|
|
404
|
-
|
|
407
|
+
print_log(self.logger, f'{models.command}', 'debug')
|
|
405
408
|
idx = 1
|
|
406
409
|
m = models
|
|
407
410
|
models_list = list(m).copy()
|
|
@@ -428,7 +431,7 @@ class Reasoning(HybridReasoning):
|
|
|
428
431
|
self.network.add_result_seeds('REASONING', search_mode, 'model_'+str(idx), size, seeds, transferred_list=trans_solution_list)
|
|
429
432
|
idx += 1
|
|
430
433
|
else:
|
|
431
|
-
|
|
434
|
+
print_log(self.logger, 'Unsatisfiable problem', "error")
|
|
432
435
|
return solution_list
|
|
433
436
|
|
|
434
437
|
|
seed2lp/reasoningcom.py
CHANGED
|
@@ -6,7 +6,7 @@ from . import color, logger
|
|
|
6
6
|
from multiprocessing import Process, Queue
|
|
7
7
|
from os import path
|
|
8
8
|
from json import loads
|
|
9
|
-
|
|
9
|
+
from .logger import init_logger, print_log
|
|
10
10
|
|
|
11
11
|
USE_MULTIPROCESSING=True
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@ USE_MULTIPROCESSING=True
|
|
|
14
14
|
################# Class Reasoning : herit Solver ##################
|
|
15
15
|
###################################################################
|
|
16
16
|
class ComReasoning(Reasoning):
|
|
17
|
-
def __init__(self, run_mode:str, run_solve:str, network:Network,
|
|
17
|
+
def __init__(self, run_mode:str, run_solve:str, network:Network, log_path:str,
|
|
18
18
|
time_limit_minute:float=None, number_solution:int=None,
|
|
19
19
|
clingo_configuration:str=None, clingo_strategy:str=None,
|
|
20
20
|
intersection:bool=False, union:bool=False,
|
|
@@ -39,7 +39,7 @@ class ComReasoning(Reasoning):
|
|
|
39
39
|
short_option (str, optional): Short way to write option on filename. Defaults to None.
|
|
40
40
|
verbose (bool, optional): Set debug mode. Defaults to False.
|
|
41
41
|
"""
|
|
42
|
-
super().__init__(run_mode, run_solve, network,
|
|
42
|
+
super().__init__(run_mode, run_solve, network, log_path,
|
|
43
43
|
time_limit_minute, number_solution,
|
|
44
44
|
clingo_configuration, clingo_strategy,
|
|
45
45
|
intersection, union,
|
|
@@ -114,6 +114,9 @@ class ComReasoning(Reasoning):
|
|
|
114
114
|
Returns:
|
|
115
115
|
solution_list (dict): a dictionnary of all found solutions
|
|
116
116
|
"""
|
|
117
|
+
|
|
118
|
+
# Init logger for child process
|
|
119
|
+
init_logger(self.log_path, self.verbose)
|
|
117
120
|
|
|
118
121
|
cobra_flux=None
|
|
119
122
|
# Guess_check or Guess_check diversity mode
|
|
@@ -197,12 +200,12 @@ class ComReasoning(Reasoning):
|
|
|
197
200
|
res = self.network.check_seeds(seeds, trans_solution_list)
|
|
198
201
|
if res[0]:
|
|
199
202
|
# valid solution
|
|
200
|
-
|
|
203
|
+
print_log(self.logger, f'CHECK Solution {size_seeds} seeds -> OK\n', 'debug', verbose=self.verbose)
|
|
201
204
|
cobra_flux=res[1]
|
|
202
205
|
self.network.add_result_seeds(mode, "Community bisteps", 'model_'+str(idx), size_seeds, seeds, flux_cobra=cobra_flux, transferred_list=trans_solution_list)
|
|
203
206
|
keep_solution=True
|
|
204
207
|
else:
|
|
205
|
-
|
|
208
|
+
print_log(self.logger, f'CHECK Solution {size_seeds} seeds -> KO\n', 'debug', verbose=self.verbose)
|
|
206
209
|
number_rejected +=1
|
|
207
210
|
keep_solution=False
|
|
208
211
|
current_timer = time() - start_time
|
|
@@ -240,12 +243,12 @@ class ComReasoning(Reasoning):
|
|
|
240
243
|
|
|
241
244
|
|
|
242
245
|
if step != "classic":
|
|
243
|
-
|
|
246
|
+
print_log(self.logger, f'Rejected solution during process: {number_rejected} \n', "info", verbose=self.verbose)
|
|
244
247
|
else:
|
|
245
248
|
number_rejected=None
|
|
246
249
|
|
|
247
250
|
if not any(solution_list):
|
|
248
|
-
|
|
251
|
+
print_log(self.logger, 'Unsatisfiable problem', "error", verbose=self.verbose)
|
|
249
252
|
|
|
250
253
|
if USE_MULTIPROCESSING:
|
|
251
254
|
queue.put([self, solution_list, None, current_timer, number_rejected])
|
|
@@ -336,15 +339,19 @@ class ComReasoning(Reasoning):
|
|
|
336
339
|
|
|
337
340
|
Args:
|
|
338
341
|
full_option (list): All Clingo option
|
|
339
|
-
solution_list (dict):
|
|
342
|
+
solution_list (dict): Dictionnary containg the solutions
|
|
340
343
|
step (str): step solving mode (classic, filter, guess_check, guess_check_div).
|
|
341
344
|
asp_files (list): List of needed ASP files to solve ASP (Clingo package)
|
|
342
345
|
queue (Queue, optional): Queue for multiprocessing program (managing time limit). Defaults to None.
|
|
343
346
|
full_path (str, optional): Full path of temporary solution file. Defaults to None.
|
|
344
347
|
|
|
345
348
|
Returns:
|
|
346
|
-
|
|
349
|
+
list, int: List of solutions and numer of rejected solutions
|
|
347
350
|
"""
|
|
351
|
+
|
|
352
|
+
# Init logger for child process
|
|
353
|
+
init_logger(self.log_path, self.verbose)
|
|
354
|
+
|
|
348
355
|
all_time_solve = 0
|
|
349
356
|
all_time_ground = 0
|
|
350
357
|
dict_by_size_seeds=dict()
|
|
@@ -396,11 +403,11 @@ class ComReasoning(Reasoning):
|
|
|
396
403
|
res = self.network.check_seeds(seeds, trans_solution_list)
|
|
397
404
|
if res[0]:
|
|
398
405
|
# valid solution
|
|
399
|
-
|
|
406
|
+
print_log(self.logger, f'CHECK Solution {size} seeds -> OK\n', 'debug', verbose=self.verbose)
|
|
400
407
|
cobra_flux=res[1]
|
|
401
408
|
keep_solution=True
|
|
402
409
|
else:
|
|
403
|
-
|
|
410
|
+
print_log(self.logger, f'CHECK Solution {size} seeds -> KO\n', 'debug', verbose=self.verbose)
|
|
404
411
|
number_rejected +=1
|
|
405
412
|
keep_solution=False
|
|
406
413
|
current_timer = time() - start_time
|
|
@@ -477,7 +484,7 @@ class ComReasoning(Reasoning):
|
|
|
477
484
|
solution_list = self.add_print_solution(solution_list, dict_by_size_seeds, mode, cobra_flux)
|
|
478
485
|
|
|
479
486
|
if step != "classic":
|
|
480
|
-
|
|
487
|
+
print_log(self.logger, f'Rejected solution during process: {number_rejected} \n', "info", verbose=self.verbose)
|
|
481
488
|
else:
|
|
482
489
|
number_rejected=None
|
|
483
490
|
|
|
@@ -590,13 +597,13 @@ class ComReasoning(Reasoning):
|
|
|
590
597
|
number_rejected = solution[3]
|
|
591
598
|
|
|
592
599
|
except Exception as e:
|
|
593
|
-
|
|
600
|
+
print_log(self.logger, f"An error occured while reading temporary file\n {full_path}:\n {e}", 'error', self.verbose)
|
|
594
601
|
|
|
595
602
|
if any(solution_list):
|
|
596
603
|
solution_list = self.add_print_solution(solution_list, dict_by_size_seeds, mode, flux_cobra)
|
|
597
604
|
|
|
598
605
|
if step != "classic":
|
|
599
|
-
|
|
606
|
+
print_log(self.logger, f'Rejected solution during process: at least {number_rejected} \n', 'info', self.verbose)
|
|
600
607
|
|
|
601
608
|
delete(full_path)
|
|
602
609
|
return solution_list, number_rejected
|
|
@@ -642,7 +649,7 @@ class ComReasoning(Reasoning):
|
|
|
642
649
|
else:
|
|
643
650
|
time_out = True
|
|
644
651
|
if time_out:
|
|
645
|
-
|
|
652
|
+
print_log(self.logger, f'Time out: {self.time_limit_minute} min expired', "error", verbose=self.verbose)
|
|
646
653
|
|
|
647
654
|
match step:
|
|
648
655
|
case "classic":
|
|
@@ -659,7 +666,7 @@ class ComReasoning(Reasoning):
|
|
|
659
666
|
queue.close()
|
|
660
667
|
|
|
661
668
|
if not any(solution_list):
|
|
662
|
-
|
|
669
|
+
print_log(self.logger, 'Unsatisfiable problem', "error", verbose=self.verbose)
|
|
663
670
|
|
|
664
671
|
if time_ground != None:
|
|
665
672
|
if time_ground != -1:
|
|
@@ -694,10 +701,10 @@ class ComReasoning(Reasoning):
|
|
|
694
701
|
match search_mode, step:
|
|
695
702
|
# CLASSIC MODE (NO FILTER, NO GUESS-CHECK)
|
|
696
703
|
case "minimize-enumeration" | "minimize-one-model", _:
|
|
697
|
-
|
|
704
|
+
print_log(self.logger, "No minimisation in community", "warning", verbose=self.verbose)
|
|
698
705
|
|
|
699
706
|
case "submin-enumeration", _:
|
|
700
|
-
|
|
707
|
+
print_log(self.logger, "SOLVING...\n", "info", verbose=self.verbose)
|
|
701
708
|
if USE_MULTIPROCESSING:
|
|
702
709
|
self.run_multiprocess(full_option, solution_list, step, asp_files, timer, output_type, suffix, search_mode)
|
|
703
710
|
else :
|
|
@@ -727,13 +734,13 @@ class ComReasoning(Reasoning):
|
|
|
727
734
|
match search_mode, step:
|
|
728
735
|
# CLASSIC MODE (NO FILTER, NO GUESS-CHECK)
|
|
729
736
|
case "minimize-enumeration" | "minimize-one-model", _:
|
|
730
|
-
|
|
737
|
+
print_log(self.logger, "No minimisation in community", "warning", verbose=self.verbose)
|
|
731
738
|
|
|
732
739
|
# Because of specific analyse of solution with "manual deletion of previous superset"
|
|
733
740
|
# All solving mode are in one function (classic, filter, guess check and gues check div)
|
|
734
741
|
# unlike all other community modes (or signle network modes)
|
|
735
742
|
case "submin-enumeration", "classic" | "filter" | "guess_check" | "guess_check_div":
|
|
736
|
-
|
|
743
|
+
print_log(self.logger, "SOLVING...\n", "info", verbose=self.verbose)
|
|
737
744
|
|
|
738
745
|
# Time limit may not work well if no solutions found within time limit
|
|
739
746
|
# But save time from writting into temporary file
|
seed2lp/reasoninghybrid.py
CHANGED
|
@@ -3,7 +3,8 @@ from .network import Network
|
|
|
3
3
|
from multiprocessing import Process, Queue
|
|
4
4
|
from .file import save, delete, write_instance_file, load_tsv, existing_file
|
|
5
5
|
import clingo
|
|
6
|
-
from . import color
|
|
6
|
+
from . import color
|
|
7
|
+
from .logger import init_logger, print_log
|
|
7
8
|
from os import path
|
|
8
9
|
import random
|
|
9
10
|
from time import time
|
|
@@ -13,7 +14,7 @@ from json import loads
|
|
|
13
14
|
############# Class HybridReasoning : herit Solver ################
|
|
14
15
|
###################################################################
|
|
15
16
|
class HybridReasoning(Solver):
|
|
16
|
-
def __init__(self, run_mode:str, network:Network,
|
|
17
|
+
def __init__(self, run_mode:str, network:Network, log_path:str,
|
|
17
18
|
time_limit_minute:float=None, number_solution:int=None,
|
|
18
19
|
clingo_configuration:str=None, clingo_strategy:str=None,
|
|
19
20
|
intersection:bool=False, union:bool=False,
|
|
@@ -37,7 +38,7 @@ class HybridReasoning(Solver):
|
|
|
37
38
|
short_option (str, optional): Short way to write option on filename. Defaults to None.
|
|
38
39
|
verbose (bool, optional): Set debug mode. Defaults to False.
|
|
39
40
|
"""
|
|
40
|
-
super().__init__(run_mode, network, time_limit_minute, number_solution, clingo_configuration,
|
|
41
|
+
super().__init__(run_mode, network, log_path, time_limit_minute, number_solution, clingo_configuration,
|
|
41
42
|
clingo_strategy, intersection, union, minimize, subset_minimal,
|
|
42
43
|
temp_dir, short_option, run_solve, verbose, community_mode)
|
|
43
44
|
|
|
@@ -76,7 +77,7 @@ class HybridReasoning(Solver):
|
|
|
76
77
|
ctrl.ground([("diversity",[])])
|
|
77
78
|
|
|
78
79
|
self.get_message("command")
|
|
79
|
-
|
|
80
|
+
print_log(self.logger, 'clingo ' + ' '.join(full_option) + ' ' + ' '.join(asp_files), 'debug', verbose=self.verbose)
|
|
80
81
|
return ctrl
|
|
81
82
|
|
|
82
83
|
|
|
@@ -385,9 +386,9 @@ class HybridReasoning(Solver):
|
|
|
385
386
|
solution_list[solution[0]] = sol
|
|
386
387
|
#get the last occurence pf rejected solutions number
|
|
387
388
|
number_rejected = solution[3]
|
|
388
|
-
|
|
389
|
+
print_log(self.logger, f'Rejected solution during process: at least {number_rejected} \n', 'info', verbose=self.verbose)
|
|
389
390
|
except Exception as e:
|
|
390
|
-
|
|
391
|
+
print_log(self.logger, f"An error occured while reading temporary file\n {full_path}:\n {e}", 'error', verbose=self.verbose)
|
|
391
392
|
|
|
392
393
|
if any(solution_list):
|
|
393
394
|
for name in solution_list:
|
|
@@ -453,7 +454,7 @@ class HybridReasoning(Solver):
|
|
|
453
454
|
else:
|
|
454
455
|
time_out = True
|
|
455
456
|
if time_out:
|
|
456
|
-
|
|
457
|
+
print_log(self.logger, f'Time out: {self.time_limit_minute} min expired', "error", self.verbose)
|
|
457
458
|
|
|
458
459
|
solution_list, number_rejected = self.get_solution_from_temp(unsat, is_one_model, full_path, suffix, search_mode)
|
|
459
460
|
p.terminate()
|
|
@@ -461,10 +462,10 @@ class HybridReasoning(Solver):
|
|
|
461
462
|
|
|
462
463
|
if is_one_model:
|
|
463
464
|
if not self.optimum_found:
|
|
464
|
-
|
|
465
|
+
print_log(self.logger, 'Optimum not found', "error", self.verbose)
|
|
465
466
|
else:
|
|
466
467
|
if not any(solution_list):
|
|
467
|
-
|
|
468
|
+
print_log(self.logger, 'Unsatisfiable problem', "error", self.verbose)
|
|
468
469
|
|
|
469
470
|
return time_solve, time_ground, solution_list, number_rejected
|
|
470
471
|
|
|
@@ -528,6 +529,9 @@ class HybridReasoning(Solver):
|
|
|
528
529
|
is_one_model (bool, optional): Define if the solution we want is to fin the optimum when minimize is used (before enumration).
|
|
529
530
|
Defaults to False.
|
|
530
531
|
"""
|
|
532
|
+
# Init logger for child process
|
|
533
|
+
init_logger(self.log_path, self.verbose)
|
|
534
|
+
|
|
531
535
|
solution_list = dict()
|
|
532
536
|
|
|
533
537
|
no_limit_solution = False
|
|
@@ -554,7 +558,7 @@ class HybridReasoning(Solver):
|
|
|
554
558
|
res = self.network.check_seeds(seeds, trans_solution_list)
|
|
555
559
|
if res[0]:
|
|
556
560
|
# valid solution
|
|
557
|
-
|
|
561
|
+
print_log(self.logger, f'CHECK Solution {size} seeds -> OK\n', 'debug', verbose=self.verbose)
|
|
558
562
|
|
|
559
563
|
message = color.cyan_light + f"Answer: {solution_idx}{color.reset} ({size} seeds{transf_short})\n"
|
|
560
564
|
self.print_answer(message, seeds, seeds_full, trans_complete)
|
|
@@ -567,7 +571,7 @@ class HybridReasoning(Solver):
|
|
|
567
571
|
self.network.add_result_seeds('REASONING FILTER', search_mode, name, size, seeds, flux_cobra=res[1], transferred_list=trans_solution_list)
|
|
568
572
|
solution_idx +=1
|
|
569
573
|
else:
|
|
570
|
-
|
|
574
|
+
print_log(self.logger, f'CHECK Solution {size} seeds -> KO\n', 'debug', verbose=self.verbose)
|
|
571
575
|
number_rejected +=1
|
|
572
576
|
current_timer = time() - start_time
|
|
573
577
|
# write all 100 rejected
|
|
@@ -588,7 +592,7 @@ class HybridReasoning(Solver):
|
|
|
588
592
|
else:
|
|
589
593
|
break
|
|
590
594
|
|
|
591
|
-
|
|
595
|
+
print_log(self.logger, f'Rejected solution during process: {number_rejected} \n', "info", verbose=self.verbose)
|
|
592
596
|
|
|
593
597
|
stats = ctrl.statistics
|
|
594
598
|
total_time = stats["summary"]["times"]["total"]
|
|
@@ -598,10 +602,10 @@ class HybridReasoning(Solver):
|
|
|
598
602
|
# Because it is needed to get all answers from clingo to have optimum, we save it after
|
|
599
603
|
# No minimize in community mode
|
|
600
604
|
if is_one_model and self.optimum_found:
|
|
601
|
-
|
|
605
|
+
print_log(self.logger, f"Optimum found.", "info", verbose=self.verbose)
|
|
602
606
|
if self.network.is_subseed:
|
|
603
|
-
|
|
604
|
-
|
|
607
|
+
print_log(self.logger, f"Number of producible targets: {- self.opt_prod_tgt}", "info", verbose=self.verbose)
|
|
608
|
+
print_log(self.logger, f"Minimal size of seed set is {self.opt_size}\n", "info", verbose=self.verbose)
|
|
605
609
|
save(full_path, self.temp_dir, solution_temp, "tsv", True)
|
|
606
610
|
self.network.add_result_seeds('REASONING FILTER', search_mode, name, size, seeds, flux_cobra=res[1], transferred_list=trans_solution_list)
|
|
607
611
|
|
|
@@ -662,6 +666,9 @@ class HybridReasoning(Solver):
|
|
|
662
666
|
is_one_model (bool, optional): Define if the solution we want is to fin the optimum when minimize is used (before enumration).
|
|
663
667
|
Defaults to False.
|
|
664
668
|
"""
|
|
669
|
+
# Init logger for child process
|
|
670
|
+
init_logger(self.log_path, self.verbose)
|
|
671
|
+
|
|
665
672
|
solution_list = dict()
|
|
666
673
|
avoided = []
|
|
667
674
|
all_time_solve = 0
|
|
@@ -724,7 +731,7 @@ class HybridReasoning(Solver):
|
|
|
724
731
|
all_time_ground += float(time_ground)
|
|
725
732
|
res = self.network.check_seeds(seeds, trans_solution_list)
|
|
726
733
|
if res[0]:
|
|
727
|
-
|
|
734
|
+
print_log(self.logger, f'CHECK Solution {size} seeds -> OK\n', 'debug', verbose=self.verbose)
|
|
728
735
|
# valid solution
|
|
729
736
|
if not is_one_model:
|
|
730
737
|
message = color.cyan_light + f"Answer: {solution_idx}{color.reset} ({size} seeds{transf_short})\n"
|
|
@@ -743,26 +750,24 @@ class HybridReasoning(Solver):
|
|
|
743
750
|
name = 'model_one_solution'
|
|
744
751
|
solution_list, solution_temp = self.complete_solutions(solution_list, name, size, seeds,
|
|
745
752
|
trans_solution_list, res[1], number_rejected)
|
|
746
|
-
|
|
753
|
+
print_log(self.logger, f"Optimum found.", "info", verbose=self.verbose)
|
|
747
754
|
self.optimum_found = True
|
|
748
|
-
mode =
|
|
755
|
+
mode = self.get_gc_mode()
|
|
749
756
|
# Do not exclude superset because we will rerun the minimize by set the size
|
|
750
757
|
# and we want to find back this first minimize found
|
|
751
758
|
if self.diversity:
|
|
752
759
|
ctrl, avoided = self.add_diversity(ctrl, seeds, avoided)
|
|
753
|
-
mode = 'REASONING GUESS-CHECK DIVERSITY'
|
|
754
760
|
save(full_path, self.temp_dir, solution_temp, "tsv", True)
|
|
755
|
-
|
|
756
761
|
self.network.add_result_seeds(mode, search_mode, name, size, seeds, flux_cobra=res[1], transferred_list=trans_solution_list)
|
|
757
762
|
self.get_separate_optimum()
|
|
758
763
|
if self.network.is_subseed:
|
|
759
|
-
|
|
760
|
-
|
|
764
|
+
print_log(self.logger, f"Number of producible targets: {- self.opt_prod_tgt}", "info", verbose=self.verbose)
|
|
765
|
+
print_log(self.logger, f"Minimal size of seed set is {self.opt_size}\n", "info", verbose=self.verbose)
|
|
761
766
|
break
|
|
762
767
|
|
|
763
768
|
else:
|
|
764
|
-
|
|
765
|
-
#
|
|
769
|
+
print_log(self.logger, f'CHECK Solution {size} seeds -> KO\n', 'debug', verbose=self.verbose)
|
|
770
|
+
#print_log(self.logger, f'{seeds}\n', 'debug')
|
|
766
771
|
|
|
767
772
|
ctrl, avoided= self.guess_check_constraints(ctrl, atoms, seeds, avoided)
|
|
768
773
|
mode = self.get_gc_mode()
|
|
@@ -782,7 +787,7 @@ class HybridReasoning(Solver):
|
|
|
782
787
|
|
|
783
788
|
if not is_one_model:
|
|
784
789
|
save(full_path, "", solution_temp, "tsv", True)
|
|
785
|
-
|
|
790
|
+
print_log(self.logger, f'Rejected solution during process: {number_rejected} \n', 'info', verbose=self.verbose)
|
|
786
791
|
|
|
787
792
|
ctrl.cleanup()
|
|
788
793
|
ctrl.interrupt()
|
seed2lp/sbml.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Routines to extract information from SBML files.
|
|
2
2
|
|
|
3
3
|
"""
|
|
4
|
+
import logging
|
|
4
5
|
import xml.etree.ElementTree as ET
|
|
5
6
|
from re import sub, match, search
|
|
6
|
-
from . import logger
|
|
7
|
+
#from . import logger
|
|
7
8
|
|
|
8
9
|
def register_all_namespaces(file:str):
|
|
9
10
|
"""Get namespaces for rewriting SBML file
|
|
@@ -245,6 +246,7 @@ def get_used_metabolites(filename, call_log=False)-> set:
|
|
|
245
246
|
Returns:
|
|
246
247
|
used_metabolites (set): Set of used metabolites
|
|
247
248
|
"""
|
|
249
|
+
logger = logging.getLogger("s2lp")
|
|
248
250
|
tree = ET.parse(filename)
|
|
249
251
|
sbml = tree.getroot()
|
|
250
252
|
model = get_model(sbml)
|
|
@@ -262,7 +264,7 @@ def get_used_metabolites(filename, call_log=False)-> set:
|
|
|
262
264
|
ubound = parameters[reaction.attrib.get('{'+fbc+'}upperFluxBound')]
|
|
263
265
|
lbound = parameters[reaction.attrib.get('{'+fbc+'}lowerFluxBound')]
|
|
264
266
|
if float(ubound) == 0 and float(lbound) == 0 and call_log:
|
|
265
|
-
logger.
|
|
267
|
+
logger.warning(f"Reaction {reaction.attrib['id']} deleted, boudaries [0,0]")
|
|
266
268
|
continue
|
|
267
269
|
else:
|
|
268
270
|
reactants,_ = get_listOfReactants(reaction,"",False)
|