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 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
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