Home > INIT > ftINITInternalAlg.m

ftINITInternalAlg

PURPOSE ^

ftINITInternalAlg

SYNOPSIS ^

function [deletedRxns,metProduction,res,turnedOnRxns,fluxes]=ftINITInternalAlg(model,rxnScores,metData,essentialRxns,prodWeight,allowExcretion,remPosRev,params,startVals,fluxes,verbose)

DESCRIPTION ^

 ftINITInternalAlg
    This function runs the MILP for a step in ftINIT.

   model           a reference model structure
   rxnScores       a vector of scores for the reactions in the model.
                   Positive scores are reactions to keep and negative
                   scores are reactions to exclude. Rxns set to 0 are excluded
                   from the problem.
   metData         boolean matrix with mets as rows and rxns as columns
                   saying which reaction produces each detected met (optional, default [])
   essentialRxns   cell array of reactions that are essential and that
                   have to be in the resulting model. This is normally
                   used when fitting a model to task (see fitTasks)
   prodWeight      a score that determines the value of having
                   net-production of metabolites. This is a way of having
                   a more functional network as it provides a reason for
                   including bad reactions for connectivity reasons. This
                   score is for each metabolite, and the sum of these weights
                   and the scores for the reactions is what is optimized
   allowExcretion  true if excretion of all metabolites should be allowed.
                   This results in fewer reactions being considered
                   dead-ends, but all reactions in the resulting model may
                   not be able to carry flux. If this is "false" then the
                   equality constraints are taken from model.b. If the
                   input model lacks exchange reactions then this should
                   probably be "true", or a large proportion of the model
                   would be excluded for connectivity reasons
   remPosRev       If true, the positive reversible reactions are removed from the problem.
                   This is used in step 1 of ftINIT
   params          parameters for the MILP, for example MIPGap and TimeLimit
   startVals       Start values for the MILP, typically used when rerunning
                   with a higher MIPGap, to use the results from the previous
                   run
   fluxes          Fluxes from the last run.
   verbose         If true, the MILP progression will be shown. 

   deletedRxns     reactions which were deleted by the algorithm (only 
                   rxns included in the problem)
   metProduction   array that indicates which of the
                   metabolites in presentMets that could be
                   produced
                   0: metabolite could not be produced
                   1: metabolite could be produced
   res             The result from the MILP
   turnedOnRxns    The reactions determined to be present (only 
                   rxns included in the problem) 
   fluxes          The fluxes from the MILP

   This function is the actual implementation of the algorithm. See
   ftINIT for a higher-level function for model reconstruction. 

 Usage: [deletedRxns,metProduction,res,turnedOnRxns,fluxes]=runINIT9(model,...
           rxnScores,presentMets,essentialRxns,prodWeight,allowExcretion,...
           remPosRev,params)

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [deletedRxns,metProduction,res,turnedOnRxns,fluxes]=ftINITInternalAlg(model,rxnScores,metData,essentialRxns,prodWeight,allowExcretion,remPosRev,params,startVals,fluxes,verbose)
0002 % ftINITInternalAlg
0003 %    This function runs the MILP for a step in ftINIT.
0004 %
0005 %   model           a reference model structure
0006 %   rxnScores       a vector of scores for the reactions in the model.
0007 %                   Positive scores are reactions to keep and negative
0008 %                   scores are reactions to exclude. Rxns set to 0 are excluded
0009 %                   from the problem.
0010 %   metData         boolean matrix with mets as rows and rxns as columns
0011 %                   saying which reaction produces each detected met (optional, default [])
0012 %   essentialRxns   cell array of reactions that are essential and that
0013 %                   have to be in the resulting model. This is normally
0014 %                   used when fitting a model to task (see fitTasks)
0015 %   prodWeight      a score that determines the value of having
0016 %                   net-production of metabolites. This is a way of having
0017 %                   a more functional network as it provides a reason for
0018 %                   including bad reactions for connectivity reasons. This
0019 %                   score is for each metabolite, and the sum of these weights
0020 %                   and the scores for the reactions is what is optimized
0021 %   allowExcretion  true if excretion of all metabolites should be allowed.
0022 %                   This results in fewer reactions being considered
0023 %                   dead-ends, but all reactions in the resulting model may
0024 %                   not be able to carry flux. If this is "false" then the
0025 %                   equality constraints are taken from model.b. If the
0026 %                   input model lacks exchange reactions then this should
0027 %                   probably be "true", or a large proportion of the model
0028 %                   would be excluded for connectivity reasons
0029 %   remPosRev       If true, the positive reversible reactions are removed from the problem.
0030 %                   This is used in step 1 of ftINIT
0031 %   params          parameters for the MILP, for example MIPGap and TimeLimit
0032 %   startVals       Start values for the MILP, typically used when rerunning
0033 %                   with a higher MIPGap, to use the results from the previous
0034 %                   run
0035 %   fluxes          Fluxes from the last run.
0036 %   verbose         If true, the MILP progression will be shown.
0037 %
0038 %   deletedRxns     reactions which were deleted by the algorithm (only
0039 %                   rxns included in the problem)
0040 %   metProduction   array that indicates which of the
0041 %                   metabolites in presentMets that could be
0042 %                   produced
0043 %                   0: metabolite could not be produced
0044 %                   1: metabolite could be produced
0045 %   res             The result from the MILP
0046 %   turnedOnRxns    The reactions determined to be present (only
0047 %                   rxns included in the problem)
0048 %   fluxes          The fluxes from the MILP
0049 %
0050 %   This function is the actual implementation of the algorithm. See
0051 %   ftINIT for a higher-level function for model reconstruction.
0052 %
0053 % Usage: [deletedRxns,metProduction,res,turnedOnRxns,fluxes]=runINIT9(model,...
0054 %           rxnScores,presentMets,essentialRxns,prodWeight,allowExcretion,...
0055 %           remPosRev,params)
0056 
0057 if isempty(essentialRxns)
0058     essentialRxns={};
0059 end
0060 essentialRxns=essentialRxns(:);
0061 if isempty(prodWeight)
0062     prodWeight=0.5;
0063 end
0064 
0065 
0066 %The model should be in the reversible format and all relevant exchange
0067 %reactions should be open
0068 if isfield(model,'unconstrained')
0069     EM='Exchange metabolites are still present in the model. Use simplifyModel if this is not intended';
0070     dispEM(EM,false);
0071 end
0072 
0073 
0074 essential = ismember(model.rxns,essentialRxns);
0075 
0076 %Some nice to have numbers
0077 nMets=numel(model.mets);
0078 nRxns=numel(model.rxns);
0079 nRxnsWithOnOff = nRxns;
0080 
0081 %Reactions with score 0 will just be left in the model, and will not be part of the problem (but can carry flux).
0082 %It is possible to set score = 0 for e.g. spontaneous reactions, exchange rxns, etc., which may not be that interesting
0083 %to remove.
0084 
0085 %if makeIrrev is on, we can just as well skip all positive reversible rxns - they will be turned on without carrying any flux
0086 %since they can form a loop within themself (fwd-rev)
0087 if remPosRev
0088     rxnScores(rxnScores > 0 & model.rev~=0) = 0;
0089 end
0090 
0091 %Handle metabolomics
0092 %A problem with the metabolomics is that some of the producer reactions
0093 %for a metabolite could be excluded from the problem. We solve this by
0094 %adding them with score 0. They can still be seen as positive, since they
0095 %either don't matter (there is another producer) or they can contribute to an
0096 %increased score.
0097 revRxns=model.rev~=0; 
0098 essRevRxns = find(revRxns & essential);
0099 essIrrevRxns = find(~revRxns & essential);
0100 
0101 if ~isempty(metData)
0102     %remove any metData rows that is connected to an essential rxn -
0103     %these will be on regardless and will cause problems below.
0104     containsEssential = any(metData(:,essential),2);
0105     metData = metData(~containsEssential,:);
0106 end
0107 
0108 if ~isempty(metData)
0109     metRxns = any(metData,1).';
0110     posRxns = rxnScores > 0 | ((rxnScores == 0) & metRxns);
0111 else
0112     posRxns = rxnScores > 0;
0113 end
0114 negRxns = rxnScores < 0;
0115 
0116 posRevRxns = find(posRxns & revRxns & ~essential);
0117 negRevRxns = find(negRxns & revRxns & ~essential);
0118 posIrrevRxns = find(posRxns & ~revRxns & ~essential);
0119 negIrrevRxns = find(negRxns & ~revRxns & ~essential);
0120 nPosRev = numel(posRevRxns);
0121 nNegRev = numel(negRevRxns);
0122 nPosIrrev = numel(posIrrevRxns);
0123 nNegIrrev = numel(negIrrevRxns);
0124 nEssRev = numel(essRevRxns);
0125 nEssIrrev = numel(essIrrevRxns); %not used, but left for symmetry
0126 nMetabolMets = size(metData,1);
0127 
0128 if ~isempty(metData)
0129     metNegRev = negRxns & revRxns & ~essential & metRxns;
0130     metNegIrrev = negRxns & ~revRxns & ~essential & metRxns;
0131     nMetNegRev = sum(metNegRev);
0132     nMetNegIrrev = sum(metNegIrrev);
0133 end
0134 
0135 
0136 milpModel = model;
0137 
0138 %These six categories need to be handled separately:
0139 %
0140 %PosIrrev (positive reaction score, irreversible):
0141 %flux >= 0.1*Yi, flux - 0.1*Yi - VPI == 0, 0 <= Yi(onoff) <= 1, 0 <= VPI <= Inf
0142 %The nice thing with rxns with positive score is that they do not require a boolean. The optimizer will
0143 %strive for maximizing the Yi here, so it can be a continuous variable, where we just force a flux if
0144 %the variable is on.
0145 %PosRev:
0146 % 1: Split up the flux into positive and negative: flux - vnrp + vnrn == 0, 0 <= vprp,vprn <= Inf.
0147 % 2. Force one of the fluxes on: vprp + vprn >= 0.1*Yi, vprp + vprn - 0.1*Yi - vprv1 == 0. 0 <= Yi(onoff) <= 1, vprv1 >= 0
0148 % 3. We need a bool to make sure that one of vprp and vprn are always zero:
0149 %    vprb E {0,1}:  vprp <= 100*vprb (if bool is 0, vprp is zero): vprp - 100*vprb + vprv2 == 0, vprv2 >= 0
0150 %    vprn <= (1-vprb)*100 (if bool is one, vprn is zero): vprn + 100*vprb + vprv3 == 0, -100 <= vprv3 <= inf
0151 %Neg Irrev:
0152 %For negative scores, we need to use an integer, I see no way around that.
0153 % flux < 100*Yi, Yi E {0,1}. Flux - 100*Yi + vni == 0
0154 %Neg Rev:
0155 %Two cases:
0156 %A: Without irrev model
0157 % 1: Split up the flux into positive and negative: flux - vnrp + vnrn == 0, 0 <= vprp,vprn <= Inf.
0158 % 2: Force the Yi (on/off) var on if the flux is on: vnrp + vnrn <= 0.1 * Yi, Yi E {0,1}: vnrp + vnrn - 0.1 * Yi + vnrv1 == 0, vnrv1 >= 0.
0159 %B: Irrev model (Not used for now)
0160 % 1. We now have two reactions, but still just boolean variable. We know that
0161 %    the flux can only be positive, so we just say that flux1 + flux2 <= 0.1 * Yi, Yi E {0,1}: flux1 + flux2 - 0.1 * Yi + vnrv1 == 0, vnrv1 >= 0.
0162 %    We don't care if there is any loop - there is just no benefit for the objective to generate one, and it doesn't matter.
0163 %Ess Irrev (essential rxn, i.e. forced to carry flux, irreversible):
0164 %flux >= 0.1 - solved with lb = 0.1.
0165 %Ess Rev (these are not really used):
0166 % 1: Split up the flux into positive and negative: flux - verp + vern == 0, 0 <= verp,vern <= Inf.
0167 % 2. Force one of the fluxes on: verp + vern >= 0.1, verp + vern - verv1 == 0. verv1 >= 0.1
0168 % 3. We need a bool to make sure that one of verp and vern are always zero:
0169 %    verb E {0,1}:  verp <= 100*verb (if bool is 0, verp is zero): verp - 100*verb + verv2 == 0, verv2 >= 0
0170 %    vern <= (1-verb)*100 (if bool is one, vern is zero): vern + 100*verb + verv3 == 0, -100 <= verv3 <= inf
0171 
0172 % Now metabolomics
0173 % The basic idea is that the bonus is gotten if any of the producer reactions are on. We can
0174 % therefore use the "on" variables directly for the reactions that are included. We therefore add one variable per met, mon, which can be
0175 % continuous and between 0 and 1. We then say that mon <= v1 + v2 + ... + vn, i.e. that
0176 % mon + mv1 - v1 - v2 ... - vn == 0, 0 <= mon <= 1, 0 <= mv1 <= inf
0177 % mon gets -prodWeight in the c vector (i.e. objective function)
0178 % A tricky part is that some of the reactions producing a metabolite are left outside the problem
0179 % This is solved by moving them into the problem, but with the score 0. They can still be treated as positive
0180 % reactions. In the end, we are not interested if they are on though, but they may
0181 % allow for production of a metabolite, giving no benefit of turning on another producer reaction.
0182 % Another tricky thing is that some metabolite producers have negative score. There is
0183 % no automatic mechanism for forcing flux on if the variable is on - this is simply
0184 % not needed for negative variables - unless they are a metabolite producer. We therefore need
0185 % to add an extra constraint there, similar to the case of positive. It gets a bit complicated.
0186 % For reversible, we need a bool to make sure that one of vnrp and vnrn stays zero:
0187 %    vnrbm E {0,1}:  vnrp <= 100*vnrbm (if bool is 0, vnrp is zero): vnrp - 100*vnrbm + vnrvm1 == 0, vnrvm1 >= 0
0188 %    vnrn <= (1-vnrbm)*100 (if bool is one, vnrn is zero): vnrn + 100*vnrbm + vnrvm2 == 0, -100 <= vnrvm2 <= inf
0189 % We then also say that vnrp + vnrn >= 0.1*Yi, vnrp + vnrn - 0.1*Yi - vnrvm3 == 0, vnrvm3 >= 0
0190 % For irreversible, it is fairly straight-forward. We just say that flux >= 0.1*Yi, i.e. flux - 0.1*Yi - vnim == 0, 0 <= vnim <= Inf.
0191 
0192 
0193 %The total matrix then looks like this. Note that we have ordered the categories, two reactions each,
0194 %in the S matrix to make it easier to follow the figure. In practice, they come in random order, which
0195 %is why the SEye variable is used further down.
0196 %all categories below have two columns - the two column starts where label starts
0197 %since the label cannot fit in two chars, they are on multiple lines
0198 %
0199 %The met variables and constraints are not in this figure for practical reasons.
0200 %
0201 %                           vprb  vprv3 vnrn  vern  verv2 mv1
0202 % pi  ni  ei  Ypi Yni vpi vprn  vprv2 vnrp  verp  verb  mon
0203 %   pr  nr  er  Ypr Ynr vprp  vprv1 vni   vnrv1 verv1 verv3
0204 % SSSSSSSSSSSS0000000000000000000000000000000000000000000000
0205 % SSSSSSSSSSSS0000000000000000000000000000000000000000000000 S block
0206 % SSSSSSSSSSSS0000000000000000000000000000000000000000000000
0207 % 1           N       -                                      Pos irrev block
0208 %  1           N       -
0209 %   1                   - 1                                  Pos rev block 1
0210 %    1                   - 1
0211 %               N       1 1   -                              Pos rev block 2
0212 %                N       1 1   -
0213 %                       1   M   1                            Pos rev block 3
0214 %                        1   M   1
0215 %                         1 C     1                          Pos rev block 4
0216 %                          1 C     1
0217 %     1           M                 1                        Neg irrev block
0218 %      1           M                 1
0219 %       1                             - 1                    Neg rev block 1
0220 %        1                             - 1
0221 %                   M                 1 1 1                  Neg rev block 2
0222 %                    M                 1 1 1
0223 %           1                               - 1              Ess rev block 1
0224 %            1                               - 1
0225 %                                           1 1 -            Ess rev block 2
0226 %                                            1 1 -
0227 %                                           1     M 1        Ess rev block 3
0228 %                                            1     M 1
0229 %                                             1   C   1      Ess rev block 4
0230 %                                              1   C   1
0231 %             --------                                  1 1  Met block - Here, we assume that all variables support each met.
0232 %             --------                                   1 1             In practice, fewer of the "on" variables with -1 should be included
0233 %
0234 %
0235 %M = -100
0236 %N = -0.1
0237 %D = 0.1
0238 %C = 100
0239 %- = -1
0240 %
0241 %It looks a bit different for the irrev model, but still quite similar
0242 
0243 %build the A matrix
0244 %S row
0245 %When forcing on essential rxns, use the flux value of the previous run (set to 0.1 the first time)
0246 %Don't set it above 0.1, may starve something else out. Leave a margin of 1% from the last run.
0247 forceOnLim = 0.1;
0248 forceOnLimEss=min(abs(fluxes)*0.99,0.1);
0249 
0250 varsPerNegRev = 3;
0251 
0252 
0253 %Figure out the number of variables needed for metabolomics
0254 if ~isempty(metData)
0255     nMetVars = 2*size(metData,1) + 4*nMetNegRev + nMetNegIrrev; %mon,mv1; vnrbm,vnrvm1,vnrvm2,vnrvm3; vnim
0256 else
0257     nMetVars = 0;
0258 end
0259 
0260 
0261 sRow = [milpModel.S sparse(nMets, nPosIrrev*2+nPosRev*7+nNegIrrev*2+nNegRev*(1+varsPerNegRev)+nEssRev*6 + nMetVars)];
0262 sEye = speye(nRxns);
0263 nYBlock = nPosIrrev+nPosRev+nNegIrrev+nNegRev;
0264 piRows = [sEye(posIrrevRxns,:) speye(nPosIrrev)*-forceOnLim sparse(nPosIrrev,nPosRev+nNegIrrev+nNegRev) speye(nPosIrrev)*-1 sparse(nPosIrrev,nPosRev*6+nNegIrrev+nNegRev*varsPerNegRev+nEssRev*6+nMetVars)];
0265 
0266 prRows1 = [sEye(posRevRxns,:) sparse(nPosRev,nYBlock + nPosIrrev) speye(nPosRev)*-1 speye(nPosRev) sparse(nPosRev,nPosRev*4+nNegIrrev+nNegRev*varsPerNegRev+nEssRev*6+nMetVars)];
0267 prRows2 = [sparse(nPosRev,nRxns + nPosIrrev) speye(nPosRev)*-forceOnLim sparse(nPosRev,nNegIrrev + nNegRev + nPosIrrev) speye(nPosRev) speye(nPosRev) sparse(nPosRev,nPosRev) speye(nPosRev)*-1 sparse(nPosRev,nPosRev*2+nNegIrrev+nNegRev*varsPerNegRev+nEssRev*6+nMetVars)];
0268 prRows3 = [sparse(nPosRev,nRxns + nYBlock + nPosIrrev) speye(nPosRev) sparse(nPosRev,nPosRev) speye(nPosRev)*-100 sparse(nPosRev,nPosRev) speye(nPosRev) sparse(nPosRev,nPosRev+nNegIrrev+nNegRev*varsPerNegRev+nEssRev*6+nMetVars)];
0269 prRows4 = [sparse(nPosRev,nRxns + nYBlock + nPosIrrev + nPosRev) speye(nPosRev) speye(nPosRev)*100 sparse(nPosRev,nPosRev*2) speye(nPosRev) sparse(nPosRev, nNegIrrev+nNegRev*varsPerNegRev+nEssRev*6+nMetVars)];
0270 
0271 niRows = [sEye(negIrrevRxns,:) sparse(nNegIrrev,nPosIrrev + nPosRev) speye(nNegIrrev)*-100 sparse(nNegIrrev,nNegRev + nPosIrrev + nPosRev*6) speye(nNegIrrev) sparse(nNegIrrev,nNegRev*varsPerNegRev + nEssRev*6+nMetVars)];
0272 
0273 nrRows1 = [sEye(negRevRxns,:) sparse(nNegRev,nYBlock + nPosIrrev + nPosRev*6 + nNegIrrev) speye(nNegRev)*-1 speye(nNegRev) sparse(nNegRev,nNegRev + nEssRev*6+nMetVars)];
0274 nrRows2 = [sparse(nNegRev,nRxns + nPosIrrev + nPosRev + nNegIrrev) speye(nNegRev)*-100 sparse(nNegRev,nPosIrrev + nPosRev*6 + nNegIrrev) speye(nNegRev) speye(nNegRev) speye(nNegRev) sparse(nNegRev,nEssRev*6+nMetVars)];
0275 nrRows = [nrRows1;nrRows2];
0276 
0277 erRows1 = [sEye(essRevRxns,:) sparse(nEssRev,nYBlock + nPosIrrev + nPosRev*6 + nNegIrrev + nNegRev*varsPerNegRev) speye(nEssRev)*-1 speye(nEssRev) sparse(nEssRev, nEssRev*4+nMetVars)];
0278 erRows2 = [sparse(nEssRev,nRxns + nYBlock + nPosIrrev + nPosRev*6 + nNegIrrev + nNegRev*varsPerNegRev) speye(nEssRev) speye(nEssRev) speye(nEssRev)*-1 sparse(nEssRev, nEssRev*3+nMetVars)];
0279 erRows3 = [sparse(nEssRev,nRxns + nYBlock + nPosIrrev + nPosRev*6 + nNegIrrev + nNegRev*varsPerNegRev) speye(nEssRev) sparse(nEssRev, nEssRev*2) speye(nEssRev)*-100 speye(nEssRev) sparse(nEssRev, nEssRev+nMetVars)];
0280 erRows4 = [sparse(nEssRev,nRxns + nYBlock + nPosIrrev + nPosRev*6 + nNegIrrev + nNegRev*varsPerNegRev + nEssRev) speye(nEssRev) sparse(nEssRev, nEssRev) speye(nEssRev)*100 sparse(nEssRev, nEssRev) speye(nEssRev) sparse(nEssRev, nMetVars)];
0281 
0282 %now the mets
0283 if ~isempty(metData)
0284     %Order of rxn "on" vars: Ypi Ypr Yni Ynr. This is a bit messy, since they are not in the
0285     %same order as the reactions in the S matrix or metData. We therefore resort the vars in
0286     %metData to match the order of the vars.
0287     srtMetData = sparse([metData(:,posIrrevRxns) metData(:,posRevRxns) metData(:,negIrrevRxns) metData(:,negRevRxns)]);
0288     
0289     %First the setup for giving bonus if the met is included.
0290     %The mon vars come first followed by the mv1 vars
0291     metRows1 = [sparse(nMetabolMets,nRxns) -srtMetData sparse(nMetabolMets,  nPosIrrev + nPosRev*6 + nNegIrrev + nNegRev*varsPerNegRev + nEssRev*6) speye(nMetabolMets) speye(nMetabolMets) sparse(nMetabolMets, 4*nMetNegRev + nMetNegIrrev)];
0292     %Then negative rev:
0293     % Variable order: eye(vnrbm),eye(vnrvm1),eye(vnrvm2),eye(vnrvm3)
0294     % vnrp,vnrn are the two first variables among the neg rev vars.
0295     % For reversible, we need a bool to make sure that one of vnrp and vnrn stays zero:
0296     %    vnrbm E {0,1}:  vnrp <= 100*vnrbm (if bool is 0, vnrp is zero): vnrp - 100*vnrbm + vnrvm1 == 0, vnrvm1 >= 0 (metRows2)
0297     %    vnrn <= (1-vnrbm)*100 (if bool is one, vnrn is zero): vnrn + 100*vnrbm + vnrvm2 == 0, -100 <= vnrvm2 <= inf (metRows3)
0298     % We then also say that vnrp + vnrn >= 0.1*Yi, -0.1*Yi + vnrp + vnrn - vnrvm3 == 0, vnrvm3 >= 0 (metRows4)
0299     nrEye = speye(nNegRev);
0300     %vnrp - 100*vnrbm + vnrvm1 == 0
0301     metRows2 = [sparse(nMetNegRev,nRxns + nYBlock + nPosIrrev + nPosRev*6 + nNegIrrev) ... %zeros up to vnrp
0302                 nrEye(metNegRev(negRevRxns),:) ... %vnrp 
0303                 sparse(nMetNegRev, nNegRev*(varsPerNegRev-1) + nEssRev*6 + nMetabolMets*2) ... %zeros up to vnrbm
0304                 speye(nMetNegRev)*-100 ... %vnrbm
0305                 speye(nMetNegRev) ... % vnrvm1
0306                 sparse(nMetNegRev, nMetNegRev*2 + nMetNegIrrev)];%fill up the rest with zeros
0307     %vnrn + 100*vnrbm + vnrvm2 == 0
0308     metRows3 = [sparse(nMetNegRev,nRxns + nYBlock + nPosIrrev + nPosRev*6 + nNegIrrev + nNegRev) ... %zeros up to vnrn
0309                 nrEye(metNegRev(negRevRxns),:) ... %vnrp 
0310                 sparse(nMetNegRev, nNegRev*(varsPerNegRev-2) + nEssRev*6 + nMetabolMets*2) ... %zeros up to vnrbm
0311                 speye(nMetNegRev)*100 ... %vnrbm
0312                 sparse(nMetNegRev, nMetNegRev) ... %zeros up to vnrvm2
0313                 speye(nMetNegRev) ... % vnrvm2
0314                 sparse(nMetNegRev, nMetNegRev + nMetNegIrrev)];%fill up the rest with zeros
0315     %-0.1*Yi + vnrp + vnrn - vnrvm3 == 0
0316     metRows4 = [sparse(nMetNegRev,nRxns + nPosIrrev + nPosRev + nNegIrrev) ... %zeros up to Yi for neg rev
0317                 nrEye(metNegRev(negRevRxns),:)*-0.1 ... %Yi for met neg rev
0318                 sparse(nMetNegRev, nPosIrrev + nPosRev*6 + nNegIrrev) ... %zeros up to vnrp
0319                 nrEye(metNegRev(negRevRxns),:) ... %vnrp
0320                 nrEye(metNegRev(negRevRxns),:) ... %vnrn
0321                 sparse(nMetNegRev, nNegRev*(varsPerNegRev-2) + nEssRev*6 + nMetabolMets*2 + nMetNegRev*3) ...%zeros up to vnrvm3
0322                 speye(nMetNegRev)*-1 ... % vnrvm3
0323                 sparse(nMetNegRev, nMetNegIrrev)];%fill up the rest with zeros
0324     
0325     %Then negative irrev, i.e. flux - 0.1*Yi - vnim == 0
0326     niEye = speye(nNegIrrev);
0327     metRows5 = [sEye(metNegIrrev,:) ... %flux
0328                 sparse(nMetNegIrrev, nPosIrrev + nPosRev) ... % zeros up to Yi for neg irrev
0329                 niEye(metNegIrrev(negIrrevRxns),:)*-0.1 ... %Yi for met neg irrev
0330                 sparse(nMetNegIrrev, nNegRev + nPosIrrev + nPosRev*6 + nNegIrrev + nNegRev*varsPerNegRev + nEssRev*6 + nMetabolMets*2 + 4*nMetNegRev) ... %zeros up to vnim
0331                 -speye(nMetNegIrrev) ]; %vnim
0332     metRows = [metRows1;metRows2;metRows3;metRows4;metRows5];
0333     metVarC = [ones(nMetabolMets,1)*-prodWeight;zeros(nMetVars - nMetabolMets,1)];
0334     %vnrbm is boolean, so between 0 and 1
0335     %vnrvm1 >= 0
0336     %-100 <= vnrvm2 <= inf
0337     % vnrvm3 >= 0
0338     %0 <= vnim <= Inf
0339     metLb = [zeros(nMetabolMets*2 + 2*nMetNegRev,1);ones(nMetNegRev,1)*-100;zeros(nMetNegRev + nMetNegIrrev,1)];
0340     metUb = [ones(nMetabolMets,1);inf(nMetabolMets,1);ones(nMetNegRev,1);inf(3*nMetNegRev + nMetNegIrrev,1)];
0341     metVartype = [repmat('C', 1, nMetabolMets*2), ...
0342                   repmat('B', 1, nMetNegRev), ...
0343                   repmat('C', 1, 3*nMetNegRev + nMetNegIrrev)];
0344 
0345 else
0346     metRows = [];
0347     metVarC = [];
0348     metLb = [];
0349     metUb = [];
0350     metVartype = [];
0351 end
0352 
0353 prob.a = [sRow;piRows;prRows1;prRows2;prRows3;prRows4;niRows;nrRows;erRows1;erRows2;erRows3;erRows4;metRows];
0354 prob.A = prob.a;
0355 prob.b = zeros(size(prob.A,1),1);
0356 prob.c = [zeros(nRxns,1);rxnScores(posIrrevRxns)*-1;rxnScores(posRevRxns)*-1;rxnScores(negIrrevRxns)*-1;rxnScores(negRevRxns)*-1;zeros(nPosIrrev + nPosRev*6 + nNegIrrev + nNegRev*varsPerNegRev + nEssRev*6,1);metVarC];
0357 prob.lb = [milpModel.lb;zeros(nYBlock + nPosIrrev + 5*nPosRev,1);ones(nPosRev,1)*-100;zeros(nNegIrrev+nNegRev*varsPerNegRev+nEssRev*2,1);ones(nEssRev,1)*forceOnLim;zeros(nEssRev*2,1);ones(nEssRev,1)*-100;metLb];
0358 prob.lb(essIrrevRxns) = forceOnLimEss(essIrrevRxns);%force flux for the ess irrev rxns - this is the only way these are handled
0359 prob.ub = [milpModel.ub;ones(nYBlock,1);inf(nPosIrrev+nPosRev*2,1);ones(nPosRev,1);inf(3*nPosRev+nNegIrrev+varsPerNegRev*nNegRev+3*nEssRev,1);ones(nEssRev,1);inf(2*nEssRev,1);metUb];
0360 
0361 prob.vartype = [repmat('C', 1, nRxns + nPosIrrev + nPosRev), ...
0362                 repmat('B', 1, nNegIrrev + nNegRev), ...
0363                 repmat('C', 1, nPosIrrev + 2*nPosRev), ... 
0364                 repmat('B', 1, nPosRev), ...
0365                 repmat('C', 1, 3*nPosRev + nNegIrrev + varsPerNegRev*nNegRev + 3*nEssRev), ...
0366                 repmat('B', 1, nEssRev), ...
0367                 repmat('C', 1, 2*nEssRev), ...
0368                 metVartype];
0369             
0370 onoffVarInd = (1:(nPosIrrev + nPosRev + nNegIrrev + nNegRev)) + nRxns;
0371 onoffPosIrrev = onoffVarInd(1:nPosIrrev);
0372 onoffPosRev = onoffVarInd((1:nPosRev)+nPosIrrev);
0373 onoffNegIrrev = onoffVarInd((1:nNegIrrev)+nPosIrrev+nPosRev);
0374 onoffNegRev = onoffVarInd((1:nNegRev)+nPosIrrev+nPosRev+nNegIrrev);
0375 
0376 metVarInd = (1:nMetabolMets) + (length(prob.vartype) - nMetVars);
0377 
0378 if allowExcretion
0379     prob.csense = [repmat('L', 1, length(milpModel.mets)), ...
0380                   repmat('E', 1, length(prob.b) - length(milpModel.mets))];
0381 else
0382     prob.csense = '=';
0383 end
0384 
0385 params.intTol = 10^-7; %This value is very important. If set too low
0386                        %there is a risk that gurobi fails due to numerical
0387                        %issues - this happened for Gurobi v. 10.0 with TestModelL.
0388                        %On the other hand, it shouldn't be too large
0389                        %either. With this value, fluxes of 10-7 can slip
0390                        %through, which should be fine. Another option if
0391                        %this becomes a problem is to set NumericFocus=2,
0392                        %which makes the solver slower but fixes the issue
0393                        %with TestModelL.
0394 
0395 prob.osense = 1; %minimize
0396 
0397 if ~isempty(startVals)
0398      prob.start = startVals; %This doesn't work...
0399 end
0400 
0401 res=optimizeProb(prob,params,verbose);
0402 
0403 
0404 if ~checkSolution(res)
0405     if strcmp(res.origStat, 'TIME_LIMIT')
0406         EM='Time limit reached without finding a solution. Try increasing the TimeLimit parameter.';
0407     else
0408         EM='The problem is infeasible';
0409     end
0410     dispEM(EM);
0411 end
0412 
0413 %get the on/off vals
0414 onoff = ones(nRxnsWithOnOff,1);%standard is on, i.e. all reactions not included in the problem + ess is on
0415 onoff(posIrrevRxns) = res.full(onoffPosIrrev);
0416 onoff(posRevRxns) = res.full(onoffPosRev);
0417 onoff(negIrrevRxns) = res.full(onoffNegIrrev);
0418 onoff(negRevRxns) = res.full(onoffNegRev);
0419 
0420 onoff2 = zeros(nRxnsWithOnOff,1);%standard is off, i.e. all reactions not included in the problem + ess is off
0421 onoff2(posIrrevRxns) = res.full(onoffPosIrrev);
0422 onoff2(posRevRxns) = res.full(onoffPosRev);
0423 onoff2(negIrrevRxns) = res.full(onoffNegIrrev);
0424 onoff2(negRevRxns) = res.full(onoffNegRev);
0425 
0426 
0427 %investigate a bit - this code could be used for fault finding. We have
0428 %this code commented out, but it is definitely worth testing this if for example
0429 %the solver is changed.
0430 %problematic = onoff < 0.99 & onoff > 0.01 & (rxnScores ~= 0).';
0431 %if sum(problematic) > 0
0432 %    disp('There are reactions that are in between on and off in the MILP. This may be due to the MILP parameter settings, the tolerances may be too large.')
0433 %    disp(['No problematic reactions: ', num2str(sum(problematic))])
0434 %end
0435 
0436 %so, it is only positive that are problematic. Likely because the 0.1 is too large. Test to change to 0.01
0437 %unique(onoff(onoff < 0.99 & onoff > 0.01))
0438 
0439 %Get all reactions used in the irreversible model
0440 %The reaction score check is for metabolomics - we add those reactions as
0441 %positive even though the score is 0. And, we don't want them included in the
0442 %results.
0443 deletedRxns=(onoff < 0.5).' & (rxnScores ~= 0).'; 
0444 turnedOnRxns=(onoff2 >= 0.5).' & (rxnScores ~= 0).';
0445 
0446 fluxes = res.full(1:nRxns);
0447 
0448 %extract the met data
0449 metProduction = logical(round(res.full(metVarInd)));
0450 
0451 end

Generated by m2html © 2005