Skip to content

Commit

Permalink
convert parsimonious wrappers to the other QP ones
Browse files Browse the repository at this point in the history
  • Loading branch information
exaexa committed Mar 3, 2023
1 parent 6a167a6 commit c0cefae
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 98 deletions.
10 changes: 9 additions & 1 deletion src/analysis/parsimonious_flux_balance_analysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,21 @@ using the callback in `qp_modifications`, which are applied after the FBA. See
the documentation of [`flux_balance_analysis`](@ref) for usage examples of
modifications.
Thhe optimum relaxation sequence can be specified in `relax` parameter, it
The optimum relaxation sequence can be specified in `relax` parameter, it
defaults to multiplicative range of `[1.0, 0.999999, ..., 0.99]` of the original
bound.
Returns an optimized model that contains the pFBA solution (or an unsolved model
if something went wrong).
# Performance
This implementation attempts to save time by executing all pFBA steps on a
single instance of the optimization model problem, trading off possible
flexibility. For slightly less performant but much more flexible use, one can
construct parsimonious models directly using
[`with_parsimonious_objective`](@ref).
# Example
```
model = load_model("e_coli_core.json")
Expand Down
25 changes: 0 additions & 25 deletions src/reconstruction/pipes/parsimonious.jl

This file was deleted.

58 changes: 48 additions & 10 deletions src/wrappers/MinimizeDistance.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,21 @@ variants of the same concept. Internally powered by
[`MinimizeSolutionDistance`](@ref).
"""
minimize_solution_distance(center::Vector{Float64}) =
model -> MinimizeSolutionDistance(center, model)
model::AbstractMetabolicModel -> MinimizeSolutionDistance(center, model)

"""
$(TYPEDSIGNATURES)
Set an objective that finds a solution of minimal norm. Typically, it is
necessary to also add more constraints to the objective that prevent optimality
of the trivial zero solution.
This can be used to implement [`parsimonious_flux_balance_analysis`](@ref) in a
flexible way that fits into larger model systems.
"""
with_parsimonious_objective() =
model::AbstractMetabolicModel ->
MinimizeSolutionDistance(zeros(n_variables(model)), model)

"""
$(TYPEDEF)
Expand All @@ -41,13 +55,14 @@ end

Accessors.unwrap_model(m::MinimizeSemanticDistance) = m.inner

Accessors.objective(m::MinimizeSemanticDistance) =
let
Sem = variable_semantic_mtx(m.semantic, m.inner)
Sem' *
[spdiagm(fill(-0.5, size(Sem, 2))) m.center] *
[Sem zeros(size(Sem, 1)); zeros(size(Sem, 2))' 1.0]
end
function Accessors.objective(m::MinimizeSemanticDistance)
(_, _, _, smtx) = Accessors.Internal.sematics(m.semantic)
Sem = smtx(m.inner)

return Sem' *
[spdiagm(fill(-0.5, size(Sem, 2))) m.center] *
[Sem zeros(size(Sem, 1)); zeros(size(Sem, 2))' 1.0]
end

"""
$(TYPEDSIGNATURES)
Expand All @@ -59,7 +74,20 @@ variant, and [`minimize_solution_distance`](@ref) for working directly upon
variables. Internally powered by [`MinimizeSemanticDistance`](@ref).
"""
minimize_semantic_distance(semantic::Symbol, center::Vector{Float64}) =
model -> MinimizeSolutionDistance(semantic, center, model)
model::AbstractMetabolicModel -> MinimizeSolutionDistance(semantic, center, model)

"""
$(TYPEDSIGNATURES)
Set an objective that finds a solution of minimal norm in a given semantic.
This can be used to implement various realistic variants of
[`parsimonious_flux_balance_analysis`](@ref).
"""
with_parsimonious_objective(semantics::Symbol) =
model::AbstractMetabolicModel -> let
(_, n_sem, _, _) = Accessors.Internal.semantics(semantics)
MinimizeSemanticDistance(semantic, zeros(n_sem(model)), model)
end

"""
$(TYPEDEF)
Expand Down Expand Up @@ -92,4 +120,14 @@ for simpler variants. Internally powered by
[`MinimizeProjectedDistance`](@ref).
"""
minimize_projected_distance(proj::SparseMat, center::Vector{Float64}) =
model -> MinimizeProjectedDistance(proj, center, model)
model::AbstractMetabolicModel -> MinimizeProjectedDistance(proj, center, model)

"""
$(TYPEDSIGNATURES)
Set a quadratic objective that minimizes the norm in a given projection of
model variables.
"""
with_parsimonious_objective(proj::SparseMat) =
model::AbstractMetabolicModel ->
MinimizeProjectedDistance(proj, zeros(size(proj, 1)), model)
59 changes: 0 additions & 59 deletions src/wrappers/ParsimoniousModel.jl

This file was deleted.

4 changes: 2 additions & 2 deletions test/analysis/parsimonious_flux_balance_analysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
d2 =
model |>
with_changed_bound("biomass1", lower_bound = 10.0) |>
with_parsimonious_solution(:reaction) |>
with_parsimonious_objective(:reaction) |>
flux_balance_analysis(Clarabel.Optimizer, modifications = [silence]) |>
values_dict

@test all(isapprox(d[k], d2[k], atol = QP_TEST_TOLERANCE) for k in keys(d2))

Q = objective(model |> with_parsimonious_solution(:reaction))
Q = objective(model |> with_parsimonious_objective(:reaction))
@test all(Q[i, i] == -1 for i = 1:7)
end
2 changes: 1 addition & 1 deletion test/reconstruction/enzyme_constrained.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
model |>
with_changed_bound("BIOMASS_Ecoli_core_w_GAM", lower_bound = growth_lb) |>
with_enzyme_constraints(; total_gene_product_mass_bound) |>
with_parsimonious_solution(:enzyme) |>
with_parsimonious_objective(:enzyme) |>
flux_balance_analysis(
Clarabel.Optimizer;
modifications = [modify_optimizer_attribute("max_iter", 1000), silence],
Expand Down

0 comments on commit c0cefae

Please sign in to comment.