コード例 #1
0
    def __init__(self,
                 Aeq,
                 beq=None,
                 Aineq=None,
                 bineq=None,
                 lb=None,
                 ub=None,
                 solver=solvers['default']):
        """ initialize the nonlinear problem

        Keyword arguments:

        Aeq     -- matrix of equality constrains (Aeq * v = beq)
        beq     -- right-hand side vector of equality constraints
        Aineq   -- matrix of inequality constrains (Aineq * v <= bineq)
        bineq   -- right-hand side vector of inequality constraints
        lb      -- list of lower bounds (indexed like matrix columns)
        ub      -- list of upper bounds (indexed like matrix columns)
        solver  -- solver to be used for Nonlinear Programming
        """
        LinearProblem.__init__(self, Aeq, beq, Aineq, bineq, lb, ub, solver)
        if solver.lower() in LinearProblem.solvers:
            # If problem has been raised from a linear problem, use default
            # solver.
            self.solver = NonLinearProblem.solvers["default"]
        self.obj = None
        self.d_obj = None
        self.nlc = None
        self.d_nlc = None
        self.x0 = [0.] * len(lb)
        self.iterator = None
        self.rlist = None
コード例 #2
0
    def __init__(self, Aeq, beq=None, Aineq=None, bineq=None, lb=None, ub=None,
                 solver=solvers['default']):
        """ initialize the quadratic problem

        Keyword arguments:

        Aeq     -- matrix of equality constrains (Aeq * v = beq)
        beq     -- right-hand side vector of equality constraints
        Aineq   -- matrix of inequality constrains (Aineq * v <= bineq)
        bineq   -- right-hand side vector of inequality constraints
        lb      -- list of lower bounds (indexed like matrix columns)
        ub      -- list of upper bounds (indexed like matrix columns)
        solver  -- solver to be used for Quadratic Programming
        """
        LinearProblem.__init__(self, Aeq, beq, Aineq, bineq, lb, ub, solver)
    
        self.obj = QuadraticProblem.OoQp()
        if _cvxmod_avail:
            self.cvxmodMatrix = cvxmod_matrix(array(Aeq))
            self.cvxmodV = optvar('v', self.cvxmodMatrix.size[1], 1)
        if _cvxpy_avail:
            self.cvxpyMatrix = array(Aeq)
            self.cvxpyV = Variable(self.cvxpyMatrix.shape[1], 1, name='v')
コード例 #3
0
    def run(self, objective, matrix, lb, ub, threshold=1.0, eqs=[], ineqs=[]):
        """ successively formulate and solve linear problems for each metabolite
            flux with inequality constraint 'objective value <= threshold'

        Arguments refer to split fluxes (i.e. non-negative flux variables).

        Keyword arguments:

        objective      -- coefficient vector for linear objective function
        matrix         -- stoichiometric matrix of the metabolic network
        lb             -- list of lower bounds (indexed like matrix columns)
        ub             -- list of upper bounds (indexed like matrix columns)
        threshold      -- objective function threshold
        eqs            -- list of (coefficient vector, right-hand side) pairs
                          for additional equality constraints
        ineqs          -- list of - '' - for additional inequality constraints

        Returns:  list of minimum values, indexed like metabolites
        """
        matrix = array(matrix)
        nMetabolites, nCols = matrix.shape
        if nMetabolites == 0:
            return []  # Nothing to do

        # Construct matrices of original equality and inequality constraints
        Aeq, beq, Aineq, bineq = FbAnalyzer.makeConstraintMatrices(
            matrix, eqs, ineqs)
        # Combine original inequality constraints and
        # 'objective function <= threshold'
        if Aineq is None:
            Aineq = [objective]
            bineq = [threshold]
        else:
            Aineq = vstack((Aineq, [objective]))
            bineq = append(bineq, threshold)

        result = []
        ubVec = []
        for i in range(nCols):
            # Impose artificial upper bounds so that all LPs are bounded
            if isinf(ub[i]):
                ubVec.append(LARGE_NUM)
            else:
                ubVec.append(ub[i])

        psSplit = LinearProblem(Aeq, beq, Aineq, bineq, array(lb),
                                array(ubVec), self.solver)

        # Compute coefficient vectors of producing metabolite fluxes
        # - pick only positive coefficients from stoichiometric matrix
        posMatrix = matrix.copy()
        for i in range(nMetabolites):
            for j in range(nCols):
                if posMatrix[i, j] < 0.:
                    posMatrix[i, j] = 0.

        # Successively minimize each flux
        for index in range(nMetabolites):
            try:
                psSplit.setObjective(map(float, posMatrix[index, :]))
            except Exception:
                # Skip all-zero rows
                result.append(0.)
                continue

            minval, s = psSplit.minimize()
            psSplit.resetObjective()

            if len(s) == 0:
                result.append(nan)
            else:
                result.append(minval)

        return result
