Exemplo n.º 1
0
def test_solver():
    """Test assignment of different solvers."""
    config = Configuration()
    config.solver = "glpk"
    assert interface_to_str(config.solver) == "glpk"
    config.solver = "glpk_exact"
    assert interface_to_str(config.solver) == "glpk_exact"
    # Restore default solver.
    config.solver = "glpk"
Exemplo n.º 2
0
    def test_choose_solver(self, model):
        so = su.choose_solver(model)
        assert su.interface_to_str(so) == "glpk"
        so = su.choose_solver(model, "glpk")
        assert su.interface_to_str(so) == "glpk"

        if any(s in su.solvers for s in su.qp_solvers):
            qp_choice = su.choose_solver(model, qp=True)
            assert su.interface_to_str(qp_choice) in su.qp_solvers
        else:
            with pytest.raises(su.SolverNotFound):
                su.choose_solver(model, qp=True)
Exemplo n.º 3
0
 def _repr_html_(self):
     return """
     <table>
         <tr>
             <td><strong>Solver</strong></td>
             <td>{solver}</td>
         </tr>
         <tr>
             <td><strong>Solver tolerance</strong></td>
             <td>{tolerance}</td>
         </tr>
         <tr>
             <td><strong>Lower bound</strong></td>
             <td>{lower_bound}</td>
         </tr>
         <tr>
             <td><strong>Upper bound</strong></td>
             <td>{upper_bound}</td>
         </tr>
         <tr>
             <td><strong>Processes</strong></td>
             <td>{processes}</td>
         </tr>
     </table>""".format(
         solver=interface_to_str(self.solver),
         tolerance=self.tolerance,
         lower_bound=self.lower_bound,
         upper_bound=self.upper_bound,
         processes=self.processes,
     )
Exemplo n.º 4
0
 def __repr__(self):
     return """
     solver: {solver}
     solver tolerance: {tolerance}
     lower_bound: {lower_bound}
     upper_bound: {upper_bound}
     processes: {processes}""".format(
         solver=interface_to_str(self.solver),
         tolerance=self.tolerance,
         lower_bound=self.lower_bound,
         upper_bound=self.upper_bound,
         processes=self.processes,
     )
Exemplo n.º 5
0
    def solver(self, value):
        not_valid_interface = SolverNotFound(
            '%s is not a valid solver interface. Pick from %s.' % (
                value, list(solvers)))
        if isinstance(value, six.string_types):
            try:
                interface = solvers[interface_to_str(value)]
            except KeyError:
                raise not_valid_interface
        elif isinstance(value, types.ModuleType) and hasattr(value, 'Model'):
            interface = value
        elif isinstance(value, optlang.interface.Model):
            interface = value.interface
        else:
            raise not_valid_interface

        # Do nothing if the solver did not change
        if self.problem == interface:
            return
        self._solver = interface.Model.clone(self._solver)
Exemplo n.º 6
0
def _multi_deletion(model, entity, element_lists, method="fba",
                    processes=None):
    """
    Provide a common interface for single or multiple knockouts.

    Parameters
    ----------
    model : cobra.Model
        The metabolic model to perform deletions in.

    entity : 'gene' or 'reaction'
        The entity to knockout (``cobra.Gene`` or ``cobra.Reaction``).

    element_lists : list
        List of iterables ``cobra.Reaction``s or ``cobra.Gene``s (or their IDs)
        to be deleted.

    method: {"fba", "moma", "linear moma"}, optional
        Method used to predict the growth rate.

    processes : int, optional
        The number of parallel processes to run. Can speed up the computations
        if the number of knockouts to perform is large. If not passed,
        will be set to the number of CPUs found.

    Returns
    -------
    pandas.DataFrame
        A representation of all combinations of entity deletions. The
        columns are 'growth' and 'status', where

        index : frozenset([str])
            The gene or reaction identifiers that were knocked out.
        growth : float
            The growth rate of the adjusted model.
        status : str
            The solution's status.
    """
    solver = sutil.interface_to_str(model.problem.__name__)
    if "moma" in method and solver not in sutil.qp_solvers:
        raise RuntimeError(
            "Cannot use MOMA since '{}' is not QP-capable."
            "Please choose a different solver or use FBA only.".format(solver))

    if processes is None:
        try:
            processes = multiprocessing.cpu_count()
        except NotImplementedError:
            warn("Number of cores could not be detected - assuming 1.")
            processes = 1

    with model:
        if "moma" in method:
            add_moma(model, linear="linear" in method)

        args = set([frozenset(comb) for comb in product(*element_lists)])
        processes = min(processes, len(args))

        def extract_knockout_results(result_iter):
            result = pd.DataFrame([
                (frozenset(ids), growth, status)
                for (ids, growth, status) in result_iter
            ], columns=['ids', 'growth', 'status'])
            result.set_index('ids', inplace=True)
            return result

        if processes > 1:
            worker = dict(gene=_gene_deletion_worker,
                          reaction=_reaction_deletion_worker)[entity]
            chunk_size = len(args) // processes
            pool = multiprocessing.Pool(
                processes, initializer=_init_worker, initargs=(model,)
            )
            results = extract_knockout_results(pool.imap_unordered(
                worker,
                args,
                chunksize=chunk_size
            ))
            pool.close()
            pool.join()
        else:
            worker = dict(gene=_gene_deletion,
                          reaction=_reaction_deletion)[entity]
            results = extract_knockout_results(map(
                partial(worker, model), args))
        return results
