Constraint system builders

Generic constraints

Comparisons

COBREXA.all_equal_constraintsMethod
all_equal_constraints(
    a,
    tree::ConstraintTrees.Tree{ConstraintTrees.Constraint}
) -> Any

A constriant tree that makes sure that all values in tree are the same as the value of a.

Names in the output ConstraintTree match the names in the tree.

source
COBREXA.difference_constraintMethod
difference_constraint(
    a,
    b,
    difference_bound
) -> ConstraintTrees.Constraint

A constraint that makes sure that the difference from a to b is within the difference_bound. For example, difference_constraint(-1, 1, 2) will always be valid. Any type of ConstraintTree.Bound can be supplied.

source
COBREXA.greater_or_equal_constraintMethod
greater_or_equal_constraint(
    a,
    b
) -> ConstraintTrees.Constraint

A constraint that makes sure that the value of a is greater than or equal to the the value of b.

source
COBREXA.less_or_equal_constraintMethod
less_or_equal_constraint(a, b) -> ConstraintTrees.Constraint

A constraint that makes sure that the value of a is less than or equal to the the value of b.

source

Constraint scaling

COBREXA.scale_boundsMethod
scale_bounds(
    tree::ConstraintTrees.Tree{ConstraintTrees.Constraint},
    factor
) -> Any

Linearly scale all bounds in a constraint tree by the factor. This actually changes the model semantics, and may not work in surprising/improper ways with some constraint systems, esp. the MILP and QP ones.

See also scale_constraints.

source
COBREXA.scale_constraintsMethod
scale_constraints(
    tree::ConstraintTrees.Tree{ConstraintTrees.Constraint},
    factor
) -> Any

Linearly scale all constraints in a constraint tree by the factor.

See also scale_bounds.

source

Sign splitting

COBREXA.sign_split_constraintsMethod
sign_split_constraints(; positive, negative, signed)

A constraint tree that bound the values present in signed to be sums of pairs of positive and negative contributions to the individual values.

Keys in the result are the same as the keys of signed constraints.

Typically, this can be used to create "unidirectional" fluxes together with unsigned_negative_contribution_variables and unsigned_positive_contribution_variables.

Use sign_split_variables to allocate the variables easily.

source

Objectives

COBREXA.squared_sum_error_valueMethod
squared_sum_error_value(
    constraints::ConstraintTrees.Tree{ConstraintTrees.Constraint},
    target
) -> Any

Construct a ConstraintTrees.Value out of squared error (in the RMSE-like squared-error sense) between the values in the constraint tree and the reference target.

target is a function that takes a symbol (key) and returns either a Float64 reference value, or nothing if the error of given key should not be considered.

source
COBREXA.squared_sum_valueMethod
squared_sum_value(
    x::ConstraintTrees.Tree{ConstraintTrees.Constraint}
) -> Any

Construct a ConstraintTrees.Value out of squared sum of all values directly present in a given constraint tree.

source
COBREXA.sum_valueMethod
sum_value(
    x...
) -> Union{ConstraintTrees.LinearValue, ConstraintTrees.QuadraticValue}

Construct a ConstraintTrees.Value out of a sum of all values directly present in a given constraint tree.

source

Analysis-specific constriants

COBREXA.loopless_constraintsMethod
loopless_constraints(
;
    fluxes,
    loopless_direction_indicators,
    loopless_driving_forces,
    internal_reactions,
    internal_nullspace,
    flux_infinity_bound,
    driving_force_nonzero_bound,
    driving_force_infinity_bound
)

Construct the loopless constraint system that binds fluxes of all internal_reactions to direction of loopless_direction_indicators and connects them to loopless_driving_forces. The solution is bounded to lie in internal_nullspace (which is a sufficient algebraic condition for loop-less-ness).

The indicators must be discrete variables, valued 1 if the reaction flux goes forward, or 0 if the reaction flux is reversed.

The simplest (but by no means the fastest) way to obtain a good internal_nullspace is to use LinearAlgebra.nullspace with the internal reactions' stoichiometry matrix. Rows of internal_nullspace must correspond to internal_reactions.

