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

📄 dualize.m

📁 optimization toolbox
💻 M
📖 第 1 页 / 共 2 页
字号:
function [Fdual,objdual,X,t,err] = dualize(F,obj,auto,extlp,extend)
% DUALIZE Create the dual of an SDP given in primal form
%
% [Fd,objd,X,t,err] = dualize(F,obj,auto)
%
% Input
%  F    : Primal constraint in form AX=b+dt, X>0, t free.
%  obj  : Primal cost CX+ct
%  auto : If set to 0, YALMIP will not automatically handle variables
%        and update variable values when the dual problem is solved.
%  extlp: If set to 0, YALMIP will not try to perform variables changes in
%         order to convert simple translated LP cones (as in x>1) to
%         standard unit cone constraints (x>0)
%
% Output
%  Fd  : Dual constraints in form C-A'y>0, c-dy==0
%  obj : Dual cost b'y (to be MAXIMIZED!)
%  X   : The detected primal cone variables
%  t   : The detected primal free variables
%  err : Error status (returns 0 if no problems)
%
% Example
%  See the HTML help.
%
% See also DUAL, SOLVESDP, PRIMALIZE

% Author Johan L鰂berg
% $Id: dualize.m,v 1.53 2006/11/21 16:10:23 joloef Exp $

% Check for unsupported problems

if isempty(F)
    F = set([]);
end

if nargin < 2
    obj = [];
end

err = 0;
p1 = ~(isreal(F) & isreal(obj));
p2 = ~(islinear(F) & islinear(obj));
p3 = any(is(F,'integer')) | any(is(F,'binary'));
if p1 | p2 | p3
    if nargout == 5
        Fdual = set([]);objdual = [];y = []; X = []; t = []; err = 1;
    else
        problems = {'Cannot dualize complex-valued problems','Cannot dualize nonlinear problems','Cannot dualize discrete problems'};
        error(problems{min(find([p1 p2 p3]))});
    end
end

if nargin<5
    extend = 1;
end

if extend
    options.dualize = 1;
    options.allowmilp = 0;
    options.solver = '';
    [F,failure,cause] = expandmodel(F,obj,options);
    if failure
        error('Failed during convexity propagation. Avoid nonlinear operators when applying dualization.');
    end
end

if nargin<3
    auto = 1;
end

if nargin<4
    extlp = 1;
end

% Cones and equalities
F_AXb = set([]);


% Shiftmatrix is a bit messy at the moment.
% We want to be able to allow cones X>shift
% by using a new variable X-shift = Z
shiftMatrix = {};
X={};

% First, get variables in initial SDP cones
% We need this to avoid adding the same variable twice
% when we add simple LP constraints (as in P>0, P(1,3)>0)
varSDP = [];
SDPset = zeros(length(F),1);
isSDP = is(F,'sdp');
for i = 1:length(F)
    if isSDP(i);
        Fi = sdpvar(F(i));
        if is(Fi,'shiftsdpcone')
            vars = getvariables(Fi);
            if isempty(findrows(varSDP,[vars(1) vars(end)]))
                SDPset(i) = 1;
                varSDP = [varSDP;vars(1) vars(end)];
                shiftMatrix{end+1} = getbasematrix(Fi,0);
                X{end+1}=Fi;
            end
        end
    end
end
F_SDP = F(find(SDPset));
F = F(find(~SDPset));

% Same thing for second order cones
% However, we must not add any SOC cones
% that we already defined as SDP cones
varSOC = [];
SOCset = zeros(length(F),1);
isSOCP = is(F,'socp');
for i = 1:length(F)
    if isSOCP(i);%is(F(i),'socp')
        Fi = sdpvar(F(i));
        if is(Fi,'socone')
            vars = getvariables(Fi);
            % Make sure these variables are not SDP cone variables
            % This can actually only happen for set(X>0) + set(Xcone((2:end,1),X(1)))
            if ~isempty(varSDP)
                inSDP = any(varSDP(:,1)<=vars(1)& vars(1) <=varSDP(:,2)) | any(varSDP(:,1)<=vars(end)& vars(end) <=varSDP(:,2));
            else
                inSDP = 0;
            end
            if ~inSDP
                SOCset(i) = 1;
                vars = getvariables(Fi);
                varSOC = [varSOC;vars(1) vars(end)];
                shiftMatrix{end+1} = getbasematrix(Fi,0);
                X{end+1}=Fi;
            end
        end
    end
