def test_change_coefficient(self, solver_test): solver, old_solution, infeasible_model = solver_test c = Metabolite("c") c._bound = 6 x = Reaction("x") x.lower_bound = 1. y = Reaction("y") y.lower_bound = 0. x.add_metabolites({c: 1}) z = Reaction("z") z.add_metabolites({c: 1}) z.objective_coefficient = 1 m = Model("test_model") m.add_reactions([x, y, z]) # change an existing coefficient lp = solver.create_problem(m) solver.solve_problem(lp) sol1 = solver.format_solution(lp, m) assert sol1.status == "optimal" solver.change_coefficient(lp, 0, 0, 2) solver.solve_problem(lp) sol2 = solver.format_solution(lp, m) assert sol2.status == "optimal" assert abs(sol1.f - 5.0) < 10 ** -3 assert abs(sol2.f - 4.0) < 10 ** -3 # change a new coefficient z.objective_coefficient = 0. y.objective_coefficient = 1. lp = solver.create_problem(m) solver.change_coefficient(lp, 0, 1, 2) solver.solve_problem(lp) solution = solver.format_solution(lp, m) assert solution.status == "optimal" assert abs(solution.x_dict["y"] - 2.5) < 10 ** -3
def test_solve_mip(self, solver_test): solver, old_solution, infeasible_model = solver_test if not hasattr(solver, "_SUPPORTS_MILP") or not solver._SUPPORTS_MILP: pytest.skip("no milp support") cobra_model = Model('MILP_implementation_test') constraint = Metabolite("constraint") constraint._bound = 2.5 x = Reaction("x") x.lower_bound = 0. x.objective_coefficient = 1. x.add_metabolites({constraint: 2.5}) y = Reaction("y") y.lower_bound = 0. y.objective_coefficient = 1. y.add_metabolites({constraint: 1.}) cobra_model.add_reactions([x, y]) float_sol = solver.solve(cobra_model) # add an integer constraint y.variable_kind = "integer" int_sol = solver.solve(cobra_model) assert abs(float_sol.f - 2.5) < 10 ** -5 assert abs(float_sol.x_dict["y"] - 2.5) < 10 ** -5 assert int_sol.status == "optimal" assert abs(int_sol.f - 2.2) < 10 ** -3 assert abs(int_sol.x_dict["y"] - 2.0) < 10 ** -3
def test_quadratic(self, solver_test): solver, old_solution, infeasible_model = solver_test if not hasattr(solver, "set_quadratic_objective"): pytest.skip("no qp support") c = Metabolite("c") c._bound = 2 x = Reaction("x") x.objective_coefficient = -0.5 x.lower_bound = 0. y = Reaction("y") y.objective_coefficient = -0.5 y.lower_bound = 0. x.add_metabolites({c: 1}) y.add_metabolites({c: 1}) m = Model() m.add_reactions([x, y]) lp = solver.create_problem(m) quadratic_obj = scipy.sparse.eye(2) * 2 solver.set_quadratic_objective(lp, quadratic_obj) solver.solve_problem(lp, objective_sense="minimize") solution = solver.format_solution(lp, m) assert solution.status == "optimal" # Respecting linear objectives also makes the objective value 1. assert abs(solution.f - 1.) < 10 ** -3 assert abs(solution.x_dict["y"] - 1.) < 10 ** -3 assert abs(solution.x_dict["y"] - 1.) < 10 ** -3 # When the linear objectives are removed the objective value is 2. solver.change_variable_objective(lp, 0, 0.) solver.change_variable_objective(lp, 1, 0.) solver.solve_problem(lp, objective_sense="minimize") solution = solver.format_solution(lp, m) assert solution.status == "optimal" assert abs(solution.f - 2.) < 10 ** -3 # test quadratic from solve function solution = solver.solve(m, quadratic_component=quadratic_obj, objective_sense="minimize") assert solution.status == "optimal" assert abs(solution.f - 1.) < 10 ** -3 c._bound = 6 z = Reaction("z") x.objective_coefficient = 0. y.objective_coefficient = 0. z.lower_bound = 0. z.add_metabolites({c: 1}) m.add_reaction(z) solution = solver.solve(m, quadratic_component=scipy.sparse.eye(3), objective_sense="minimize") # should be 12 not 24 because 1/2 (V^T Q V) assert solution.status == "optimal" assert abs(solution.f - 6) < 10 ** -3 assert abs(solution.x_dict["x"] - 2) < 10 ** -6 assert abs(solution.x_dict["y"] - 2) < 10 ** -6 assert abs(solution.x_dict["z"] - 2) < 10 ** -6
def construct_ll_test_model(): test_model = Model() test_model.add_metabolites(Metabolite("A")) test_model.add_metabolites(Metabolite("B")) test_model.add_metabolites(Metabolite("C")) EX_A = Reaction("EX_A") EX_A.add_metabolites({test_model.metabolites.A: 1}) DM_C = Reaction("DM_C") DM_C.add_metabolites({test_model.metabolites.C: -1}) v1 = Reaction("v1") v1.add_metabolites({ test_model.metabolites.A: -1, test_model.metabolites.B: 1 }) v2 = Reaction("v2") v2.add_metabolites({ test_model.metabolites.B: -1, test_model.metabolites.C: 1 }) v3 = Reaction("v3") v3.add_metabolites({ test_model.metabolites.C: -1, test_model.metabolites.A: 1 }) test_model.add_reactions([EX_A, DM_C, v1, v2, v3]) DM_C.objective_coefficient = 1 return test_model
def test_add_reactions(self, model): r1 = Reaction('r1') r1.add_metabolites({Metabolite('A'): -1, Metabolite('B'): 1}) r1.lower_bound, r1.upper_bound = -999999., 999999. r2 = Reaction('r2') r2.add_metabolites({ Metabolite('A'): -1, Metabolite('C'): 1, Metabolite('D'): 1 }) r2.lower_bound, r2.upper_bound = 0., 999999. model.add_reactions([r1, r2]) r2.objective_coefficient = 3. assert r2.objective_coefficient == 3. assert model.reactions[-2] == r1 assert model.reactions[-1] == r2 assert isinstance(model.reactions[-2].reverse_variable, model.problem.Variable) coefficients_dict = model.objective.expression. \ as_coefficients_dict() biomass_r = model.reactions.get_by_id('Biomass_Ecoli_core') assert coefficients_dict[biomass_r.forward_variable] == 1. assert coefficients_dict[biomass_r.reverse_variable] == -1. assert coefficients_dict[model.reactions.r2.forward_variable] == 3. assert coefficients_dict[model.reactions.r2.reverse_variable] == -3.
def test_gapfilling(self): try: get_solver_name(mip=True) except SolverNotFound: pytest.skip("no MILP solver found") m = Model() m.add_metabolites(map(Metabolite, ["a", "b", "c"])) r = Reaction("EX_A") m.add_reaction(r) r.add_metabolites({m.metabolites.a: 1}) r = Reaction("r1") m.add_reaction(r) r.add_metabolites({m.metabolites.b: -1, m.metabolites.c: 1}) r = Reaction("DM_C") m.add_reaction(r) r.add_metabolites({m.metabolites.c: -1}) r.objective_coefficient = 1 U = Model() r = Reaction("a2b") U.add_reaction(r) r.build_reaction_from_string("a --> b", verbose=False) r = Reaction("a2d") U.add_reaction(r) r.build_reaction_from_string("a --> d", verbose=False) # GrowMatch result = gapfilling.growMatch(m, U)[0] assert len(result) == 1 assert result[0].id == "a2b" # SMILEY result = gapfilling.SMILEY(m, "b", U)[0] assert len(result) == 1 assert result[0].id == "a2b" # 2 rounds of GrowMatch with exchange reactions result = gapfilling.growMatch(m, None, ex_rxns=True, iterations=2) assert len(result) == 2 assert len(result[0]) == 1 assert len(result[1]) == 1 assert {i[0].id for i in result} == {"SMILEY_EX_b", "SMILEY_EX_c"}
def test_gapfilling(self): try: get_solver_name(mip=True) except SolverNotFound: pytest.skip("no MILP solver found") m = Model() m.add_metabolites(map(Metabolite, ["a", "b", "c"])) r = Reaction("EX_A") m.add_reaction(r) r.add_metabolites({m.metabolites.a: 1}) r = Reaction("r1") m.add_reaction(r) r.add_metabolites({m.metabolites.b: -1, m.metabolites.c: 1}) r = Reaction("DM_C") m.add_reaction(r) r.add_metabolites({m.metabolites.c: -1}) r.objective_coefficient = 1 U = Model() r = Reaction("a2b") U.add_reaction(r) r.build_reaction_from_string("a --> b", verbose=False) r = Reaction("a2d") U.add_reaction(r) r.build_reaction_from_string("a --> d", verbose=False) # GrowMatch result = gapfilling.growMatch(m, U)[0] assert len(result) == 1 assert result[0].id == "a2b" # SMILEY result = gapfilling.SMILEY(m, "b", U)[0] assert len(result) == 1 assert result[0].id == "a2b" # 2 rounds of GrowMatch with exchange reactions result = gapfilling.growMatch(m, None, ex_rxns=True, iterations=2) assert len(result) == 2 assert len(result[0]) == 1 assert len(result[1]) == 1 assert {i[0].id for i in result} == {"SMILEY_EX_b", "SMILEY_EX_c"}
def construct_ll_test_model(): test_model = Model() test_model.add_metabolites(Metabolite("A")) test_model.add_metabolites(Metabolite("B")) test_model.add_metabolites(Metabolite("C")) EX_A = Reaction("EX_A") EX_A.add_metabolites({test_model.metabolites.A: 1}) DM_C = Reaction("DM_C") DM_C.add_metabolites({test_model.metabolites.C: -1}) v1 = Reaction("v1") v1.add_metabolites({test_model.metabolites.A: -1, test_model.metabolites.B: 1}) v2 = Reaction("v2") v2.add_metabolites({test_model.metabolites.B: -1, test_model.metabolites.C: 1}) v3 = Reaction("v3") v3.add_metabolites({test_model.metabolites.C: -1, test_model.metabolites.A: 1}) test_model.add_reactions([EX_A, DM_C, v1, v2, v3]) DM_C.objective_coefficient = 1 return test_model
def test_add_reactions(model): r1 = Reaction("r1") r1.add_metabolites({Metabolite("A"): -1, Metabolite("B"): 1}) r1.lower_bound, r1.upper_bound = -999999.0, 999999.0 r2 = Reaction("r2") r2.add_metabolites({ Metabolite("A"): -1, Metabolite("C"): 1, Metabolite("D"): 1 }) r2.lower_bound, r2.upper_bound = 0.0, 999999.0 model.add_reactions([r1, r2]) r2.objective_coefficient = 3.0 assert r2.objective_coefficient == 3.0 assert model.reactions[-2] == r1 assert model.reactions[-1] == r2 assert isinstance(model.reactions[-2].reverse_variable, model.problem.Variable) coefficients_dict = model.objective.expression.as_coefficients_dict() biomass_r = model.reactions.get_by_id("Biomass_Ecoli_core") assert coefficients_dict[biomass_r.forward_variable] == 1.0 assert coefficients_dict[biomass_r.reverse_variable] == -1.0 assert coefficients_dict[model.reactions.r2.forward_variable] == 3.0 assert coefficients_dict[model.reactions.r2.reverse_variable] == -3.0
def test_add_reactions(self, model): r1 = Reaction('r1') r1.add_metabolites({Metabolite('A'): -1, Metabolite('B'): 1}) r1.lower_bound, r1.upper_bound = -999999., 999999. r2 = Reaction('r2') r2.add_metabolites( {Metabolite('A'): -1, Metabolite('C'): 1, Metabolite('D'): 1}) r2.lower_bound, r2.upper_bound = 0., 999999. model.add_reactions([r1, r2]) r2.objective_coefficient = 3. assert r2.objective_coefficient == 3. assert model.reactions[-2] == r1 assert model.reactions[-1] == r2 assert isinstance(model.reactions[-2].reverse_variable, model.problem.Variable) coefficients_dict = model.objective.expression. \ as_coefficients_dict() biomass_r = model.reactions.get_by_id('Biomass_Ecoli_core') assert coefficients_dict[biomass_r.forward_variable] == 1. assert coefficients_dict[biomass_r.reverse_variable] == -1. assert coefficients_dict[ model.reactions.r2.forward_variable] == 3. assert coefficients_dict[ model.reactions.r2.reverse_variable] == -3.
def optimize_minimum_flux(model, objective_sense='maximize', tolerance_optimality=1e-8, tolerance_feasibility=1e-8): # return the flux distribution in which the total amount of fluxes is minimum while the growth is maximum #Get the optimal wt objective value and adjust based on optimality tolerances model.optimize() optimal_value = deepcopy(model.solution.f) # print('opt val: %s' % optimal_value) if objective_sense == 'maximize': optimal_value = floor(optimal_value/tolerance_optimality)*tolerance_optimality else: optimal_value = ceil(optimal_value/tolerance_optimality)*tolerance_optimality # print('adjusted opt val: %s' % optimal_value) #Add in the virtual objective metabolite to constrain the wt_model to the space where #the objective was maximal objective_metabolite = Metabolite('objective metabolite') objective_metabolite._bound = optimal_value if objective_sense == 'maximize': objective_metabolite._constraint_sense = 'G' else: objective_metabolite._constraint_sense = 'L' # print('objm const sense: %s, objm bound: %s' % (objective_metabolite._constraint_sense, objective_metabolite._bound)) # construct irreversible model to assure all flux values are positive irreve_model = model.copy() # this is necessary to avoid invalid bound error when model is changed to irreversible for r in irreve_model.reactions: if r.upper_bound < 0: reverse_reaction = Reaction(r.id + "_reverse") reverse_reaction.lower_bound = r.upper_bound * -1 reverse_reaction.upper_bound = r.lower_bound * -1 reverse_reaction.objective_coefficient = r.objective_coefficient * -1 reaction_dict = dict([(k, v*-1) for k, v in r.metabolites.items()]) reverse_reaction.add_metabolites(reaction_dict) irreve_model.add_reaction(reverse_reaction) r.upper_bound, r.lower_bound = 0, 0 cobra.manipulation.modify.convert_to_irreversible(irreve_model) objective_reaction_coefficient_dict = dict([(x.id, x.objective_coefficient) for x in model.reactions if x.objective_coefficient]) # this couples the objective reaction to the virtual metabolite [irreve_model.reactions.get_by_id(k).add_metabolites({objective_metabolite: v}) for k, v in objective_reaction_coefficient_dict.items()] # print('irregular metabolites: %s' % [(m.id, m._constraint_sense, m._bound) # for m in irreve_model.metabolites if m._constraint_sense != 'E' or m._bound != 0]) # minimize the sum of fluxes for r in irreve_model.reactions: r.objective_coefficient = 1 # print([r.id for r in irreve_model.reactions if r.objective_coefficient != 1]) # print(tolerance_feasibility) irreve_model.optimize(objective_sense='minimize', tolerance_feasibility=tolerance_feasibility) # adjust this to the solution of wt_model original_flux = model.solution.x_dict irreve_flux = irreve_model.solution.x_dict for k in original_flux.keys(): original_flux[k] = irreve_flux[k] # if reverse reaction exists and its flux is not zero, assign as a negative flux in wt_flux if k + '_reverse' in irreve_flux.keys() and irreve_flux[k + '_reverse'] != 0: if irreve_flux[k] != 0: print('Attention: non-optimal solution') original_flux[k] = -irreve_flux[k + '_reverse'] model.solution.status = irreve_model.solution.status model.solution.f = sum([irreve_model.reactions.get_by_id(k).x * v for k, v in objective_reaction_coefficient_dict.items()]) return model.solution