⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dualize.m

📁 optimization toolbox
💻 M
📖 第 1 页 / 共 2 页
字号:

% Sort the SDP cone variables X according to YALMIP
% This is just to simplify some indexing later
ns = [];
first_var = [];
for i = 1:length(F_CONE)    
    ns = [ns length(X{i})];
    first_var = [first_var min(getvariables(X{i}))];    
end
[sorted,index] = sort(first_var);
X={X{index}};
shiftMatrix={shiftMatrix{index}};

shift = [];
for i = 1:length(F_CONE)     
    ns(i) = length(X{i});
    if size(X{i},2)==1
        % SOCP
        shift = [shift;shiftMatrix{i}(:)];
    else
        % SDP
        ind =  find(tril(reshape(1:ns(i)^2,ns(i),ns(i))));
        shift = [shift;shiftMatrix{i}(ind)];
    end
end

% Free variables (here called t) is everything except the cone variables
X_variables = getvariables(F_CONE);
x_variables = getvariables(x);
Xx_variables = [X_variables x_variables]; 

other_variables = [getvariables(obj) getvariables(F_AXb)];
% For quadratic case
%other_variables = [depends(obj) getvariables(F_AXb)];

all_variables = uniquestripped([other_variables Xx_variables]);

% Avoid set-diff 
if isequal(all_variables,Xx_variables)
    t_variables = [];
    t_in_all = [];
    t = [];
else
    t_variables = setdiff(all_variables,Xx_variables);   
    ind = ismembc(all_variables,t_variables);
    t_in_all = find(ind);
    t = recover(t_variables);    
end

ind = ismembc(all_variables,x_variables);
x_in_all = find(ind);
ind = ismembc(all_variables,X_variables);
X_in_all = find(ind);