Exemplo n.º 7
0
 def test_interface_str(self):
     assert su.interface_to_str("nonsense") == "nonsense"
     assert su.interface_to_str("optlang.glpk_interface") == "glpk"
     assert su.interface_to_str("optlang-cplex") == "cplex"
Exemplo n.º 8
0
def _multi_deletion(model,
                    entity,
                    element_lists,
                    method="fba",
                    solution=None,
                    processes=None,
                    **kwargs):
    """
    Provide a common interface for single or multiple knockouts.

    Parameters
    ----------
    model : cobra.Model
        The metabolic model to perform deletions in.
    entity : 'gene' or 'reaction'
        The entity to knockout (``cobra.Gene`` or ``cobra.Reaction``).
    element_lists : list
        List of iterables ``cobra.Reaction``s or ``cobra.Gene``s (or their IDs)
        to be deleted.
    method: {"fba", "moma", "linear moma", "room", "linear room"}, optional
        Method used to predict the growth rate.
    solution : cobra.Solution, optional
        A previous solution to use as a reference for (linear) MOMA or ROOM.
    processes : int, optional
        The number of parallel processes to run. Can speed up the computations
        if the number of knockouts to perform is large. If not passed,
        will be set to the number of CPUs found.
    kwargs :
        Passed on to underlying simulation functions.

    Returns
    -------
    pandas.DataFrame
        A representation of all combinations of entity deletions. The
        columns are 'growth' and 'status', where

        index : tuple(str)
            The gene or reaction identifiers that were knocked out.
        growth : float
            The growth rate of the adjusted model.
        status : str
            The solution's status.
    """
    solver = sutil.interface_to_str(model.problem.__name__)
    if method == "moma" and solver not in sutil.qp_solvers:
        raise RuntimeError(
            "Cannot use MOMA since '{}' is not QP-capable."
            "Please choose a different solver or use FBA only.".format(solver))

    if processes is None:
        processes = configuration.processes

    with model:
        if "moma" in method:
            add_moma(model, solution=solution, linear="linear" in method)
        elif "room" in method:
            add_room(model,
                     solution=solution,
                     linear="linear" in method,
                     **kwargs)

        args = set([frozenset(comb) for comb in product(*element_lists)])
        processes = min(processes, len(args))

        def extract_knockout_results(result_iter):
            result = pd.DataFrame(
                [(
                    set(ids),
                    growth,
                    status,
                ) for (ids, growth, status) in result_iter],
                columns=["ids", "growth", "status"],
            )
            return result

        if processes > 1:
            worker = dict(gene=_gene_deletion_worker,
                          reaction=_reaction_deletion_worker)[entity]
            chunk_size = len(args) // processes

            with ProcessPool(processes,
                             initializer=_init_worker,
                             initargs=(model, )) as pool:
                results = extract_knockout_results(
                    pool.imap_unordered(worker, args, chunksize=chunk_size))
        else:
            worker = dict(gene=_gene_deletion,
                          reaction=_reaction_deletion)[entity]
            results = extract_knockout_results(
                map(partial(worker, model), args))
        return results
Exemplo n.º 9
0
def test_interface_str() -> None:
    """Test the string representation of solver interfaces."""
    assert su.interface_to_str("nonsense") == "nonsense"
    assert su.interface_to_str("optlang.glpk_interface") == "glpk"
    assert su.interface_to_str("optlang-cplex") == "cplex"