flux_infinity_bound is used as the maximal bound for fluxes (for constraints that connect them to indicator variables); it should optimally be greater than the maximum possible absolute value of any flux in the original model.

driving_force_nonzero_bound and driving_force_infinity_bound are similarly used to limit the individual reaction's driving forces.

source
COBREXA.knockout_constraintsMethod
knockout_constraints(
    knockout_test::Function,
    fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint}
) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}

Make a ConstraintTree that knocks out fluxes given by the predicate knockout_test. The predicate function is called with a single parameter (the key of the flux in tree fluxes) and must return a boolean. Returning true means that the corresponding flux (usually a reaction flux) will be knocked out.

source
COBREXA.enzyme_constraintsMethod
enzyme_constraints(
;
    fluxes_forward,
    fluxes_reverse,
    isozyme_forward_amounts,
    isozyme_reverse_amounts,
    kcat_forward,
    kcat_reverse,
    isozyme_gene_product_stoichiometry,
    gene_product_molar_mass,
    capacity_limits,
    isozyme_flux_forward_balance_name,
    isozyme_flux_reverse_balance_name,
    gene_product_amounts_name,
    gene_product_capacity_name
)

Connect variables returned by enzyme_variables to unidirectional fluxes. This is used to construct the contraint system for enzyme_constrained_flux_balance_constraints.

Parameters fluxes_forward, fluxes_reverse, isozyme_forward_amounts, isozyme_reverse_amounts and gene_product_amounts should correspond to parameters and results of enzyme_variables.

Further, parameter functions kcat_forward and kcat_reverse specify the turnover numbers for reaction and isozyme IDs given in parameters; isozyme_gene_product_stoichiometry specifies the composition of the reaction-isozyme IDs given in parameter by returning an interable mapping of gene product IDs to numbers (such as Dict{Symbol, Float64}), and gene_product_molar_mass specifies a numeric mass for a given gene product ID. All parameter functions may return nothing, at which point the given object is considered nonexistent and is omitted from constraints.

capacity_limits is an interable container of triples (limit_id, gene_product_ids, capacity_bound) which are converted to a constraint identified by the limit_id that limits the total mass of gene_product_ids (which is any iterable container) by capacity_bound.

source
COBREXA.enzyme_variablesMethod
enzyme_variables(
;
    fluxes_forward,
    fluxes_reverse,
    isozyme_ids,
    isozyme_forward_ids,
    isozyme_reverse_ids,
    isozyme_forward_amounts_name,
    isozyme_reverse_amounts_name
)

Returns a constraint tree with enzyme capacity constraints, added for reactions in fluxes_forward and fluxes_reverse. This is used to construct the constraint system in enzyme_constrained_flux_balance_constraints.

Parameter function isozyme_ids takes a reaction ID and returns nothing if the reaction does not have isozymes associated with it, or an iterable container of all the isozyme IDs for that reaction (as Symbols).

Parameters isozyme_forward_ids and isozyme_reverse_ids can be used to fine-tune the generated isozymes in either direction; both default to isozyme_ids.

The keys in the output constraint tree can be customized by setting isozyme_forward_amounts_name, isozyme_reverse_amounts_name and gene_product_amounts_name.

source
COBREXA.isozyme_amount_variablesMethod
isozyme_amount_variables(
    fluxes,
    flux_isozymes
) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}

Create a ConstraintTree with variables for isozyme contributions to reaction fluxes. The tree has 2 levels: the first contains all reaction flux IDs that have isozymes, the second contains the isozyme IDs for each reaction flux.

fluxes should be anything that can be iterated to give reaction flux IDs.

flux_isozymes is a function that, for a given reaction flux ID, returns anything iterable that contains the isozyme IDs for the given reaction flux. Returning an empty iterable prevents allocating the subtree for the given flux.

