Dynamic-Calibration/utils/YALMIP-master/extras/vecquaddecomp.m

119 lines
3.9 KiB
Matlab
Executable File

function [Q,c,f,x,info] = vecquaddecomp(p,z)
%QUADDECOMP Internal function to decompose quadratic expression
[n,m]=size(p);
info = 0;
Q = cell(n*m,1);
c = cell(n*m,1);
f = cell(n*m,1);
% Involved in polynomial expression
[mt,variabletype] = yalmip('monomtable');
x_lin = getvariables(p);
x_var = find(any(mt(x_lin,:),1));
if nargin==2
x_var = union(x_var,depends(z));
end
x = recover(x_var);
basis = getbase(p);
vars = getvariables(p);
vt = variabletype;
mt = mt(x_lin,x_var);
variabletype = variabletype(x_lin);
% If all monomials are different. we can do things faster
hash = mt*randn(size(mt,2),1);
simple = length(unique(hash))==length(hash);
linear = find(variabletype==0);
quadratic = find(variabletype==2);
bilinear = find(variabletype==1);
[il,jl,kl] = find(mt(linear,:));
[jb,ib,kb] = find(mt(bilinear,:)');
[iq,jq,kq] = find(mt(quadratic,:));
bilinindex = sub2ind([length(x) length(x)],jb(1:2:end),jb(2:2:end));
quadindex = sub2ind([length(x) length(x)],jq,jq);
for index = 1:n*m
base = basis(index,:);
if all(vt(vars(find(base(2:end)))) == 0)
n = length(x);
Q{index} = spalloc(n,n,0);
fc = basis(index,:);
f{index} = fc(1);
c{index} = zeros(length(x),1);
[aux,loc] = ismember(vars,x_var);
i = 1+(1:length(vars));
nz = find(loc);
loc = loc(nz);
i = i(nz);
c{index}(loc) = fc(i);
else
if all(vt(vars(find(base(2:end)))) <= 2)
Qtemp = spalloc(length(x),length(x),2*nnz(base));
ctemp = spalloc(length(x),1,0);
f{index} = base(1);
base = base(2:end);
if 0%simple
if length(linear)>0
ctemp(jl)=base(linear);
end
if length(bilinear)>0
Qtemp(bilinindex) = base(bilinear(:))/2;
end
if length(quadratic)>0
Qtemp(quadindex) = base(quadratic(:))/2;
end
Qtemp = Qtemp+Qtemp';
else
% Old version of code
[jj,ii,kk] = find(mt');ii = [ii(:) ;0];
top = 1;
if 1
%Qtemp2=Qtemp;
%ctemp2=ctemp;
bilinear_places = find(diff(ii)==0);
quadratic_places = find(diff(ii)~=0 & kk==2);
Qtemp(sub2ind(size(Qtemp),jj(bilinear_places),jj(bilinear_places+1)))= base(ii(bilinear_places))/2;
Qtemp(sub2ind(size(Qtemp),jj(quadratic_places),jj(quadratic_places)))= base(ii(quadratic_places))/2;
linear_places = find(variabletype==0);
[iii,jjj] = find(mt(linear_places,:));
ctemp(jjj) = base(linear_places);
else
%Qtemp(jj(bilinear_places),jj(bilinear_places+1))
for i = 1:length(x_lin)
if ii(top) == ii(top+1)
% Variable i is the product of two
Qtemp(jj(top),jj(top+1))=Qtemp(jj(top),jj(top+1)) + base(i)/2;
%Qtemp(jj(top),jj(top+1)) = base(i)/2;
top = top + 2;
else
j = [jj(top)];
if kk(top)==1
ctemp(j)=base(i);
else
Qtemp(j,j)=Qtemp(j,j) + base(i)/2;
% Qtemp(j,j) = base(i)/2;
end
top = top + 1;
end
end
end
Qtemp = Qtemp+Qtemp';
end
Q{index} = Qtemp;
c{index} = ctemp;
else
info = 1;
x = [];
end
end
end