def single_reaction_deletion_fba(cobra_model,
                                 reaction_list,
                                 solver=None,
                                 **solver_args):
    """Sequentially knocks out each reaction in a model using FBA.

    Not supposed to be called directly use
    `single_reactions_deletion(..., method="fba")` instead.

    Parameters
    ----------
    cobra_model : cobra.Model
        The model from which to delete the reactions. The model will not be
        modified.
    reaction_list : iterable
        List of reaction Ids or cobra.Reaction.
    solver: str, optional
        The name of the solver to be used.

    Returns
    -------
    tuple of dicts
        A tuple ({reaction_id: growth_rate}, {reaction_id: status})
    """
    legacy = False
    if solver is None:
        solver = cobra_model.solver
    elif "optlang-" in solver:
        solver = solvers.interface_to_str(solver)
        solver = solvers.solvers[solver]
    else:
        legacy = True
        solver = legacy_solvers.solver_dict[solver]
        lp = solver.create_problem(cobra_model)

    growth_rate_dict = {}
    status_dict = {}

    if not legacy:
        with cobra_model as m:
            m.solver = solver
            for reaction in reaction_list:
                with m:
                    reaction.knock_out()
                    obj_value = m.slim_optimize()
                    status_dict[reaction.id] = m.solver.status
                    growth_rate_dict[reaction.id] = obj_value
    else:
        # This entire block can be removed once the legacy solvers are
        # deprecated
        for reaction in reaction_list:
            old_bounds = (reaction.lower_bound, reaction.upper_bound)
            index = cobra_model.reactions.index(reaction)
            solver.change_variable_bounds(lp, index, 0., 0.)
            solver.solve_problem(lp, **solver_args)
            # get the status and growth rate
            status = solver.get_status(lp)
            status_dict[reaction.id] = status
            growth_rate_dict[reaction.id] = solver.get_objective_value(lp) \
                if status == "optimal" else 0.
            # reset the problem
            solver.change_variable_bounds(lp, index, old_bounds[0],
                                          old_bounds[1])
    return growth_rate_dict, status_dict
def single_gene_deletion_moma(cobra_model,
                              gene_list,
                              linear=False,
                              solver=None,
                              **solver_args):
    """Sequentially knocks out each gene in a model using MOMA.

    Not supposed to be called directly use
    `single_reactions_deletion(..., method="moma")` instead.

    Parameters
    ----------
    gene_list : iterable
        List of gene IDs or cobra.Reaction.
    linear : bool
        Whether to use linear MOMA.
    solver : str, optional
        The name of the solver to be used.

    Returns
    -------
    tuple of dicts
        A tuple ({reaction_id: growth_rate}, {reaction_id: status})
    """
    if moma is None:
        raise RuntimeError("scipy required for moma")

    legacy = False
    if solver is None:
        solver = cobra_model.solver
    elif "optlang-" in solver:
        solver = solvers.interface_to_str(solver)
        solver = solvers.solvers[solver]
    else:
        legacy = True
        solver = legacy_solvers.solver_dict[solver]
        moma_model, moma_objective = moma.create_euclidian_moma_model(
            cobra_model)

    growth_rate_dict = {}
    status_dict = {}

    if not legacy:
        solution = cobra_model.optimize()
        with cobra_model as m:
            m.solver = solver
            moma.add_moma(m, solution=solution, linear=linear)
            for gene in gene_list:
                with m:
                    gene.knock_out()
                    status = m.solver.optimize()
                    status_dict[gene.id] = status
                    if status == OPTIMAL:
                        growth = m.variables.moma_old_objective.primal
                    else:
                        growth = float("nan")
                    growth_rate_dict[gene.id] = growth
    else:
        for gene in gene_list:
            delete_model_genes(moma_model, [gene.id])
            solution = moma.solve_moma_model(moma_model,
                                             moma_objective,
                                             solver=solver,
                                             **solver_args)
            status_dict[gene.id] = solution.status
            growth_rate_dict[gene.id] = solution.f
            undelete_model_genes(moma_model)
    return growth_rate_dict, status_dict
