def minimal_medium(model, min_objective_value=<NUM_LIT:0.1>, exports=False,<EOL>minimize_components=False, open_exchanges=False):
exchange_rxns = find_boundary_types(model, "<STR_LIT>")<EOL>if isinstance(open_exchanges, bool):<EOL><INDENT>open_bound = <NUM_LIT:1000><EOL><DEDENT>else:<EOL><INDENT>open_bound = open_exchanges<EOL><DEDENT>with model as mod:<EOL><INDENT>if open_exchanges:<EOL><INDENT>LOGGER.debug("<STR_LIT>",<EOL>len(exchange_rxns))<EOL>for rxn in exchange_rxns:<EOL><INDENT>rxn.bounds = (-open_bound, open_bound)<EOL><DEDENT><DEDENT>LOGGER.debug("<STR_LIT>")<EOL>obj_const = mod.problem.Constraint(<EOL>mod.objective.expression, lb=min_objective_value,<EOL>name="<STR_LIT>")<EOL>mod.add_cons_vars([obj_const])<EOL>mod.solver.update()<EOL>mod.objective = Zero<EOL>LOGGER.debug("<STR_LIT>")<EOL>tol = mod.solver.configuration.tolerances.feasibility<EOL>if minimize_components:<EOL><INDENT>add_mip_obj(mod)<EOL>if isinstance(minimize_components, bool):<EOL><INDENT>minimize_components = <NUM_LIT:1><EOL><DEDENT>seen = set()<EOL>best = num_components = mod.slim_optimize()<EOL>if mod.solver.status != OPTIMAL:<EOL><INDENT>LOGGER.warning("<STR_LIT>")<EOL>return None<EOL><DEDENT>exclusion = mod.problem.Constraint(Zero, ub=<NUM_LIT:0>)<EOL>mod.add_cons_vars([exclusion])<EOL>mod.solver.update()<EOL>media = []<EOL>for i in range(minimize_components):<EOL><INDENT>LOGGER.info("<STR_LIT>", (i + <NUM_LIT:1>))<EOL>vars = [mod.variables["<STR_LIT>" + s] for s in seen]<EOL>if len(seen) > <NUM_LIT:0>:<EOL><INDENT>exclusion.set_linear_coefficients(<EOL>dict.fromkeys(vars, <NUM_LIT:1>))<EOL>exclusion.ub = best - <NUM_LIT:1><EOL><DEDENT>num_components = mod.slim_optimize()<EOL>if mod.solver.status != OPTIMAL or num_components > best:<EOL><INDENT>break<EOL><DEDENT>medium = _as_medium(exchange_rxns, tol, exports=exports)<EOL>media.append(medium)<EOL>seen.update(medium[medium > <NUM_LIT:0>].index)<EOL><DEDENT>if len(media) > <NUM_LIT:1>:<EOL><INDENT>medium = pd.concat(media, axis=<NUM_LIT:1>, sort=True).fillna(<NUM_LIT:0.0>)<EOL>medium.sort_index(axis=<NUM_LIT:1>, inplace=True)<EOL><DEDENT>else:<EOL><INDENT>medium = media[<NUM_LIT:0>]<EOL><DEDENT><DEDENT>else:<EOL><INDENT>add_linear_obj(mod)<EOL>mod.slim_optimize()<EOL>if mod.solver.status != OPTIMAL:<EOL><INDENT>LOGGER.warning("<STR_LIT>")<EOL>return None<EOL><DEDENT>medium = _as_medium(exchange_rxns, tol, exports=exports)<EOL><DEDENT><DEDENT>return medium<EOL>
Find the minimal growth medium for the model.

Finds the minimal growth medium for the model which allows for
model as well as individual growth. Here, a minimal medium can either
be the medium requiring the smallest total import flux or the medium
requiring the least components (ergo ingredients), which will be much
slower due to being a mixed integer problem (MIP).

Arguments
---------
model : cobra.model
    The model to modify.
min_objective_value : positive float or array-like object
    The minimum growth rate (objective) that has to be achieved.
exports : boolean
    Whether to include export fluxes in the returned medium. Defaults to
    False which will only return import fluxes.
minimize_components : boolean or positive int
    Whether to minimize the number of components instead of the total
    import flux. Might be more intuitive if set to True but may also be
    slow to calculate for large communities. If set to a number `n` will
    return up to `n` alternative solutions all with the same number of
    components.
open_exchanges : boolean or number
    Whether to ignore currently set bounds and make all exchange reactions
    in the model possible. If set to a number all exchange reactions will
    be opened with (-number, number) as bounds.

Returns
-------
pandas.Series, pandas.DataFrame or None
    A series giving the import flux for each required import
    reaction and (optionally) the associated export fluxes. All exchange
    fluxes are oriented into the import reaction e.g. positive fluxes
    denote imports and negative fluxes exports. If `minimize_components`
    is a number larger 1 may return a DataFrame where each column is a
    minimal medium. Returns None if the minimization is infeasible
    (for instance if min_growth > maximum growth rate).

Notes
-----
Due to numerical issues the `minimize_components` option will usually only
minimize the number of "large" import fluxes. Specifically, the detection
limit is given by ``integrality_tolerance * max_bound`` where ``max_bound``
is the largest bound on an import reaction. Thus, if you are interested
in small import fluxes as well you may have to adjust the integrality
tolerance at first with
`model.solver.configuration.tolerances.integrality = 1e-7` for instance.
However, this will be *very* slow for large models especially with GLPK.