コード例 #4
0
    def run(self, objective, matrix, lb, ub, threshold=.95, eqs=[], ineqs=[]):
        """ successively formulate and solve linear problems for each flux with
            inequality constraint 'objective value <= threshold'

        Keyword arguments:

        objective -- coefficient vector for linear objective function
        matrix    -- stoichiometric matrix
        lb        -- list of lower bounds, indexed like reactions
        ub        -- list of upper bounds, indexed like reactions
        threshold -- objective function threshold
        eqs       -- list of (coefficient vector, right-hand side) pairs for
                     additional equality constraints
        ineqs     -- list of - '' - for additional inequality constraints

        Returns:  list of pairs (minimum, maximum), indexed like reactions
        """
        # Construct matrices of original equality and inequality constraints
        Aeq, beq, Aineq, bineq = FbAnalyzer.makeConstraintMatrices(
            matrix, eqs, ineqs)
        #lb = [-1000]*939
        #ub = [1000]*939
        # Combine original inequality constraints and
        # 'objective function <= threshold'
        if Aineq is None:
            Aineq = [objective]
            bineq = [threshold]
        else:
            Aineq = vstack((Aineq, [objective]))
            bineq = append(bineq, threshold)

        nReactions = len(lb)
        lbVec, ubVec = [], []
        for i in range(nReactions):
            if isinf(lb[i]):
                lbVec.append(-LARGE_NUM)
            else:
                lbVec.append(lb[i])
            if isinf(ub[i]):
                ubVec.append(LARGE_NUM)
            else:
                ubVec.append(ub[i])

        ps = LinearProblem(Aeq, beq, Aineq, bineq, lbVec, ubVec, self.solver)
        minmax = [None] * nReactions

        # First maximize each flux
        for index in range(nReactions):

            ps.setObjective([0.] * index + [-1.] + [0.] *
                            (nReactions - index - 1))
            s = ps.minimize()[1]
            ps.resetObjective()

            # catch random infeasible solution that resolves if the solver is recreated
            if len(s) == 0:
                ps = LinearProblem(Aeq, beq, Aineq, bineq, lbVec, ubVec,
                                   self.solver)
                ps.setObjective([0.] * index + [-1.] + [0.] *
                                (nReactions - index - 1))
                s = ps.minimize()[1]
                ps.resetObjective()

            if len(s) != 0:
                maxval = s[index]
            else:
                maxval = nan
                s = None
            minmax[index] = maxval

        # Now minimize each flux
        for index in range(nReactions):

            ps.setObjective([0.] * index + [1.] + [0.] *
                            (nReactions - index - 1))
            s = ps.minimize()[1]
            ps.resetObjective()

            # catch random infeasible solution that resolves if the solver is recreated
            if len(s) == 0:
                ps = LinearProblem(Aeq, beq, Aineq, bineq, lbVec, ubVec,
                                   self.solver)
                ps.setObjective([0.] * index + [-1.] + [0.] *
                                (nReactions - index - 1))
                s = ps.minimize()[1]
                ps.resetObjective()

            if len(s) != 0:
                minval = s[index]
            else:
                minval = nan
                s = None
            minmax[index] = minval, minmax[index]

        return minmax
