Esempio n. 1
0
 def selectSubMatrix(self, model, rowFilter = None, columnFilter = None, union = False):
     regexRow = None
     regexColumn = None
     
     if rowFilter != None:
         regexRow = re.compile(rowFilter)
     if columnFilter != None:
         regexColumn = re.compile(columnFilter)
     
     result = LinearModel()
     for key in model.data.keys():
         (rowName,columnName) = key
         value = model.getData(rowName,columnName)
         
         if regexRow: rowCheck = regexRow.match(rowName)
         else: rowCheck = False
         if regexColumn: columnCheck = regexColumn.match(columnName)
         else: columnCheck = False
         
         if union:
             if rowCheck and columnCheck:
                 result.addData(rowName,columnName,value)
         else:
             if rowCheck or columnCheck:
                 result.addData(rowName,columnName,value)
             
     return result
 def _constructDualRegulation(self,model,names,prefix):
     '''
     Construct limit / freedom variable for dual
     These are the dual analog control variables
     S'lambda + ... - delta - c' = 0
     '''
     
     rName = self.dualRName + prefix
     jmodel = LinearModel()
     equation = "%s" % (self.cdName)
     jmodel = self.parseEquations.applyRelation(jmodel,rName,equation,names,prefixPattern="%s"+prefix)
     
     imodel = LinearModel()
     for name in names:
         rName = self.dualRName + prefix + name
         sName = self.cdName + prefix + name
         imodel.addData(rName,sName,1)
         imodel.addColumnLimit(sName,(None,None))
     
     if not imodel == jmodel:
         print "---------------------------------apply equation faliure: Dual control-----------------------------------------"
         
     model.addConstraints(imodel)
         
     return model
def findBoundaryProduction(originalModel, bounds, combiLimits, objectiveName, productionName):
    model = LinearModel()
    model.extend(originalModel)
    if combiLimits != None:
        for (targetValues,limit) in combiLimits:
            model = addCombinationLimit(model, targetValues,limit)
    #objectiveMap = {objectiveName:-1.0}
    objectiveMap = {productionName:1.0}
    model.addColumnLimits(bounds)
    lp = LPSolver()
    fluxMap = lp.run(model,objectiveMap)
    objectiveValue = fluxMap[objectiveName]
    productionValue = fluxMap[productionName]
    return (fluxMap,objectiveValue,productionValue)
Esempio n. 4
0
 def findMinMax(self, model, objectiveName, minValue, targets):
     positive = {}
     negative = {}
     imodel = LinearModel()
     imodel.extend(model)
     if minValue < 0:
         imodel.addColumnLimit(objectiveName,(None,minValue))
     else:
         imodel.addColumnLimit(objectiveName,(minValue,None))
     
     lp = LinearOptimization()
     lp.setModel(model)
     for t in targets:
         lp.clearObjective()
         lp.setObjectiveMap({t: -1})
         lp.runSimplex()
         fluxes = lp.getPredictionMap()
         lowValue = fluxes[t]
         negative[t] = lowValue
         
         lp.clearObjective()
         lp.setObjectiveMap({t: 1})
         lp.runSimplex()
         fluxes = lp.getPredictionMap()
         highValue = fluxes[t]
         positive[t] = highValue
         
     return (positive,negative)
 
     
 def construct(self,model,controlNames,newObjective):
     '''
     Top Level Function
     Build Complete Framework
     '''
     
     self.newObjective = newObjective
     result = LinearModel()
     result.addModel(model)
     sObjective = self._scaleMap(model.getObjective(),self.objectiveCoeffecent)
     sObjective[self.newObjective] = .01
     result.setObjective(sObjective)
     
     for (libName,libPrefix) in self.libdata:
         result = self._constructRegulationObjecive(result, controlNames, libName, libPrefix, -1.0)
         pass
     
     result = self._primalDual(result, result.getObjective())
     
     for (libName,libPrefix) in self.libdata:
         result = self.constructControl(result,controlNames,libPrefix,libName)
     
         if self.rGeneMap != None:
             self.geneControl(result,libPrefix + "y__",controlNames,libName)
             
     if self.simoLimit !=0:
         result = self._controlValueLimit(result,controlNames,postfix="y__")
                 
     return result
    def generateModel(self, modelName=None):
        if modelName == None:
            modelName = self.modelName
        dir = self.basedir
        
        model = None
        fluxLimits = None
        objective = None

        if self.rxnfile != '':
            rxnFile =dir + self.rxnfile
            model = self.rxnParser.parse(rxnFile)
        else:
            model = LinearModel()
        
        if self.fluxlimitfile != '':
            fluxLimitFile = dir + self.fluxlimitfile
            fluxLimits = self.limitParser.parse(fluxLimitFile)
        else:
            fluxLimits = {}
            
        if self.objectivefile != '':
            objectiveFile = dir + self.objectivefile
            objective = self.objParser.parse(objectiveFile)
        else:
            objective = {}
            
        if self.directionCheck:
            #fluxLimits = self.checkDirectionality(network, fluxLimits)
            pass
        
        model.addColumnLimits(fluxLimits)
        
        for (key,value) in objective.items():
            model.addObjective(key, value)
            
        for name in model.getRowNames():
            model.addRowLimit(name, (0.0,0.0))
                        
        return model
