Exemplo n.º 1
0
def parallel_ko_worker(comm,
                       model,
                       solver,
                       wtVec,
                       fbaParams,
                       koGroups=None,
                       weights=None,
                       numIter=1,
                       useMoma=When.AUTO,
                       lethalityCutoff=_CUTOFF_LETHAL):
    """ compute process (worker) for parallel knockout analysis

    Keyword arguments:

    comm       -- MPI communicator
    model      -- the MetabolicModel
    solver     -- name of QP/NLP solver (or "default")
    wtVec      -- FBA solution for wildtype
    fbaParams  -- parameters for FBA (incl. linear equality and inequality
                                      constraints)
    koGroups   -- list of pairs (group name, list of reactions)
    weights    -- weight vector for weighted MOMA (None -> perform regular MOMA,
                  else: weight flux i with weights[i])
    numIter    -- number of NLP runs (if NLP solver is used) for MOMA
    useMoma    -- selector of optimization strategy, enum values (class When):
                  NEVER  - always perform FBA (LP)
                  AUTO   - perform FBA first, followed by MOMA if not lethal
                  ALWAYS - always perform MOMA (QP)
    lethalityCutoff
               -- threshold for biomass flux signifying lethality
    """
    if not koGroups:
        koGroups = _makeDefaultKoGroups(model)


#    print "worker: %d reactions, %d knockout groups" % (len(model),
#                                                        len(koGroups))
    wtSolution = MetabolicFlux(model, wtVec)
    nanVec = array([nan] * len(wtVec))
    infVec = array([inf] * len(wtVec))
    moma = MomaAnalyzer(solver)

    # index of reaction group to be knocked out (as 0-dimensional numpy array)
    i = array(0, 'i')
    comm.Recv(i)
    while i >= 0:
        group, reaList = koGroups[i]

        # Restrict flux through all reactions in group to zero
        tmp_lb = {}  # {index in model : LB value}
        tmp_ub = {}  # {  - '' -       : UB  ''  }
        for rea in reaList:
            try:
                rIndex = model.reactionDict[rea]
            except KeyError:
                # Skip any blocked reactions (knockout has no effect)
                continue
            tmp_lb[rIndex] = model.reactions[rIndex].lb
            tmp_ub[rIndex] = model.reactions[rIndex].ub
            model.reactions[rIndex].lb = model.reactions[rIndex].ub = 0.

        if not tmp_lb:
            print "  - skipped group '%s' (only blocked reactions)" % group
            comm.Send(wtVec)
            comm.Recv(i)
            continue

        obj_val = lethalityCutoff + 1.

        # Perform FBA first to check for lethality
        if useMoma != When.ALWAYS:
            fba = FbAnalyzer(fbaParams.solver)
            # Note: Model is already reduced
            obj_val, solutionFlux = fba.runOnModel(model,
                                                   fbaParams,
                                                   rmDeadEnds=False)[:2]
            status = SolverStatus.PREPARED
            if not solutionFlux:
                obj_val = 0.

        # Perform MOMA if knockout not already predicted by FBA to be lethal
        if useMoma != When.NEVER and abs(obj_val) > lethalityCutoff:
            solutionFlux, status = moma.runOnModel(model, wtSolution,
                                                   fbaParams.linConstraints,
                                                   numIter, weights)[1:3]

        # Send result to dispatcher
        if status == SolverStatus.UNKNOWN:
            # If status is 'unknown, not converged', send vector with only 'nan'
            # entries
            comm.Send(nanVec)
        elif status in (SolverStatus.PRIM_INFEAS, SolverStatus.DUAL_INFEAS):
            # If status is 'infeasible', send vector with only 'inf' entries
            comm.Send(infVec)
        elif len(solutionFlux) == 0:
            if status == SolverStatus.PREPARED:
                # FBA infeasible
                comm.Send(infVec)
            else:
                comm.Send(nanVec)
        else:
            solutionVec = array(solutionFlux.getVecOrderedByModel(model))
            comm.Send(solutionVec)

        # Restore original constraints
        for rea in reaList:
            try:
                rIndex = model.reactionDict[rea]
            except KeyError:
                continue
            model.reactions[rIndex].lb = tmp_lb[rIndex]
            model.reactions[rIndex].ub = tmp_ub[rIndex]

        # Get next index
        comm.Recv(i)
Exemplo n.º 2
0
def serial_knockout(model,
                    solver,
                    objective,
                    wtSolution,
                    fbaParams,
                    koGroups=None,
                    filePrefix=None,
                    wtObjVal=None,
                    weights=None,
                    numIter=1,
                    useMoma=When.AUTO,
                    lethalityCutoff=_CUTOFF_LETHAL):
    """ perform knockout analysis in serial fashion (single process)

    Keyword arguments:

    model      -- the MetabolicModel
    solver     -- name of QP/NLP solver (or "default")
    objective  -- coefficient vector of linear objective function of FBA
    wtSolution -- FBA solution for wildtype
    fbaParams  -- parameters for FBA (incl. linear equality and inequality
                                      constraints)
    koGroups   -- list of pairs (group name, list of reactions)
    filePrefix -- if given, write MOMA/FBA solutions to files starting with this
                  prefix; if not given, solutions are discarded
    wtObjVal   -- objective function value for wildtype solution (optional)
    weights    -- weight vector for weighted MOMA (None -> perform regular MOMA,
                  else: weight flux i with weights[i])
    numIter    -- number of NLP runs (if NLP solver is used) for MOMA
    useMoma    -- selector of optimization strategy, enum values (class When):
                  NEVER  - always perform FBA (LP)
                  AUTO   - perform FBA first, followed by MOMA if not lethal
                  ALWAYS - always perform MOMA (QP)
    lethalityCutoff
               -- threshold for biomass flux signifying lethality

    Returns list of (distance, diff, obj_val) tuples, indexed like koGroups,

    distance -- value of actual MOMA/FBA objective function at solution
    diff     -- summed absolute difference between mutant and wildtype solutions
    obj_val  -- value of FBA objective function at MOMA/FBA solution for mutant
    """
    if not koGroups:
        koGroups = _makeDefaultKoGroups(model)


#    print "serial: %d reactions, %d knockout groups" % (len(model),
#                                                        len(koGroups))
    wtVec = wtSolution.getVecOrderedByModel(model)
    if wtObjVal is None:
        wtObjVal = dot(objective, wtVec)
    moma = MomaAnalyzer(solver)

    result = []
    for group, reaList in koGroups:
        print group

        # Restrict flux through all reactions in group to zero
        tmp_lb = {}  # {index in model : LB value}
        tmp_ub = {}  # {  - '' -       : UB  ''  }
        for rea in reaList:
            try:
                rIndex = model.reactionDict[rea]
            except KeyError:
                # Skip any blocked reactions (knockout has no effect)
                continue
            tmp_lb[rIndex] = model.reactions[rIndex].lb
            tmp_ub[rIndex] = model.reactions[rIndex].ub
            model.reactions[rIndex].lb = model.reactions[rIndex].ub = 0.

        if not tmp_lb:
            print "  -> skipped (only blocked reactions)"
            result.append((0., 0., wtObjVal))
            if filePrefix:
                wtSolution.writeToFile(filePrefix + group + _FILE_SUFFIX)
            continue

        obj_val = lethalityCutoff + 1.

        # Perform FBA first to check for lethality
        if useMoma != When.ALWAYS:
            fba = FbAnalyzer(fbaParams.solver)
            # Note: Model is already reduced
            obj_val, solutionFlux = fba.runOnModel(model,
                                                   fbaParams,
                                                   rmDeadEnds=False)[:2]
            status = SolverStatus.PREPARED
            dist = None
            if not solutionFlux:
                obj_val = 0.

        # Perform MOMA if knockout not already predicted by FBA to be lethal
        if useMoma != When.NEVER and abs(obj_val) > lethalityCutoff:
            dist, solutionFlux, status = moma.runOnModel(
                model, wtSolution, fbaParams.linConstraints, numIter,
                weights)[:3]

        if status == SolverStatus.UNKNOWN:
            result.append((nan, nan, 0.))
        elif status in (SolverStatus.PRIM_INFEAS, SolverStatus.DUAL_INFEAS):
            result.append((inf, inf, 0.))
        elif len(solutionFlux) == 0:
            if status == SolverStatus.PREPARED:
                # FBA infeasible
                result.append((inf, inf, 0.))
            else:
                result.append((nan, nan, 0.))
        else:
            diff = sum(solutionFlux.absDiff(wtSolution).fluxDict.values())
            if dist is None:
                dist = moma.evalObjFunc(
                    wtVec, solutionFlux.getVecOrderedByModel(model), weights)
            else:
                obj_val = max(
                    0., dot(objective,
                            solutionFlux.getVecOrderedByModel(model)))
            result.append((dist, diff, obj_val))
            if filePrefix:
                solutionFlux.writeToFile(filePrefix + group + _FILE_SUFFIX)

        # Restore original constraints
        for rea in reaList:
            try:
                rIndex = model.reactionDict[rea]
            except KeyError:
                continue
            model.reactions[rIndex].lb = tmp_lb[rIndex]
            model.reactions[rIndex].ub = tmp_ub[rIndex]

    return result
