119 lines
3.0 KiB
Matlab
Executable File
119 lines
3.0 KiB
Matlab
Executable File
function x_extract = extractsolution(momentdata,options)
|
|
%EXTRACTSOLUTIONS Tries to extract solutions from moment matrices
|
|
%
|
|
%
|
|
% xoptimal = extractsolution(momentstructure)
|
|
%
|
|
% xoptimal : Extracted solutions
|
|
%
|
|
% momentdata : Problem data, obtained from SOLVEMOMENT (or SOLVESDP)
|
|
% options : Options structure from SDPSETTINGS
|
|
%
|
|
% See also SOLVEMOMENT, SDPSETTINGS
|
|
|
|
% Author Johan Löfberg
|
|
% $Id: extractsolution.m,v 1.1 2006-03-30 13:36:38 joloef Exp $
|
|
|
|
moment = momentdata.moment;
|
|
x = momentdata.x;
|
|
monomials = momentdata.monomials;
|
|
n = momentdata.n;
|
|
d = momentdata.d;
|
|
|
|
[U,S,V,ranks] = numranks(moment);
|
|
|
|
if options.moment.extractrank>0
|
|
% We try a extraction from highest order moment no matter what
|
|
flat = length(moment);
|
|
ranks(flat) = options.moment.extractrank;
|
|
else
|
|
% Find a flat extension
|
|
flat = d+min(find(ranks(1+d:end)-ranks(1:end-d)==0));
|
|
end
|
|
|
|
if ~isempty(flat)
|
|
|
|
% Find a basis
|
|
r = ranks(flat);
|
|
V = U{flat}(:,1:r)*sqrt(diag(diag(S{flat}(1:r,1:r))));
|
|
if options.moment.rceftol >= 0
|
|
[R,pivot] = rref(V',options.moment.rceftol);R = R';
|
|
else
|
|
% Try to find a reasonable tolerance by avoiding severly badly
|
|
% conditioned R. Hack.., but seem to behave rather robustly.
|
|
cV = cond(V);
|
|
tol = 1e-10;
|
|
[R,pivot] = rref(V',tol);R = R';
|
|
while tol<1 & (cond(R)/cond(cV)>1e4)
|
|
tol = tol*5;
|
|
[R,pivot] = rref(V',tol);R = R';
|
|
end
|
|
end
|
|
|
|
% Figure out multiplying matrices using YALMIP code
|
|
w = monomials(pivot);
|
|
for i = 1:n
|
|
xw = x(i)*w;
|
|
k = [];
|
|
for j = 1:length(xw)
|
|
k = [k;find(ismember(xw(j),monomials))];
|
|
end
|
|
N{i} = R(k,:);
|
|
end
|
|
|
|
% Things missing in the basis...
|
|
if ~all(cellfun('prodofsize',N)==length(w)^2)
|
|
x_extract = {[]};
|
|
return;
|
|
end
|
|
|
|
% Create random convex combination
|
|
rands = rand(n,1);rands = rands/sum(rands);
|
|
M = 0;
|
|
for i = 1:n
|
|
M = M + rands(i)*N{i};
|
|
end
|
|
|
|
[Q,T] = schur(M);
|
|
% Extract solution
|
|
for i = 1:r
|
|
for j = 1:n
|
|
x_extract{i}(j,1) = Q(:,i)'*N{j}*Q(:,i);
|
|
end
|
|
end
|
|
|
|
% Refine solutions v-Rw = e(x)=0
|
|
if options.moment.refine>0
|
|
xtemp = double(x);
|
|
e = monomials(1:size(R,1))-R*w;
|
|
dedx = jacobian(e,x);
|
|
for j = 1:r
|
|
assign(x,x_extract{j});
|
|
for i = 1:options.moment.refine
|
|
assign(x,double(x)-double(dedx)\double(e));
|
|
end
|
|
x_extract{j} = double(x);
|
|
end
|
|
assign(x,xtemp);
|
|
end
|
|
|
|
else
|
|
x_extract = {};
|
|
end
|
|
|
|
% Somewhat more stable rank detection
|
|
% looking for sharp drops in singular value
|
|
function [U,S,V,ranks] = numranks(moment)
|
|
for i = 1:length(moment)
|
|
[U{i},S{i},V{i}] = svd(moment{i});
|
|
s = diag(S{i});
|
|
decay = s(2:end)./(eps+s(1:end-1));
|
|
r = min(find(decay<1e-3));
|
|
if isempty(r)
|
|
ranks(i) = rank(moment{i},1e-8);
|
|
else
|
|
ranks(i) = min(r,rank(moment{i},1e-8));
|
|
end
|
|
end
|
|
|