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