Skip to content

Commit

Permalink
updated version number
Browse files Browse the repository at this point in the history
  • Loading branch information
VonAlphaBisZulu committed Jul 19, 2024
1 parent 8862120 commit 16aacdd
Show file tree
Hide file tree
Showing 13 changed files with 46 additions and 31 deletions.
2 changes: 1 addition & 1 deletion conda-recipe/meta.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% set version = '1.11' %}
{% set version = '1.12' %}

package:
name: straindesign
Expand Down
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
author = "Philipp Schneider"

# The full version, including alpha/beta/rc tags
release = "1.11"
release = "1.12"

# -- General configuration ---------------------------------------------------

Expand Down
10 changes: 4 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name="straindesign",
version="1.11",
version="1.12",
url="https://github.com/klamt-lab/straindesign.git",
description="Computational strain design package for the COBRApy framework",
long_description=
Expand All @@ -21,11 +21,9 @@
"Documentation": "https://straindesign.readthedocs.io/en/latest/index.html"
},
classifiers=[
"Intended Audience :: Science/Research", "Development Status :: 3 - Alpha",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12",
"Natural Language :: English", "Operating System :: OS Independent",
"Topic :: Scientific/Engineering :: Bio-Informatics"
"Intended Audience :: Science/Research", "Development Status :: 3 - Alpha", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12",
"Natural Language :: English", "Operating System :: OS Independent", "Topic :: Scientific/Engineering :: Bio-Informatics"
],
keywords=["metabolism", "constraint-based", "mixed-integer", "strain design"],
zip_safe=False,
Expand Down
4 changes: 1 addition & 3 deletions straindesign/compute_strain_designs.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ def compute_strain_designs(model: Model, **kwargs: dict) -> SDSolutions:
solution_approach = kwargs.pop(SOLUTION_APPROACH)
else:
solution_approach = BEST

# solve MILP
if solution_approach == ANY:
cmp_sd_solution = sd_milp.compute(**kwargs_computation)
Expand All @@ -431,8 +431,6 @@ def compute_strain_designs(model: Model, **kwargs: dict) -> SDSolutions:
sd_solutions = SDSolutions(orig_model, sd, cmp_sd_solution.status, setup)
logging.info(str(len(sd)) + ' solutions found.')



return sd_solutions


