📄 compilesos.m
字号:
% *********************************************
exponent_p_monoms = uniquesafe(exponent_p_monoms,'rows');
if options.sos.reuse & constraint > 1 & isequal(previous_exponent_p_monoms,exponent_p_monoms)
% We don't have to do anything, candidate monomials can be-used
if options.verbose>1;disp(['Re-using all candidate monomials (same problem structure)']);end
else
% *********************************************
%% PRUNE W.R.T USER DEFINED
%*********************************************
% if ~isempty(exponent_c)
% hash = randn(size(exponent_m{1},2),1);
% for i = 1:length(exponent_m)
% hash = randn(size(exponent_m{i},2),1);
% keep = find(ismember(exponent_m{i}*hash,exponent_c{1}*hash));
% if length(keep)>0
% exponent_m{i} = exponent_m{i}(keep,:);
% else
% exponent_m{i}=[];
% end
% end
% end
% *********************************************
% User has supplied the whole candidate structure
% Don't process this
% *********************************************
if ~isempty(exponent_c)
exponent_m{1} = [];
N = {};
for i = 1:length(exponent_c)
exponent_m{i} = [exponent_m{1};exponent_c{i}];
N{i,1} = exponent_c{i};
end
else
% *********************************************
%% CORRELATIVE SPARSITY PATTERN
% *********************************************
[C,csclasses] = corrsparsity(exponent_p_monoms,options);
% *********************************************
%% GENERATE MONOMIALS
% *********************************************
exponent_m = monomialgeneration(exponent_p_monoms,csclasses);
% *********************************************
%% REDUCE #of MONOMIALS
% *********************************************
% Fix for matrix case, perform newton w.r.t
% diagonal polynomials only. This can be
% improved, but for now, keep it simple...
n = length(p{constraint});diag_elements = 1:(n+1):n^2;used_diagonal = find(any(p_base(diag_elements,:),1));
exponent_p_monoms_diag = exponent_p(used_diagonal,MonomIndicies);
exponent_m = monomialreduction(exponent_m,exponent_p_monoms_diag,options,csclasses,LPmodel);
% *********************************************
%% BLOCK PARTITION THE MONOMIALS BY CONGRUENCE
% *********************************************
N = congruenceblocks(exponent_m,exponent_p_monoms,options,csclasses);
% *********************************************
%% REDUCE FURTHER BY EXPLOITING BLOCK-STRUCTURE
% *********************************************
N = blockmonomialreduction(exponent_p_monoms_diag,N,options);
end
% *********************************************
%% PREPARE FOR SDP FORMULATION BY CALCULATING ALL
% POSSIBLE MONOMIAL PRODUCS IN EACH BLOCK
% *********************************************
[exponent_m2,N_unique] = monomialproducts(N);
% *********************************************
%% CHECK FOR BUG/IDIOT PROBLEMS IN FIXED PROBLEM
% *********************************************
if isempty(ParametricIndicies)
if ~isempty(setdiff(exponent_p_monoms,N_unique(:,3:end),'rows'))
for i = 1:length(p)
Q{i} = [];
m{i} = [];
end
residuals = [];everything = [];
sol.problem = 2;
sol.info = yalmiperror(1,'YALMIP');
warning('Problem is trivially infeasible (odd highest power?)');
return
end
end
end
previous_exponent_p_monoms = exponent_p_monoms;
% *********************************************
%% GENERATE DATA FOR SDP FORMULATIONS
% *********************************************
p_base_parametric = [];
n = length(p{constraint});
for i=1:length(p{constraint})
for j = 1:length(p{constraint})
p_base_parametric = [p_base_parametric parameterizedbase(p{constraint}(i,j),z,params,ParametricIndicies,exponent_p,p_base((i-1)*n+j,:))];
end
end
[BlockedA{constraint},Blockedb{constraint}] = generate_kernel_representation_data(N,N_unique,exponent_m2,exponent_p,p{constraint},options,p_base_parametric,ParametricIndicies,MonomIndicies,constraint==1);
% SAVE FOR LATER
BlockedN{constraint} = N;
Blockedx{constraint} = x;
Blockedvarchange{constraint}=varchange;
end
% *********************************************
%% And now get the SDP formulations
%
% The code above has generated matrices A and b
% in AQ == b(parametric)
%
% We use these to generate kernel or image models
% *********************************************
sol.problem = 0;
switch options.sos.model
case 1
% Kernel model
[F,obj,BlockedQ,Primal_matrices,Free_variables] = create_kernelmodel(BlockedA,Blockedb,F_parametric,parobj,options,[]);
case 2
% Image model
[F,obj,BlockedQ,sol] = create_imagemodel(BlockedA,Blockedb,F_parametric,parobj,options);
case 3
% Un-official model to solve bilinearly parameterized SOS using SDPLR
[F,obj,options] = create_lrmodel(BlockedA,Blockedb,F_parametric,parobj,options,ParametricVariables);
otherwise
end
for constraint = 1:length(p)
if constraint > 1 & isequal(BlockedN{constraint},BlockedN{constraint-1}) & isequal(Blockedx{constraint},Blockedx{constraint-1}) & isequal(Blockedvarchange{constraint},Blockedvarchange{constraint-1}) & isequal(sizep(constraint),sizep(constraint-1))
monoms{constraint} = monoms{constraint-1};
else
monoms{constraint} = [];
totalN{constraint} = [];
N = BlockedN{constraint};
x = Blockedx{constraint};
for i = 1:length(N)
% Original variable
for j = 1:size(N{i},1)
N{i}(j,:)=N{i}(j,:).*Blockedvarchange{constraint};
end
if isempty(N{i})
monoms{constraint} = [monoms{constraint};[]];
else
mi = kron(eye(sizep(constraint)),recovermonoms(N{i},x));
monoms{constraint} = [monoms{constraint};mi];
end
end
if isempty(monoms{constraint})
monoms{constraint}=1;
end
end
end
m = monoms;
function p_base_parametric = parameterizedbase(p,z, params,ParametricIndicies,exponent_p,p_base)
% Check for linear parameterization
parametric_basis = exponent_p(:,ParametricIndicies);
if all(sum(parametric_basis,2)==0)
p_base_parametric = full(p_base(:));
return
end
if all(sum(parametric_basis,2)<=1)
p_base_parametric = full(p_base(:));
n = length(p_base_parametric);
if 1
[ii,vars] = find(parametric_basis);
ii = ii(:)';
vars = vars(:)';
else
ii = [];
vars = [];
js = sum(parametric_basis,1);
indicies = find(js);
for i = indicies
if js(i)
j = find(parametric_basis(:,i));
ii = [ii j(:)'];
vars = [vars repmat(i,1,js(i))];
end
end
end
k = setdiff1D(1:n,ii);
if isempty(k)
p_base_parametric = p_base_parametric.*sparse(ii,repmat(1,1,n),params(vars));
else
pp = params(vars); % Must do this, bug in ML 6.1 (x=sparse(1);x([1 1]) gives different result in 6.1 and 7.0!)
p_base_parametric = p_base_parametric.*sparse([ii k(:)'],repmat(1,1,n),[pp(:)' ones(1,1,length(k))]);
end
else
% Bummer, nonlinear parameterization sucks...
for i = 1:length(p_base)
j = find(exponent_p(i,ParametricIndicies));
if ~isempty(j)
temp = p_base(i);
for k = 1:length(j)
if exponent_p(i,ParametricIndicies(j(k)))==1
temp = temp*params(j(k));
else
temp = temp*params(j(k))^exponent_p(i,ParametricIndicies(j(k)));
end
end
xx{i} = temp;
else
xx{i} = p_base(i);
end
end
p_base_parametric = stackcell(sdpvar(1,1),xx)';
end
function [A,b] = generate_kernel_representation_data(N,N_unique,exponent_m2,exponent_p,p,options,p_base_parametric,ParametricIndicies,MonomIndicies,FirstRun)
persistent saveData
exponent_p_parametric = exponent_p(:,ParametricIndicies);
exponent_p_monoms = exponent_p(:,MonomIndicies);
pcoeffs = getbase(p);
if any(exponent_p_monoms(1,:))
pcoeffs=pcoeffs(:,2:end); % No constant term in p
end
b = [];
parametric = full((~isempty(ParametricIndicies) & any(any(exponent_p_parametric))));
% For problems with a lot of similar cones, this saves some time
reuse = 0;
if ~isempty(saveData) & isequal(saveData.N,N) & ~FirstRun
n = saveData.n;
ind = saveData.ind;
if isequal(saveData.N_unique,N_unique) & isequal(saveData.exponent_m2,exponent_m2)% & isequal(saveData.epm,exponent_p_monoms)
reuse = 1;
end
else
% Congruence partition sizes
for k = 1:size(N,1)
n(k) = size(N{k},1);
end
% Save old SOS definition
saveData.N = N;
saveData.n = n;
saveData.N_unique = N_unique;
saveData.exponent_m2 = exponent_m2;
saveData.N_unique = N_unique;
end
if reuse & options.sos.reuse
% Get old stuff
if size(exponent_m2{1},2)==2 % Stupid set(sos(parametric)) case
ind = spalloc(1,1,0);
ind(1)=1;
allj = 1:size(exponent_p_monoms,1);
used_in_p = ones(size(exponent_p_monoms,1),1);
else
allj = [];
used_in_p = zeros(size(exponent_p_monoms,1),1);
hash = randn(size(exponent_p_monoms,2),1);
exponent_p_monoms_hash = exponent_p_monoms*hash;
for i = 1:size(N_unique,1)
monom = sparse(N_unique(i,3:end));
j = find(exponent_p_monoms_hash == (monom*hash));
if isempty(j)
b = [b 0];
allj(end+1,1) = 0;
else
used_in_p(j) = 1;
allj(end+1,1:length(j)) = j(:)';
end
end
ind = saveData.ind;
end
else
allj = [];
used_in_p = zeros(size(exponent_p_monoms,1),1);
if size(exponent_m2{1},2)==2 % Stupid set(sos(parametric)) case
ind = spalloc(1,1,0);
ind(1)=1;
allj = 1:size(exponent_p_monoms,1);
used_in_p = ones(size(exponent_p_monoms,1),1);
else
% To speed up some searching, we random-hash data
hash = randn(size(exponent_p_monoms,2),1);
for k = 1:length(exponent_m2)
if isempty(exponent_m2{k})
exp_hash{k}=[];
else
exp_hash{k} = sparse((exponent_m2{k}(:,3:end)))*hash; % SPARSE NEEDED DUE TO STRANGE NUMERICS IN MATLAB ON 0s (the stuff will differ on last bit in hex format)
end
end
p_hash = exponent_p_monoms*hash;
ind = spalloc(size(N_unique,1),sum(n.^2),0);
for i = 1:size(N_unique,1)
monom = N_unique(i,3:end);
monom_hash = sparse(monom)*hash;
LHS = 0;
start = 0;
for k = 1:size(N,1)
j = find(exp_hash{k} == monom_hash);
if ~isempty(j)
pos=exponent_m2{k}(j,1:2);
nss = pos(:,1);
mss = pos(:,2);
indicies = nss+(mss-1)*n(k);
ind(i,indicies+start) = ind(i,indicies+start) + 1;
end
start = start + (n(k))^2;
% start = start + (matrixSOSsize*n(k))^2;
end
j = find(p_hash == monom_hash);
if isempty(j)
allj(end+1,1) = 0;
else
used_in_p(j) = 1;
allj(end+1,1:length(j)) = j(:)';
end
end
end
end
saveData.ind = ind;
% Some parametric terms in p(x,t) do not appear in v'Qv
% So these have to be added 0*Q = b
not_dealt_with = find(used_in_p==0);
while ~isempty(not_dealt_with)
j = findrows(exponent_p_monoms,exponent_p_monoms(not_dealt_with(1),:));
allj(end+1,1:length(j)) = j(:)';
used_in_p(j) = 1;
not_dealt_with = find(used_in_p==0);
ind(end+1,1)=0;
end
matrixSOSsize = length(p);
if parametric
% Inconsistent behaviour in MATLAB
if size(allj,1)==1
uu = [0;p_base_parametric];
b = sum(uu(allj+1))';
else
b = [];
for i = 1:matrixSOSsize
for j = i:matrixSOSsize
if i~=j
uu = [0;2*p_base_parametric(:,(i-1)*matrixSOSsize+j)];
else
uu = [0;p_base_parametric(:,(i-1)*matrixSOSsize+j)];
end
b = [b sum(uu(allj+1),2)'];
end
end
end
else
if matrixSOSsize == 1
uu = [zeros(size(pcoeffs,1),1) pcoeffs]';
b = sum(uu(allj+1,:),2)';
else
b = [];
for i = 1:matrixSOSsize
for j = i:matrixSOSsize
if i~=j
uu = [0;2*pcoeffs((i-1)*matrixSOSsize+j,:)'];
else
uu = [0;pcoeffs((i-1)*matrixSOSsize+j,:)'];
end
b = [b;sum(uu(allj+1,:),2)'];
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -