288 lines
8.2 KiB
Mathematica
288 lines
8.2 KiB
Mathematica
|
|
function output = callsdpt34(interfacedata)
|
||
|
|
|
||
|
|
% Retrieve needed data
|
||
|
|
options = interfacedata.options;
|
||
|
|
F_struc = interfacedata.F_struc;
|
||
|
|
c = interfacedata.c;
|
||
|
|
K = interfacedata.K;
|
||
|
|
x0 = interfacedata.x0;
|
||
|
|
ub = interfacedata.ub;
|
||
|
|
lb = interfacedata.lb;
|
||
|
|
|
||
|
|
% Bounded variables converted to constraints
|
||
|
|
if ~isempty(ub)
|
||
|
|
[F_struc,K] = addStructureBounds(F_struc,K,ub,lb);
|
||
|
|
end
|
||
|
|
|
||
|
|
if any(K.m > 0)
|
||
|
|
% Messy to keep track of
|
||
|
|
options.sdpt3.smallblkdim = 0;
|
||
|
|
end
|
||
|
|
|
||
|
|
if ~isempty(interfacedata.lowrankdetails)
|
||
|
|
options.sdpt3.smallblkdim = 1;
|
||
|
|
end
|
||
|
|
|
||
|
|
if isempty(K.schur_funs)
|
||
|
|
% Simple...
|
||
|
|
[blk,A,C,b,oldKs]=sedumi2sdpt3(F_struc(:,1),F_struc(:,2:end),c,K,options.sdpt3.smallblkdim);
|
||
|
|
else
|
||
|
|
% A bit messy if we have a Schur compiler (i.e. STRUL)
|
||
|
|
% SDPT3 reorders SDP constraints in order to put many small ones in a
|
||
|
|
% common block. Hence, it might happen that it mixes up SDP constraints
|
||
|
|
% with Schur compilers and those without. At the moment, we take a
|
||
|
|
% conservative approach. If all SDP constraints have a Schur compiler,
|
||
|
|
% we allow blocking. If not, we don't. This way our code will work
|
||
|
|
if ~any(cellfun(@isempty,K.schur_funs))
|
||
|
|
% All have Schur functions
|
||
|
|
[blk,A,C,b,oldKs]=sedumi2sdpt3(F_struc(:,1),F_struc(:,2:end),c,K,options.sdpt3.smallblkdim);
|
||
|
|
else
|
||
|
|
% Messy case, don't allow blocking for now
|
||
|
|
options.sdpt3.smallblkdim = 1;
|
||
|
|
[blk,A,C,b,oldKs]=sedumi2sdpt3(F_struc(:,1),F_struc(:,2:end),c,K,options.sdpt3.smallblkdim);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
options.sdpt3.printyes=double(options.verbose);
|
||
|
|
options.sdpt3.printlevel=double(options.verbose)*3;
|
||
|
|
options.sdpt3.expon=options.sdpt3.expon(1);
|
||
|
|
|
||
|
|
% Setup the logarithmic barrier cost. We exploit the fact that we know that
|
||
|
|
% the only logaritmic cost is in the last SDP constraint
|
||
|
|
if abs(K.m) > 0
|
||
|
|
lpLogsStart = 1;
|
||
|
|
for i = 1:size(blk,1)
|
||
|
|
if isequal(blk{i,1},'l')
|
||
|
|
options.sdpt3.parbarrier{i,1} = zeros(1,blk{i,2});
|
||
|
|
elseif isequal(blk{i,1},'u')
|
||
|
|
lpLogsStart = 2;
|
||
|
|
options.sdpt3.parbarrier{i,1} = zeros(1,blk{i,2});
|
||
|
|
else
|
||
|
|
options.sdpt3.parbarrier{i,1} = 0*blk{i,2};
|
||
|
|
end
|
||
|
|
end
|
||
|
|
n_sdp_logs = nnz(K.m > 1);
|
||
|
|
n_lp_logs = nnz(K.m == 1);
|
||
|
|
if n_lp_logs>0
|
||
|
|
lp_count = n_lp_logs;
|
||
|
|
end
|
||
|
|
if n_sdp_logs>0
|
||
|
|
sdp_count = n_sdp_logs;
|
||
|
|
end
|
||
|
|
for i = 1:length(K.m)
|
||
|
|
if K.m(i) == 1
|
||
|
|
% We placed it in the linear cone
|
||
|
|
options.sdpt3.parbarrier{lpLogsStart,1}(end-lp_count+1) = -K.maxdetgain(i);
|
||
|
|
lp_count = lp_count-1;
|
||
|
|
elseif K.m(i) > 1
|
||
|
|
% We placed it in the SDP cone
|
||
|
|
options.sdpt3.parbarrier{end-sdp_count+1,1} = -K.maxdetgain(i);
|
||
|
|
sdp_count = sdp_count-1;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
%options.saveduals = 0;
|
||
|
|
end
|
||
|
|
|
||
|
|
% Setup structures for user-defined Schur compilers
|
||
|
|
if isfield(K,'schur_funs')
|
||
|
|
top = 1;
|
||
|
|
if ~isempty(K.schur_funs)
|
||
|
|
if K.f>0
|
||
|
|
options.sdpt3.schurfun{top} = '';
|
||
|
|
options.sdpt3.schurfun_par{top,1} = [];
|
||
|
|
top = top+1;
|
||
|
|
end
|
||
|
|
if K.l > 0
|
||
|
|
options.sdpt3.schurfun{top} = '';
|
||
|
|
options.sdpt3.schurfun_par{top,1} = [];
|
||
|
|
top = top+1;
|
||
|
|
end
|
||
|
|
if K.q > 0
|
||
|
|
options.sdpt3.schurfun{top} = '';
|
||
|
|
options.sdpt3.schurfun_par{top,1} = [];
|
||
|
|
top = top+1;
|
||
|
|
end
|
||
|
|
if 0
|
||
|
|
for i = 1:length(K.s)
|
||
|
|
if ~isempty(K.schur_funs{i})
|
||
|
|
options.sdpt3.schurfun{top} = 'schurgateway';
|
||
|
|
S = createSchurFun(options,K,interfacedata,i);
|
||
|
|
options.sdpt3.schurfun_par{top,1} = S;
|
||
|
|
V = {S.extra,S.data{:}};
|
||
|
|
feval(S.fun,[],[],V{:});
|
||
|
|
else
|
||
|
|
options.sdpt3.schurfun{top} = '';
|
||
|
|
options.sdpt3.schurfun_par{top,1} = [];
|
||
|
|
end
|
||
|
|
top = top+1;
|
||
|
|
end
|
||
|
|
else
|
||
|
|
iSDP = 1;
|
||
|
|
while top <= size(blk,1)
|
||
|
|
for j = 1:length(blk{top,2})
|
||
|
|
i = oldKs(iSDP);iSDP = iSDP + 1;
|
||
|
|
if ~isempty(K.schur_funs{i})
|
||
|
|
Sname = 'schurgateway';
|
||
|
|
% options.sdpt3.schurfun{top} = 'schurgateway';
|
||
|
|
S = createSchurFun(options,K,interfacedata,i);
|
||
|
|
S.j = j;
|
||
|
|
S.blk = blk(top,2);
|
||
|
|
options.sdpt3.schurfun_par{top,j} = S;
|
||
|
|
else
|
||
|
|
Sname = '';
|
||
|
|
% options.sdpt3.schurfun{top} = '';
|
||
|
|
options.sdpt3.schurfun_par{top,1} = [];
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
options.sdpt3.schurfun{top} = Sname;
|
||
|
|
top = top+1;
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if options.savedebug
|
||
|
|
ops = options.sdpt3;
|
||
|
|
save sdpt3debug blk A C b ops x0 -v6
|
||
|
|
end
|
||
|
|
|
||
|
|
if options.showprogress;showprogress(['Calling ' interfacedata.solver.tag],options.showprogress);end
|
||
|
|
solvertime = tic;
|
||
|
|
[obj,X,y,Z,info,runhist] = sdpt3(blk,A,C,b,options.sdpt3,[],x0,[]);
|
||
|
|
solvertime = toc(solvertime);
|
||
|
|
|
||
|
|
% Create YALMIP dual variable and slack
|
||
|
|
Dual = [];
|
||
|
|
Slack = [];
|
||
|
|
top = 1;
|
||
|
|
if K.f>0
|
||
|
|
Dual = [Dual;X{top}(:)];
|
||
|
|
Slack = [Slack;Z{top}(:)];
|
||
|
|
top = top+1;
|
||
|
|
end
|
||
|
|
if K.l>0
|
||
|
|
Dual = [Dual;X{top}(:)];
|
||
|
|
Slack = [Slack;Z{top}(:)];
|
||
|
|
top = top + 1;
|
||
|
|
end
|
||
|
|
if K.q(1)>0
|
||
|
|
Dual = [Dual;X{top}(:)];
|
||
|
|
Slack = [Slack;Z{top}(:)];
|
||
|
|
top = top + 1;
|
||
|
|
end
|
||
|
|
if K.s(1)>0
|
||
|
|
% Messy format in SDPT3 to block and sort small SDPs
|
||
|
|
u = blk(:,1);
|
||
|
|
u = find([u{:}]=='s');
|
||
|
|
s = 1;
|
||
|
|
for top = u
|
||
|
|
ns = blk(top,2);ns = ns{1};
|
||
|
|
k = 1;
|
||
|
|
for i = 1:length(ns)
|
||
|
|
Xi{oldKs(s)} = X{top}(k:k+ns(i)-1,k:k+ns(i)-1);
|
||
|
|
Zi{oldKs(s)} = Z{top}(k:k+ns(i)-1,k:k+ns(i)-1);
|
||
|
|
s = s + 1;
|
||
|
|
k = k+ns(i);
|
||
|
|
end
|
||
|
|
end
|
||
|
|
for i = 1:length(Xi)
|
||
|
|
Dual = [Dual;Xi{i}(:)];
|
||
|
|
Slack = [Slack;Zi{i}(:)];
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if any(K.m > 0)
|
||
|
|
% Dual = [];
|
||
|
|
end
|
||
|
|
|
||
|
|
Primal = -y; % Primal variable in YALMIP
|
||
|
|
|
||
|
|
% Convert error code
|
||
|
|
switch info.termcode
|
||
|
|
case 0
|
||
|
|
problem = 0; % No problems detected
|
||
|
|
case {-1,-5,-9}
|
||
|
|
problem = 5; % Lack of progress
|
||
|
|
case {3,-2,-3,-4,-7}
|
||
|
|
problem = 4; % Numerical problems
|
||
|
|
case -6
|
||
|
|
problem = 3; % Maximum iterations exceeded
|
||
|
|
case -10
|
||
|
|
problem = 7; % YALMIP sent incorrect input to solver
|
||
|
|
case 1
|
||
|
|
problem = 2; % Dual feasibility
|
||
|
|
case 2
|
||
|
|
problem = 1; % Primal infeasibility
|
||
|
|
otherwise
|
||
|
|
problem = -1; % Unknown error
|
||
|
|
end
|
||
|
|
infostr = yalmiperror(problem,interfacedata.solver.tag);
|
||
|
|
|
||
|
|
if options.savesolveroutput
|
||
|
|
solveroutput.obj = obj;
|
||
|
|
solveroutput.X = X;
|
||
|
|
solveroutput.y = y;
|
||
|
|
solveroutput.Z = Z;
|
||
|
|
solveroutput.info = info;
|
||
|
|
solveroutput.runhist = runhist;
|
||
|
|
else
|
||
|
|
solveroutput = [];
|
||
|
|
end
|
||
|
|
|
||
|
|
if options.savesolverinput
|
||
|
|
solverinput.blk = blk;
|
||
|
|
solverinput.A = A;
|
||
|
|
solverinput.C = C;
|
||
|
|
solverinput.b = b;
|
||
|
|
solverinput.X0 = [];
|
||
|
|
solverinput.y0 = x0;
|
||
|
|
solverinput.Z0 = [];
|
||
|
|
solverinput.options = options.sdpt3;
|
||
|
|
else
|
||
|
|
solverinput = [];
|
||
|
|
end
|
||
|
|
|
||
|
|
% Standard interface
|
||
|
|
output = createOutputStructure(Primal,Dual,[],problem,infostr,solverinput,solveroutput,solvertime);
|
||
|
|
|
||
|
|
function [F_struc,K] = deblock(F_struc,K);
|
||
|
|
X = any(F_struc(end-K.s(end)^2+1:end,:),2);
|
||
|
|
X = reshape(X,K.s(end),K.s(end));
|
||
|
|
[v,dummy,r,dummy2]=dmperm(X);
|
||
|
|
blks = diff(r);
|
||
|
|
|
||
|
|
lint = F_struc(1:end-K.s(end)^2,:);
|
||
|
|
logt = F_struc(end-K.s(end)^2+1:end,:);
|
||
|
|
|
||
|
|
newlogt = [];
|
||
|
|
for i = 1:size(logt,2)
|
||
|
|
temp = reshape(logt(:,i),K.s(end),K.s(end));
|
||
|
|
temp = temp(v,v);
|
||
|
|
newlogt = [newlogt temp(:)];
|
||
|
|
end
|
||
|
|
logt = newlogt;
|
||
|
|
|
||
|
|
pattern = [];
|
||
|
|
for i = 1:length(blks)
|
||
|
|
pattern = blkdiag(pattern,ones(blks(i)));
|
||
|
|
end
|
||
|
|
|
||
|
|
F_struc = [lint;logt(find(pattern),:)];
|
||
|
|
K.s(end) = [];
|
||
|
|
K.s = [K.s blks];
|
||
|
|
K.m = blks;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function S = createSchurFun(options,K,interfacedata,i);
|
||
|
|
S.extra.par = options.sdpt3;
|
||
|
|
S.data = K.schur_data{i};
|
||
|
|
[init,loc] = ismember(K.schur_variables{i},interfacedata.used_variables);
|
||
|
|
S.index = loc;
|
||
|
|
S.fun = K.schur_funs{i};
|
||
|
|
S.nvars = length(interfacedata.used_variables);
|
||
|
|
%options.sdpt3.schurfun_par{top,1} = S;
|
||
|
|
% V = {S.extra,S.data{:}};
|
||
|
|
% feval(S.fun,[],[],V{:});
|