Exemplo n.º 3
0
    def run(self, fbaParams, syntaxOk=True, printExcepted=False):
        """ check assertions against results of FBA, FVA, & split-ratio analysis

        This function performs FBA, split-ratio analysis, and FVA and evaluates
        the assertions. It enumerates all assertions that do not hold.

        Keyword arguments:
        fbaParams     -- objective function and solver for FBA
        syntaxOk      -- if False, previously performed syntax check has failed
        printExcepted -- if False, syntax errors in assertions are not reported
        """

        # 1. Perform flux balance analysis on the metabolic network

        fba = FbAnalyzer(fbaParams.solver)
        self.flux = fba.runOnModel(self.model, fbaParams)[1]
        if len(self.flux) == 0:
            print(
                "No FBA solution was obtained. The optimization problem is "
                "either unbounded or infeasible.")
            return

        # 2. Compute metabolite fluxes and split ratios

        splitRatios = self.flux.computeAllSplitRatios(self.model)
        self.metFlux, self.outRatios, self.inRatios = {}, {}, {}
        for met in splitRatios:
            outRatios, inRatios = splitRatios[met]
            self.metFlux[met] = sum(inRatios[rea][1] for rea in inRatios)
            self.outRatios[met] = dict(
                (rea, outRatios[rea][0]) for rea in outRatios)
            self.inRatios[met] = dict(
                (rea, inRatios[rea][0]) for rea in inRatios)

        # 3. Perform flux variability analysis on the model

        fva = FvAnalyzer("default")  # always use GLPK (=> fastFVA)
        minmax = fva.runOnModel(self.model, fbaParams, self.fvaTolerance,
                                self.flux)[0]

        self.minFlux, self.maxFlux = {}, {}
        for i in range(len(self.model)):
            self.minFlux[self.model.reactions[i].name], self.maxFlux[
                self.model.reactions[i].name] = minmax[i]

        # 4. Check assertions

        failed = []
        excepted = []
        for i in range(len(self.assertions)):
            try:
                if not eval(self.assertions[i]):
                    failed.append(repr(self.assertions_orig[i]))
            except (SyntaxError, NameError):
                excepted.append(repr(self.assertions_orig[i]))

        if printExcepted and excepted:
            print(
                "The following assertions could not be evaluated due to "
                "errors:\n  " + "\n  ".join(excepted))
        if failed:
            print "The following assertions failed:\n  " + "\n  ".join(failed)
        else:
            if not syntaxOk or (printExcepted and excepted):
                print "All other assertions hold."
            else:
                print "All assertions hold."
Exemplo n.º 4
0
                print(
                    "Error in file %s: FBA solution and model must have the "
                    "same reactions." % os.path.basename(options.wtSolution))
                _mpi_exit(comm, 1)

            # Build coefficient vector of linear objective function
            objective = array(
                ParamParser.convertObjFuncToLinVec(objStr, model.reactionDict))
            wt_obj_value = dot(objective,
                               wtSolution.getVecOrderedByModel(model))

        # 7.b If FBA solution is not given, perform FBA

        else:
            # Compute wildtype solution via FBA
            fba = FbAnalyzer(fbaSolver)

            wt_obj_value, wtSolution, ndim = fba.runOnModel(
                model, fbaParams, rmDeadEnds=not options.useFullMatrix)
            if not options.useFullMatrix:
                print(
                    "Info: The reduced network for FBA has %u reactions and "
                    "%u metabolites." % ndim[1::-1])
            if len(wtSolution) == 0:
                print "Model is infeasible or unbounded. Nothing to do."
                _mpi_exit(comm)

        solver = options.solver
        if not solver:
            solver = "default"
        numIter = options.numIter
Exemplo n.º 5
0
                    "Error: Only one transporter type can have factors.\n"
                    "Found factors with types %s and %s" % (main_type, typ))
                exit()

            index += 1

    for i in range(len(transpByType)):
        if transpByType[i][0][0] == main_type:
            main_index = i
            break

    # 7. Perform flux balance analysis for all combinations of transporters

    if solver == "":
        solver = "default"
    fba = FbAnalyzer(solver)

    resultList = []
    checkRecursive(resultList, transpByType[main_index],
                   transpByType[:main_index] + transpByType[main_index + 1:],
                   fba, matrix, reactions, model.getReactionNames(), lb, ub,
                   fbaParams)

    # For debugging: Output lb/ub to console
    if debugFlag:
        keys = resultList[0].keys()
        keys.remove("solution")
        keys.remove("bounds")
        keys.sort()
        for result in resultList:
            print "***",
Exemplo n.º 6
0
def checkRecursive(resultList,
                   currentList,
                   otherLists,
                   fba,
                   matrix,
                   reactions,
                   reaction_names,
                   lb,
                   ub,
                   fbaParams,
                   partialResult=[]):
    """ recursively enumerate all meaningful combinations of transporters and
        launch FBA on each such combination

    Keyword arguments:

    resultList     -- list for storage of results on innermost recursion level
    currentList    -- list of importers of the same type (perform FBA if empty)
    otherLists     -- list of lists of importers of other types (may be empty)
    fba            -- FbAnalyzer to be used for FBA
    matrix         -- the stoichiometric matrix of the metabolic network
    reactions      -- dictionary of all reactions { name : matrix column }
    reaction_names -- list of reaction names (column index -> name)
    lb             -- list of lower bounds (indexed like matrix columns)
    ub             -- list of upper bounds (indexed like matrix columns)
    fbaParams      -- ParamParser object for getting nonlinear constraints
    partialResult  -- growing result dictionary

    Returns: nothing, appends results to resultList

    resultList is list of dictionaries containing keys <type>, <type>_co,
    <type>_flux, <type>_co_flux for every importer and co-importer and key
    "solution" for the FBA solution
    """
    if currentList == []:
        # Recursion anchor: We have picked transporters of every type -> run FBA

        matrixSplit, reactionsSplit, lbSplit, ubSplit = \
            FbAnalyzer.splitFluxes(matrix, reaction_names, lb, ub)

        solutionSplit = fba.run(reactionsSplit, matrixSplit, lbSplit, ubSplit,
                                fbaParams)[1]

        keys = partialResult.keys()
        if solutionSplit == []:
            solution = []
            for key in keys:
                rea = partialResult[key]
                partialResult[key + "_flux"] = None
        else:
            solution = array(
                FbAnalyzer.rejoinFluxes(solutionSplit, reactionsSplit,
                                        reactions))
            for key in keys:
                rea = partialResult[key]
                if rea in reactions:
                    partialResult[key + "_flux"] = solution[reactions[rea]]
                else:
                    partialResult[key + "_flux"] = None

        partialResult["solution"] = solution

        # for debugging: store LB/UB as dictionary
        if debugFlag:
            lbub = {}
            for rea in reactions:
                rea_index = reactions[rea]
                lbub[rea] = (lb[rea_index], ub[rea_index])
            partialResult["bounds"] = lbub

        resultList.append(partialResult)
    else:
        # It's sufficient to query the first element as all members of
        # currentList[i] have the same type.
        typ = currentList[0][0]

        # Set next currentList for recursion (head of otherLists if not empty)
        if otherLists == []:
            nextList = []
        else:
            nextList = otherLists[0]

        for (_, trans_name, factor, cotrans) in currentList:
            # Make a copy of partialResult and extend by keys for current type
            tmpResult = dict(partialResult)
            tmpResult[typ] = trans_name
            tmpResult[typ + "_co"] = None

            if factor is not None:
                # Set flux through transporter to fix value
                index = reactions[trans_name]
                tmp_lb_trans = lb[index]
                tmp_ub_trans = ub[index]
                lb[index] = ub[index] = factor
                if cotrans is not None:
                    # make another copy of partial result
                    tmpResBak = dict(tmpResult)

                # First perform FBA without cotransporter
                checkRecursive(resultList, nextList, otherLists[1:], fba,
                               matrix, reactions, reaction_names, lb, ub,
                               fbaParams, tmpResult)

                # Now set flux through cotransporter to appropriate value
                # (factor)
                if cotrans is not None:
                    # get copy of partial result
                    tmpResult = tmpResBak
                    tmpResult[typ + "_co"] = cotrans

                    # Find factor cotrans_fac in currentList
                    for (_, cotrans_name, cotrans_fac, _) in currentList:
                        if cotrans_name == cotrans:
                            break

                    co_index = reactions[cotrans]
                    tmp_lb_cotrans = lb[co_index]
                    tmp_ub_cotrans = ub[co_index]
                    lb[co_index] = ub[co_index] = cotrans_fac

                    checkRecursive(resultList, nextList, otherLists[1:], fba,
                                   matrix, reactions, reaction_names, lb, ub,
                                   fbaParams, tmpResult)

                    lb[co_index] = tmp_lb_cotrans
                    ub[co_index] = tmp_ub_cotrans

                lb[index] = tmp_lb_trans
                ub[index] = tmp_ub_trans
            else:
                # Allow arbitrary flux through transporter
                index = reactions[trans_name]
                tmp_lb_trans = lb[index]
                tmp_ub_trans = ub[index]
                lb[index] = -inf
                ub[index] = inf

                # First perform FBA without cotransporter
                checkRecursive(resultList, nextList, otherLists[1:], fba,
                               matrix, reactions, reaction_names, lb, ub,
                               fbaParams, tmpResult)

                # Now also allow arbitrary flux through cotransporter
                if cotrans is not None:
                    # make another copy of partial result
                    tmpResult = dict(tmpResult)
                    tmpResult[typ + "_co"] = cotrans
                    co_index = reactions[cotrans]
                    tmp_lb_cotrans = lb[co_index]
                    tmp_ub_cotrans = ub[co_index]
                    lb[co_index] = -inf
                    ub[co_index] = inf

                    checkRecursive(resultList, nextList, otherLists[1:], fba,
                                   matrix, reactions, reaction_names, lb, ub,
                                   fbaParams, tmpResult)

                    lb[co_index] = tmp_lb_cotrans
                    ub[co_index] = tmp_ub_cotrans

                lb[index] = tmp_lb_trans
                ub[index] = tmp_ub_trans
