opencobra / optlang

optlang - sympy based mathematical programming language
http://optlang.readthedocs.org/
Apache License 2.0
248 stars 51 forks source link

Error creating quadratic objectives #41

Closed the-code-magician closed 7 years ago

the-code-magician commented 7 years ago

Hi!

I'm stuck with a "maximum recursion depth exceeded in comparison" when creating a quadratic objective.

Code:

from cameo import models
from cameo.flux_analysis import moma
model = models.bigg.iJO1366
ref = model.solve().fluxes
model.reactions.PGI.knock_out()
res = moma(model, reference=ref)

Error:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-8-fecd89f0a3e4> in <module>()
----> 1 res = moma(model, reference=ref)

/Users/joao/Documents/repos/cameo/cameo/flux_analysis/simulation.py in moma(model, reference, cache, reactions, *args, **kwargs)
    193                                                     sloppy=True)
    194 
--> 195         cache.add_objective(create_objective, None, cache.variables.values())
    196 
    197         solution = model.solve()

/Users/joao/Documents/repos/cameo/cameo/util.py in add_objective(self, create, update, *args)
    184     def add_objective(self, create, update, *args):
    185         if self.objective is None:
--> 186             self.objective = create(self.model, *args)
    187             self.time_machine(
    188                 do=partial(setattr, self.model, 'objective', self.objective),

/Users/joao/Documents/repos/cameo/cameo/flux_analysis/simulation.py in create_objective(model, variables)
    191             return model.solver.interface.Objective(Add(*[FloatOne * var ** 2 for var in variables]),
    192                                                     direction="min",
--> 193                                                     sloppy=True)
    194 
    195         cache.add_objective(create_objective, None, cache.variables.values())

/Users/joao/.virtualenvs/cameo-py3/lib/python3.4/site-packages/optlang/cplex_interface.py in __init__(self, *args, **kwargs)
    302         super(Objective, self).__init__(*args, **kwargs)
    303         self._expression_expired = False
--> 304         if not (self.is_Linear or self.is_Quadratic):
    305             raise ValueError("Cplex only supports linear and quadratic objectives.")
    306 

/Users/joao/.virtualenvs/cameo-py3/lib/python3.4/site-packages/optlang/interface.py in is_Linear(self)
    464             return True
    465         else:
--> 466             poly = self.expression.as_poly(*self.variables)
    467             if poly is not None:
    468                 return poly.is_linear

/Users/joao/.virtualenvs/cameo-py3/lib/python3.4/site-packages/sympy/core/basic.py in as_poly(self, *gens, **args)
    695 
    696         try:
--> 697             poly = Poly(self, *gens, **args)
    698 
    699             if not poly.is_Poly:

/Users/joao/.virtualenvs/cameo-py3/lib/python3.4/site-packages/sympy/polys/polytools.py in __new__(cls, rep, *gens, **args)
     87                 return cls._from_poly(rep, opt)
     88             else:
---> 89                 return cls._from_expr(rep, opt)
     90 
     91     @classmethod

/Users/joao/.virtualenvs/cameo-py3/lib/python3.4/site-packages/sympy/polys/polytools.py in _from_expr(cls, rep, opt)
    198         """Construct a polynomial from an expression. """
    199         rep, opt = _dict_from_expr(rep, opt)
--> 200         return cls._from_dict(rep, opt)
    201 
    202     def _hashable_content(self):

/Users/joao/.virtualenvs/cameo-py3/lib/python3.4/site-packages/sympy/polys/polytools.py in _from_dict(cls, rep, opt)
    147                 rep[monom] = domain.convert(coeff)
    148 
--> 149         return cls.new(DMP.from_dict(rep, level, domain), *gens)
    150 
    151     @classmethod

/Users/joao/.virtualenvs/cameo-py3/lib/python3.4/site-packages/sympy/polys/polyclasses.py in from_dict(cls, rep, lev, dom)
    257     def from_dict(cls, rep, lev, dom):
    258         """Construct and instance of ``cls`` from a ``dict`` representation. """
--> 259         return cls(dmp_from_dict(rep, lev, dom), dom, lev)
    260 
    261     @classmethod

/Users/joao/.virtualenvs/cameo-py3/lib/python3.4/site-packages/sympy/polys/densebasic.py in dmp_from_dict(f, u, K)
   1013 
   1014         if coeff is not None:
-> 1015             h.append(dmp_from_dict(coeff, v, K))
   1016         else:
   1017             h.append(dmp_zero(v))

... last 1 frames repeated, from the frame below ...

/Users/joao/.virtualenvs/cameo-py3/lib/python3.4/site-packages/sympy/polys/densebasic.py in dmp_from_dict(f, u, K)
   1013 
   1014         if coeff is not None:
-> 1015             h.append(dmp_from_dict(coeff, v, K))
   1016         else:
   1017             h.append(dmp_zero(v))

RuntimeError: maximum recursion depth exceeded in comparison
KristianJensen commented 7 years ago

I can reproduce it. It looks like an easy fix.

KristianJensen commented 7 years ago

The sloppy keyword was broken. Now using sloppy=True will cause the expression not be tested by is_Linear or is_Quadratic. If sloppy=False this error can still occur for very large expressions, but making sure that the expression is canonical should prevent it.