Expand Down
2 changes: 1 addition & 1 deletion straindesign/cplex_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def __init__(self, c=None, A_ineq=None, b_ineq=None, A_eq=None, b_eq=None, lb=No
# yield only optimal solutions in pool
if seed is None:
# seed = random.randint(0, _const.CPX_BIGINT)
seed = int(random.randint(0, 2**16-1))
seed = int(random.randint(0, 2**16 - 1))
self.parameters.randomseed.set(seed)
self.parameters.mip.pool.absgap.set(0.0)
self.parameters.mip.pool.relgap.set(0.0)
Expand Down
2 changes: 1 addition & 1 deletion straindesign/glpk_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class GLPK_MILP_LP():
A GLPK MILP/LP interface class.
"""

def __init__(self, c=None, A_ineq=None, b_ineq=None, A_eq=None, b_eq=None, lb=None, ub=None, vtype=None, indic_constr=None, M=None):
self.glpk = glp_create_prob()
# Careful with indexing! GLPK indexing starts with 1 and not with 0
Expand Down
6 changes: 3 additions & 3 deletions straindesign/gurobi_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def __init__(self, c=None, A_ineq=None, b_ineq=None, A_eq=None, b_eq=None, lb=No
if A_ineq.shape[0]:
self.addMConstr(A_ineq, x, grb.LESS_EQUAL, array(b_ineq))
if A_eq.shape[0]:
self.addMConstr(A_eq, x, grb.EQUAL, array(b_eq))
self.addMConstr(A_eq, x, grb.EQUAL, array(b_eq))

# add indicator constraints
if not indic_constr == None:
Expand All @@ -138,8 +138,8 @@ def __init__(self, c=None, A_ineq=None, b_ineq=None, A_eq=None, b_eq=None, lb=No
if 'B' in vtype or 'I' in vtype:
if seed is None:
# seed = random(0, grb.MAXINT)
seed = int(random.randint(0, 2**16-1))
logging.info(' MILP Seed: '+str(seed))
seed = int(random.randint(0, 2**16 - 1))
logging.info(' MILP Seed: ' + str(seed))
self.params.Seed = seed
self.params.IntFeasTol = 1e-9 # (0 is not allowed by Gurobi)
# yield only optimal solutions in pool
Expand Down
12 changes: 6 additions & 6 deletions straindesign/scip_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class SCIP_MILP(pso.Model):
A SCIP MILP interface class.
"""

def __init__(self, c=None, A_ineq=None, b_ineq=None, A_eq=None, b_eq=None, lb=None, ub=None, vtype=None, indic_constr=None, seed = None):
def __init__(self, c=None, A_ineq=None, b_ineq=None, A_eq=None, b_eq=None, lb=None, ub=None, vtype=None, indic_constr=None, seed=None):
super().__init__()
# uncomment to forward SCIP output to python terminal
# self.redirectOutput()
Expand Down Expand Up @@ -164,7 +164,7 @@ def __init__(self, c=None, A_ineq=None, b_ineq=None, A_eq=None, b_eq=None, lb=No
if seed is None:
# seed = randint(0, 2**31 - 1)
seed = int(random.randint(2**16 - 1))
logging.info(' MILP Seed: '+str(seed))
logging.info(' MILP Seed: ' + str(seed))
self.setParam('randomization/randomseedshift', seed)
self.setEmphasis(0)
# self.setParam('constraints/indicator/forcerestart',True)
Expand All @@ -178,7 +178,7 @@ def __init__(self, c=None, A_ineq=None, b_ineq=None, A_eq=None, b_eq=None, lb=No
# self.setParam('display/lpinfo',False)
# self.setParam('reoptimization/enable',True)
self.setParam('display/verblevel', 0)

# SCIP_PARAMEMPHASIS_DEFAULT = 0, /**< use default values */
# SCIP_PARAMEMPHASIS_CPSOLVER = 1, /**< get CP like search (e.g. no LP relaxation) */
# SCIP_PARAMEMPHASIS_EASYCIP = 2, /**< solve easy problems fast */
Expand Down Expand Up @@ -333,7 +333,7 @@ def set_objective(self, c):
self.setParam('display/verblevel', 0)
else:
self.setEmphasis(1)

def set_objective_idx(self, C):
"""Set the objective function with index-value pairs
Expand All @@ -349,7 +349,7 @@ def set_objective_idx(self, C):
self.setParam('display/verblevel', 0)
else:
self.setEmphasis(1)

def set_ub(self, ub):
"""Set the upper bounds to a given vector"""
self.freeTransform()
Expand Down Expand Up @@ -403,7 +403,7 @@ def add_eq_constraints(self, A_eq, b_eq):
The right hand side vector
"""
self.freeTransform()
eqs = [self.addCons(pso.Expr() == b_i,modifiable=True) for b_i in b_eq]
eqs = [self.addCons(pso.Expr() == b_i, modifiable=True) for b_i in b_eq]
for row, a_eq in zip(eqs, A_eq):
X = [self.vars[i] for i in a_eq.indices]
for col, coeff in zip(X, a_eq.data):
Expand Down
10 changes: 6 additions & 4 deletions straindesign/solver_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ class MILP_LP(object):
"""

def __init__(self, **kwargs):
allowed_keys = {'c', 'A_ineq', 'b_ineq', 'A_eq', 'b_eq', 'lb', 'ub', 'vtype', 'indic_constr', 'M', 'solver', 'skip_checks', 'tlim', SEED}
allowed_keys = {
'c', 'A_ineq', 'b_ineq', 'A_eq', 'b_eq', 'lb', 'ub', 'vtype', 'indic_constr', 'M', 'solver', 'skip_checks', 'tlim', SEED
}
# set all keys passed in kwargs
for key, value in kwargs.items():
if key in allowed_keys:
Expand Down Expand Up @@ -181,11 +183,11 @@ def __init__(self, **kwargs):
if self.solver == CPLEX:
from straindesign.cplex_interface import Cplex_MILP_LP
self.backend = Cplex_MILP_LP(self.c, self.A_ineq, self.b_ineq, self.A_eq, self.b_eq, self.lb, self.ub, self.vtype,
self.indic_constr,self.seed)
self.indic_constr, self.seed)
elif self.solver == GUROBI:
from straindesign.gurobi_interface import Gurobi_MILP_LP
self.backend = Gurobi_MILP_LP(self.c, self.A_ineq, self.b_ineq, self.A_eq, self.b_eq, self.lb, self.ub, self.vtype,
self.indic_constr,self.seed)
self.indic_constr, self.seed)
elif self.solver == SCIP:
from straindesign.scip_interface import SCIP_MILP, SCIP_LP
self.isLP = all(v == 'C' for v in self.vtype)
Expand All @@ -194,7 +196,7 @@ def __init__(self, **kwargs):
return
else:
self.backend = SCIP_MILP(self.c, self.A_ineq, self.b_ineq, self.A_eq, self.b_eq, self.lb, self.ub, self.vtype,
self.indic_constr,self.seed)
self.indic_constr, self.seed)
elif self.solver == GLPK:
from straindesign.glpk_interface import GLPK_MILP_LP
self.backend = GLPK_MILP_LP(self.c, self.A_ineq, self.b_ineq, self.A_eq, self.b_eq, self.lb, self.ub, self.vtype,
Expand Down
15 changes: 10 additions & 5 deletions straindesign/strainDesignProblem.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ def addModule(self, sd_module):
# 4. connect primal w/ undesired region and dual w/o undesired region (i.e. biomass) via c = c_inner.
A_ineq_p = sparse.block_diag((A_ineq_v, A_ineq_dual)).tocsr()
b_ineq_p = b_ineq_v + b_ineq_dual
A_eq_p = sparse.vstack((sparse.block_diag((A_eq_v, A_eq_dual)), sparse.hstack((sparse.csr_matrix(c_v), sparse.csr_matrix(c_inner_dual))))).tocsr()
A_eq_p = sparse.vstack((sparse.block_diag(
(A_eq_v, A_eq_dual)), sparse.hstack((sparse.csr_matrix(c_v), sparse.csr_matrix(c_inner_dual))))).tocsr()
b_eq_p = b_eq_v + b_eq_dual + [0.0]
lb_p = lb_v + lb_dual
ub_p = ub_v + ub_dual
Expand Down Expand Up @@ -299,7 +300,8 @@ def addModule(self, sd_module):
# 5. connect primal w/ undesired region and dual w/o undesired region (i.e. biomass) via c = c_inner.
A_ineq_p = sparse.block_diag((A_ineq_v, A_ineq_dual)).tocsr()
b_ineq_p = b_ineq_v + b_ineq_dual
A_eq_p = sparse.vstack((sparse.block_diag((A_eq_v, A_eq_dual)), sparse.hstack((sparse.csr_matrix(c_v), sparse.csr_matrix(c_inner_dual))))).tocsr()
A_eq_p = sparse.vstack((sparse.block_diag(
(A_eq_v, A_eq_dual)), sparse.hstack((sparse.csr_matrix(c_v), sparse.csr_matrix(c_inner_dual))))).tocsr()
b_eq_p = b_eq_v + b_eq_dual + [0.0]
lb_p = lb_v + lb_dual
ub_p = ub_v + ub_dual
Expand All @@ -316,7 +318,8 @@ def addModule(self, sd_module):
# 8. Connect outer problem to the dualized combined inner problem to construct min-max problem.
A_ineq_q = sparse.block_diag((A_ineq_r, A_ineq_dl_mmx)).tocsr()
b_ineq_q = b_ineq_r + b_ineq_dl_mmx
A_eq_q = sparse.vstack((sparse.block_diag((A_eq_r, A_eq_dl_mmx)), sparse.hstack((sparse.csr_matrix(c_r), sparse.csr_matrix(c_dl_mmx))))).tocsr()
A_eq_q = sparse.vstack((sparse.block_diag(
(A_eq_r, A_eq_dl_mmx)), sparse.hstack((sparse.csr_matrix(c_r), sparse.csr_matrix(c_dl_mmx))))).tocsr()
b_eq_q = b_eq_r + b_eq_dl_mmx + [0.0]
lb_q = lb_r + lb_dl_mmx
ub_q = ub_r + ub_dl_mmx
Expand Down Expand Up @@ -344,7 +347,9 @@ def addModule(self, sd_module):
# 8. Create no-production bi-level system.
A_ineq_b = sparse.block_diag((A_ineq_r, A_ineq_r_dl), format='csr')
b_ineq_b = b_ineq_r + b_ineq_dl_r_dl
A_eq_b = sparse.vstack((sparse.block_diag((A_eq_r, A_eq_dl_r_dl)), sparse.hstack((sparse.csr_matrix(c_r), sparse.csr_matrix(c_r_dl)))), format='csr')
A_eq_b = sparse.vstack((sparse.block_diag(
(A_eq_r, A_eq_dl_r_dl)), sparse.hstack((sparse.csr_matrix(c_r), sparse.csr_matrix(c_r_dl)))),
format='csr')
b_eq_b = b_eq_r + b_eq_r_dl + [0.0]
lb_b = lb_r + lb_r_dl
ub_b = ub_r + ub_r_dl
Expand Down Expand Up @@ -847,7 +852,7 @@ def farkas_dualize(A_ineq_p, b_ineq_p, A_eq_p, b_eq_p, lb_p, ub_p,
else:
A_ineq_d, b_ineq_d, A_eq_d, b_eq_d, lb_f, ub_f, c_d = LP_dualize(A_ineq_p, b_ineq_p, A_eq_p, b_eq_p, lb_p, ub_p, c_p)
# add constraint b_prim'y or (c_dual'*y) <= -1;
A_ineq_f = sparse.vstack((A_ineq_d,sparse.csr_matrix(c_d))).tocsr()
A_ineq_f = sparse.vstack((A_ineq_d, sparse.csr_matrix(c_d))).tocsr()
b_ineq_f = b_ineq_d + [-1]
A_eq_f = A_eq_d
b_eq_f = b_eq_d
Expand Down
3 changes: 3 additions & 0 deletions tests/test_03_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,21 @@
from .test_01_load_models_and_solvers import *
import straindesign as sd


@pytest.mark.timeout(15)
def test_plot_2d_flux_space(curr_solver, model_weak_coupling):
"""Test plot with constraints."""
constr = ['r4 = 0', 'r7 = 0', 'r9 = 0', 'r_BM >= 4']
sd.plot_flux_space(model_weak_coupling, ('r_P', 'r_S'), constraints=constr, plt_backend='template')


@pytest.mark.timeout(15)
def test_plot_2d_yield_space(curr_solver, model_weak_coupling):
"""Test plot with constraints."""
constr = ['r4 = 0', 'r7 = 0', 'r9 = 0', 'r_BM >= 4']
sd.plot_flux_space(model_weak_coupling, (('r_P', 'r_S'), ('r_BM', 'r_S')), constraints=constr, plt_backend='template')


@pytest.mark.timeout(15)
def test_plot_3d_space(curr_solver, model_weak_coupling):
"""Test plot with constraints."""
Expand Down
2 changes: 2 additions & 0 deletions tests/test_04_preprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import straindesign as sd
from numpy import inf


@pytest.mark.timeout(15)
def test_gpr_extension_compression1(model_gpr):
gkocost = {
Expand All @@ -21,6 +22,7 @@ def test_gpr_extension_compression1(model_gpr):
assert (len(gkocost) == 4)
assert (len(gkicost) == 3)


@pytest.mark.timeout(15)
def test_gpr_extension_compression2(model_gpr):
gkocost = {
Expand Down
7 changes: 7 additions & 0 deletions tests/test_05_straindesign.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import straindesign as sd
from numpy import inf


@pytest.mark.timeout(15)
def test_mcs(curr_solver, model_small_example, comp_approach, bigM, compression):
modules = [sd.SDModule(model_small_example, SUPPRESS, constraints=["R3 - 0.5 R1 <= 0.0", "R2 <= 0", "R1 >= 0.1"])]
Expand Down Expand Up @@ -31,6 +32,7 @@ def test_mcs(curr_solver, model_small_example, comp_approach, bigM, compression)
assert ({'R7': -1.0} in sols)
assert ({'R10': -1.0} in sols)


@pytest.mark.timeout(15)
def test_mcs_opt(curr_solver, model_weak_coupling, comp_approach, bigM, compression):
"""Test MCS computation with nested optimization constraints."""
Expand All @@ -57,6 +59,7 @@ def test_mcs_opt(curr_solver, model_weak_coupling, comp_approach, bigM, compress
solution = sd.compute_strain_designs(model_weak_coupling, sd_setup=sd_setup)
assert (len(solution.reaction_sd) == 3)


@pytest.mark.timeout(15)
def test_mcs_gpr(model_gpr, comp_approach):
"""Test MCS computation with gpr rules."""
Expand Down Expand Up @@ -91,6 +94,7 @@ def test_mcs_gpr(model_gpr, comp_approach):
solution = sd.compute_strain_designs(model_gpr, sd_setup=sd_setup)
assert (len(solution.gene_sd) == 4)


@pytest.mark.timeout(15)
def test_mcs_gpr2(model_gpr, comp_approach):
"""Test MCS computation gpr rule (compression)."""
Expand Down Expand Up @@ -126,6 +130,7 @@ def test_mcs_gpr2(model_gpr, comp_approach):
assert (len(solution.gene_sd) == 4)
assert (any(['G_g4 <= 0.4' in sol for sol in solution.get_gene_sd()]))


@pytest.mark.timeout(15)
def test_optknock(curr_solver, model_weak_coupling, comp_approach_best_populate, bigM, compression):
"""Test OptKnock computation."""
Expand All @@ -152,6 +157,7 @@ def test_optknock(curr_solver, model_weak_coupling, comp_approach_best_populate,
solution = sd.compute_strain_designs(model_weak_coupling, sd_setup=sd_setup)
assert (len(solution.reaction_sd) == 3)


@pytest.mark.timeout(15)
def test_robustknock(curr_solver, model_weak_coupling, comp_approach_best_populate, bigM, compression):
"""Test RobustKnock computation."""
Expand Down Expand Up @@ -192,6 +198,7 @@ def test_robustknock(curr_solver, model_weak_coupling, comp_approach_best_popula
sol_min_P = sd.fba(m, obj_sense='minimize', obj='r_P', constraints="r_BM >= " + str(sol_max_BM.objective_value))
assert (sol_min_P.objective_value > 0)


@pytest.mark.timeout(15)
def test_optcouple(curr_solver, model_weak_coupling, comp_approach_best_populate, bigM, compression):
"""Test OptCouple computation."""
Expand Down

0 comments on commit 16aacdd

Please sign in to comment.