コード例 #5
0
class FbAnalyzer(object):
    """ Class for flux-balance analysis
    """
    def __init__(self, solver="default"):
        """ initialize FBA class

        Keyword arguments:

        solver    -- name of the solver to be used for the LP/QP/NLP
        """
        self.solver = solver

    @staticmethod
    def splitFluxes(matrix, reaction_names, lb, ub):
        """ split the fluxes into non-negative components

        This is done by duplicating and negating matrix columns for reversible
        reactions and just negating the matrix columns corresponding to flipped
        irreversible reactions.

        Keyword arguments:

        matrix         -- the stoichiometric matrix
        reaction_names -- list of reactions (indexed like matrix columns)
        lb             -- list of lower bounds (indexed like matrix columns)
        ub             -- list of upper bounds (indexed like matrix columns)

        Returns:
        matrixSplit, reactionsSplit, lbSplit, ubSplit

        matrixSplit    -- matrix with extra columns for negative flux components
        reactionsSplit -- dictionary { name : pair of indexes } - indexes can be
                          None; if both are not None, the first is the pos. and
                          the second is the neg. component (v = v[0] - v[1])
        lbSplit        -- list of lower bounds (indexed like columns of
                                                matrixSplit)
        ubSplit        -- list of upper bounds ( - '' - )
        """
        matrixSplit = matrix.copy()  # Perform deep copy
        reactionsSplit = {}
        lbSplit = []
        ubSplit = []
        newIndex = 0  # Index in matrixSplit

        for i in range(len(reaction_names)):
            rea = reaction_names[i]
            if lb[i] >= 0.:
                # Reaction is irreversible (pos. flux only or restricted to 0)
                reactionsSplit[rea] = (newIndex, None)
                lbSplit.append(lb[i])
                ubSplit.append(ub[i])
            elif ub[i] <= 0.:
                # Reaction is irreversible & flipped => negate
                reactionsSplit[rea] = (None, newIndex)
                matrixSplit[:, newIndex] *= -1
                lbSplit.append(-ub[i])
                ubSplit.append(-lb[i])
            else:
                # Reaction is reversible => split (copy, then negate the copy)
                reactionsSplit[rea] = (newIndex, newIndex + 1)
                matrixSplit = insert(matrixSplit,
                                     newIndex + 1,
                                     -matrixSplit[:, newIndex],
                                     axis=1)
                lbSplit.append(0.)
                ubSplit.append(ub[i])
                lbSplit.append(0.)
                ubSplit.append(-lb[i])
                newIndex += 1

            newIndex += 1

        return matrixSplit, reactionsSplit, lbSplit, ubSplit

    @staticmethod
    def splitFluxVector(vec, reaction_names, reactionsSplit):
        """ split the given vector as described by reactionsSplit

        Keyword arguments:

        vec            -- the flux vector to be split
        reaction_names -- list of reactions corresponding to entries of vec
        reactionsSplit -- dictionary { name : tuple of indexes } - indexes can
                          be None; if both are not None, the first is the pos.
                          and the second is the neg. component (v = v[0] - v[1])
                          (as computed by FbAnalyzer.splitFluxes)

        Returns:  split vector (containing only non-negative values)
        """
        vecSplit = []
        for i in range(len(reaction_names)):
            rea = reaction_names[i]
            indexPos, indexNeg = reactionsSplit[rea]
            if len(reactionsSplit[rea]) != 2:
                raise TypeError("reactionsSplit tuples must exactly 2 entries")
            if vec[i] == 0.:
                if indexPos is not None:
                    vecSplit.append(0.)
                if indexNeg is not None:
                    vecSplit.append(0.)
            elif vec[i] > 0.:
                if indexPos is None:
                    print rea, indexPos, indexNeg
                    raise ValueError("Value %u (%g) out of range in split "
                                     "vector (must not be positive)" %
                                     (i, vec[i]))
                vecSplit.append(vec[i])
                if indexNeg is not None:
                    vecSplit.append(0.)
            else:
                if indexPos is not None:
                    vecSplit.append(0.)
                if indexNeg is None:
                    raise ValueError("Value %u (%g) out of range in split "
                                     "vector (must not be negative)" %
                                     (i, vec[i]))
                vecSplit.append(-vec[i])

        return vecSplit

    @staticmethod
    def rejoinFluxes(solutionSplit, reactionsSplit, reactions):
        """ rejoin the fluxes in the given solution by applying reactionsSplit

        This assumes that solutionSplit has been obtained by performing FBA on
        the split matrix corresponding to reactionsSplit. This function combines
        the split fluxes by subtracting the negative component from the positive
        one.

        Keyword arguments:

        solutionSplit  -- vector of non-negative fluxes
        reactionsSplit -- dictionary { name : tuple of indexes } - indexes can
                          be None; if both are not None, the first is the pos.
                          and the second is the neg. component (v = v[0] - v[1])
                          (as computed by FbAnalyzer.splitFluxes)
        reactions      -- dictionary of all reactions { name : original matrix
                                                                        column }

        Returns:  joined flux vector (indexed like original matrix columns)
        """
        if len(solutionSplit) == 0:
            return solutionSplit  # Nothing to do
        solution = [0.] * len(reactions)

        for rea in reactionsSplit:
            rea_index_orig = reactions[rea]
            indexPos, indexNeg = reactionsSplit[rea]

            if indexPos is not None:
                solution[rea_index_orig] += solutionSplit[indexPos]

            if indexNeg is not None:
                solution[rea_index_orig] -= solutionSplit[indexNeg]

        return solution

    @staticmethod
    def makeConstraintMatrices(matrix, eqs, ineqs):
        """ transform the given matrix and equality and inequality constraints
            to left-hand-side matrices and right-hand-side vectors of equality
            and inequality constraints

        Keyword arguments:

        matrix -- the stoichiometric matrix of the metabolic network
        eqs    -- list of (coefficient vector, right-hand side) pairs for the
                  equality constraints
        ineqs  -- list of - '' - for the inequality constraints

        """
        if eqs:
            Aeq = vstack((matrix, array([row[0] for row in eqs])))
            beq = array([0.] * len(matrix) + [row[1] for row in eqs])
        else:
            Aeq = matrix
            beq = array([0.] * len(matrix))
        if ineqs:
            Aineq = array([row[0] for row in ineqs])
            bineq = array([row[1] for row in ineqs])
        else:
            Aineq, bineq = None, None

        return Aeq, beq, Aineq, bineq

    def run(self, reactions, matrix, lb, ub, fbaParams):
        """ analyze objective function, and solve the LP/QP/NLP

        Keyword arguments:

        reactions  -- dictionary of all reactions { name : matrix column } or
                      { name : tuple of indices } for split fluxes
        matrix    -- the stoichiometric matrix of the metabolic network
        lb        -- list of lower bounds (indexed like matrix columns)
        ub        -- list of upper bounds (indexed like matrix columns)
        fbaParams -- optimization parameters (incl. objective function)

        Returns:
        obj_value, solution

        obj_value -- optimal value of objective function
        solution  -- a solution where the objective function assumes obj_value
        """
        maxmin, objStr, numIter = (fbaParams.maxmin, fbaParams.objStr,
                                   fbaParams.numIter)
        # Multiply by -1 for maximization
        maxmin_factor = -1. if maxmin == True else 1.
        nCols = len(lb)

        threshold = 0.95
        nReactions = len(lb)

        # Get additional linear equality and inequality constraints
        try:
            Aeq, beq, Aineq, bineq = self.makeConstraintMatrices(
                matrix,
                *ParamParser.linConstraintsToVectors(fbaParams.linConstraints,
                                                     reactions, nCols))
        except ValueError:
            # If any linear constraint is contradictory, return empty solution
            return 0., []

        try:
            objective = ParamParser.convertObjFuncToLinVec(
                objStr, reactions, nCols, maxmin)
        except Exception, strerror:
            print(
                "Error while trying to build coefficient vector of "
                "linear objective function:")
            print strerror
            exit()

        if fbaParams.nlc == []:
            if Aineq is None:
                Aineq = [objective]
                bineq = [threshold]
            else:
                Aineq = vstack((Aineq, [objective]))
                bineq = append(bineq, threshold)

            # Linear function and linear constraints only

            # If flux variables are not split, use GLPK through OpenOpt
            solver = (_OOGLPK if self.solver.lower() == _GLPK
                      and nCols == len(reactions) else self.solver)
            try:
                ps = LinearProblem(Aeq, beq, Aineq, bineq, lb, ub, solver)
            except ValueError, strerror:
                print strerror
                exit()
            #print "lb:", len(lb)
            minmax = [None] * nReactions
            # First maximize each flux
            for index in range(nReactions):
                ps.setObjective([0.] * index + [-1.] + [0.] *
                                (nReactions - index - 1))
                #print len([0.]*index+[-1.]+[0.]*(nReactions-index-1))
                obj_value, solution = ps.minimize()
                ps.resetObjective()

                minmax[index] = obj_value
            print minmax
