solveCobraLPCPLEX

PURPOSE ^

[solution,LPProblem]=solveCobraLPCPLEX(LPProblem,printLevel,basisReuse,conflictResolve,contFunctName,minNorm)

SYNOPSIS ^

function [solution,LPProblem]=solveCobraLPCPLEX(LPProblem,printLevel,basisReuse,conflictResolve,contFunctName,minNorm)

DESCRIPTION ^

 [solution,LPProblem]=solveCobraLPCPLEX(LPProblem,printLevel,basisReuse,conflictResolve,contFunctName,minNorm)
 call CPLEX to solve an LP problem
 By default, use the matlab interface to cplex written by TOMLAB, in
 preference to the one written by ILOG.
 
INPUT
 LPproblem Structure containing the following fields describing the LP
 problem to be solved
  A or S       m x n LHS matrix
  b            m x 1 RHS vector
  c            n x 1 Objective coeff vector
  lb           n x 1 Lower bound vector
  ub           n x 1 Upper bound vector
  osense       scalar Objective sense (-1 max, +1 min)

OPTIONAL INPUT
 LPProblem.rxns    cell array of reaction abbreviations (necessary for
                   making a readable confilict resolution file).
 LPProblem.csense  Constraint senses, a string containting the constraint sense for
                   each row in A ('E', equality, 'G' greater than, 'L' less than).

 LPProblem.LPBasis Basis from previous solution of similar LP problem. 
                   See basisReuse

 PrintLevel    Printing level in the CPLEX m-file and CPLEX C-interface.
               = 0    Silent 
               = 1    Warnings and Errors
               = 2    Summary information (Default)
               = 3    More detailed information
               > 10   Pause statements, and maximal printing (debug mode)

 basisReuse = 0   Use this for one of soluion of an LP (Default)
            = 1   Returns a basis for reuse in the next LP 
                  i.e. outputs LPProblem.LPBasis

 conflictResolve  = 0   (Default)
                  = 1   If LP problem is proven to be infeasible by CPLEX,
                        it will print out a 'conflict resolution file', 
                        which indicates the irreducible infeasible set of
                        equaltiy & inequality constraints that together, 
                        combine to make the problem infeasible. This is 
                        useful for debugging an LP problem if you want to
                        try to resolve a constraint conflict

 contFunctName        = [] Use all default CLPEX control parameters, (Default)
                      = someString e.g. 'someFunctionName'
                        uses the user specified control parameters defined
                        in someFunctionName.m
                       (see template function CPLEXParamSet for details).
                      = cpxControl structure (output from a file like CPLEXParamSet.m)

 minNorm       {(0), 1 , n x 1 vector} If not zero then, minimise the Euclidean length 
               of the solution to the LP problem. Gives the same objective,
               but minimises the square of flux. minNorm ~1e-6 should be
               high enough for regularisation yet keep the same objective

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [solution,LPProblem]=solveCobraLPCPLEX(LPProblem,printLevel,basisReuse,conflictResolve,contFunctName,minNorm)
0002 % [solution,LPProblem]=solveCobraLPCPLEX(LPProblem,printLevel,basisReuse,conflictResolve,contFunctName,minNorm)
0003 % call CPLEX to solve an LP problem
0004 % By default, use the matlab interface to cplex written by TOMLAB, in
0005 % preference to the one written by ILOG.
0006 %
0007 %INPUT
0008 % LPproblem Structure containing the following fields describing the LP
0009 % problem to be solved
0010 %  A or S       m x n LHS matrix
0011 %  b            m x 1 RHS vector
0012 %  c            n x 1 Objective coeff vector
0013 %  lb           n x 1 Lower bound vector
0014 %  ub           n x 1 Upper bound vector
0015 %  osense       scalar Objective sense (-1 max, +1 min)
0016 %
0017 %OPTIONAL INPUT
0018 % LPProblem.rxns    cell array of reaction abbreviations (necessary for
0019 %                   making a readable confilict resolution file).
0020 % LPProblem.csense  Constraint senses, a string containting the constraint sense for
0021 %                   each row in A ('E', equality, 'G' greater than, 'L' less than).
0022 %
0023 % LPProblem.LPBasis Basis from previous solution of similar LP problem.
0024 %                   See basisReuse
0025 %
0026 % PrintLevel    Printing level in the CPLEX m-file and CPLEX C-interface.
0027 %               = 0    Silent
0028 %               = 1    Warnings and Errors
0029 %               = 2    Summary information (Default)
0030 %               = 3    More detailed information
0031 %               > 10   Pause statements, and maximal printing (debug mode)
0032 %
0033 % basisReuse = 0   Use this for one of soluion of an LP (Default)
0034 %            = 1   Returns a basis for reuse in the next LP
0035 %                  i.e. outputs LPProblem.LPBasis
0036 %
0037 % conflictResolve  = 0   (Default)
0038 %                  = 1   If LP problem is proven to be infeasible by CPLEX,
0039 %                        it will print out a 'conflict resolution file',
0040 %                        which indicates the irreducible infeasible set of
0041 %                        equaltiy & inequality constraints that together,
0042 %                        combine to make the problem infeasible. This is
0043 %                        useful for debugging an LP problem if you want to
0044 %                        try to resolve a constraint conflict
0045 %
0046 % contFunctName        = [] Use all default CLPEX control parameters, (Default)
0047 %                      = someString e.g. 'someFunctionName'
0048 %                        uses the user specified control parameters defined
0049 %                        in someFunctionName.m
0050 %                       (see template function CPLEXParamSet for details).
0051 %                      = cpxControl structure (output from a file like CPLEXParamSet.m)
0052 %
0053 % minNorm       {(0), 1 , n x 1 vector} If not zero then, minimise the Euclidean length
0054 %               of the solution to the LP problem. Gives the same objective,
0055 %               but minimises the square of flux. minNorm ~1e-6 should be
0056 %               high enough for regularisation yet keep the same objective
0057 
0058 %OUTPUT
0059 % solution Structure containing the following fields describing a LP
0060 % solution
0061 %  full         Full LP solution vector
0062 %  obj          Objective value
0063 %  rcost        Lagrangian multipliers to the simple inequalties (Reduced costs)
0064 %  dual         Lagrangian multipliers to the equalities
0065 %  nInfeas      Number of infeasible constraints
0066 %  sumInfeas    Sum of constraint violation
0067 %  stat         COBRA Standardized solver status code:
0068 %               1   Optimal solution
0069 %               2   Unbounded solution
0070 %               0   Infeasible
0071 %               -1  No solution reported (timelimit, numerical problem etc)
0072 %  origStat     CPLEX status code. Use cplexStatus(solution.origStat) for
0073 %               more information from the CPLEX solver
0074 %  solver       solver used by cplex
0075 %  time         time taken to solve the optimization problem
0076 %
0077 %OPTIONAL OUTPUT
0078 % LPProblem.LPBasis When input basisReuse=1, we return a basis for reuse in
0079 %                   the next LP
0080 %
0081 % CPLEX consists of 4 different LP solvers which can be used to solve sysbio optimization problems
0082 % you can control which of the solvers, e.g. simplex vs interior point solver using the
0083 % CPLEX control parameter cpxControl.LPMETHOD. At the moment, the solver is
0084 % automatically chosen for you
0085 %
0086 % Ronan Fleming 10 June 08
0087 %               20 Mar  09  min norm can be specific to each variable
0088 %               12 Jul  09  more description of basis reuse
0089 %               23 Oct  09  ILOG-CPLEX matlab simple interface by default
0090 %                           See solveCobraCPLEX for full control of CPLEX
0091 %                           12.1 via API
0092 
0093 if ~exist('printLevel','var')
0094     printLevel=2;
0095 end
0096 if ~exist('basisReuse','var')
0097     basisReuse=0;
0098 end
0099 if ~exist('conflictResolve','var')
0100     conflictResolve=0;
0101 end
0102 if ~exist('contFunctName','var')
0103     cpxControl=[];
0104 else
0105     if isstruct(contFunctName)
0106         cpxControl=contFunctName;
0107     else
0108         if ~isempty(contFunctName)
0109             %calls a user specified function to create a CPLEX control structure
0110             %specific to the users problem. A TEMPLATE for one such function is
0111             %CPLEXParamSet
0112             cpxControl=eval(contFunctName);
0113         else
0114             cpxControl=[];
0115         end
0116     end
0117 end
0118 if ~exist('minNorm','var')
0119     minNorm=0;
0120 end
0121 
0122 if basisReuse
0123     if isfield(LPProblem,'LPBasis')
0124         basis=LPProblem.LPBasis;
0125         %use advanced starting information when optimization is initiated.
0126         cpxControl.ADVIND=1;
0127     else
0128         basis=[];
0129     end
0130 else
0131     basis=[];
0132     %do not use advanced starting information when optimization is initiated.
0133     cpxControl.ADVIND=0;
0134 end
0135 
0136 if ~isfield(LPProblem,'A')
0137     if ~isfield(LPProblem,'S')
0138             error('Equality constraint matrix must either be a field denoted A or S.')
0139     end
0140     LPProblem.A=LPProblem.S;
0141 end
0142 
0143 if ~isfield(LPProblem,'csense')
0144     nMet=size(LPProblem.A);
0145     if printLevel>0
0146         fprintf('%s\n','Assuming equality constraints, i.e. S*v=b');
0147     end
0148     %assuming equality constraints
0149     LPProblem.csense(1:nMet,1)='E';
0150 end
0151     
0152 if ~isfield(LPProblem,'osense')
0153     %assuming maximisation
0154     LPProblem.osense=-1;
0155     if printLevel>0
0156         fprintf('%s\n','Assuming maximisation of objective');
0157     end
0158 end
0159 
0160 %get data
0161 [c,x_L,x_U,b,csense,osense] = deal(LPProblem.c,LPProblem.lb,LPProblem.ub,LPProblem.b,LPProblem.csense,LPProblem.osense);
0162 %modify objective to correspond to osense
0163 c=full(c*osense);
0164 
0165 %cplex expects it dense
0166 b=full(b);
0167 %Conflict groups descriptor (cpxBuildConflict can be used to generate the input). Set this if
0168 %conflict refinement is desired in the case that infeasibility is detected
0169 %by CPLEX.
0170 if conflictResolve
0171     [m_lin,n]=size(LPProblem.A);
0172     m_quad=0;
0173     m_sos=0;
0174     m_log=0;
0175     %determines how elaborate the output is
0176     mode='full';%'minimal';
0177     fprintf('%s\n%s\n','Building Structure for Conflict Resolution...','...this slows CPLEX down so should not be used for repeated LP');
0178     confgrps = cpxBuildConflict(n,m_lin,m_quad,m_sos,m_log,mode);
0179     prefix=pwd;
0180     suffix='LP_CPLEX_conflict_file.txt';
0181     conflictFile=[prefix '\' suffix];
0182 else
0183     confgrps=[]; conflictFile=[];
0184 end
0185 
0186 %Name of file to write the CPLEX log information to. If empty, no log is
0187 %written.
0188 logfile=[];
0189 
0190 %Name of a file to save the CPLEX problem object (Used for submitting
0191 %possible bugs in CPLEX to ILOG)
0192 savefile=[]; savemode=[];
0193 % savefile='C:\CPLEX_possible_bug.txt';
0194 
0195 % vector defining which callbacks to use in CPLEX. If the ith entry of the logical vector
0196 % callback is set, the corresponding callback is defined. The callback calls the m-file specified
0197 % in Table 7 below. The user may edit this file, or make a new copy, which is put in a directory
0198 % that is searched before the cplex directory in the Matlab path.
0199 callback=[]; %I'm not really sure what this option means as yet
0200 
0201 %this is not a tomlab problem so this is not needed
0202 Prob=[];
0203 
0204 % variables not used in LP problems
0205 IntVars=[]; PI=[]; SC=[]; SI=[]; sos1=[]; sos2=[];
0206 
0207 %quadratic constraint matrix, size n x n
0208 if sum(minNorm)~=0
0209     if length(minNorm)==1
0210         % same weighting of min norm for all variables
0211         F=speye(length(c))*minNorm;
0212     else
0213         if length(minNorm)~=length(c)
0214             error('Either minNorm is a scalar, or is an n x 1 vector')
0215         else
0216             % individual weighting of min norm for all variables
0217             F=spdiags(minNorm,0,length(c),length(c));
0218         end
0219     end
0220 else
0221     F=[];
0222 end
0223 %Structure array defining quadratic constraints
0224 qc=[];
0225 
0226 %Structure telling whether and how you want CPLEX to perform a sensitivity analysis (SA).
0227 %This may be useful in future but probably will have more meaning with an
0228 %additional term in the objective
0229 saRequest =[];
0230 
0231 %Vector with MIP starting solution, if known
0232 xIP=[];
0233 
0234 %Logical constraints, i.e. an additional set of single-sided linear constraints that are controlled
0235 %by a binary variable (switch) in the problem
0236 logcon=[];
0237    
0238 %call cplex
0239 tic;
0240 %tic;
0241 %by default use the complex ILOG-CPLEX interface
0242 ILOGcomplex=1;
0243 tomlab_cplex=1; %by default use the tomlab_cplex interface
0244 if ~isempty(which('cplexlp')) && tomlab_cplex==0
0245     if ILOGcomplex
0246         %complex ibm ilog cplex interface
0247         if ~isempty(csense)
0248             %set up constant vectors for CPLEX
0249             b_L(csense == 'E',1) = b(csense == 'E');
0250             b_U(csense == 'E',1) = b(csense == 'E');
0251             b_L(csense == 'G',1) = b(csense == 'G');
0252             b_U(csense == 'G',1) = Inf;
0253             b_L(csense == 'L',1) = -Inf;
0254             b_U(csense == 'L',1) = b(csense == 'L');
0255         else
0256             b_L = b;
0257             b_U = b;
0258         end
0259 
0260         
0261         % Initialize the CPLEX object
0262         try
0263             ILOGcplex = Cplex('fba');
0264         catch ME
0265             error('CPLEX not installed or licence server not up')
0266         end
0267 
0268         ILOGcplex.Model.sense = 'minimize';
0269         
0270         % Now populate the problem with the data
0271         ILOGcplex.Model.obj   = c;
0272         ILOGcplex.Model.lb    = x_L;
0273         ILOGcplex.Model.ub    = x_U;
0274         ILOGcplex.Model.A     = LPProblem.A;
0275         ILOGcplex.Model.lhs   = b_L;
0276         ILOGcplex.Model.rhs   = b_U;
0277 
0278         if ~isempty(F)
0279             %quadratic constraint matrix, size n x n
0280             ILOGcplex.Model.Q=F;
0281         end
0282 
0283         if ~isempty(cpxControl)
0284             if isfield(cpxControl,'LPMETHOD')
0285                 %set the solver
0286                 ILOGcplex.Param.lpmethod.Cur=cpxControl.LPMETHOD;
0287             end
0288         end
0289         
0290         if printLevel==0
0291             ILOGcplex.DisplayFunc=[];
0292         else
0293             %print level
0294             ILOGcplex.Param.barrier.display.Cur = printLevel;
0295             ILOGcplex.Param.simplex.display.Cur = printLevel;
0296             ILOGcplex.Param.sifting.display.Cur = printLevel;
0297         end
0298         
0299         % Optimize the problem
0300         ILOGcplex.solve();
0301 
0302         solution.obj        = osense*ILOGcplex.Solution.objval;
0303         solution.full       = ILOGcplex.Solution.x;
0304         solution.rcost      = ILOGcplex.Solution.reducedcost;
0305         solution.dual       = ILOGcplex.Solution.dual;
0306         solution.nInfeas    = NaN;
0307         solution.sumInfeas  = NaN;
0308         %solution.stat       = ILOGcplex.Solution.
0309         solution.origStat   = ILOGcplex.Solution.status;
0310         solution.solver     = ILOGcplex.Solution.method;
0311         solution.time       = ILOGcplex.Solution.time;
0312     else
0313         try
0314            ILOGcplex = Cplex('fba');
0315         catch ME
0316             error('CPLEX not installed or licence server not up')
0317         end
0318         %simple ibm ilog cplex interface
0319         options = cplexoptimset;
0320         switch printLevel
0321             case 0
0322                 options = cplexoptimset(options,'Display','off');
0323             case 1
0324                 options = cplexoptimset(options,'Display','off');
0325                 case 1
0326                 options = cplexoptimset(options,'Display','off');
0327             case 1
0328                 options = cplexoptimset(options,'Display','off');
0329         end
0330                 
0331         if ~isempty(csense)
0332             if sum(minNorm)~=0
0333                 Aineq = [LPProblem.A(csense == 'L',:); - LPProblem.A(csense == 'G',:)];
0334                 bineq = [b(csense == 'L',:); - b(csense == 'G',:)];
0335                 %             min      0.5*x'*H*x+f*x or f*x
0336                 %             st.      Aineq*x     <= bineq
0337                 %             Aeq*x    = beq
0338                 %             lb <= x <= ub
0339                 [x,fval,exitflag,output,lambda] = cplexqp(F,c,Aineq,bineq,LPProblem.A(csense == 'E',:),b(csense == 'E',1),x_L,x_U,[],options);
0340             else
0341                 Aineq = [LPProblem.A(csense == 'L',:); - LPProblem.A(csense == 'G',:)];
0342                 bineq = [b(csense == 'L',:); - b(csense == 'G',:)];
0343                 %        min      c*x
0344                 %        st.      Aineq*x <= bineq
0345                 %                 Aeq*x    = beq
0346                 %                 lb <= x <= ub
0347                 [x,fval,exitflag,output,lambda] = cplexlp(c,Aineq,bineq,LPProblem.A(csense == 'E',:),b(csense == 'E',1),x_L,x_U,[],options);
0348             end
0349             %primal
0350             solution.obj=osense*fval;
0351             solution.full=x;
0352             %this is the dual to the equality constraints but it's not the chemical potential
0353             solution.dual=lambda.eqlin;
0354         else
0355             Aineq=[];
0356             bineq=[];
0357             if sum(minNorm)~=0
0358                 [x,fval,exitflag,output,lambda] = cplexqp(F,c,Aineq,bineq,LPProblem.A,b,x_L,x_U,[],options);
0359             else
0360                 [x,fval,exitflag,output,lambda] = cplexlp(c,Aineq,bineq,LPProblem.A,b,x_L,x_U,[],options);
0361             end
0362             solution.obj=osense*fval;
0363             solution.full=x;
0364             %this is the dual to the equality constraints but it's not the chemical potential
0365             solution.dual=sparse(size(LPProblem.A,1),1);
0366             solution.dual(csense == 'E')=lambda.eqlin;
0367             %this is the dual to the inequality constraints but it's not the chemical potential
0368             solution.dual(csense == 'L')=lambda.ineqlin(1:nnz(csense == 'L'),1);
0369             solution.dual(csense == 'G')=lambda.ineqlin(nnz(csense == 'L')+1:end,1);
0370         end
0371         %this is the dual to the simple ineequality constraints : reduced costs
0372         solution.rcost=lambda.lower-lambda.upper;
0373         solution.nInfeas = [];
0374         solution.sumInfeas = [];
0375         solution.origStat = output.cplexstatus;
0376     end
0377     %1 = (Simplex or Barrier) Optimal solution is available.
0378     Inform = solution.origStat;
0379     
0380 else
0381     %tomlab cplex interface
0382     if ~isempty(csense)
0383         %set up constant vectors for CPLEX
0384         b_L(csense == 'E',1) = b(csense == 'E');
0385         b_U(csense == 'E',1) = b(csense == 'E');
0386         b_L(csense == 'G',1) = b(csense == 'G');
0387         b_U(csense == 'G',1) = Inf;
0388         b_L(csense == 'L',1) = -Inf;
0389         b_U(csense == 'L',1) = b(csense == 'L');
0390     else
0391         b_L = b;
0392         b_U = b;
0393     end
0394 
0395     %tomlab cplex interface
0396     %   minimize   0.5 * x'*F*x + c'x     subject to:
0397     %      x             x_L <=    x   <= x_U
0398     %                    b_L <=   Ax   <= b_U
0399     [x, slack, v, rc, f_k, ninf, sinf, Inform, basis] = cplex(c, LPProblem.A, x_L, x_U, b_L, b_U, ...
0400         cpxControl, callback, printLevel, Prob, IntVars, PI, SC, SI, ...
0401         sos1, sos2, F, logfile, savefile, savemode, qc, ...
0402         confgrps, conflictFile, saRequest, basis, xIP, logcon);
0403 
0404     solution.full=x;
0405     %this is the dual to the equality constraints but it's not the chemical potential
0406     solution.dual=v;
0407     %this is the dual to the simple ineequality constraints : reduced costs
0408     solution.rcost=rc;
0409     if Inform~=1
0410         solution.obj = NaN;
0411     else
0412         if minNorm==0
0413             solution.obj=f_k*osense;
0414         else
0415             solution.obj=c'*x*osense;
0416         end
0417         %     solution.obj
0418         %     norm(x)
0419     end
0420     solution.nInfeas = ninf;
0421     solution.sumInfeas = sinf;
0422     solution.origStat = Inform;
0423 end
0424 %timeTaken=toc;
0425 timeTaken=NaN;
0426 
0427 if Inform~=1 && ~isempty(which('cplex'))
0428     if conflictResolve ==1
0429         if isfield(LPProblem,'mets') && isfield(LPProblem,'rxns')
0430             %this code reads the conflict resolution file and replaces the
0431             %arbitrary names with the abbreviations of metabolites and reactions
0432             [nMet,nRxn]=size(LPProblem.A);
0433             totAbbr=nMet+nRxn;
0434             conStrFind=cell(nMet+nRxn,1);
0435             conStrReplace=cell(nMet+nRxn,1);
0436             %only equality constraint rows
0437             for m=1:nMet
0438                 conStrFind{m,1}=['c' int2str(m) ':'];
0439                 conStrReplace{m,1}=[LPProblem.mets{m} ':  '];
0440             end
0441             %reactions
0442             for n=1:nRxn
0443                 conStrFind{nMet+n,1}=['x' int2str(n) ' '];
0444                 conStrReplace{nMet+n,1}=[LPProblem.rxns{n} ' '];
0445             end
0446             fid1 = fopen(suffix);
0447             fid2 = fopen(['COBRA_' suffix], 'w');
0448             while ~feof(fid1)
0449                 tline{1}=fgetl(fid1);
0450                 %replaces all occurrences of the string str2 within string str1
0451                 %with the string str3.
0452                 %str= strrep(str1, str2, str3)
0453                 for t=1:totAbbr
0454                     tline= strrep(tline, conStrFind{t}, conStrReplace{t});
0455                 end
0456                 fprintf(fid2,'%s\n', tline{1});
0457             end
0458             fclose(fid1);
0459             fclose(fid2);
0460             %delete other file without replacements
0461             %         delete(suffix)
0462         else
0463             warning('Need reaction and metabolite abbreviations in order to make a readable conflict resolution file');
0464         end
0465         fprintf('%s\n',['Conflict resolution file written to: ' prefix '\COBRA_' suffix]);
0466         fprintf('%s\n%s\n','The Conflict resolution file gives an irreducible infeasible subset ','of constraints which are making this LP Problem infeasible');
0467     else
0468         if printLevel>0
0469             fprintf('%s\n','No conflict resolution file. Perhaps set conflictResolve = 1 next time.');
0470         end
0471     end
0472     solution.solver = 'cplex_direct';
0473 end
0474 
0475 % Try to give back COBRA Standardized solver status:
0476 %           1   Optimal solution
0477 %           2   Unbounded solution
0478 %           0   Infeasible
0479 %           -1  No solution reported (timelimit, numerical problem etc)
0480 if Inform==1
0481     solution.stat = 1;
0482     if printLevel>0
0483     %use tomlab code to print out exit meassage
0484     [ExitText,ExitFlag] = cplexStatus(Inform);
0485     solution.ExitText=ExitText;
0486     solution.ExitFlag=ExitFlag;
0487     fprintf('\n%s%g\n',[ExitText ', Objective '],  c'*solution.full*osense);
0488     end
0489 else
0490     if Inform==2
0491         solution.stat = 2;
0492         %use tomlab code to print out exit meassage
0493         [ExitText,ExitFlag] = cplexStatus(Inform);
0494         solution.ExitText=ExitText;
0495         solution.ExitFlag=ExitFlag;
0496         fprintf('\n%s%g\n',[ExitText ', Objective '],  c'*solution.full*osense);
0497     else
0498         if Inform==3
0499             solution.stat = 0;
0500         else
0501             %this is a conservative view
0502             solution.stat = -1;
0503             %use tomlab code to print out exit meassage
0504             [ExitText,ExitFlag] = cplexStatus(Inform);
0505             solution.ExitText=ExitText;
0506             solution.ExitFlag=ExitFlag;
0507             fprintf('\n%s%g\n',[ExitText ', Objective '],  c'*solution.full*osense);
0508         end
0509     end
0510 end
0511 solution.time = timeTaken;
0512 
0513 %return basis
0514 if basisReuse
0515     LPProblem.LPBasis=basis;
0516 end
0517 
0518 if sum(minNorm)~=0
0519     fprintf('%s\n','This objective corresponds to a flux with minimum Euclidean norm.');
0520     fprintf('%s%d%s\n','The weighting for minimising the norm was ',minNorm,'.');
0521     fprintf('%s\n','Check that the objective is the same without minimising the norm.');
0522 end

Generated on Thu 21-Jun-2012 15:39:23 by m2html © 2003