383 lines
8.7 KiB
Matlab
383 lines
8.7 KiB
Matlab
function [x,y,info]=sedumiwrapC(A,b,c,K,pars,OPTION);
|
|
|
|
%
|
|
% SeDuMi wrapper for SDPA
|
|
%
|
|
% [x,y,info]=sedumiwrapC(A,b,c,K,pars,OPTION);
|
|
% or
|
|
% [x,y,info]=sedumiwrapC(A,b,c,K); % with SDPA-M default parameter
|
|
%
|
|
% Note :
|
|
% 'A', in each SDP block, only upper triangle part is used.
|
|
% 'K' can include only 'f'(free) 'l'(linear) 's'(SDP) cones.
|
|
% 'pars' information is NOT used (just for SeDuMi compatibility)
|
|
% 'OPTION' is option structure for SDPA-M (for details, try 'help param')
|
|
% 'info' information is based on SDPA-M
|
|
%
|
|
% This file is a component of SDPA
|
|
% Copyright (C) 2004-2013 SDPA Project
|
|
%
|
|
% This program is free software; you can redistribute it and/or modify
|
|
% it under the terms of the GNU General Public License as published by
|
|
% the Free Software Foundation; either version 2 of the License, or
|
|
% (at your option) any later version.
|
|
%
|
|
% This program is distributed in the hope that it will be useful,
|
|
% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
% GNU General Public License for more details.
|
|
%
|
|
% You should have received a copy of the GNU General Public License
|
|
% along with this program; if not, write to the Free Software
|
|
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
%
|
|
% SDPA-M: $Revision: 7.3 $
|
|
|
|
|
|
t = cputime;
|
|
|
|
fprintf('-SeDuMi Wrapper for SDPA-C Start-\n');
|
|
|
|
if (nargin < 4 || nargin > 6)
|
|
error('incorrect number of input arguments')
|
|
end
|
|
if nargin >= 5
|
|
if isfield(OPTION,'print') && ~isempty(OPTION.print)
|
|
fprintf('Note: pars information [5th argument] is not used\n');
|
|
end
|
|
end
|
|
if nargin < 6
|
|
OPTION = paramC;
|
|
else
|
|
OPTION = paramC(OPTION);
|
|
end
|
|
|
|
if isfield(K,'q') && ~isempty(K.q)
|
|
error('Current Wrapper cannot handle K.q');
|
|
end
|
|
|
|
if isfield(K,'r') && ~isempty(K.r)
|
|
error('Current Wrapper cannot handle K.r');
|
|
end
|
|
|
|
if size(b,2) ~= 1
|
|
% fprintf('Transposing b to a column vector');
|
|
b = b';
|
|
end
|
|
if size(b,2) ~= 1
|
|
error('b must be a vector');
|
|
end
|
|
|
|
if size(c,2) ~= 1
|
|
% fprintf('Transposing c to a column vector\n');
|
|
c = c';
|
|
end
|
|
if size(c,2) ~= 1
|
|
error('c must be a vector');
|
|
end
|
|
|
|
%%%%%
|
|
% Constructing at least one SDP cone if necesary
|
|
if (~isfield(K,'s')) || (isempty(K.s))
|
|
[K] = LPtoLP_SDP(K);
|
|
end
|
|
%%%%%
|
|
|
|
totalLength = 0;
|
|
Kf = 0;
|
|
if isfield(K,'f') && ~isempty(K.f)
|
|
totalLength = totalLength + K.f;
|
|
Kf = K.f;
|
|
end
|
|
if isfield(K,'l') && ~isempty(K.l)
|
|
totalLength = totalLength + K.l;
|
|
else
|
|
K.l = 0;
|
|
end
|
|
if isfield(K,'s') && ~isempty(K.s)
|
|
if size(K.s,2) ~= 1
|
|
% fprintf('Transposing K.s to a column vector\n');
|
|
K.s = K.s';
|
|
end
|
|
Ks = sum(K.s .* K.s);
|
|
totalLength = totalLength + Ks;
|
|
else
|
|
error('Cannot handle empty K.s');
|
|
end
|
|
m = size(b,1);
|
|
n = size(c,1);
|
|
|
|
[mA,nA] = size(A);
|
|
if (m~=mA || n~=nA) && (m~=nA || n~=mA)
|
|
fprintf('Inconsistent Size of A,b,c\n');
|
|
fprintf('size(A) = [%d,%d], size(b) = %d, size(c) = %d\n',...
|
|
mA,nA, m,n);
|
|
error('Cannot continue...');
|
|
end
|
|
|
|
if (n~=totalLength)
|
|
fprintf('Inconsistent Size of c and K\n');
|
|
fprintf('size(c) = %d, totalSize(K) = %d\n',...
|
|
n, totalLength);
|
|
error('Cannot continue...');
|
|
end
|
|
|
|
if ~issparse(A)
|
|
if isfield(OPTION,'print') && ~isempty(OPTION.print)
|
|
fprintf('Converting A from dense to sparse\n');
|
|
end
|
|
A = sparse(A);
|
|
end
|
|
|
|
if issparse(b)
|
|
% fprintf('Converting b from sparse to dense\n');
|
|
b = full(b);
|
|
end
|
|
|
|
if ~issparse(c)
|
|
% fprintf('Converting c from dense to sparse\n');
|
|
c = sparse(c);
|
|
end
|
|
|
|
if issparse(K.s)
|
|
% fprintf('Converting K.s from sparse to dense\n');
|
|
K.s = full(K.s);
|
|
end
|
|
|
|
if Kf ~= 0
|
|
if isfield(OPTION,'print') && ~isempty(OPTION.print)
|
|
fprintf(['Free Variables are divided into positive and ' ...
|
|
'negative part of LP cone\n']);
|
|
end
|
|
Af = A(:,1:Kf);
|
|
Kl = K.l;
|
|
Al = A(:,Kf+1:Kf+Kl);
|
|
As = A(:,Kf+Kl+1:Kf+Kl+Ks);
|
|
Anew = [Af, -Af, Al, As];
|
|
|
|
cf = c(1:Kf);
|
|
cl = c(Kf+1:Kf+Kl);
|
|
cs = c(Kf+Kl+1:Kf+Kl+Ks);
|
|
cnew = [cf; -cf; cl; cs];
|
|
|
|
Knew.l = 2*Kf + Kl;
|
|
Knew.s = K.s;
|
|
|
|
A = Anew;
|
|
c = cnew;
|
|
K = Knew;
|
|
|
|
clear Af;
|
|
clear Al;
|
|
clear As;
|
|
clear Anew;
|
|
clear cf;
|
|
clear cl;
|
|
clear cs;
|
|
clear cnew;
|
|
clear Knew;
|
|
end
|
|
|
|
if isfield(K,'s') && ~isempty(K.s)
|
|
if size(K.s,2) ~= 1
|
|
K.s = Ks';
|
|
end
|
|
end
|
|
|
|
%%%%%
|
|
% Aggregating small SDP cones into larger SDP cones
|
|
aggSW = 0;
|
|
minNoSDPcones = 3;
|
|
if (isfield(OPTION,'aggConeSize')) && (~isempty(OPTION.aggConeSize)) && (isnumeric(OPTION.aggConeSize)) && ...
|
|
((OPTION.aggConeSize > 0)) && (length(K.s') > minNoSDPcones) && (length(find(K.s' < OPTION.aggConeSize)) > minNoSDPcones)
|
|
fprintf('OPTION.aggConeSize = %d\n',OPTION.aggConeSize)
|
|
K0 = K;
|
|
aggSW = 1;
|
|
[A,c,K1] = aggSDPcones(A,c,K,OPTION.aggConeSize);
|
|
A = sparse(A);
|
|
c = sparse(c);
|
|
K = K1;
|
|
end
|
|
%%%%%
|
|
|
|
|
|
% A should be transposed when passed to mex
|
|
[mA,nA] = size(A);
|
|
if mA ~= K.l + sum(K.s.*K.s)
|
|
A = A';
|
|
end
|
|
% fprintf('size(A) = (%d,%d)\n',size(A,2),size(A,1));
|
|
% fprintf('length(K.s) = %d\n',length(K.s));
|
|
|
|
[x,y,info] = mexSedumiWrapC(A,b,c,K,OPTION);
|
|
|
|
%%%%%
|
|
% Retrieving the origianl primal SDP cone variables
|
|
if aggSW == 1
|
|
if (isfield(K,'l')) && (~isempty(K.l)) && (K.l > 0)
|
|
xSDP = x(K.l+1:size(x,1),1);
|
|
xLP = x(1:K.l,1);
|
|
[xSDP] = mexDisAggSDPsol(xSDP,K0.s,K1.s);
|
|
x = [xLP; xSDP];
|
|
else
|
|
[x] = mexDisAggSDPsol(x,K0.s,K1.s);
|
|
end
|
|
end
|
|
%%%%%
|
|
|
|
if Kf ~=0
|
|
xlength = size(x);
|
|
xnew = x(1:Kf) - x(Kf+1:Kf+Kf);
|
|
xnew = [xnew; x(Kf+Kf+1:xlength)];
|
|
x = xnew;
|
|
end
|
|
|
|
info.cpusec = cputime-t;
|
|
% if isfield(OPTION,'print') && ~isempty(OPTION.print)
|
|
fprintf('-SeDuMi Wrapper for SDPA-C End-\n');
|
|
% end
|
|
|
|
% End of File
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
function [K] = LPtoLP_SDP(K)
|
|
|
|
if isfield(K,'q') && ~isempty(K.q)
|
|
error('Current Wrapper cannot handle K.q');
|
|
end
|
|
|
|
if isfield(K,'r') && ~isempty(K.r)
|
|
error('Current Wrapper cannot handle K.r');
|
|
end
|
|
|
|
if isfield(K,'s') && ~isempty(K.s)
|
|
return;
|
|
elseif ~isfield(K,'l') || isempty(K.l)
|
|
error('Both LP and SDP cones are empty, so the problem can not be solved');
|
|
else
|
|
K.l = K.l-1;
|
|
if K.l == 0
|
|
K.l = [];
|
|
end
|
|
K.s = 1;
|
|
end
|
|
|
|
return
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
function [A1,c1,K1] = aggSDPcones(A,c,K0,aggConeSize)
|
|
%
|
|
% [A1,c1,K1] = aggSDPcones(A,c,K0,aggConeSize)
|
|
% Input : SeDuMi format
|
|
% aggConeSize : the block size into which small blocks are converted
|
|
% Output: Sedumi format with larger SDP cone matrices
|
|
%
|
|
|
|
if (size(K0.s,2) > 1)
|
|
K0.s = K0.s';
|
|
end
|
|
|
|
if size(A,1) > size(A,2)
|
|
A = A';
|
|
end
|
|
% if size(c,1) < size(c,2)
|
|
% c = c';
|
|
% end
|
|
[m,n] = size(A);
|
|
%
|
|
if ~isfield(K0,'f') || isempty(K0.f)
|
|
fDim = 0;
|
|
else
|
|
fDim = K0.f;
|
|
end
|
|
%
|
|
if ~isfield(K0,'l') || isempty(K0.l)
|
|
ellDim = 0;
|
|
else
|
|
ellDim = K0.l;
|
|
end
|
|
%
|
|
if ~isfield(K0,'q')
|
|
qDim = 0;
|
|
else
|
|
if size(K0.q,1) > size(K0.q,2)
|
|
K0.q = K0.q'; % a row vector
|
|
end
|
|
qDim = sum(K0.q);
|
|
end
|
|
%
|
|
if ~isfield(K0,'s') || isempty(K0.s)
|
|
K1 = K0;
|
|
A1 = A;
|
|
c1 = c;
|
|
return
|
|
else
|
|
if size(K0.s,2) > size(K0.s,1)
|
|
K0.s = K0.s'; % a column vector
|
|
end
|
|
sDim = sum(K0.s .* K0.s);
|
|
end
|
|
|
|
nonSDim = fDim+ellDim+qDim;
|
|
if nonSDim == 0
|
|
cNonSDP = [];
|
|
AnonSDP = [];
|
|
c0SDP = c;
|
|
A0SDP = A;
|
|
else
|
|
cNonSDP = c(1:nonSDim,1);
|
|
AnonSDP = A(:,1:nonSDim);
|
|
c0SDP = c(nonSDim+1:n,1);
|
|
A0SDP = A(:,nonSDim+1:n);
|
|
end
|
|
|
|
K1s = [];
|
|
coneSize = 0;
|
|
for p=1:length(K0.s)
|
|
if (K0.s(p) > aggConeSize)
|
|
if coneSize > 0
|
|
K1s = [K1s; coneSize; K0.s(p)];
|
|
coneSize = 0;
|
|
else
|
|
K1s = [K1s; K0.s(p)];
|
|
coneSize = 0;
|
|
end
|
|
elseif ((coneSize + K0.s(p) > aggConeSize))
|
|
K1s = [K1s; coneSize];
|
|
coneSize = K0.s(p);
|
|
elseif ((coneSize + K0.s(p) == aggConeSize))
|
|
K1s = [K1s; coneSize + K0.s(p)];
|
|
coneSize = 0;
|
|
else
|
|
coneSize = coneSize + K0.s(p);
|
|
end
|
|
end
|
|
if (coneSize > 0)
|
|
K1s = [K1s; coneSize];
|
|
end
|
|
|
|
K0s = K0.s; % K0.s is a column vector
|
|
K1 = K0;
|
|
K1.s = K1s; % K1s is a column vector
|
|
|
|
tStart = tic;
|
|
% C0SDP, K0s and K1s need to be clolumn vector
|
|
[A1SDP,c1SDP] = mexAggSDPcones(A0SDP,c0SDP',K0s,K1s);
|
|
tElapsed = toc(tStart);
|
|
fprintf('Original SDP: the max cone size, the number of cones = %3d, %3d\n',full(max(K0.s)),length(K0.s));
|
|
fprintf('Transformed SDP: the max cone size, the number of cones = %3d, %3d\n',full(max(K1.s)),length(K1.s));
|
|
% fprintf('Elapsed time for transformation = %6.2e\n',tElapsed);
|
|
|
|
c1SDP = c1SDP';
|
|
|
|
A1 = sparse([AnonSDP, A1SDP]);
|
|
c1 = sparse([cNonSDP;c1SDP]);
|
|
|
|
% checkData(A1,b1,c1,K1);
|
|
|
|
% sedumi(A1,b1,c1,K1);
|
|
|
|
return
|
|
|
|
|