vecF1 = [];
nvars = length(all_variables);
for i = 1:length(F_AXb)
    AXb = sdpvar(F_AXb(i));
    mapper = find(ismembc(all_variables,getvariables(AXb)));

    [n,m] = size(AXb);
    data = getbase(AXb);
    [iF,jF,sF] = find(data);
    if 1 % New
        smapper = [1 1+mapper(:)'];
        F_structemp = sparse(iF,smapper(jF),sF,n*m,1+nvars);
    else
        F_structemp  = spalloc(n*m,1+nvars,nnz(data));
        F_structemp(:,[1 1+mapper(:)'])= data;
    end
    vecF1 = [vecF1;F_structemp];
end

%Remove trivially redundant constraints
h = 1+rand(size(vecF1,2),1);
h = vecF1*h;
[dummy,uniquerows] =  uniquesafe(h);
if length(uniquerows) < length(h)  
    % Sort to ensure run-to-run consistency
    vecF1 = vecF1((sort(uniquerows)),:);
end

if isempty(obj)
    vecF1(end+1,1) = 0;
else
    if is(obj,'linear')
        mapper = find(ismembc(all_variables,getvariables(obj)));
        [n,m] = size(obj);
        data = getbase(obj);
        [iF,jF,sF] = find(data);
        if 1
            smapper = [1 1+mapper(:)'];
            F_structemp = sparse(iF,smapper(jF),sF,n*m,1+nvars);  
        else
            F_structemp  = spalloc(n*m,1+nvars,nnz(data));
            F_structemp(:,[1 1+mapper(:)'])= data;
        end
        vecF1 = [vecF1;F_structemp];
    else
        % FIX: Generalize to QP duality
        % min c'x+0.5x'Qx, Ax==b, x>=0
        % max b'y-0.5x'Qx, c-A'y+Qx >=0 
        [Q,c,xreally,info] = quaddecomp(obj,recover(all_variables))
        mapper = find(ismembc(all_variables,getvariables(c'*xreally)));
        [n,m] = size(c'*xreally);
        data = getbase(c'*xreally);
        F_structemp  = spalloc(n*m,1+nvars,nnz(data));
        F_structemp(:,[1 1+mapper(:)'])= data;
        vecF1 = [vecF1;F_structemp]
    end
   
end

vecF1(end+1,1) = 0;
Fbase = vecF1;

%Fbase = unique(Fbase','rows')';

b = Fbase(1:end-2,1);

Fbase = -Fbase(1:end-1,2:end);
vecA = [];
Fbase_t = Fbase(:,t_in_all);
Fbase_x = Fbase(:,x_in_all);
Fbase_X = Fbase;
%Fbase_X(:,unionstripped(t_in_all,x_in_all)) = [];
if 1
    removethese = unique([t_in_all x_in_all]);
    if length(removethese) > 0.5*size(Fbase_X,2)
        Fbase_X = Fbase_X(:,setdiff(1:size(Fbase_X,2),removethese));
    else
        Fbase_X(:,[t_in_all x_in_all]) = [];
    end
else
    removecols = uniquestripped([t_in_all x_in_all]);
    if ~isempty(removecols)
     [i,j,k] = find(Fbase_X);
     keep = find(~ismember(j,removecols));
     i = i(keep);
     k = k(keep);
     j = j(keep);
     map = find(1:length(unique(j)),j);
   
    end
end

% Shift due to translated dual cones X = Z+shift
if length(shift > 0)
    b = b + Fbase_X(1:end-1,:)*shift;
end
if length(x)>0
    % Arrgh
    base = getbase(x);
    constant = base(:,1);
    base = base(:,2:end);[i,j,k] = find(base);
    b = b + Fbase_x(1:end-1,:)*constant(i);
end

start = 0;
n_cones = length(ns);
% All LPs in one cone
if length(x)>0
    n_lp = 1;
else
    n_lp = 0;
end
n_free = length(t_variables);

% SDP cones
for j = 1:1:n_cones

    if size(X{j},1)==size(X{j},2)
        % SDP cone
        ind = reshape(1:ns(j)^2,ns(j),ns(j));
        ind = find(tril(ind));

        % Get non-symmetric constraint AiX=b
        Fi = Fbase_X(1:length(b),start+(1:length(ind)))'/2;
        
        if 1
            [iF,jF,sF] = find(Fi);
            iA = ind(iF);
            jA = jF;
            sA = sF;
            the_col = 1+floor((iA-1)/ns(j));
            the_row = iA-(the_col-1)*ns(j);
            these_must_be_transposed = find(the_row > the_col);
            if ~isempty(these_must_be_transposed)
                new_rowcols = the_col(these_must_be_transposed) + (the_row(these_must_be_transposed)-1)*ns(j);
                iA = [iA;new_rowcols];
                jA = [jA;jA(these_must_be_transposed)];
                sA = [sA;sA(these_must_be_transposed)];
            end
            % Fix diagonal term
            diags = find(diag(1:ns(j)));
            id = find(ismembc(iA,diags));
            sA(id) = 2*sA(id);
            Ai = sparse(iA,jA,sA,ns(j)^2,length(b));

        else % Old slooooooow version
            Ai = spalloc(ns(j)^2,length(b),nnz(Fi));
            Ai(ind,:) = Fi;
            % Symmetrize
            [rowcols,varindicies,vals]=find(Ai);
            the_col = 1+floor((rowcols-1)/ns(j));
            the_row = rowcols-(the_col-1)*ns(j);
            these_must_be_transposed = find(the_row > the_col);
            if ~isempty(these_must_be_transposed)
                new_rowcols = the_col(these_must_be_transposed) + (the_row(these_must_be_transposed)-1)*ns(j);
                Ai(sub2ind(size(Ai),new_rowcols,varindicies(these_must_be_transposed))) = vals(these_must_be_transposed);
            end

            % Fix diagonal term
            diags = find(diag(1:ns(j)));
            Ai(diags,:) = 2*Ai(diags,:);
        end
        
%        if norm(Ai-Ai2,inf)>1e-12
%            error
%        end
      
        
        vecA{j} = Ai;

        start = start + length(ind);
    else
        % Second order cone
        ind = 1:ns(j);

        % Get constraint AiX=b
        Fi = Fbase_X(1:length(b),start+(1:length(ind)))';
        Ai = spalloc(ns(j),length(b),nnz(Fi));
        Ai(ind,:) = Fi;
        vecA{j} = Ai;
        start = start + length(ind);
    end

end
% LP Cone
if n_lp>0  
    Alp=Fbase_x(1:length(b),:)';
end
% FREE VARIABLES
start = 0;
if n_free>0    
    Afree=Fbase_t(1:length(b),:)';
end

% COST MATRIX
% SDP CONE
start = 0;
for j = 1:1:n_cones
    if size(X{j},1)==size(X{j},2)
       %ind = reshape(1:ns(j)^2,ns(j),ns(j));
       %ind = find(tril(ind));
       %C{j} = spalloc(ns(j),ns(j),0);
       %C{j}(ind) = -Fbase_X(end,start+(1:length(ind)));
       %C{j} = (C{j}+ C{j}')/2;
       %start = start + length(ind);

       ind = reshape(1:ns(j)^2,ns(j),ns(j));
       [indi,indj] = find(tril(ind));
       C{j} = sparse(indi,indj,-Fbase_X(end,start+(1:length(indi))),ns(j),ns(j));
       C{j} = (C{j}+ C{j}')/2;
       start = start + length(indi);            
    else
        ind = 1:ns(j);
        C{j} = spalloc(ns(j),1,0);
        C{j}(ind) = -Fbase_X(end,start+(1:length(ind)));
        start = start + length(ind);
    end
end
% LP CONE
for j = 1:1:n_lp
    Clp = -Fbase_x(end,:)';
end
% FREE CONE
if n_free>0
    Cfree = -Fbase_t(end,1:end)';
end

% Create dual
y = sdpvar(length(b),1);
yvars = getvariables(y);
cf = [];
Af = [];
Fdual = set([]);
for j = 1:n_cones
    if size(X{j},1)==size(X{j},2)
        % Yep, this is optimized...
        S = sdpvar(ns(j),ns(j),[],yvars,[C{j}(:) -vecA{j}]);        
        % Fast call avoids symmetry check
        Fdual = Fdual + lmi(S,[],[],[],1);
    else
        Ay = reshape(vecA{j}*y,ns(j),1);
        S = C{j}-Ay;
        Fdual = Fdual + lmi(cone(S(2:end),S(1)));
    end
end
if n_lp > 0
    keep = any(Alp,2);
    if ~all(keep)
        % Fix for unused primal cones
        preset=find(~keep);
        xfix = x(preset);        
        assign(xfix(:),Clp(preset(:)));       
    end
    keep = find(keep);
    if ~isempty(keep)
        z = Clp(keep)-Alp(keep,:)*y;
        if isa(z,'double')
            assign(x(:),z(:));
        else
            Fdual = Fdual + set(z);
            x =x(keep);
            X{end+1} = x(:); % We have worked with a row for performance reasons
        end
    end
end
if n_free > 0
    CfreeAfreey = Cfree-Afree*y;
    if isa(CfreeAfreey,'double')
        if nnz(CfreeAfreey)>0        
            error('Trivially unbounded!');
        end
    else
        Fdual = Fdual + set(0 == CfreeAfreey);
    end
end

objdual = b'*y;
if auto
    for i = 1:length(X)
        yalmip('associatedual',getlmiid(Fdual(i)),X{i});
    end
    if n_free>0
        yalmip('associatedual',getlmiid(Fdual(end)),t);
    end
end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -