def __init__(self):
     #Boolean controls
     self.verbose = True
     self.unityControl = False
     self.useControlPenalty = False
     self.simoControl = 1.0
     self.simoLimit = 0.0
     
     #data holders
     self.parseEquations = ParseEquations()
     self.parseEquations.identity = "I"
     
     self.originalObjective = {}
     self.newObjective = ''
     
     self.primeControlLimits = {}
     self.dualControlLimits = {}
     
     #ControlLibrary Values
     self.regulationLibrary= {}
     self.controlPrefixMap = {}
     self.libdata = []
     
     self.rGeneMap = None
     self.geneList = None
     
     #static value defaults
     self.controlMin = 0
     self.controlMax = 1
     
     self.minOObjective = 0.0
     
     self.posControlBound = 1e3
     self.negControlBound = -1e3
     self.posfluxControlBound = 100
     self.negfluxControlBound = -100
     
     self.coeffecentDefault = 0.0
     self.objectiveCoeffecent = 1.0
     self.regCoeffecent = 1.0
     self.delta = 1e-4
     self.controlDelta = 1e-6
     
     #Variable Names
     self.pName = "" #prefix for prime variables
     self.dName = "__lamda__" #dual variables for row equality
     self.cName = "__y__" #prefix for binary control variable" 
     self.cdName = "__sigma__"  #prefix for slack dual variable
     
     self.cvName = "__n__" #prefix for analog control variable"
     self.cnvName = "__nv__" #prefix for slack analog control variable"
     
     #Relation names
     self.primeRName = "c1_" #prime limits
     self.dualRName = "c2_" #dual limits
     self.equalityRName = "c3_" #prime dual equality relation
