• Main Page
  • Namespaces
  • Classes
  • Files
  • File List

/home/mark/model/software/ScrumPy/ScrumPy/LP/ScrumPyLP.py

00001 
00002 """
00003 ScrumPyLP - (c) Mark Poolman 2008 onwards.
00004 A module to allow LP optimisation and analysis of of metabolic models with ScrumPy.
00005 
00006 
00007 This module is still experimental and is
00008 
00009   *************************   NOT TO BE REDISTRIBUTED  ***************************
00010 
00011 without the prior consent of the author.
00012 
00013 """
00014 
00015 
00016 
00017 
00018 
00019 
00020 import sys, types, exceptions
00021 
00022 SysStderr = sys.stderr
00023 NullF =  open("/dev/null", "w")
00024 
00025 
00026 import glpk
00027 
00028 from Util import Set, DynMatrix
00029 from Data import DataSets
00030 from Structural import StoMat
00031 
00032 
00033 def SplitRev(sm,Conv=float): # copy of sm with reversible reacs split into forward and back irreversible pairs
00034 
00035     rv = sm.Copy(Conv)
00036     rv.Reversed = reversed = []
00037     rv.Backs = backs = []
00038 
00039     for r in sm.cnames:
00040         if sm.RevProps[r] == StoMat.t_Rever:
00041             sto = sm.InvolvedWith(r)
00042             rback = r+"_back"
00043             rv.NewReaction(rback,sto)
00044             rv.MulCol(rback,k=-1)
00045             backs.append(rback)
00046 
00047         elif sm.RevProps[r] == StoMat.t_BackIrrev:
00048            sm.MulCol(r,  k=-1)
00049            reversed.append(r)
00050 
00051     return rv
00052 
00053 def SplitRevOld(sm,Conv=float): # copy of sm with reversible reacs split into forward and back irreversible pairs
00054     sm = sm.Copy(Conv)
00055     revs = Set.Complement(sm.cnames, sm.Irrevs)
00056     backs = []
00057     for r in revs:
00058         sto = sm.InvolvedWith(r)
00059         for met in sto:
00060             sto[met] *= -1
00061         rback = r+"_back"
00062         sm.NewReaction(rback,sto)
00063         backs.append(rback)
00064     sm.Irrevs = sm.cnames[:]
00065     sm.Backs = backs
00066     return sm
00067 
00068 
00069 
00070 def SplitAll(sm,Conv=float):
00071 
00072     sm = sm.Copy(Conv)
00073     irbacks = []
00074     for r in sm.cnames[:]:
00075         sto = sm.InvolvedWith(r)
00076         for met in sto:
00077             sto[met] *= -1
00078         newreac = r+"_back"
00079         sm.NewReaction(newreac,sto)
00080         if r in sm.Irrevs:
00081             irbacks.append(newreac)
00082 
00083     sm.Irrevs = sm.cnames[:]
00084     sm.irbacks = irbacks
00085     return sm
00086 
00087 
00088 
00089 class lp(glpk.lp):
00090 
00091     def __init__(self, model):
00092 
00093         name = model.FileName.split("/")[-1].split(".")[0]
00094         sm = self.sm = SplitRev(model.sm)
00095 
00096         glpk.lp.__init__(self,name)
00097         self.AddRows(sm.rnames[:])
00098         self.AddCols(sm.cnames[:])
00099         for reac in sm.cnames:
00100             self.SetColBounds(reac,0)
00101 
00102         for row in sm.rnames:
00103             self.SetRowVals(row, map(float, sm[row]))
00104             self.SetRowBounds(row, 0,0)
00105 
00106 
00107     def _irrev_check(self,reac,rate):
00108         print "_irev_check disabled"
00109         return
00110         #
00111         #        if  rate <0 and reac in self.sm.Irrevs:
00112         #            sys.stderr.write("""
00113         #            ! Warning  -ve rate is inconsistent with irreverisibily
00114         #            ! assumptions. (doing it anyway) """)
00115 
00116 
00117     def _BackReac(self, reac):
00118 
00119         rback = reac + "_back"
00120         if rback in self.sm.Backs:
00121             return rback
00122         return None
00123 
00124 
00125     def SetObjective(self,reacs):
00126 
00127         if type(reacs)==types.DictType:
00128             reacs = dict(reacs)
00129             for reac in reacs.keys():
00130                 back = self._BackReac(reac)
00131                 if back != None:
00132                     reacs[back] = reacs[reac]
00133             self.SetObjCoefsFromDic(reacs)
00134 
00135         else:
00136             reacs = reacs[:]
00137             for reac in reacs:
00138                 back = self._BackReac(reac)
00139                 if back != None and back not in reacs:
00140                     reacs.append(back)
00141             self.SetObjCoefsFromLists(reacs,[1]*len(reacs))
00142 
00143     def SetObjCoef(self, c, coef):
00144 
00145         glpk.lp.SetObjCoef(self, c, coef)
00146 
00147         if not self.sm.IsIrrev(c):
00148             glpk.lp.SetObjCoef(self, c+"_back", coef)
00149 
00150 
00151 
00152 
00153 
00154     def SetFixedFlux(self, reacs):
00155 
00156         for reac in reacs:
00157 
00158             rate = reacs[reac]
00159             if reac in self.sm.Reversed:
00160                 rate *= -1
00161 
00162             rback = reac + "_back"
00163             hasback = rback in self.sm.Backs
00164 
00165             if rate >= 0:
00166                 self.SetColBounds(reac, rate, rate)
00167                 if hasback:
00168                     self.SetColBounds(rback, 0,0)
00169             else:
00170                 if not hasback:
00171                     sys.stderr.write("! Setting inconsitant flux in irreversible reaction %s\n" % reac)
00172                     self.SetColBounds(reac, rate, rate)
00173                 else:
00174                     self.SetColBounds(reac, 0, 0)
00175                     self.SetColBounds(rback, -rate, -rate)
00176 
00177 
00178     def UnboundFlux(self, reac):
00179 
00180         self.SetColBounds(reac, 0, None)
00181 
00182         rback = self._BackReac(reac)
00183         if rback != None:
00184             self.SetColBounds(rback, 0, None)
00185 
00186 
00187     def FiniteBoundFlux(self, reac, lo, hi):
00188 
00189         if hi < lo:
00190             lo,hi = hi,lo
00191 
00192         rback = self._BackReac(reac)
00193         if rback == None:
00194             if lo < 0:
00195                 raise exceptions.ValueError, "attempt to set -ve bound on irreversible "+reac
00196             self.SetColBounds(reac, lo,hi)
00197         else:
00198             if hi < 0:
00199                 self.SetColBounds(reac,0,0)
00200                 self.SetColBounds(rback, -hi, -lo)
00201             elif lo < 0:
00202                 self.SetColBounds(reac,0,hi)
00203                 self.SetColBounds(rback, 0, -lo)
00204             else:
00205                 self.SetColBounds(reac,lo,hi)
00206                 self.SetColBounds(rback, 0, 0)
00207 
00208 
00209 
00210 
00211     def SetFluxBounds(self, reacs):
00212         """ Pre: reacs = {name:(lo,hi)...}, (lo<=hi OR hi==None) """
00213 
00214         for reac in reacs:
00215 
00216             lo, hi = reacs[reac]
00217 
00218             if lo == hi == None:
00219                 self.UnboundFlux(reac)
00220 
00221             elif lo == hi:
00222                 self.SetFixedFlux({reac:lo})
00223 
00224             elif not None in (lo,hi):
00225                 self.FiniteBoundFlux(reac, lo, hi)
00226 
00227             else:                                  # lo == None xor hi == None
00228                 rback = self._BackReac(reac)
00229 
00230                 if rback == None:                  # irreversible
00231                     self.SetColBounds(reac, lo, hi)
00232                 else:                              # reversible reaction
00233                     if lo == None:                 # lo == None
00234                         if hi < 0.0:
00235                             self.SetColBounds(reac, 0,0)
00236                             self.SetColBounds(rback, -hi, None)
00237                         else:
00238                             self.SetColBounds(reac,  0, hi)
00239                             self.SetColBounds(rback, 0, None)
00240                     else:
00241                         if lo < 0.0:                # hi == None
00242                             self.SetColBounds(reac, 0,None)
00243                             self.SetColBounds(rback, 0, -lo)
00244                         else:
00245                             self.SetColBounds(reac, lo,None)
00246                             self.SetColBounds(rback, 0, 0)
00247 
00248     def SetSumFluxConstraint(self,  reacs, total,  name):
00249 
00250         self.AddRows([name])
00251         nc  =self.GetDims()[1]
00252         vals = [0.0] * nc  # TODO - need a GetRow/ColVec in glpk
00253         reacs = reacs[:]
00254         for r in reacs[:]:
00255             rback = self._BackReac(r)
00256             if rback != None:
00257                 reacs.append(rback)
00258         idxs = glpk.SubOne(self.GetColIdxs(reacs))
00259         print idxs
00260         for idx in idxs:
00261             vals[idx] = 1.0
00262         self.SetRowVals(name,vals)
00263         self.SetRowBounds(name,  total, total)
00264 
00265         print "SetSumFluxCostraint testing !"
00266 
00267 
00268 
00269 
00270 
00271     def Solve(self,PrintStatus=True):
00272         glpk.lp.Solve(self)
00273         if PrintStatus:
00274             print self.GetStatusMsg()
00275 
00276 
00277     def GetPrimSol(self, IncZeroes=False,FixBack=True,AsMtx=False):
00278 
00279         sol = {}
00280 
00281         if self.GetStatusMsg()=="Optimal":
00282             for r in range(len(self.sm.cnames)):
00283                 name = self.sm.cnames[r]
00284                 val = self._glp_lpx_get_col_prim(r+1)
00285                 if IncZeroes or not glpk.IsZero(val):
00286                     sol[name] = self._glp_lpx_get_col_prim(r+1)
00287 
00288         for rev in Set.Intersect(self.sm.Reversed,  sol.keys()):
00289             sol[rev] *= -1
00290 
00291         if FixBack:     #### all this lacks elegance - needs a re-think.svn
00292             for reac in sol.keys():
00293                 if reac.endswith("_back"):
00294                     val = sol[reac]
00295                     if not glpk.IsZero(val):
00296                         r2 = reac[:-5]
00297                         if not sol.has_key(r2):
00298                             sol[r2] = 0.0
00299                         sol[r2] -= val
00300                     del sol[reac]
00301 
00302         if  AsMtx:
00303             rv = StoMat.StoMat(cnames=["lp_sol"],rnames=sol.keys(),Conv=float)
00304             for r in sol:
00305                 rv[r][0] = sol[r]
00306         else:
00307             rv = sol
00308 
00309         return rv
00310 
00311 
00312     def GetSimplexAsMtx(self):
00313 
00314         rnames = self.GetRowNames()
00315         cnames = self.GetColNames()
00316         rows   = self.GetRowsAsLists()
00317 
00318         rv = DynMatrix.matrix(rnames=rnames, cnames=cnames, Conv=float)
00319         rv.rows =rows
00320 
00321         return rv
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330     def MatchFlux(self,fluxes, IncZeroes=False, AsMtx=False, SupressWarnings=True):
00331 
00332         if SupressWarnings:
00333             sys.stderr = NullF
00334 
00335         self.SetFixedFlux(fluxes)
00336         self.SetObjective(self.sm.cnames)
00337         self.Solve()
00338 
00339         if SupressWarnings:
00340             sys.stderr = SysStderr
00341 
00342         return self.GetPrimSol(IncZeroes=IncZeroes, AsMtx=AsMtx)
00343 
00344 
00345 
00346 
00347     def FixedFluxScan(self, reaction, lo, hi, n_p):
00348 
00349         rv = DataSets.DataSet(ItemNames=[reaction,"ObjVal"])
00350         lo = float(lo)
00351         hi = float(hi)
00352 
00353         inc = (hi - lo)/(n_p-1)
00354         cur = lo
00355 
00356         for n in range(n_p):
00357             self.SetFixedFlux({reaction:cur})
00358             self.Solve(False)
00359 
00360             sol = self.GetPrimSol()
00361 
00362             if len(sol)==0:
00363                 obval = float("NaN") # indicate fail
00364             else:
00365                 obval =  self.GetObjVal()
00366 
00367             sol["ObjVal"] = obval
00368             sol[reaction] = cur
00369             rv.UpdateFromDic(sol)
00370 
00371             cur += inc
00372 
00373         return rv
00374 
00375 
00376 
00377 
00378 
00379 

Generated on Tue Sep 4 2012 15:38:02 for ScrumPy by  doxygen 1.7.1