Exemplo n.º 7
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
Exemplo n.º 8
0
    def runOnModel(self,
                   model,
                   fbaParams,
                   threshp=.95,
                   objFuncVal=None,
                   rmDeadEnds=True):
        """ perform metabolite flux minimization on the given model with
            objective value <= threshp * maximum

        Keyword arguments:

        model        -- the MetabolicModel
        fbaParams    -- FBA parameters
        threshp      -- threshold percentage (objective_value <= thresp*maximum)
        objFuncVal   -- FBA optimum for objective function (optional)
        rmDeadEnds   -- if True, remove all reactions with dead ends before
                        analysis (faster and gives an optimal solution, as well)

        Returns:
        minVec, dimReduced

        minVec       -- list of minimum values, indexed like metabolites
        dimReduced   -- pair (nRows, nColumns) with dimensions of reduced matrix
        """
        if rmDeadEnds:
            deadReactions = model.findDeadEnds(True)[1]
            modelRed = model.getSubModelByExcludeList(deadReactions)
            cbz = model.canBeZero(deadReactions)
            nonZeroDeadEnds = [
                deadReactions[i] for i in range(len(deadReactions))
                if not cbz[i]
            ]
            if nonZeroDeadEnds:
                print(
                    "The following blocked reactions are constrained to a "
                    "non-zero flux:\n  " + "\n  ".join(nonZeroDeadEnds) +
                    "\nThe problem is infeasible.")
                return [], array(modelRed.getStoichiometricMatrix()).shape
        else:
            modelRed = model

        matrix = array(modelRed.getStoichiometricMatrix())
        dimReduced = matrix.shape
        lb, ub = modelRed.getBounds()

        # Split fluxes into non-negative components
        matrixSplit, reactionsSplit, lbSplit, ubSplit = \
            FbAnalyzer.splitFluxes(matrix, modelRed.getReactionNames(), lb, ub)

        # Build (negative) objective function vector for split fluxes
        objective = ParamParser.convertObjFuncToLinVec(fbaParams.objStr,
                                                       reactionsSplit,
                                                       len(lbSplit),
                                                       fbaParams.maxmin)
        maxmin_factor = -1. if fbaParams.maxmin else 1.

        # If the optimum of the objective function is not given, perform FBA
        if objFuncVal is None:
            fba = FbAnalyzer(self.solver)

            objFuncVal, sFlux = fba.run(reactionsSplit, matrixSplit, lbSplit,
                                        ubSplit, fbaParams)

            if len(sFlux) == 0:
                return [], dimReduced

        # Use negative threshold (objective value >= threshold is equivalent to
        # -objective value <= -threshold, and objective already has coefficient
        # -1 due to maximization)
        threshold = maxmin_factor * objFuncVal * threshp
        print "obj func. opt:", objFuncVal
        print "Threshold: ", threshold
        try:
            eqs, ineqs = ParamParser.linConstraintsToVectors(
                fbaParams.linConstraints, modelRed.reactionDict, len(lbSplit))
        except ValueError, e:
            # If any linear constraint is contradictory, report error
            print "Optimization not possible due to contradictory constraints:"
            print "  " + e
            exit()
