Skip to content

Commit efb2c06

Browse files
authored
Merge pull request #1477 from opencobra/develop
Regular merge of develop
2 parents 2ed83d1 + 177535e commit efb2c06

File tree

65 files changed

+10459
-128
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+10459
-128
lines changed

deprecated/OMNI.m

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
function [OMNISol,bilevelMILPProblem] = OMNI(model, selectedRxnList, options, constrOpt, measOpt, prevSolutions, verbFlag)
2+
%
3+
%% ***********************NOT WORKING**************************************
4+
%
5+
6+
%function [OMNISol,bilevelMILPProblem] = OMNI(model,selectedRxnList,options,constrOpt,prevSolutions,verbFlag,solutionFileNameTmp)
7+
8+
%OMNI Run OMNI in the most general form
9+
%
10+
% OMNI(model,selectedRxnList,options,constrOpt,prevSolutions,verbFlag,solutionFileName)
11+
%
12+
%INPUTS
13+
% model Structure containing all necessary variables to
14+
% describe a stoichiometric model
15+
% rxns Rxns in the model
16+
% mets Metabolites in the model
17+
% S Stoichiometric matrix (sparse)
18+
% b RHS of Sv = b (usually zeros)
19+
% c Objective coefficients
20+
% lb Lower bounds for fluxes
21+
% ub Upper bounds for fluxes
22+
% rev Reversibility of fluxes
23+
% selectedRxnList List of reactions that can be knocked-out in OMNI
24+
% options OMNI options
25+
% numDel # of bottlenecks
26+
% numDelSense Direction of # of bottleneck constraint (G/E/L)
27+
% vMax Max flux
28+
% solveOMNI Solve problem within Matlab
29+
% createGams Create GAMS input file
30+
% gamsFile GAMS input file name
31+
% constrOpt Explicitly constrained reaction options
32+
% rxnList Reaction list
33+
% values Values for constrained reactions
34+
% sense Constraint senses for constrained reactions
35+
% (G/E/L)
36+
% measOpt Measured flux options
37+
% rxnSel Names of measured reactions
38+
% values Flux values of measured reactions
39+
% weights Weights for measured fluxes
40+
%
41+
%OPTIONAL INPUTS
42+
% prevSolutions Previous solutions
43+
% verbFlag Verbose flag
44+
% solutionFileName File name for storing temporary solutions
45+
%
46+
%OUTPUTS
47+
% OMNISol OMNI solution structure
48+
% bilevelMILPProblem bi-level MILP problem structure used
49+
%
50+
% Markus Herrgard 3/28/05
51+
52+
% Set these for MILP callbacks
53+
global MILPproblemType;
54+
global selectedRxnIndIrrev;
55+
%global rxnList;
56+
global irrev2rev;
57+
%global solutionFileName;
58+
%global biomassRxnID;
59+
%global OMNIKOrxnList;
60+
%global OMNIObjective;
61+
%global OMNIGrowth;
62+
%global solID;
63+
64+
if (nargin < 5)
65+
prevSolutions = [];
66+
end
67+
if (nargin < 6)
68+
verbFlag = false;
69+
end
70+
% if (nargin < 7)
71+
% solutionFileName = 'OMNISolutions.mat';
72+
% else
73+
% solutionFileName = solutionFileNameTmp;
74+
% end
75+
76+
% Convert to irreversible rxns
77+
[modelIrrev,matchRev,rev2irrev,irrev2rev] = convertToIrreversible(model);
78+
79+
% Create the index of the previous KO's suggested by OMNI to avoid obtaining the same
80+
% solution again
81+
selPrevSolIrrev = [];
82+
for i = 1:size(prevSolutions,2)
83+
prevSolRxnList = model.rxns(prevSolutions(:,i)==1);
84+
selPrevSol = ismember(model.rxns,prevSolRxnList);
85+
selPrevSolIrrev(:,i) = selPrevSol(irrev2rev);
86+
end
87+
88+
[nMets,nRxns] = size(modelIrrev.S);
89+
90+
% Create matchings for reversible reactions in the set selected for KOs
91+
% This is to ensure that both directions of the reaction are knocked out
92+
selSelectedRxn = ismember(model.rxns,selectedRxnList);
93+
selSelectedRxnIrrev = selSelectedRxn(irrev2rev);
94+
selectedRxnIndIrrev = find(selSelectedRxnIrrev);
95+
cnt = 0;
96+
%prevRxnID = -10;
97+
nSelected = length(selectedRxnIndIrrev);
98+
selRxnCnt = 1;
99+
while selRxnCnt <= nSelected
100+
rxnID = selectedRxnIndIrrev(selRxnCnt);
101+
if (matchRev(rxnID)>0)
102+
cnt = cnt + 1;
103+
selectedRxnMatch(cnt,1) = selRxnCnt;
104+
selectedRxnMatch(cnt,2) = selRxnCnt+1;
105+
selRxnCnt = selRxnCnt + 1;
106+
end
107+
selRxnCnt = selRxnCnt + 1;
108+
end
109+
110+
% Set inner constraints for the LP
111+
constrOptIrrev = setConstraintsIrrevModel(constrOpt,model,modelIrrev,rev2irrev);
112+
% constrOptIrrev = model;
113+
% constrOptIrrev = [];
114+
115+
% Set objectives for linear and integer parts
116+
cLinear = zeros(nRxns,1);
117+
cInteger = zeros(sum(selSelectedRxnIrrev),1);
118+
119+
% Set the correct objective coefficient (not necessary for OMNI)
120+
% targetRxnID = find(ismember(model.rxns,options.targetRxn));
121+
% targetRxnIDirrev = rev2irrev{targetRxnID}(1);
122+
% cLinear(targetRxnIDirrev) = 1;
123+
124+
% Set measured reaction in objective
125+
sel_meas_rxn = measOpt.rxnSel';
126+
b_meas_rxn = measOpt.values';
127+
wt_meas_rxn = measOpt.weights';
128+
n_m = length(sel_meas_rxn);
129+
130+
% Create selection vector in the decoupled representation
131+
% This is to ensure that the objective function for measured reversible
132+
% reactions is constructed correctly
133+
sel_m = zeros(nRxns,1);
134+
ord_ir = [];
135+
b_meas_tmp = [];
136+
wt_meas_tmp = [];
137+
for i = 1:n_m
138+
rxn_name = sel_meas_rxn{i};
139+
rxn_id = find(strcmp(model.rxns,rxn_name));
140+
if (~isempty(rxn_id)) % Protect against measured fluxes that are not part of the model
141+
b_meas_tmp = [b_meas_tmp;b_meas_rxn(i)];
142+
wt_meas_tmp = [wt_meas_tmp;wt_meas_rxn(i)];
143+
% Reversible rxns
144+
if (model.rev(rxn_id))
145+
rxn_id_ir = rev2irrev{rxn_id}(1);
146+
sel_m(rxn_id_ir) = 1;
147+
sel_m(rxn_id_ir+1) = -1;
148+
else
149+
% Irrev rxns
150+
rxn_id_ir = rev2irrev{rxn_id};
151+
sel_m(rxn_id_ir) = 1;
152+
end
153+
% Figure out ordering in decoupled representation
154+
ord_ir = [ord_ir rxn_id_ir];
155+
end
156+
end
157+
% Get ordering indices
158+
[tmp,ord_ind] = sort(ord_ir);
159+
% Reorder or create weights
160+
if (sum(wt_meas_rxn) == 0)
161+
measOpts.weights = ones(n_m,1);
162+
else
163+
measOpts.weights = wt_meas_tmp(ord_ind);
164+
end
165+
% Reorder measured flux values
166+
measOpts.values = b_meas_tmp(ord_ind);
167+
168+
measOpts.rxnSel = sel_m;
169+
170+
% Create the constraint matrices for the bilevel MILP
171+
bilevelMILPProblem = createBilevelMILPproblem(modelIrrev,cLinear,cInteger,selSelectedRxnIrrev,...
172+
selectedRxnMatch,constrOptIrrev,measOpts,options,selPrevSolIrrev);
173+
174+
% Initial guess (random)
175+
%bilevelMILPProblem.x0 = round(rand(length(bilevelMILPProblem.c),1));
176+
if isfield(options,'initSolution')
177+
if (length(options.initSolution) > options.numDel | ~all(ismember(options.initSolution,selectedRxnList)))
178+
warning('Initial solution not valid - starting from a random initial solution')
179+
bilevelMILPProblem.x0 = [];
180+
else
181+
% Set initial integer solution
182+
selInitRxn = ismember(model.rxns,options.initSolution);
183+
selInitRxnIrrev = selInitRxn(irrev2rev);
184+
initRxnIndIrrev = find(selInitRxnIrrev);
185+
initIntegerSol = ~ismember(selectedRxnIndIrrev,initRxnIndIrrev);
186+
selInteger = bilevelMILPProblem.vartype == 'B';
187+
[nConstr,nVar] = size(bilevelMILPProblem.A);
188+
bilevelMILPProblem.x0 = nan(nVar,1);
189+
bilevelMILPProblem.x0(selInteger) = initIntegerSol;
190+
191+
% LPproblem.b = bilevelMILPProblem.b - bilevelMILPProblem.A(:,selInteger)*initIntegerSol;
192+
% LPproblem.A = bilevelMILPProblem.A(:,bilevelMILPProblem.vartype == 'C');
193+
% LPproblem.c = bilevelMILPProblem.c(bilevelMILPProblem.vartype == 'C');
194+
% LPproblem.lb = bilevelMILPProblem.lb(bilevelMILPProblem.vartype == 'C');
195+
% LPproblem.ub = bilevelMILPProblem.ub(bilevelMILPProblem.vartype == 'C');
196+
% LPproblem.osense = -1;
197+
% LPproblem.csense = bilevelMILPProblem.csense;
198+
% LPsol = solveCobraLP(LPproblem);
199+
%
200+
% bilevelMILPProblem.x0(~selInteger) = LPsol.full;
201+
end
202+
else
203+
bilevelMILPProblem.x0 = [];
204+
end
205+
206+
% Minimize
207+
bilevelMILPProblem.osense = 1;
208+
209+
if (verbFlag)
210+
[nConstr,nVar] = size(bilevelMILPProblem.A);
211+
nInt = length(bilevelMILPProblem.intSolInd);
212+
fprintf('MILP problem with %d constraints %d integer variables and %d continuous variables\n',...
213+
nConstr,nInt,nVar);
214+
end
215+
216+
bilevelMILPProblem.model = modelIrrev;
217+
218+
% Set these for CPLEX callbacks
219+
MILPproblemType = 'OMNI';
220+
% rxnList = model.rxns;
221+
% biomassRxnID = find(modelIrrev.c==1);
222+
% solID = 0;
223+
% OMNIObjective = [];
224+
% OMNIGrowth = [];
225+
% OMNIKOrxnList = {};
226+
227+
% Solve problem
228+
if (options.solveOMNI)
229+
OMNISol = solveCobraMILP(bilevelMILPProblem,'printLevel',0);
230+
if OMNISol.stat~=0
231+
if (~isempty(OMNISol.cont))
232+
OMNISol.fluxes = convertIrrevFluxDistribution(OMNISol.cont(1:length(matchRev)),matchRev);
233+
end
234+
if (~isempty(OMNISol.int))
235+
% Figure out the KO reactions
236+
OMNIRxnInd = selectedRxnIndIrrev(OMNISol.int < 1e-4);
237+
OMNISol.kos = model.rxns(unique(irrev2rev(OMNIRxnInd)));
238+
239+
% %sanity check
240+
% modelTemp = changeRxnBounds(model,OMNISol.kos,0,'b');
241+
% solTemp = optimizeCbModel(modelTemp);
242+
% if abs(solTemp.f - OMNISol.obj) > 1e-4
243+
% [OMNISol,bilevelMILPProblem] = OMNI(model, selectedRxnList, options, constrOpt, measOpt, prevSolutions, verbFlag);
244+
% previous_solutions(:,end+1) = zeros(length(model.rxns),1);
245+
% end
246+
end
247+
else
248+
OMNISol.fluxes=[];
249+
OMNISol.kos={};
250+
end
251+
else
252+
OMNISol.rxnList = {};
253+
OMNISol.fluxes = [];
254+
end
255+
256+
257+
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
changeCobraSolver('gurobi6','all');
2+
%Load data
3+
4+
% Load the stoichiometrically consistent par of Recon2
5+
load 'Recon2.v04_sc.mat';
6+
7+
[m,n] = size(model.S);
8+
model_Ex = findSExRxnInd(model);
9+
intRxnBool = model_Ex.SIntRxnBool;
10+
exRxnBool = true(size(intRxnBool));
11+
exRxnBool(find(intRxnBool)) = false;
12+
13+
%Relax the model to make it flux conssitent
14+
relaxOption.internalRelax = 2;
15+
relaxOption.exchangeRelax = 2;
16+
relaxOption.steadyStateRelax = 1;
17+
18+
relaxOption.nbMaxIteration = 1000;
19+
relaxOption.epsilon = 10e-6;
20+
relaxOption.gamma0 = 100; %trade-off parameter of l0 part of v
21+
relaxOption.gamma1 = 10; %trade-off parameter of l1 part of v
22+
relaxOption.lambda0 = 10; %trade-off parameter of l0 part of r
23+
relaxOption.lambda1 = 0; %trade-off parameter of l1 part of r
24+
relaxOption.alpha0 = 10; %trade-off parameter of l0 part of p and q
25+
relaxOption.alpha1 = 0; %trade-off parameter of l1 part of p and q
26+
relaxOption.theta = 2; %parameter of capped l1 approximation
27+
28+
solution = relaxFBA(model,relaxOption);
29+
30+
[v,r,p,q] = deal(solution.v,solution.r,solution.p,solution.q);
31+
if solution.stat == 1
32+
maxUB = max(model.ub);
33+
minLB = min(model.lb);
34+
35+
display(strcat('Number of relaxations on internal reactions:',num2str(size(find(p>0 & intRxnBool),1)+size(find(q>0 & intRxnBool),1))));
36+
intRxnFiniteBound = ((model.ub < maxUB) & (model.lb > minLB)) & intRxnBool;
37+
display(strcat(' - Relaxations on internal reactions with finite bounds:',num2str(size(find(p>0 & intRxnFiniteBound),1)+size(find(q>0 & intRxnFiniteBound),1))));
38+
39+
display(strcat('Number of relaxations on exchange reactions:',num2str(size(find(p>0 & exRxnBool),1)+size(find(q>0 & exRxnBool),1))));
40+
exRxn00 = ((model.ub == 0) & (model.lb == 0)) & exRxnBool;
41+
display(strcat(' - Relaxations on exchange reactions of type [0,0]:',num2str(size(find(p>0 & exRxn00),1)+size(find(q>0 & exRxn00),1))));
42+
43+
display(strcat('Number of relaxations on steady state constraints:',num2str(size(find(abs(r)>0),1))));
44+
45+
display(strcat('Reactions unblocked = ',num2str(length(find(abs(v)>1e-4 & ~model.rbool)))));
46+
else
47+
disp('Can not find any solution');
48+
end

0 commit comments

Comments
 (0)