Changing optimizer parameters
Many optimizers require fine-tuning to produce best results. We can pass in additional optimizer settings via the settings
parameter of flux_balance_analysis
. These include e.g.
set_optimizer_attribute
, allowing us to tune e.g. iteration limits, tolerances, or floating-point precision (see JuMP documentation for more solver-specific settings)set_objective_sense
, allowing the user to change and reverse the optimization direction, if requiredsilence
for disabling the debug output of the optimizersset_optimizer
for replacing the optimizer implementation used (this is not quite useful in this case, but becomes beneficial with more complex, multi-stage optimization problems)set_time_limit
for putting a time limit on the solver computation (this is quite useful for MILP solvers)
To demonstrate this, let's use the usual toy model:
using COBREXA
import JSONFBCModels, Tulip
download_model(
"http://bigg.ucsd.edu/static/models/e_coli_core.json",
"e_coli_core.json",
"7bedec10576cfe935b19218dc881f3fb14f890a1871448fc19a9b4ee15b448d8",
)
model = load_model("e_coli_core.json")
JSONFBCModels.JSONFBCModel(#= 95 reactions, 72 metabolites =#)
Running a FBA with a silent optimizer that has slightly increased iteration limit for IPM algorithm may now look as follows:
solution = flux_balance_analysis(
model,
optimizer = Tulip.Optimizer,
settings = [set_optimizer_attribute("IPM_IterationsLimit", 1000)],
)
ConstraintTrees.Tree{Float64} with 4 elements:
:coupling => ConstraintTrees.Tree{Float64}(#= 0 elements =#)
:flux_stoichiometry => ConstraintTrees.Tree{Float64}(#= 72 elements =#)
:fluxes => ConstraintTrees.Tree{Float64}(#= 95 elements =#)
:objective => 0.873922
To see some of the effects of the configuration changes, we may e.g. deliberately cripple the optimizer's possibilities to a few iterations and only a little time, which will cause it to fail and return no solution:
solution = flux_balance_analysis(
model,
optimizer = Tulip.Optimizer,
settings = [set_optimizer_attribute("IPM_IterationsLimit", 2), set_time_limit(0.1)],
)
println(solution)
nothing
To see what failed, users may examine the solver output. Because all solver output is silenced by default for efficiency reasons, we need to explicitly pass in the unsilence
setting:
solution = flux_balance_analysis(
model,
optimizer = Tulip.Optimizer,
settings = [
set_optimizer_attribute("IPM_IterationsLimit", 2),
set_time_limit(0.1),
unsilence,
],
)
Problem info
Name :
Constraints : 262
Variables : 95
Non-zeros : 550
Reduced problem info
Constraints : 62 (removed 200)
Variables : 81 (removed 14)
Non-zeros : 325 (removed 225)
Presolve time : 0.000s
Optimizer info (HSD)
Constraints : 62
Variables : 81
RHS : [+0.00e+00, +0.00e+00]
Lower bounds : [-2.32e+03, +1.25e+01]
Upper bounds : [+0.00e+00, +1.16e+04]
Linear solver options
Arithmetic : Float64
Backend : CHOLMOD
System : Augmented system (K2)
Itn PObj DObj PFeas DFeas GFeas Mu Time
0 -0.0000000e+00 +1.7686535e+05 1.16e+04 8.59e-02 1.77e+05 1.0e+00 0.00
1 -5.3305641e-02 +1.7675067e+05 7.98e+03 5.26e-02 1.21e+05 6.9e-01 0.00
2 -8.5532053e-02 +1.7615681e+05 2.06e+03 1.69e-02 3.13e+04 1.8e-01 0.00
Solver exited with status Trm_IterationLimit
Applicable optimizer attributes are documented in the documentations of the respective optimizers. To browse the possibilities, one might want to see the JuMP documentation page that summarizes the references to the available optimizers.
Default solver settings can be examined and changed via Configuration
.
This page was generated using Literate.jl.