Exemplo n.º 9
0
    def run(self,
            matrix,
            lb,
            ub,
            wtSolution,
            eqs=[],
            ineqs=[],
            numIter=1,
            weights=None):
        """ construct and solve the quadratic optimization problem

        Keyword arguments:

        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)
        wtSolution -- FBA solution for the wildtype
                     (list indexed like matrix columns)
        eqs        -- list of (coefficient vector, right-hand side) pairs for
                      additional equality constraints
        ineqs      -- list of - '' - for additional inequality constraints
        numIter    -- number of iterations of NLP to perform
        weights    -- weight vector for weighted MOMA (None -> perform regular
                      MOMA, else: weight flux i with weights[i])

        Returns:
        distance, solution, status

        distance   -- minimum possible distance from wtSolution with the given
                      matrix & constraints
        solution   -- a flux vector with minimal distance to wtSolution
                     (list indexed like matrix columns)
        status     -- SolverStatus after optimization
        """
        wtVec = array(wtSolution)
        # Construct matrices of original equality and inequality constraints
        Aeq, beq, Aineq, bineq = FbAnalyzer.makeConstraintMatrices(
            matrix, eqs, ineqs)
        try:
            if MomaProblem.isCvxQpSolver(self.solver):
                ps = MomaProblem(Aeq, beq, Aineq, bineq, lb, ub, self.solver,
                                 wtVec, weights)
            else:
                ps = NonLinearProblem(Aeq, beq, Aineq, bineq, lb, ub,
                                      self.solver)
                if weights is None:
                    ps.setObjective(lambda x: dot(x - wtVec, x - wtVec))
                    ps.setObjGrad(lambda x: 2 * (x - wtVec))
                else:
                    if not isinstance(weights, ndarray):
                        weights = array(weights)
                    ps.setObjective(lambda x: dot(x - wtVec,
                                                  (x - wtVec) * weights))
                    ps.setObjGrad(lambda x: 2 * sqrt(weights) * (x - wtVec))
                spIter = StartPointIterator(len(lb), numIter)
                spIter.setRange(-1., 1.)
                ps.setStartPointIterator(spIter)

        except ValueError, strerror:
            print strerror
            exit()
Exemplo n.º 10
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
Exemplo n.º 11
0
            if not sFlux.hasSameReactions(model):
                print "Error: Solution and model must have the same reactions."
                exit()

            # Sort solution like matrix columns
            sFlux = sFlux.getVecOrderedByModel(modelRed)

            # Evaluate the objective function at solution
            obj_value = maxmin_factor * dot(objective, sFlux)

        # Case 3. Perform flux balance analysis on the metabolic network
        #         (only if no solution file is given)

        else:
            fba = FbAnalyzer(self.solver)

            if splitFluxes:
                # Split flux variables for FBA
                matrixSplit, reactionsSplit, lbSplit, ubSplit = \
                    FbAnalyzer.splitFluxes(matrix, modelRed.getReactionNames(),
                                           lb, ub)
                obj_value, sFlux = fba.run(reactionsSplit, matrixSplit,
                                           lbSplit, ubSplit, fbaParams)
                # Get joined solution (for output)
                sFlux = array(
                    FbAnalyzer.rejoinFluxes(sFlux, reactionsSplit,
                                            modelRed.reactionDict))
            else:
                obj_value, sFlux = fba.run(modelRed.getReactionNames(), matrix,
                                           lb, ub, fbaParams)