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
Esempio n. 2
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 _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