コード例 #6
0
            exit()

        if start_value_total is None or start_value_total < 0.:
            start_value_total = float(len(reactions))

        # Prepare left and right border for binary search
        l = start_value_total / 2.
        r = start_value_total * 1.5
        m = start_value_total

        # Use GLPK through OpenOpt
        solver = (_OOGLPK if
                  (self.solver.lower() == _GLPK
                   or self.solver.lower() == "default") else self.solver)
        try:
            ps = LinearProblem(Aeq, beq, Aineq, bineq + [m], lb, ub, solver)
#            ps = LinearProblem(Aeq, beq, lb=lb, ub=ub, solver=solver)
        except ValueError, strerror:
            print strerror
            exit()
        ps.setObjective(objective)

        #        ps.setInequalityConstraints(Aineq, bineq+[m])

        try:
            m_value = ps.minimize()[0]
        except ValueError, strerror:
            if self.solver == "default":
                print "Default solver reported an error:"
            else:
                print "Solver %s reported an error:" % self.solver
コード例 #7
0
                objective = ParamParser.convertObjFuncToLinVec(objStr,
                                                    reactions, nCols, maxmin)
            except Exception, strerror:
                print ("Error while trying to build coefficient vector of "
                       "linear objective function:")
                print strerror
                exit()

            if fbaParams.nlc == []:
                # Linear function and linear constraints only

                # If flux variables are not split, use GLPK through OpenOpt
                solver = (_OOGLPK if self.solver.lower() == _GLPK and
                          nCols == len(reactions) else self.solver)
                try:
                    ps = LinearProblem(Aeq, beq, Aineq, bineq, lb, ub, solver)
                except ValueError, strerror:
                    print strerror
                    exit()
                #print "lb:", len(lb)
                ps.setObjective(objective)
            else:
                # Linear function but nonlinear constraints
                try:
                    ps = NonLinearProblem(Aeq, beq, Aineq, bineq, lb, ub,
                                          self.solver)
                except ValueError, strerror:
                    print strerror
                    exit()

                ps.setObjective(lambda x : dot(x, objective))