end
F_SOC = F(find(SOCset));
F = F(find(~SOCset));

% Merge SDP and SOC data
varCONE = [varSDP;varSOC];
F_CONE = F_SDP + F_SOC;

% Find all LP constraints, add slacks and extract simple cones
% to speed up things, we treat LP cone somewhat different
% compared to the conceptually similiar SOCP/SDP cones
% This code is pretty messy, since there are a lot off odd
% cases to take care of (x>0 and x>1 etc etc)
elementwise = is(F,'element-wise');
elementwise_index = find(elementwise);
if ~isempty(elementwise_index)

    % Find element-wise inequalities
    Flp = F(elementwise_index);
    F = F(find(~elementwise)); % remove these LPs
    % Find LP cones
    lpconstraint = [];
    for i = 1:length(Flp)
        temp = sdpvar(Flp(i));
        if min(size(temp))>1
            temp = temp(:);
        end
        lpconstraint = [lpconstraint reshape(temp,1,length(temp))];
    end

    % Find all constraints of type a_i+x_i >0 and extract the unique and
    % most constraining inequalities (i.e. remove redundant lower bounds)
    base = getbase(lpconstraint);
    candidates = find(sum(base(:,2:end)~=0,2)==1);
    if length(candidates)>0
        % The other ones...
        alwayskeep = find(sum(base(:,2:end)~=0,2)~=1);
        w1 =  lpconstraint(alwayskeep);
        w2 =  lpconstraint(candidates);
                  
        % Find unique rows
        base = getbase(w2);
        [i,uniquerows,k] = unique(base(:,2:end)*randn(size(base,2)-1,1));   
        aUniqueRow=k(:)';
        keep = [];
        rhsLP = base(:,1);
        rr = histc(k,[1:max(k)]);
        if all(rr==1)
            lpconstraint = [w1 w2];
        else
            for i=1:length(k)
                sameRow=find(k==k(i));
                if length(sameRow)==1
                    keep = [keep sameRow];
                else
                    rhs=base(sameRow,1);
                    [val,pos]=min(rhsLP(sameRow));
                    keep = [keep sameRow(pos)];
                end
            end
            lpconstraint = [w1 w2(unique(keep))];
        end
       
    end

    % LP cone will be saved in a vector for speed
    x = [];

    % Pure cones of the type x>0
    base = getbase(lpconstraint);
    purelpcones = (base(:,1)==0) & (sum(abs(base(:,2:end)),2)==1) & (sum(base(:,2:end)==1,2)==1);
    if ~isempty(purelpcones)
        x  = [x lpconstraint(purelpcones)];      
        lpconstraint = lpconstraint(find(~purelpcones));
    end

    
    % Translated cones x>k, k positive
    % User does not want to make variable changes based on k
    % But if k>=0, we can at-least mark x as a simple LP cone variable and
    % thus avoid a free variable.
    if ~extlp & ~isempty(lpconstraint)
        base = getbase(lpconstraint);
        lpcones = (base(:,1)<0) & (sum(abs(base(:,2:end)),2)==1) & (sum(base(:,2:end)==1,2)==1);
        if ~isempty(find(lpcones))
            s = recover(getvariables(lpconstraint(find(lpcones))));
            x  = [x reshape(s,1,length(s))];
        end
    end

    % Translated cones x>k
    % Extract these and perform the associated variable change y=x-k
    if ~isempty(lpconstraint)%Avoid warning in 5.3.1
       base = getbase(lpconstraint);
       lpcones = (sum(abs(base(:,2:end)),2)==1) & (sum(base(:,2:end)==1,2)==1);
       if ~isempty(lpcones) & extlp
          x  = [x lpconstraint(find(lpcones))];
          nlp = lpconstraint(find(~lpcones));
          if ~isempty(nlp)
             s = sdpvar(1,length(nlp));
             F_AXb = F_AXb + set(nlp-s==0);
             x = [x s];
          end
       elseif length(lpconstraint) > 0
          s = sdpvar(1,length(lpconstraint));
          x = [x s]; % New LP cones
          F_AXb = F_AXb + set(lpconstraint-s==0);
       end
    end
    
    
    % Sort asccording to variable index
    % (Code below assumes x is sorted in increasing variables indicies)
    base = getbase(x);base = base(:,2:end);[i,j,k] = find(base);
    x = x(i);
    xv = getvariables(x);
        
    % For mixed LP/SDP problems, we must ensure that LP cone variables are
    % not actually an element in a SDP cone variable  
    if ~isempty(varCONE)        
        keep = zeros(length(x),1);
        for i = 1:length(xv)
            if any(varCONE(:,1)<=xv(i) & xv(i) <=varCONE(:,2))
            else
                keep(i) = 1;
            end
        end
        if ~all(keep)
            % We need to add some explicit constraints on some elements and
            % remove the x variables since they are already in a cone
            % variable
            xcone = x(find(~keep));
            s = sdpvar(1,length(xcone));
            F_AXb = F_AXb + set(xcone-s==0);
            x = x(find(keep));
            x = [x s];
        end
    end
