opencobra / cobrapy

COBRApy is a package for constraint-based modeling of metabolic networks.
http://opencobra.github.io/cobrapy/
GNU General Public License v2.0
455 stars 211 forks source link

[BUG] using gurobi on non-linear optimization #1381

Closed lbugnon closed 3 months ago

lbugnon commented 4 months ago

Is there an existing issue for this?

Problem description

I'm trying to optimize a model flux product (fluxA*fluxB). Gurobi rises error "GurobiError: Unable to retrieve attribute 'RC'". If its not a bug, a hint in documentation would be nice

Code sample

import cobra
from cobra.io import load_model

model = load_model("textbook")
model.solver = "gurobi"
quadratic_objective = model.problem.Objective(
    model.reactions.Biomass_Ecoli_core.flux_expression*model.reactions.ETOHt2r.flux_expression,
    direction='max')
model.objective = quadratic_objective
print(model.objective)
sp = model.optimize()
---------------------------------------------------------------------------
GurobiError                               Traceback (most recent call last)
Cell In[14], [line 17](vscode-notebook-cell:?execution_count=14&line=17)
     [15](vscode-notebook-cell:?execution_count=14&line=15) model.objective = quadratic_objective
     [16](vscode-notebook-cell:?execution_count=14&line=16) print(model.objective)
---> [17](vscode-notebook-cell:?execution_count=14&line=17) sp = model.optimize()
     [18](vscode-notebook-cell:?execution_count=14&line=18) print(sp)

File [~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/model.py:1233](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/model.py:1233), in Model.optimize(self, objective_sense, raise_error)
   [1229](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/model.py:1229) self.objective.direction = {"maximize": "max", "minimize": "min"}.get(
   [1230](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/model.py:1230)     objective_sense, original_direction
   [1231](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/model.py:1231) )
   [1232](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/model.py:1232) self.slim_optimize()
-> [1233](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/model.py:1233) solution = get_solution(self, raise_error=raise_error)
   [1234](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/model.py:1234) self.objective.direction = original_direction
   [1235](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/model.py:1235) return solution

File [~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/solution.py:185](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/solution.py:185), in get_solution(model, reactions, metabolites, raise_error)
    [183](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/solution.py:183)     met_index = [met.id for met in metabolites]
    [184](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/solution.py:184) else:
--> [185](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/solution.py:185)     var_duals = model.solver.reduced_costs
    [186](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/solution.py:186)     for i, rxn in enumerate(reactions):
    [187](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/cobra/core/solution.py:187)         forward = rxn.id

File [~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1303](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1303), in Model.reduced_costs(self)
   [1294](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1294) @property
   [1295](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1295) def reduced_costs(self):
   [1296](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1296)     """The reduced costs/dual values of all variables.
   [1297](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1297) 
   [1298](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1298)     Returns
   [1299](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1299)     -------
   [1300](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1300)     collections.OrderedDict
   [1301](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1301)     """
   [1302](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1302)     return OrderedDict(
-> [1303](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1303)         zip(self._get_variables_names(), self._get_reduced_costs())
   [1304](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/interface.py:1304)     )

File [~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/gurobi_interface.py:780](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/gurobi_interface.py:780), in Model._get_reduced_costs(self)
    [777](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/gurobi_interface.py:777) if self.is_integer:
    [778](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/gurobi_interface.py:778)     raise ValueError(
    [779](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/gurobi_interface.py:779)         "Reduced costs are not well defined for integer problems.")
--> [780](https://file+.vscode-resource.vscode-cdn.net/home/lbugnon/gsm_gurobi/~/.virtualenvs/amn/lib/python3.11/site-packages/optlang/gurobi_interface.py:780) return self.problem.RC

File src/gurobipy/model.pxi:368, in gurobipy.Model.__getattr__()

File src/gurobipy/model.pxi:1928, in gurobipy.Model.getAttr()

File src/gurobipy/attrutil.pxi:151, in gurobipy._gettypedattrlist()

GurobiError: Unable to retrieve attribute 'RC'

Environment

Anything else?

No response

cdiener commented 4 months ago

Hi, your problem is not convex, so there are no reduced costs which triggers the error. We could maybe raise a better error or return only the primal values in optlang if those are available. But non-convex optimization is not supported well in cobrapy at the moment.

lbugnon commented 4 months ago

Great thank you!

Palaract commented 3 months ago

That's actually a similar problem to what I already had: https://github.com/opencobra/cobrapy/issues/1372#issue-2098982839 I looked into the code and have a general idea on how to tackle this. I think it would be the best to have a default case which is executed if shadow prices and/or reduced costs can't be accessed. This is relatively ease to mitigate, so I will make a PR soon which introduces better error handling.