Esempio n. 7
0
    def _parseNetwork(self,network,limits):
        result = LinearModel()
        result.data.rowCache.extend(network.speciesCache)
        result.data.columnCache.extend(network.reactionCache)
        result.addDataCache(network.dataCache)

        rowNames = network.getOrderedSpeciesNames()
        columnNames = network.getOrderedReactionNames()
        
        for rowName in rowNames:
            result.addRowLimit(rowName,(0.0,0.0))    
                    
        for columnName in columnNames:
            if columnName in limits.keys():
                (lower,upper) = limits[columnName]
                result.addColumnLimit(columnName,(lower,upper))
            
        return result
 def parse( self, file ):
     model = LinearModel()
     rxnParser = ReactionEquationParser()
     self.startFile(file)
     d = self.getTagedLine()
     annotation = {}
     
     while d != None:
         if d != "":
             (reaction,direction) = rxnParser.parseEquation(d["Equation"])
             name = d["Name"]
             
             model.addColumn(name, reaction)
             model.addColumnLimit(name, direction)
             annotation[name] = d.annotation
         
         d = self.getTagedLine()
         
     self.closeFile()
     model.annotation = annotation 
     return model 
    def _constructControl(self,model,controlNames,binaryPrefix,controlValuePref,regPrefix,climits,zero):
        '''
        Create binary control variables
        
        one = off:
        if y = 0: low < v < high
        if y = 1: v = 0
        v + high*y <= high
        v + low*y >= low
        
        zero = off:
        if y = 1: 0 < v < d
        if y = 0: v = 0
        v - high*y <= 0
        v - low*y >= 0
        
        ==>
        for v in reaction targets
        pc: v - high*pc < 0
        nc: v - low* < 0
        
        '''
        
        binaryLimitName = "control_"
        
        posControlRow = regPrefix+"_pc_"
        negControlRow = regPrefix+"_nc_"

        jmodel = LinearModel()
        if zero:
            equation1 = "%s_pc_%s:%s + %s %s < 0" % (regPrefix,"%s",controlValuePref,-1.0*self.posControlBound,binaryPrefix)
            equation2 = "%s_nc_%s:%s + %s %s > 0" % (regPrefix,"%s",controlValuePref,-1.0*self.negControlBound,binaryPrefix)
        else:
            equation1 = "%s_pc_%s:%s + %s %s < %s" % (regPrefix,"%s",controlValuePref,self.posControlBound,binaryPrefix,self.posControlBound)
            equation2 = "%s_nc_%s:%s + %s %s > %s" % (regPrefix,"%s",controlValuePref,self.negControlBound,binaryPrefix,self.negControlBound)
            
        jmodel = self.parseEquations.applyRelation(jmodel,posControlRow,equation1,controlNames,prefixPattern="%s")
        jmodel = self.parseEquations.applyRelation(jmodel,negControlRow,equation2,controlNames,prefixPattern="%s")

        result = LinearModel()
        
        for columnName in controlNames:
            
                iCName = binaryPrefix + columnName
                iDName = controlValuePref + columnName
                
                posControlName = regPrefix + "_pc_" + columnName
                negControlName = regPrefix + "_nc_" + columnName
                
                if columnName in climits and False: # this method is currently broken
                    (negBound,posBound) = climits[columnName]
                    if negBound == None:
                        negBound = self.negControlBound
                    if posBound == None:
                        posBound = self.posControlBound
                else:
                    posBound = self.posControlBound
                    negBound = self.negControlBound
                
                '''
                y = 1: l < v < u
                '''
                if(zero):
                    result.addData(posControlName,iDName,1.0)
                    result.addData(negControlName,iDName,1.0)
                    
                    result.addData(posControlName,iCName,-posBound)
                    result.addData(negControlName,iCName,-negBound)
 
                    result.addRowLimit(posControlName,(None,0.0))
                    result.addRowLimit(negControlName,(0.0,None))
                    
                else:
                    result.addData(posControlName, iDName, 1.0)
                    result.addData(negControlName, iDName, 1.0)
                    
                    result.addData(posControlName, iCName, posBound)
                    result.addData(negControlName, iCName, negBound)
                
                    result.addRowLimit(posControlName,(None,posBound))
                    result.addRowLimit(negControlName,(negBound,None))
        
        jmodel.columnLimits = {}
        
        if not result == jmodel:
            #print "---------------------------------apply equation failure: control-----------------------------------------"
            #! currently apply version does not handleA a map/list of boundary values
            pass

        model.addConstraints(result)

        '''
        w is limit of controls
        y is actual control state variable
        w - y = 0 as starting state ie all controls default to 0
        sum w > control min
        sum w < control max 
        '''

        self.parseEquations.defaultLimit = (0.0,1.0)
        
        iCName = binaryPrefix
        iDName = controlValuePref
        rowName = "_rcr_" + binaryPrefix
        equation = "_rcr_%s:_rc_%s + -1.0 %s = 0" % (binaryPrefix+"%s",iCName,iCName)
        
        jmodel = LinearModel()
        jmodel = self.parseEquations.applyRelation(jmodel,rowName,equation,controlNames,prefixPattern="%s")
        jmodel.setMipColumnNames(controlNames,tag=iCName+"%s")
        self.parseEquations.defaultLimit = (None,None)
        
        result = LinearModel()
        
        for columnName in controlNames:
        
                iCName = binaryPrefix + columnName
                iDName = controlValuePref + columnName        

                result.setMipColumnName(iCName)
                    
                result.addColumnLimit(iCName,(0.0,1.0))
                
                result.addColumnLimit("_rc_" + iCName,(0.0,1.0))
                
                result.addData("_rcr_" + iCName, "_rc_" + iCName, 1.0)
                result.addData("_rcr_" + iCName, iCName, -1.0)
                result.addRowLimit("_rcr_" + iCName, (0.0,0.0))

        if not result == (jmodel):
            print "---------------------------------apply equation failure: control-----------------------------------------"
  

        for columnName in controlNames:
                
                iCName = binaryPrefix + columnName
                iDName = controlValuePref + columnName

                result.addData(binaryLimitName,"_rc_"+ iCName,1.0)
        
        #Limit on control variables        
        result.addRowLimit(binaryLimitName,(self.controlMin,self.controlMax))
        
        model.addConstraints(result)
            
        return model
    def _constructRegulationObjecive(self,model,names,lib,prefix,dir):
        '''
        Hybrid Objective
        Z += C'v + A'n
        Control of adjustment objective in hybrid objective
        if y = 1: n = v, d=0 
        if y = 0: n = 0, d=v
        
        
        ==>
        
        n + d - v = 0
        -G * (y(i)) <= n <= G * (y(i)) : objective coefficient
        -G * (1-y(i))<= d <= G * (1-y(i)) : slack variable
        
        ==>
        n + d - v = 0
        0 <= n + G * y(i)
        n - G * y(i) <= 0
        0 <= d + (1- y(y(i)) * G 
        d - (1 - y(i)) * G <= 0

        it is important to only create controls for coefficients that exist in the library 
        '''
        #! This is a new addition and may change the way RD works.  Added to fix target / lib comparison failure.
        names = self._confirmControlTargets(lib, names)
        limits = model.getColumnLimits()
        
        rName = prefix + "reg__"

        jmodel = LinearModel()
        equation = "%s:n + d + %sI= 0" % (prefix+ "reg__%s",dir)
        jmodel = self.parseEquations.applyRelation(jmodel,rName,equation,names,prefixPattern=prefix+"%s__")
    
        imodel = LinearModel()
        rName = prefix + "reg__"
        
        for name in names:
            if name in limits:
                limit = limits[name]
            else:
                limit = (self.negfluxControlBound,self.posfluxControlBound) 
                
            vName = name
            rName = prefix + "reg__" + name
            cName = prefix + "n__" + name
            dName = prefix + "d__" + name
        
            imodel.addColumnLimit(cName,(None,None))
            imodel.addColumnLimit(dName,(None,None))
            
            #!imodel.addColumnLimit(cName,(limit[0],limit[1]))
            #!imodel.addColumnLimit(dName,(limit[0],limit[1]))
            
            imodel.addRowLimit(rName,(0.0,0.0))
            
            imodel.addData(rName, vName, dir)
            imodel.addData(rName, cName,  1.0)
            imodel.addData(rName, dName,  1.0)           
        
        if not jmodel == imodel:
            print "----------------------------apply equation failure-----------------------------"
            
        model.addConstraints(imodel)
                
        '''
        Z^hybrid  = C^nat*v + C^adj*n
        '''
        
        objective = {}
        originalObjective = model.getObjective()        
        objective.update(originalObjective)        
        
        imodel = LinearModel()
        
        #Set coefficients for controls
        for name in names:
            iname = prefix + "n__" + name
            coeffecent = self._getRegulationCoeffecent(lib,name)
            iCoeffecent = float(coeffecent) * float(self.regCoeffecent)
            objective[iname] = -iCoeffecent
            imodel.addData("adjValue",iname,-iCoeffecent)
        
        #This constraint maybe cause of failure because of overloading of coefficients * fluxes in dual
        #This constraint combined with the use of the control penalty causes infeasibility issues
        #imodel.addRowLimit("adjValue",(None,None))
        #model.addConstraints(imodel)
        
        jmodel = LinearModel()
        equation = "adjValue%s:objectiveVar + adjVar = 0"
        jmodel = self.parseEquations.applyRelation(jmodel,relationName="adjValue",value=equation,targets=[''],prefixPattern="%s")
        del jmodel.columnLimits["objectiveVar"]
        jmodel.addColumnLimit("objectiveVar",(None,None))

        imodel = LinearModel()
        imodel.addData("adjValue","objectiveVar",1)
        imodel.addData("adjValue","adjVar",1)
        imodel.addRowLimit("adjValue",(0,0))
        imodel.addColumnLimit("adjVar",(None,None))
        imodel.addColumnLimit("objectiveVar",(None,None))

        if not jmodel == imodel:
            print "---------------------------------apply equation faliure: control objective-----------------------------------------"
        
        #This constraint maybe cause of failure because of overloading of coefficients * fluxes in dual
        #This constraint along with a control penalty causes infeasibility issues in the optimization
        #model.addConstraints(imodel)#! consider removing to insure that adjValue is not messing up the system
        model.setObjective(objective)
        
        return model
   def _primalDual(self,model,objective,prime=True,dual=True,equal=True):
       '''
       class PathwayTarget:
   
       @type model: LinearModel
       @rtype: LinearModel
       
       Construct Core Linear Optimization Matrix with primal dual equality
       
       row i and column j
       
       Primal:
       min Z = sum(j): [c(j)*v(j)]
           ST.
           sum(j) [S(ij)*v(j)] = 0 E i
           l(j) < v(j) < u(j) E j
       
       Hameltonian:
       Max(lambda,mu,nu): Min(v): sum(j)c(j)*v(j) + sum(i)lambda(i)*S(ij)v(j) + mu(j)(l(j)-v(j)) + nu(j)(v(j)-u(j))
       => c'v + lambda*(Sv) + mu(l-v) + nu(v-u)
       => Max: mu*l - nu*u
           ST
           c + lambda*S + mu + nu = 0
       
       Dual:
       max Z_dual = l*mu - u*nu
           ST.
           S'*lambda - mu + nu = -c'
           mu(j) > 0 E j
           nu(j) > 0 E j
       
       Equality condition:
       Z = Z_dual
       ==> sum(j) [c(j)'*v(j)] = sum(j) [l(j)*mu(j) - u(j)*nu]
       ==> -c*v + mu*l - u*nu = 0
       ''' 
       
       pName = self.pName
       dName = self.dName
       
       result = LinearModel()
 
       #Primal:
       if prime:
           #S*v 
           for (row, column, value) in model.getSparseMatrix():
               result.addData(self.primeRName + row, pName + column, value)
           #S*v <=> b
           for row in model.getRowLimits().keys():
               result.addRowLimit(self.primeRName + row, model.getRowLimit(row))
           #u<=v<=l
           for column in model.getColumnNames():
               result.addColumnLimit(pName + column, model.getColumnLimit(column))
       
       #Dual:
       if dual:
           #S'*lambda
           for (row, column, value) in model.getSparseMatrix():
               result.addData(self.dualRName + column, dName + row, value)
           
           #lambda <=> +- inf
           for row in model.getRowLimits().keys():
               result.addColumnLimit(dName + row, (None,None))
               
           #S'*lambda = -c'
           for column in model.getColumnNames():
               if column in objective.keys():
                   value = objective[column]
                   result.addRowLimit(self.dualRName + column, (-value, -value))
               else:
                   result.addRowLimit(self.dualRName + column, (0.0, 0.0))
           
           #S'*lambda - mu + nu = -c'
           for column in model.getColumnLimits().keys():
               (lower, upper) = model.getColumnLimit(column)
               if lower != None:
                   result.addData(self.dualRName + column, '__mu__' + column, -1)
                   result.addColumnLimit('__mu__' + column, (0.0, None))
               if upper != None:
                   result.addData(self.dualRName + column, '__nu__' + column, 1)
                   result.addColumnLimit('__nu__' + column, (0.0, None))
       
       if equal:                          
           #objective relation
           #Z^prime = Z^dual
           # cv = l*mu - u*nu = 0
           # -cv + l*mu - u*nu = 0
           
           for column in model.getColumnNames():
               if column in objective.keys():
                   value = objective[column]
                   result.addData(self.equalityRName, pName + column, -value)
               else:
                   result.addData(self.equalityRName, pName + column, 0)
         
           for column in model.getColumnLimits().keys():
               (lower, upper) = model.getColumnLimit(column)
               if lower != None and lower != 0.0:
                   result.addData(self.equalityRName, '__mu__' + column, lower)
               if upper != None and upper != 0.0:
                   result.addData(self.equalityRName, '__nu__' + column, -upper)
                   
           result.addRowLimit(self.equalityRName,(0,0))
       
       objective = {}
       objective[self.pName + self.newObjective] = -1
       result.setObjective(objective)
       
       return result