else
    x = [];
end

% Check for mixed cones, ie terms C-A'y > 0.
keep = ones(length(F),1);
isSDP  = is(F,'sdp');
isSOCP = is(F,'socp');

% Pre-allocate all SDP slacks in one call
% This is a lot faster
if nnz(isSDP) > 0
    SDPindicies = find(isSDP)';
    for i = 1:length(SDPindicies)%find(isSDP)'
        Fi = sdpvar(F(SDPindicies(i)));
        ns(i) = size(Fi,1);
        ms(i) = ns(i);
    end
    Slacks = sdpvar(ns,ms);
    if ~isa(Slacks,'cell')
        Slacks = {Slacks};
    end
end
prei = 1;
for i = 1:length(F)
    if isSDP(i)
        % Semidefinite dual-form cone
        Fi = sdpvar(F(i));
        n  = size(Fi,1);
 %      S  = sdpvar(n,n);
        S  = Slacks{prei};prei = prei + 1;
        slack = Fi-S;
        ind = find(triu(reshape(1:n^2,n,n)));
        F_AXb =  F_AXb + set(slack(ind)==0);
        F_CONE = F_CONE + lmi(S,[],[],[],1);
        shiftMatrix{end+1} = spalloc(n,n,0);
        X{end+1}=S;
        keep(i)=0;
    elseif isSOCP(i)
        % SOC dual-form cone
        Fi = sdpvar(F(i));
        n  = size(Fi,1);
       S  = sdpvar(n,1);
%        S = Slacks{i};
        slack = Fi-S;
        F_AXb =  F_AXb + set(slack==0);
        F_CONE = F_CONE + set(cone(S(2:end),S(1)));
        shiftMatrix{end+1} = spalloc(n,1,0);
        X{end+1}=S;
        keep(i)=0;
    end
end

% Now, remove all mixed cones...
F = F(find(keep));

% Get the equalities
AXbset = is(F,'equality');
if any(AXbset)
    % Get the constraints
    F_AXb = F_AXb + F(find(AXbset));
    F = F(find(~AXbset));
end

% Is thee something we missed in our tests?
if length(F)>0
    error('DUALIZE can only treat standard SDPs (and LPs) at the moment.')
end

⌨️ 快捷键说明

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