generic.jl 2.41 KB
Newer Older
1
2
3
4
5
6
7

"""
    constrain_objective_value(tolerance)

Limit the objective value to `tolerance`-times the current objective value, as
with [`objective_bounds`](@ref).
"""
8
9
constrain_objective_value(tolerance) =
    (_, opt_model) -> begin
10
11
12
13
14
15
        lambda_min, lambda_max = objective_bounds(tolerance)(objective_value(opt_model))
        old_objective = objective_function(opt_model)
        @constraint(opt_model, lambda_min <= sum(old_objective) <= lambda_max)
    end

"""
16
    change_constraint(id::String; lb=nothing, ub=nothing)
17

St. Elmo's avatar
St. Elmo committed
18
Change the lower and upper bounds (`lb` and `ub` respectively) of variable `id` if supplied.
19
"""
20
change_constraint(id::String; lb = nothing, ub = nothing) =
21
    (model, opt_model) -> begin
St. Elmo's avatar
St. Elmo committed
22
        ind = first(indexin([id], [reactions(model); genes(model)]))
St. Elmo's avatar
format    
St. Elmo committed
23
24
        isnothing(ind) &&
            throw(DomainError(id, "No matching reaction or gene was found."))
25
26
27
28
        set_optmodel_bound!(ind, opt_model, lb = lb, ub = ub)
    end

"""
29
    change_objective(new_objective::Union{String,Vector{String}}; weights=[], sense=MAX_SENSE)
30
31
32
33
34
35

Modification that changes the objective function used in a constraint based
analysis function.  `new_objective` can be a single reaction identifier, or an
array of reactions identifiers.

Optionally, the objective can be weighted by a vector of `weights`, and a
36
optimization `sense` can be set to either `MAX_SENSE` or `MIN_SENSE`.
37
"""
38
change_objective(
39
40
    new_objective::Union{String,Vector{String}};
    weights = [],
41
    sense = MAX_SENSE,
42
) =
43
44
45
46
    (model, opt_model) -> begin

        # Construct objective_indices array
        if typeof(new_objective) == String
St. Elmo's avatar
St. Elmo committed
47
            objective_indices = indexin([new_objective], [reactions(model); genes(model)])
48
        else
St. Elmo's avatar
format    
St. Elmo committed
49
50
51
52
            objective_indices = [
                first(indexin([id], [reactions(model); genes(model)])) for
                id in new_objective
            ]
53
54
55
56
57
58
59
        end

        any(isnothing.(objective_indices)) && throw(
            DomainError(new_objective, "No matching reaction found for one or more ids."),
        )

        # Initialize weights
St. Elmo's avatar
St. Elmo committed
60
        opt_weights = spzeros(size(stoichiometry(model), 2))
61
62
63
64
65
66
67
68
69
70

        isempty(weights) && (weights = ones(length(objective_indices))) # equal weights

        for (j, i) in enumerate(objective_indices)
            opt_weights[i] = weights[j]
        end

        v = opt_model[:x]
        @objective(opt_model, sense, sum(opt_weights[i] * v[i] for i in objective_indices))
    end