def LinearModelVariableBoundarys(originalModel, objectiveName, targets=None, pickleFileName=None, strict=False, minObjectivePercent=None,searchSize=1):
    '''
    Find min and max boundaries for the dependent variables of a linear model. 
    Uses limitMap as constraints on model.
     
    Add cumulative boundary persistence as pickle file function.
    
    @param linearModel: linear model to be analyzed
    @type linearModel: LinearModel
    @param limitMap: map of variable names and lower and upper limits
    @type limitMap: {variableName, (float, float)  
    @param targets: list of variables to perform analysis on
    @type targets: list
    @return: dictionary of lower and upper limits for each variable
    @rtype: {variableName: (lowerlimit, upperlimit)}
    '''
    
    linearModel = LinearModel()
    linearModel.extend(originalModel)
    
    if pickleFileName != None:
        if os.path.isfile(pickleFileName):
            print "loading saved flux boundaries"
            pFile = open(pickleFileName)
            result = pickle.load(pFile)
            pFile.close()
            return result
    
    originalLimits = linearModel.getColumnLimits()
    originalObjectiveLimit = originalLimits[objectiveName]
    objectiveVector = {objectiveName:-1.0}
    
    solver = LPSolver()
    originalValues = solver.run(model=linearModel, objective=objectiveVector)
    originalObjectiveValue = originalValues[objectiveName]
        
    if minObjectivePercent != None:
        minObjectiveValue = originalObjectiveValue * minObjectivePercent
        linearModel.addColumnLimit(objectiveName,(minObjectiveValue,None))
    
    if targets == None:
        targets = linearModel.getColumnNames()
    targets.add(objectiveName)

    print "Searching flux boundaries for %s > %s" % (objectiveName, minObjectiveValue)
    result = {}
    targetValues = targetValueCombinations(targets, [-1.0,1.0])
    controlSubSets = combinations(targetValues,searchSize)
    xcontrolSubSets = set(controlSubSets)
    
    for name in targets:
        nameTag = name
    #   if name not in linearModel.getColumnNames():
    #       print "target %s not found in model"
    #       print "boundary discovery not possible"
    #       continue
        
    #for iTargetValues in xcontrolSubSets:
    #    name = "testControlValue"
    #    nameTag = iTargetValues
    #    linearModel = combinationLimitBuilder(linearModel, iTargetValues, name)
        
        result[name] = (None,None)
        negObjective = {name:1.0}
        posObjective = {name:-1.0}
        
        solver.clearObjective()
        negValues = solver.run(linearModel, objective=negObjective)
        negValue = negValues[name]
        
        solver.clearObjective()
        posValues = solver.run(linearModel, objective=posObjective)
        posValue = posValues[name]
        
        delta = 1e-4
        if posValue != 0 or negValue !=0:
            pass
        
        if False:
            originalValue = originalValues[name]
            originalLimit = originalLimits[name]
        
            if not (negValue - delta <= originalValue <= posValue + delta):
                print "original value not in boundary"
                print "objective value [%s] (%s) %s <= %s <= %s (%s)" % (name, originalLimit[0], negValue, originalValue, posValue, originalLimit[1])
                #print "value neg code %s pos code %s" % (nscode, pscode)
                (negValue,posValue) = (originalLimit[0],originalLimit[1])
            else:
                #print "objective value [%s] (%s) %s <= %s <= %s (%s)" % (name, originalLimit[0], negValue, originalValue, posValue, originalLimit[1])
                pass
                
            if negValue == None or negValue == float("-inf"):
                continue
    
            if posValue == None or posValue == float("-inf"):
                continue
        
        result[nameTag] = (negValue,posValue)
        print "%s < [%s] < %s " % (negValue,nameTag,posValue)
    
    if pickleFileName != None:
        pFile = open(pickleFileName,'w')
        pickle.dump(result, pFile)
        pFile.close()
        
    solver.clear()
    del solver
    
    linearModel.addColumnLimit(objectiveName,originalObjectiveLimit)
    #targets.remove(objectiveName)
        
    return result