class ConstructRegulationOptimization:
    '''
        primal:
        min Z=c'*v
        st
            S*v = 0
            a <= v <= b
            
        dual:
        max Z_dual = u*nu - l*mu
        st
            S'*lamda - mu + nu = c'
            mu >= 0
            nu >= o

        
        Equality condition:
        Z = Z_dual
        c'*v = -l*mu + u*nu
        
        Control:
        Z += a'*n
        y = 0 : n = 0
        y = 1 : n = v
        
        primal control:
        n > 0
        Z += a'*n
        S += v - n > 0
        n + vMax*y < vMax
        n + vMin*y > vMin
        
        Dual Control:
        S'*lambda + nd  = a'
        n=0 -> nd = free or n=v -> nd = 0
        sigma - sMax*y < 0
        sigma + sMin*y > 0
        
        columns:
        : prime Names
        __lambda__" dual names
        __y__; control name
        __n__: controled value
        __nv__: negative controled value
        
        rows:
        __c1__: prime contstraints
        __c2__: dual constraints
        __c3__: equality constraints
        
    '''
    
    def __init__(self):
        #Boolean controls
        self.verbose = True
        self.unityControl = False
        self.useControlPenalty = False
        self.simoControl = 1.0
        self.simoLimit = 0.0
        
        #data holders
        self.parseEquations = ParseEquations()
        self.parseEquations.identity = "I"
        
        self.originalObjective = {}
        self.newObjective = ''
        
        self.primeControlLimits = {}
        self.dualControlLimits = {}
        
        #ControlLibrary Values
        self.regulationLibrary= {}
        self.controlPrefixMap = {}
        self.libdata = []
        
        self.rGeneMap = None
        self.geneList = None
        
        #static value defaults
        self.controlMin = 0
        self.controlMax = 1
        
        self.minOObjective = 0.0
        
        self.posControlBound = 1e3
        self.negControlBound = -1e3
        self.posfluxControlBound = 100
        self.negfluxControlBound = -100
        
        self.coeffecentDefault = 0.0
        self.objectiveCoeffecent = 1.0
        self.regCoeffecent = 1.0
        self.delta = 1e-4
        self.controlDelta = 1e-6
        
        #Variable Names
        self.pName = "" #prefix for prime variables
        self.dName = "__lamda__" #dual variables for row equality
        self.cName = "__y__" #prefix for binary control variable" 
        self.cdName = "__sigma__"  #prefix for slack dual variable
        
        self.cvName = "__n__" #prefix for analog control variable"
        self.cnvName = "__nv__" #prefix for slack analog control variable"
        
        #Relation names
        self.primeRName = "c1_" #prime limits
        self.dualRName = "c2_" #dual limits
        self.equalityRName = "c3_" #prime dual equality relation
        
    def _scaleMap(self,m,s):
        '''
        mulitply values in map m by scalar s
        @type m: dict
        @type s: float
        '''
        result = {}
        for key in m.keys():
            value = m[key]
            result[key] = value*s
        return result
    
    def _confirmControlTargets(self,libraryName,targets):
        libraryControlNames = self.regulationLibrary[libraryName]
        result = set(libraryControlNames).intersection(targets)
        return result
    
    def _addControlLibrary(self,name,values):
        ivalues = {}
        for (key,value) in values.items():
            ivalue = float(value)
            if abs(ivalue) > self.controlDelta:
                ivalues[key] = ivalue
            else:
                continue
        self.regulationLibrary[name] = ivalues
        return None
    
    def extendControl(self,constructor):
        self.regulationLibrary.update(constructor.regulationLibrary)
        self.controlPrefixMap.update(constructor.controlPrefixMap)
        for lib in constructor.libdata:
            if lib not in self.libdata:
                self.libdata.append(lib)
        if self.rGeneMap == None:
            self.rGeneMap = {} 
        self.rGeneMap.update(constructor.rGeneMap)
        return None
    
    def getGeneTargetMap(self):
        if self.rGeneMap == None:
            return None
        
        result = {}
        for (r,gs) in self.rGeneMap.items():
            for g in gs:
                if g not in result.keys():
                    result[g] = set()
                result[g].add(r)
        return result
                 
            
    def addRegulationLibrary(self,name,prefix,value):
        '''
        @type name: string
        @type prefix: string
        @type value: dict
        '''
        if len(value) == 0:
            return None
        
        self.controlPrefixMap[name] = prefix
        self.libdata.append((name,prefix))
        self._addControlLibrary(name,value)
        
        return None
    
    def clearControlLibraries(self):
        self.regulationLibrary= {}
        self.controlPrefixMap = {}
        self.libdata = []
        return None
    
    
    def addRegulationLibraries(self,values):
        '''
        @type values: [(name,prefix,dict)]
        '''
        for v in values:
            name = v[0]
            prefix = v[1]
            value = v[2]
            self.addRegulationLibrary(name,prefix,value)
        return None
    
    def setGeneMap(self,data):
        '''
        @type data: {string,set(string)}
        '''
        if data == None:
            return None
        self.rGeneMap = data
        self.geneList = set()

        for (key,values) in data.items():
            self.geneList = self.geneList.union(set(values))

        return None    
    
    def _getRegulationCoeffecent(self,lib,name):
        '''
        Retrieve coeffecent value for control variable
        @type name: string
        @rtype: double
        '''
        if lib not in self.regulationLibrary.keys():
            pass
        if lib in self.regulationLibrary.keys():
            l = self.regulationLibrary[lib]
            if name in l.keys():
                value = l[name]
                return value
            
        return self.coeffecentDefault
    
    def _getNonZeroRegulationNames(self,libName,names):
        result = []
        for name in names:
            value = self._getRegulationCoeffecent(libName,name)
            if value != 0:
                result.append(name)
        return result
    
    def getGeneControlMap(self,libName,geneName):
        result = {}
        if libName not in self.regulationLibrary.keys():
            return None
        controlMap = self.regulationLibrary[libName]
        for (key,value) in controlMap.items():
            if key not in self.rGeneMap:
                continue
            iGeneControls = self.rGeneMap[key]
            if geneName in iGeneControls:
                result[key] = value
        return result 

    def getLibraryGeneControlMap(self,libName):
        result = {}
        for geneName in self.geneList:
            geneControlMap = self.getGeneControlMap(libName, geneName)
            if geneControlMap != {}:
                result[geneName] = geneControlMap
        return result
    
    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 _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 _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 _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 _constructPDControlRelation(self,model,controlNames,controlPrefix,variablePrefix,rowPrefix,zeroed,controlLibraryName):
        '''
        Construct primal and dual control limitation relation to binary control variable.
        '''
        controlNames = self._confirmControlTargets(controlLibraryName, controlNames)
        result = model
        pRowPrefix = "__p_" + rowPrefix + "__" #prime control
        dRowPrefix = "__d_" + rowPrefix + "__" #dual control
        
        result = self._constructControl(result, controlNames, controlPrefix, variablePrefix, pRowPrefix, self.primeControlLimits, zeroed)
        result = self._constructControl(result, controlNames, controlPrefix, "__sigma__" + variablePrefix, dRowPrefix, self.dualControlLimits, not zeroed)
        result = self._constructDualRegulation(result,controlNames,variablePrefix)
        return result    
        
    def _constructControlRestriction(self,model,names,prefix):
        '''
        Build restriction that one control library can be used for a control type.
        Hopefully limit search space somewhat.
        updated 8 12 08
        
        0 < y + ny < 1
        '''
        scLimit = float(self.simoControl) 
        result = model
        for name in names:
            vname = prefix + name
            rowName = "__rest_row__" + name
            model.addData(rowName,vname, 1)
            #model.addRowLimit(rowName,(0,1))
            model.addRowLimit(rowName,(0,scLimit))
            
        return result
    
    def _constructControlPenalty(self,model,controlNames,prefix):
        '''
        This method can cause optimization infeasiblity problems 
         if variable boundaries are to large or model is large.
        cp = y
        objective = objective + delta*cp
        '''
        
        result = model
        cpRow = "r_control_pentalty"
        cpColumn = "c_control_penalty"
        
        for name in controlNames:
            iName = prefix+name
            result.addData(cpRow,iName,1.0)
        
        #These relations and controls are repeatedly created, so far does not cause problems    
        result.addData(cpRow,cpColumn,-1.0)
        result.addRowLimit(cpRow,(0,0))
        result.addColumnLimit(cpColumn,(0,None))
        
        objective = model.getObjective()
        
        iObjective = {}
        iObjective.update(objective)
        iObjective.update({cpColumn:self.controlDelta})
        result.setObjective(iObjective)
        
        return result
    
    def _controlValueLimit(self,model,controlNames,postfix):
        '''
        Limits the absolute value of control effects 
        from any single flux control
        Sum(t)Y(tj)*beta(tj) <= k
        '''
        
        result = model
        if self.simoLimit == 0:
            return model
        
        for name in controlNames:
            cpRow = "r_con_val_limit_%s" % name
            for (libName,libPrefix) in self.libdata:
                controlValue = self._getRegulationCoeffecent(libName, name)
                iName = libPrefix+postfix+name
                result.addData(cpRow,iName,controlValue)
            cvLimit = (-self.simoLimit,self.simoLimit)
            result.addRowLimit(cpRow,cvLimit)
                    
        return result
    
    
    def constructControl(self,lp,controlNames, prefix, controlLibraryName):
        result = lp
        #! This is a new addition and may change the way RD works.
        controlNames = self._confirmControlTargets(controlLibraryName, controlNames)
        #Construct control relation in primal form of bi-level model
        result = self._constructPDControlRelation(result, controlNames, prefix + "y__", prefix + "n__" , prefix + "p_", True, controlLibraryName)
        #Construct control relation in dual form of bi-level model
        result = self._constructPDControlRelation(result, controlNames, prefix + "y__", prefix + "d__" , prefix + "g_", False, controlLibraryName)
        #Restriction that positive and negative part of control cannot be used together: !seems to be broken taken out for testing!
        result = self._constructControlRestriction(result, controlNames, prefix + "y__",)
        #Creates objective for minimizing controls, causes infeasible solution in larger models 
        if self.useControlPenalty:
            result = self._constructControlPenalty(result,controlNames, prefix + "y__")
                
        return result
    
    def _getGeneNames(self):
        return self.geneList
    
    def _getReactionGenePairs(self):
        result = []
        for (rxn,genes) in self.rGeneMap.items():
            for gene in genes:
                result.append((rxn,gene))
        return result

    def geneControl(self,lp,prefix,controlNames,libName):
        '''
        Gene level control optimization relations
        geneData in format [(rxn name, gene name)]
        
        for reaction i in mapping to gene g:
        
        reaction control(i) - gene control(g) = 0
        
        or 
        
        rc(i) - gc(g) > 0
        rc(i) - gc(g) < 0
        '''
        geneData = self._getReactionGenePairs()
        libData = self.regulationLibrary[libName]
        controlNames = self._confirmControlTargets(libName, controlNames)
        
        binaryLimitName = "control_"
        geneBinaryLimitName = "geneControl_"
        
        geneControlNames = set()
        reactionControlNames = set()
        
        if geneData == None:
            return lp
        
        iGeneData = []
        for (key,value) in geneData:
            if key in controlNames:
                iGeneData.append((key,value))
        geneData = iGeneData
                
        for (key,value) in geneData:
            
            if key not in controlNames:
                continue
            
            if value == None:
                print "Failed to map (%s, %s)" % (key,value)
                continue
            
            if key not in libData.keys():
                if self.verbose: print "In control Library [%s] gene [%s] linked to rxn [%s] no control value" % (libName,value,key)
                continue
            
            equalRowName = "_meta_gene_" + prefix + key
            lowRowName = "_low_meta_gene_" + prefix + key
            highRowName = "_high_meta_gene_" + prefix + key
            reactionControl = prefix + key
            geneControl = prefix + value
            geneControlNames.add(geneControl)
            reactionControlNames.add(reactionControl)
            
            #-----------------------------------------------------------------------------
            # Scip previously could not cannot handle this binary equality
            # This may have been a large variable problem and could currently be solved.
            #-----------------------------------------------------------------------------
            if self.unityControl:
                lp.addData(equalRowName,reactionControl,1.0)
                lp.addData(equalRowName,geneControl,-1.0)
                lp.addRowLimit(equalRowName,(0,0))
            else:         
                lp.addData(lowRowName,reactionControl,1.0)
                lp.addData(lowRowName,geneControl,-1.0)
                lp.addRowLimit(lowRowName,(0,None))
                
                lp.addData(highRowName,reactionControl,1.0)
                lp.addData(highRowName,geneControl,-1.0)
                lp.addRowLimit(highRowName,(None,0))
           
            equation1 = "%s: %s + -1.0 %s > 0" % (lowRowName,reactionControl,geneControl)
            equation2 = "%s: %s + -1.0 %s < 0" % (highRowName,reactionControl,geneControl)
      
        '''
        w is limit of change in controls
        y is actual control state variable
        sum w > control min
        sum w < control max 
        '''
        
        for name in geneControlNames:
            lp.addColumnLimit(name,(0,1))
                
            lp.addColumnLimit("_rc_" + name,(0.0,1.0))
                
            lp.setMipColumnName(name)
            lp.setMipColumnName("_rc_" + name)
                
            lp.addData("_rcr_" + name, "_rc_" + name, 1.0)
            lp.addData("_rcr_" + name, name, -1.0)
            lp.addRowLimit("_rcr_" + name, (0.0,0.0))

            lp.addData(geneBinaryLimitName,"_rc_"+ name,1.0)
        
        #Limit on control variables        
        lp.addRowLimit(binaryLimitName,(None,None))
        lp.addRowLimit(geneBinaryLimitName,(self.controlMin,self.controlMax))
        
        return lp
            
    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 _aproxEqual(self,v1,v2,delta):
        return abs(v1 - v2) < delta
 
    def _updateIterationControl(self,model,names,prefix,prediction,controlLibrary):
        '''
        updates framework status to new neighborhood point.
        w,y in {0,1}
        
        y is active / inactive variable
        w is search limitation variable
        
        if y = 1 and w = 0: control is on and unchanged:
            w + y = 1
        if y = 0 and w = 0: control is off, return to state w=y:
            w - y = 0
        if y = 1 and w = 1: Means control has been turned on, change to default y = 1, when w = 0
            w + y = 1
        if y = 0 and w = 1: Means control has been turned off, change default to y = 0 and w = 0
            w - y = 0
        y = prefix + name
        w = _rc_ + prefix + name

        '''
             
        for name in names:
            iCName = prefix + name #Acitive control
            tCName = "_rc_" + iCName #Change control
            
            if iCName not in prediction.keys():
                continue
            else:
                value = prediction[iCName]
            
            if tCName not in prediction.keys():
                if self.verbose: print "Analog slack variable %s not found" % (tCName)
            else:
                tValue = prediction[tCName]
            
            value = round(value,4)
            tValue = round(tValue,4)

            #!if value == 1.0 and tValue == 1.0:
            if value == 1.0:
                #if self.verbose: print "Making %s default active" % (name) 
                model.addData("_rcr_" + iCName, tCName, 1.0)
                model.addData("_rcr_" + iCName, iCName, 1.0)
                model.addRowLimit("_rcr_" + iCName, (1.0,1.0))
                
                #equation = "_rcr_%s:%s + %s = 1.0" % (iCName,tCName,iCName)
                
            #!if value == 0.0 and tValue == 1.0:
            if value == 0.0:
                model.addData("_rcr_" + iCName, tCName, 1.0)
                model.addData("_rcr_" + iCName, iCName, -1.0)
                model.addRowLimit("_rcr_" + iCName, (0.0,0.0))
                
                #equation = "_rcr_%s:%s + %s = 0.0" % (iCName,tCName,iCName)

        return model
 
    def setControl(self,model,prefix,targets,on,binary=False):
        #! merge with iterative control update
        '''
        updates framework status to new neighborhood point.
        w,y in {0,1}
        if y = 1 and w = 1: Means control has been turned on, change to default y = 1, when w = 0
            w + y = 1
        if y = 0 and w = 1: Means control has been turned off, change default to y = 0 and w = 0
            w - y = 0
        y = prefix + name
        w = _rc_ + prefix + name

        '''
        for name in targets:
            iCName = prefix + name
            tCName = "_rc_" + iCName
            
            if iCName not in model.getColumnNames():
                if self.verbose: print "%s control not found" % (iCName)
                continue
            
            if tCName not in model.getColumnNames():
                if self.verbose: print "%s slack control not found" % (tCName)
                continue
            
            if on == True: #Turn control on
                if binary:
                    model.addColumnLimit(iCName,(1.0,1.0))
                    model.addColumnLimit(tCName,(0.0,1.0))
                else:
                    model.addColumnLimit(iCName,(0.0,1.0))
                    model.addColumnLimit(tCName,(0.0,1.0))
                    model.addData("_rcr_" + iCName, iCName, 1.0)
                    model.addData("_rcr_" + iCName, tCName, 1.0)
                    model.addRowLimit("_rcr_" + iCName, (1.0,1.0))
                                
            if on == False: # Turn control off
                if binary:
                    model.addColumnLimit(iCName,(0.0,1.0))
                    model.addColumnLimit(tCName,(0.0,1.0))
                else:
                    model.addColumnLimit(iCName,(0.0,1.0))
                    model.addColumnLimit(tCName,(0.0,1.0))
                    model.addData("_rcr_" + iCName, tCName, 1.0)
                    model.addData("_rcr_" + iCName, iCName, -1.0)
                    model.addRowLimit("_rcr_" + iCName, (0.0,0.0))
                    
                #equation = "_rcr_%s:%s - %s = 0.0" % (iCName,tCName,iCName)

        return model
    
    def activateControl(self,model,libControl,on=True):
        for(libName,targets) in libControl.items():
            prefix = self.controlPrefixMap[libName]
            self.setControl(model, prefix+"y__", targets, on)
        return model
    
    def iterate(self,model,targets,libdata,prediction):

        for (libName,prefix) in libdata:
            if self.rGeneMap != None:
                itargets = self.geneList
            else:
                itargets = self._confirmControlTargets(libName, targets)
            self._updateIterationControl(model,itargets,prefix + "y__",prediction, libName)

        return model
    
    def findControl(self,controlMap):
        result = []
        for (key,prefix) in self.libdata:
            valueMap = self.regulationLibrary[key]
            ukeys = set(valueMap.keys()).intersection(controlMap.keys())
            for uk in ukeys:
                if valueMap[uk] == controlMap[uk]:
                    result.append((uk,prefix,valueMap[uk]))
        return result
    
    def generateControlObjective(self,activeControl):
        yControlNames = []
        wControlNames = []
        controlLibrary = self.findControl(activeControl)
                        
        for (key,prefix,value) in controlLibrary:
            if self.rGeneMap == None or len(self.rGeneMap) == 0:
                yControlName = prefix + "y__" + key
                yControlNames.append(yControlName)
                wControlNames.append("_rc_" + yControlName)
            elif self.rGeneMap != None:
                if key in self.rGeneMap.keys():
                    gNames = self.rGeneMap[key]
                    for gName in gNames:
                        yControlName = prefix + "y__" + gName
                        yControlNames.append(yControlName)
                        wControlNames.append("_rc_" + yControlName)
        
        result = {}
        for i in yControlNames:
            result[i] = 1.0
        for i in wControlNames:
            result[i] = 1.0
            
        return result                
    
    def iterateObjectiveControl(self,model,targets,prefix,libdata,objective,prediction):
        #controls = self._activateControl(prefix,objective.keys())
        model = self.iterate(model,targets,libdata,prediction)
        return model
    
    def generateCoeffecents(self,targets,prefix,predictions,controlName):
        result = {}
        for name in targets:
            iCName = prefix + name
            if iCName not in predictions:
                continue 
            value = predictions[iCName]
            if value >=  1.0 - self.delta:
                controlValue = self._getRegulationCoeffecent(controlName, name)
                controlValue = -1.0 * controlValue
                result[name] = controlValue
        return result
    
    def _convertToGeneNames(self,reactionName):
        if reactionName not in self.rGeneMap.keys():
            return None
        geneNames = self.rGeneMap[reactionName]
        if type(geneNames) == type(""):
            return set([geneNames])
        else:
            return geneNames
        
    def _convertToGeneTag(self,reactionName,geneClusters = None):
        geneNames = self._convertToGeneNames(reactionName)
        if geneNames == None:
            return reactionName
        iGeneNames = set(geneNames)
        for geneName in geneNames:
            if geneClusters != None:
                if geneName in geneClusters.keys():
                    for iGeneName in geneClusters[geneName]:
                        iGeneNames.add(iGeneName)
        geneTag = ''
        for iGeneName in iGeneNames:
                geneTag = geneTag + " " + iGeneName
        geneTag = geneTag[1:]
        
        return geneTag
                
    def printGeneObjective(self,iObjective,geneClusters=None):
        iGeneObjective = {}
        iOtherObjective = {}
        igControl = {}
        for rxnName in iObjective.keys():
            rControl = iObjective[rxnName]
            if rxnName not in self.rGeneMap.keys():
                iOtherObjective[rxnName] = rControl
            else:
                geneTag = self._convertToGeneTag(rxnName, geneClusters)
                
                if geneTag not in iGeneObjective:
                    igControl[geneTag] = []
                igControl[geneTag].append(rControl)
        
        for k in igControl.keys():
            iGeneObjective[k] = mean(igControl[k])
            
        return (iGeneObjective,iOtherObjective)

    def generateObjective(self,model,targets,predictions):
        result = {}
        libresult = {}
        objective = model.getObjective()

        for name in objective.keys():
            value = objective[name]
            result[name] = value * self.objectiveCoeffecent
            
        for pair in self.libdata:
            libName = pair[0]
            prefix = pair[1]            
            controls = self.generateCoeffecents(targets,prefix + "y__",predictions,libName)
            libcontrols = {}
            for key in controls.keys():
                libcontrols[(libName,key)] = controls[key]
                if key not in result.keys():
                    result[key] = 0
                ir = result[key]
                result[key] = ir + controls[key]
            libresult.update(libcontrols)
        
        return (result,libresult)
    
    def getControlNames(self,targets,predictions,prefix=True):
        rControls = []
        
        for pair in self.libdata:
            libName = pair[0]
            libPrefix = pair[1]
            iControls = self._getNonZeroRegulationNames(libName,targets)
            
            controls = self.generateCoeffecents(targets,libPrefix + "y__",predictions,libName)
            iControls = controls
            
            if self.rGeneMap != None:
                zControls = set()
                for controlName in iControls:
                    if controlName in self.rGeneMap.keys():
                        for gcn in self.rGeneMap[controlName]:
                            zControls.add(gcn)
                iControls = zControls
                        
            for controlName in iControls:
                if prefix: 
                    rControl = (libName,libPrefix,controlName)
                else:
                    rControl = (libName,controlName)
                if rControl not in rControls:
                    rControls.append(rControl)
                     
        controlNames = rControls
        #tcontrolNames = controlNames.intersection(self.targets)
        return controlNames
    

    def _createReportItem(self,predictions,names,prefix):
        '''
        Create report item from framework result
        '''
        result = {}
        for name in names:
            tName = prefix + name
            if tName in predictions:
                result[name] = predictions[tName]
                
        return result
    
    def getFluxValues(self,predictions,fluxNames):
        return self._createReportItem(predictions, fluxNames, self.pName)
    
    def createReport(self, predictions, fluxNames, targets, geneReduction = None):
        '''
        Create report from framework result
        '''
        
        fluxNames.append("objectiveVar")
        fluxNames.append("objectiveVarFull")
        
        report = Report()
        report["flux"] = self._createReportItem(predictions, fluxNames, self.pName)
        
        geneSet = set()

        if self.rGeneMap != None:
            for (key,values) in self.rGeneMap.items():
                geneSet = geneSet.union(set(values))
        
        for (libName,prefix) in self.libdata:
            controlMap = self.regulationLibrary[libName]
            report[libName] = self._createReportItem(predictions,targets,prefix+"y__")
            report[libName+"_Value"] = controlMap
            if self.rGeneMap != None:
                geneControl = self._createReportItem(predictions,geneSet,prefix+"y__")

                if geneReduction != None:
                    reducedGeneValues = {}
                    for k in geneControl.keys():
                        if k in geneReduction.keys():
                            for reducedGene in geneReduction[k]:
                                reducedGeneValues[reducedGene] = geneControl[k]
                    geneControl.update(reducedGeneValues)
                            
                r1 = report[libName]
                r1.update(geneControl)
                report[libName] = r1
                
        #report["BioControl"] = self._createReportItem(predictions,targets,"__y__")
        #report["adjustment pos"] = self._createReportItem(predictions,targets,self.cvName)
        #report["difference pos"] = self._createReportItem(predictions,targets,"__d__")
        #report["BioCoeffecents"] = self.posCoeffecentMap
        
        #report["SynControl"] = self._createReportItem(predictions,targets,"__ny__")
        #report["adjustment neg"] = self._createReportItem(predictions,targets,"__nn__")
        #report["difference neg"] = self._createReportItem(predictions,targets,"__nd__")
        #report["SynCoeffecents"] = self.negCoeffecentMap

            
        return report