source
COBREXA.isozyme_flux_constraintsMethod
isozyme_flux_constraints(
    isozyme_amounts::ConstraintTrees.Tree{ConstraintTrees.Constraint},
    fluxes::ConstraintTrees.Tree{ConstraintTrees.Constraint},
    kcat
) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}

A constraint tree that sums up partial contributions of reaction isozymes to the fluxes of reactions.

For practical purposes, both fluxes and isozymes are here considered to be unidirectional, i.e., one would typically apply this twice to constraint both "forward" and "reverse" fluxes.

Function kcat should return the kcat value for a given reaction and isozyme (IDs of which respectively form the 2 parameters for each call).

source
COBREXA.isozyme_gene_product_amount_constraintsMethod
isozyme_gene_product_amount_constraints(
    isozyme_amounts,
    isozyme_stoichiometry
) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}

A constraint tree that computes the gene product amounts from given isozyme amounts their multiplicities (aka. stoichiometries, protein units, ...) given by isozyme_stoichiometry.

Values in ConstraintTree gene_product_amounts should describe the gene product allocations. Allocation for the isozyme is ignored if the gene product is missing in gene_product_amounts.

isozyme_amounts is an iterable that contains several ConstraintTrees that describe the allocated isozyme amounts (typically these would be created by isozyme_amount_variables. The multiple trees may describe several different kinds of isozyme use, e.g., you can use it to pass in both forward- and reverse-direction amounts at once. To only use a single tree, use an uni-tuple: isozyme_amounts = tuple(my_tree).

Parameter function isozyme_stoichiometry gets called with a reaction and isozyme IDs as given by the isozyme amount trees. It should return nothing in case there's no information – in such case, the isozyme is not going to be included in the calculation of gene product mass.

source
COBREXA.simplified_enzyme_constraintsMethod
simplified_enzyme_constraints(
;
    fluxes_forward,
    fluxes_reverse,
    mass_cost_forward,
    mass_cost_reverse,
    capacity_limits
)

Build a constraint system that bounds fluxes according to their enzyme mass requirements, with respect to per-reaction enzyme mass costs.

Parameter functions mass_cost_forward and mass_cost_reverse take a flux ID (corresponding to a flux in fluxes_forward and fluxes_reverse) and return the enzyme mass required to catalyze one "unit" of reaction in the forward or reverse direction, respectively. Returning nothing ignores the mass cost.

capacity_limits is an iterable container of triples (limit_id, flux_ids, bound), which creates the capacity bounds over groups of fluxes (in the same manner as for gene products in enzyme_constraints).

source
COBREXA.simplified_isozyme_gene_product_amount_constraintsMethod
simplified_isozyme_gene_product_amount_constraints(
    x...
) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}

Like isozyme_gene_product_amount_constraints, but works with the "simplified" view where each reaction has an uniquely determined catalytic isozyme, as with simplified_enzyme_constraints.

As the main difference, the arguments are tuples that contain first the constraint tree without the "isozyme" layer (i.e., fluxes), and second a function that returns the gene product stoichiometry and the turnover number (again in a tuple) for the given flux identifier.

source

Interfacing of constraint systems

COBREXA.interface_constraintsMethod
interface_constraints(
    ps::Pair...;
    default_interface,
    out_interface,
    out_balance,
    ignore,
    bound
) -> ConstraintTrees.Tree{ConstraintTrees.Constraint}

Join multiple constraint tree modules with interfaces into a bigger module with an interface.

Modules are like usual constraint trees, but contain an explicitly declared interface part, marked properly in arguments using e.g. a tuple (the parameters should form a dictionary constructor that would generally look such as :module_name => (module, module.interface); the second tuple member may also be specified just by name as e.g. :interface, or omitted while relying on default_interface).

Interface parts get merged and constrained to create a new interface; networks are intact with disjoint variable sets.

Compatible modules with ready-made interfaces may be created e.g. by flux_balance_constraints.

ignore may be used to selectively ignore parts of interfaces given the "module name" identifier and constraint path in the interface (these form 2 parameters passed to ignore). Similarly, bound may be used to specify bounds for the new interface, if required.

source