def single_gene_deletion_fba(cobra_model,
                             gene_list,
                             solver=None,
                             **solver_args):
    """Sequentially knocks out each gene in a model using FBA.

    Not supposed to be called directly use
    `single_reactions_deletion(..., method="fba")` instead.

    Parameters
    ----------
    gene_list : iterable
        List of gene IDs or cobra.Reaction.
    solver: str, optional
        The name of the solver to be used.

    Returns
    -------
    tuple of dicts
        A tuple ({reaction_id: growth_rate}, {reaction_id: status})
    """
    legacy = False
    if solver is None:
        solver = cobra_model.solver
    elif "optlang-" in solver:
        solver = solvers.interface_to_str(solver)
        solver = solvers.solvers[solver]
    else:
        legacy = True
        solver = legacy_solvers.solver_dict[solver]
        lp = solver.create_problem(cobra_model)

    growth_rate_dict = {}
    status_dict = {}

    if not legacy:
        with cobra_model as m:
            m.solver = solver
            for gene in gene_list:
                with m:
                    gene.knock_out()
                    obj_value = m.slim_optimize()
                    status_dict[gene.id] = m.solver.status
                    growth_rate_dict[gene.id] = obj_value
    else:
        for gene in gene_list:
            old_bounds = {}
            for reaction in find_gene_knockout_reactions(cobra_model, [gene]):
                index = cobra_model.reactions.index(reaction)
                old_bounds[index] = reaction.bounds
                solver.change_variable_bounds(lp, index, 0., 0.)
            solver.solve_problem(lp, **solver_args)
            # get the status and growth rate
            status = solver.get_status(lp)
            status_dict[gene.id] = status
            growth_rate = solver.get_objective_value(lp) \
                if status == "optimal" else 0.
            growth_rate_dict[gene.id] = growth_rate
            # reset the problem
            for index, bounds in iteritems(old_bounds):
                solver.change_variable_bounds(lp, index, bounds[0], bounds[1])
    return growth_rate_dict, status_dict
def single_reaction_deletion_moma(cobra_model,
                                  reaction_list,
                                  linear=False,
                                  solver=None,
                                  **solver_args):
    """Sequentially knocks out each reaction in a model using MOMA.

    Not supposed to be called directly use
    `single_reactions_deletion(..., method="moma")` instead.

    Parameters
    ----------
    cobra_model : cobra.Model
        The model from which to delete the reactions. The model will not be
        modified.
    reaction_list : iterable
        List of reaction IDs or cobra.Reaction.
    linear : bool
        Whether to use linear MOMA.
    solver: str, optional
        The name of the solver to be used.

    Returns
    -------
    tuple of dicts
        A tuple ({reaction_id: growth_rate}, {reaction_id: status})
    """
    # The same function can not be used because MOMA can not re-use the
    # same LP object. Problem re-use leads to incorrect solutions.
    # This is *not* true for optlang solvers!
    if moma is None:
        raise RuntimeError("scipy required for moma")

    legacy = False
    if solver is None:
        solver = cobra_model.solver
    elif "optlang-" in solver:
        solver = solvers.interface_to_str(solver)
        solver = solvers.solvers[solver]
    else:
        legacy = True
        solver = legacy_solvers.solver_dict[solver]
        moma_model, moma_objective = moma.create_euclidian_moma_model(
            cobra_model)

    growth_rate_dict = {}
    status_dict = {}

    if not legacy:
        solution = cobra_model.optimize()
        with cobra_model as m:
            m.solver = solver
            moma.add_moma(m, solution=solution, linear=linear)
            for reaction in reaction_list:
                with m:
                    reaction.knock_out()
                    status = m.solver.optimize()
                    status_dict[reaction.id] = status
                    if status == OPTIMAL:
                        growth = m.variables.moma_old_objective.primal
                    else:
                        growth = float("nan")
                    growth_rate_dict[reaction.id] = growth
    else:
        for reaction in reaction_list:
            index = cobra_model.reactions.index(reaction)
            solution = moma.moma_knockout(moma_model,
                                          moma_objective, (index, ),
                                          solver=solver,
                                          **solver_args)
            status_dict[reaction.id] = solution.status
            growth_rate_dict[reaction.id] = solution.f
    return growth_rate_dict, status_dict
Exemplo n.º 14
0
 def test_interface_str(self):
     assert su.interface_to_str("nonsense") == "nonsense"
     assert su.interface_to_str("optlang.glpk_interface") == "glpk"
     assert su.interface_to_str("optlang-cplex") == "cplex"