From 8146469d6a3b305debb654cf8225a76a6407f13f Mon Sep 17 00:00:00 2001 From: lhtxa Date: Tue, 15 Oct 2024 16:13:43 +0200 Subject: [PATCH 1/2] fix --- reframed/cobra/simulation.py | 51 ++++++++++++++++--------------- reframed/solvers/cplex_solver.py | 22 ++++++++++++- reframed/solvers/gurobi_solver.py | 22 +++++++++++++ reframed/solvers/scip_solver.py | 29 +++++++++++++++++- reframed/solvers/solver.py | 16 ++++------ 5 files changed, 104 insertions(+), 36 deletions(-) diff --git a/reframed/cobra/simulation.py b/reframed/cobra/simulation.py index 0a5a3a9..0869de3 100644 --- a/reframed/cobra/simulation.py +++ b/reframed/cobra/simulation.py @@ -70,9 +70,9 @@ def pFBA(model, objective=None, obj_frac=None, minimize=False, constraints=None, return pre_solution if obj_frac is None: - solver.add_constraint('obj', objective, '=', pre_solution.fobj, update=False) + solver.add_constraint('obj', objective, '=', pre_solution.fobj) else: - solver.add_constraint('obj', objective, '>', obj_frac * pre_solution.fobj, update=False) + solver.add_constraint('obj', objective, '>', obj_frac * pre_solution.fobj) if not reactions: reactions = model.reactions.keys() @@ -82,15 +82,15 @@ def pFBA(model, objective=None, obj_frac=None, minimize=False, constraints=None, for r_id in reactions: if model.reactions[r_id].reversible: pos, neg = r_id + '_p', r_id + '_n' - solver.add_variable(pos, 0, inf, update=False) - solver.add_variable(neg, 0, inf, update=False) - solver.update() + solver.add_variable(pos, 0, inf) + solver.add_variable(neg, 0, inf) + #solver.update() for r_id in reactions: if model.reactions[r_id].reversible: pos, neg = r_id + '_p', r_id + '_n' - solver.add_constraint('c' + pos, {r_id: -1, pos: 1}, '>', 0, update=False) - solver.add_constraint('c' + neg, {r_id: 1, neg: 1}, '>', 0, update=False) - solver.update() + solver.add_constraint('c' + pos, {r_id: -1, pos: 1}, '>', 0) + solver.add_constraint('c' + neg, {r_id: 1, neg: 1}, '>', 0) + #solver.update() objective = dict() for r_id in reactions: @@ -100,6 +100,8 @@ def pFBA(model, objective=None, obj_frac=None, minimize=False, constraints=None, objective[neg] = 1 else: objective[r_id] = 1 + + solver.update() solution = solver.solve(objective, minimize=True, constraints=constraints) solution.pre_solution = pre_solution @@ -195,8 +197,8 @@ def CAFBA(model, objective=None, minimize=False, wc=0, we=8.3e-4, wr=0.169, pmax if carbon_source in model.reactions[r_id].stoichiometry: if model.reactions[r_id].reversible: pos, neg = r_id + '+', r_id + '-' - solver.add_variable(pos, 0, inf, update=False) - solver.add_variable(neg, 0, inf, update=False) + solver.add_variable(pos, 0, inf) + solver.add_variable(neg, 0, inf) uptake.append(r_id + '+') uptake.append(r_id + '-') splits[r_id] = pos, neg @@ -206,8 +208,8 @@ def CAFBA(model, objective=None, minimize=False, wc=0, we=8.3e-4, wr=0.169, pmax for r_id in model.get_reactions_by_type(ReactionType.ENZYMATIC): if model.reactions[r_id].reversible: pos, neg = r_id + '+', r_id + '-' - solver.add_variable(pos, 0, inf, update=False) - solver.add_variable(neg, 0, inf, update=False) + solver.add_variable(pos, 0, inf) + solver.add_variable(neg, 0, inf) enzymatic.append(r_id + '+') enzymatic.append(r_id + '-') splits[r_id] = pos, neg @@ -217,8 +219,8 @@ def CAFBA(model, objective=None, minimize=False, wc=0, we=8.3e-4, wr=0.169, pmax solver.update() for r_id, (pos, neg) in splits.items(): - solver.add_constraint('c' + pos, {r_id: -1, pos: 1}, '>', 0, update=False) - solver.add_constraint('c' + neg, {r_id: 1, neg: 1}, '>', 0, update=False) + solver.add_constraint('c' + pos, {r_id: -1, pos: 1}, '>', 0) + solver.add_constraint('c' + neg, {r_id: 1, neg: 1}, '>', 0) solver.update() main_constr = {} @@ -228,10 +230,11 @@ def CAFBA(model, objective=None, minimize=False, wc=0, we=8.3e-4, wr=0.169, pmax main_constr[r_id] = wc main_constr[model.biomass_reaction] = wr - solver.add_constraint('alloc', main_constr, '=', pmax, update=True) - + solver.add_constraint('alloc', main_constr, '=', pmax) + solver.update() + solution = solver.solve(objective, minimize=minimize, constraints=constraints) - + solver.remove_constraint('alloc') if cleanup: @@ -308,13 +311,13 @@ def lMOMA(model, reference=None, constraints=None, reactions=None, solver=None): solver.lMOMA_flag = True for r_id in reactions: d_pos, d_neg = r_id + '_d+', r_id + '_d-' - solver.add_variable(d_pos, 0, inf, update=False) - solver.add_variable(d_neg, 0, inf, update=False) + solver.add_variable(d_pos, 0, inf) + solver.add_variable(d_neg, 0, inf) solver.update() for r_id in reactions: d_pos, d_neg = r_id + '_d+', r_id + '_d-' - solver.add_constraint('c' + d_pos, {r_id: -1, d_pos: 1}, '>', -reference[r_id], update=False) - solver.add_constraint('c' + d_neg, {r_id: 1, d_neg: 1}, '>', reference[r_id], update=False) + solver.add_constraint('c' + d_pos, {r_id: -1, d_pos: 1}, '>', -reference[r_id]) + solver.add_constraint('c' + d_neg, {r_id: 1, d_neg: 1}, '>', reference[r_id]) solver.update() objective = dict() @@ -370,7 +373,7 @@ def ROOM(model, reference=None, constraints=None, wt_constraints=None, reactions for r_id in reactions: y_i = 'y_' + r_id - solver.add_variable(y_i, 0, 1, vartype=VarType.BINARY, update=False) + solver.add_variable(y_i, 0, 1, vartype=VarType.BINARY) objective[y_i] = 1 solver.update() @@ -384,8 +387,8 @@ def ROOM(model, reference=None, constraints=None, wt_constraints=None, reactions w_i_max = reference[r_id] w_u = w_i_max + delta * abs(w_i_max) + epsilon w_l = w_i_min - delta * abs(w_i_min) - epsilon - solver.add_constraint('c' + r_id + '_u', {r_id: 1, y_i: (w_u - U)}, '<', w_u, update=False) - solver.add_constraint('c' + r_id + '_l', {r_id: 1, y_i: (w_l - L)}, '>', w_l, update=False) + solver.add_constraint('c' + r_id + '_u', {r_id: 1, y_i: (w_u - U)}, '<', w_u) + solver.add_constraint('c' + r_id + '_l', {r_id: 1, y_i: (w_l - L)}, '>', w_l) solver.update() if solutions == 1: diff --git a/reframed/solvers/cplex_solver.py b/reframed/solvers/cplex_solver.py index 6cf448f..626aef8 100644 --- a/reframed/solvers/cplex_solver.py +++ b/reframed/solvers/cplex_solver.py @@ -77,7 +77,6 @@ def add_variables(self, var_dict): def add_constraints(self, constr_dict): - constr_ids = list(constr_dict.keys()) lhs_all = [SparsePair(ind=list(lhs.keys()), val=list(lhs.values())) for (lhs, _, _) in constr_dict.values()] map_sense = {'=': 'E', '<': 'L', '>': 'G'} @@ -87,7 +86,28 @@ def add_constraints(self, constr_dict): self.problem.linear_constraints.add(lin_expr=lhs_all, senses=sense_all, rhs=rhs_all, names=constr_ids) self.constraints.extend(constr_ids) + def remove_constraint(self, constr_id): + """ Remove a constraint from the current problem. + Arguments: + constr_id (str): constraint identifier + """ + if constr_id in self.constraints: + self.problem.linear_constraints.delete(constr_id) + self.constraints.remove(constr_id) + + def update(self): + """ Update internal structure. Used for efficient lazy updating. """ + + if len(self._cached_vars) > 0: + self.add_variables(self._cached_vars) + self._cached_vars = {} + + if len(self._cached_constrs) > 0: + self.add_constraints(self._cached_constrs) + self._cached_constrs = {} + + def set_objective(self, objective, minimize=True): if isinstance(objective, str): diff --git a/reframed/solvers/gurobi_solver.py b/reframed/solvers/gurobi_solver.py index a8c0c5d..d7a0ff8 100644 --- a/reframed/solvers/gurobi_solver.py +++ b/reframed/solvers/gurobi_solver.py @@ -74,6 +74,28 @@ def add_constraints(self, constr_dict): self.constraints.extend(constr_dict.keys()) self.problem.update() + def remove_constraint(self, constr_id): + """ Remove a constraint from the current problem. + + Arguments: + constr_id (str): constraint identifier + """ + + if constr_id in self.constraints: + self.problem.remove(self.problem.getConstrByName(constr_id)) + self.constraints.remove(constr_id) + + def update(self): + """ Update internal structure. Used for efficient lazy updating. """ + + if len(self._cached_vars) > 0: + self.add_variables(self._cached_vars) + self._cached_vars = {} + + if len(self._cached_constrs) > 0: + self.add_constraints(self._cached_constrs) + self._cached_constrs = {} + def set_objective(self, objective, minimize=True): diff --git a/reframed/solvers/scip_solver.py b/reframed/solvers/scip_solver.py index 873a392..004ba45 100644 --- a/reframed/solvers/scip_solver.py +++ b/reframed/solvers/scip_solver.py @@ -97,7 +97,34 @@ def add_constraints(self, constr_dict): self._cons_dict[constr_id] = self.problem.addCons(constr, name=constr_id) self.constraints.extend(constr_dict.keys()) - + + def remove_constraint(self, constr_id): + """ Remove a constraint from the current problem. + + Arguments: + constr_id (str): constraint identifier + """ + + if constr_id in self.constraints: + self.problem.freeTransform() + self.problem.delCons(self._cons_dict[constr_id]) + del self._cons_dict[constr_id] + self.constraints.remove(constr_id) + + + def update(self): + """ Update internal structure. Used for efficient lazy updating. """ + + self.problem.freeTransform() + + if len(self._cached_vars) > 0: + self.add_variables(self._cached_vars) + self._cached_vars = {} + + if len(self._cached_constrs) > 0: + self.add_constraints(self._cached_constrs) + self._cached_constrs = {} + def set_objective(self, objective, minimize=True): diff --git a/reframed/solvers/solver.py b/reframed/solvers/solver.py index 93df49f..1f3a817 100644 --- a/reframed/solvers/solver.py +++ b/reframed/solvers/solver.py @@ -68,18 +68,14 @@ def add_constraint(self, constr_id, lhs, sense='=', rhs=0): def add_constraints(self, constr_dict): """ Solver specific implementation """ + pass - def update(self): - """ Update internal structure. Used for efficient lazy updating. """ - - if len(self._cached_vars) > 0: - self.add_variables(self._cached_vars) - self._cached_vars = {} - - if len(self._cached_constrs) > 0: - self.add_constraints(self._cached_constrs) - self._cached_constrs = {} + def remove_constraint(self, constr_id): + """ Solver specific implementation """ + pass + def update(self): + pass def build_problem(self, model): """ Create problem structure for a given model. From 26ae6de0f39a4246ba5244b96990d5ddceef88fa Mon Sep 17 00:00:00 2001 From: lhtxa Date: Tue, 15 Oct 2024 19:58:24 +0200 Subject: [PATCH 2/2] scip fixes --- reframed/solvers/cplex_solver.py | 11 ----------- reframed/solvers/gurobi_solver.py | 11 ----------- reframed/solvers/scip_solver.py | 18 +++--------------- reframed/solvers/solver.py | 10 +++++++++- 4 files changed, 12 insertions(+), 38 deletions(-) diff --git a/reframed/solvers/cplex_solver.py b/reframed/solvers/cplex_solver.py index 626aef8..89defbc 100644 --- a/reframed/solvers/cplex_solver.py +++ b/reframed/solvers/cplex_solver.py @@ -96,17 +96,6 @@ def remove_constraint(self, constr_id): self.problem.linear_constraints.delete(constr_id) self.constraints.remove(constr_id) - def update(self): - """ Update internal structure. Used for efficient lazy updating. """ - - if len(self._cached_vars) > 0: - self.add_variables(self._cached_vars) - self._cached_vars = {} - - if len(self._cached_constrs) > 0: - self.add_constraints(self._cached_constrs) - self._cached_constrs = {} - def set_objective(self, objective, minimize=True): diff --git a/reframed/solvers/gurobi_solver.py b/reframed/solvers/gurobi_solver.py index d7a0ff8..ccf5dd1 100644 --- a/reframed/solvers/gurobi_solver.py +++ b/reframed/solvers/gurobi_solver.py @@ -85,17 +85,6 @@ def remove_constraint(self, constr_id): self.problem.remove(self.problem.getConstrByName(constr_id)) self.constraints.remove(constr_id) - def update(self): - """ Update internal structure. Used for efficient lazy updating. """ - - if len(self._cached_vars) > 0: - self.add_variables(self._cached_vars) - self._cached_vars = {} - - if len(self._cached_constrs) > 0: - self.add_constraints(self._cached_constrs) - self._cached_constrs = {} - def set_objective(self, objective, minimize=True): diff --git a/reframed/solvers/scip_solver.py b/reframed/solvers/scip_solver.py index 004ba45..80d18bf 100644 --- a/reframed/solvers/scip_solver.py +++ b/reframed/solvers/scip_solver.py @@ -80,6 +80,7 @@ def __init__(self, model=None): def add_variables(self, var_dict): + self.problem.freeTransform() for var_id, (lb, ub, vartype) in var_dict.items(): lb = None if lb == -inf else lb @@ -90,7 +91,8 @@ def add_variables(self, var_dict): self.variables.extend(var_dict.keys()) def add_constraints(self, constr_dict): - + + self.problem.freeTransform() for constr_id, (lhs, sense, rhs) in constr_dict.items(): expr = quicksum(self._vars_dict[var_id] * coeff for var_id, coeff in lhs.items()) constr = sense_mapping[sense](expr,rhs) @@ -112,20 +114,6 @@ def remove_constraint(self, constr_id): self.constraints.remove(constr_id) - def update(self): - """ Update internal structure. Used for efficient lazy updating. """ - - self.problem.freeTransform() - - if len(self._cached_vars) > 0: - self.add_variables(self._cached_vars) - self._cached_vars = {} - - if len(self._cached_constrs) > 0: - self.add_constraints(self._cached_constrs) - self._cached_constrs = {} - - def set_objective(self, objective, minimize=True): if self.problem.getStage() > Stage.PRESOLVED.value: diff --git a/reframed/solvers/solver.py b/reframed/solvers/solver.py index 1f3a817..4c1160a 100644 --- a/reframed/solvers/solver.py +++ b/reframed/solvers/solver.py @@ -75,7 +75,15 @@ def remove_constraint(self, constr_id): pass def update(self): - pass + """ Update internal structure. Used for efficient lazy updating. """ + + if len(self._cached_vars) > 0: + self.add_variables(self._cached_vars) + self._cached_vars = {} + + if len(self._cached_constrs) > 0: + self.add_constraints(self._cached_constrs) + self._cached_constrs = {} def build_problem(self, model): """ Create problem structure for a given model.