Home > utilities > didi2bmi2.m

didi2bmi2

PURPOSE ^

This routine converts input structure PEN for PenBMI (as described

SYNOPSIS ^

function [bmidata]=didi2bmi2(pen, name)

DESCRIPTION ^

 This routine converts input structure PEN for PenBMI (as described 
 in PenOpt/PenBMI manual Section 5.2) into a structure accepted by 
 PenLab via BMI2 or PMI modules, for details see manual or
    modules/BMI2/bmi2_define.m.
 Note that the convertor doesn't do any heavy checking on the input
 structure. If there were any inconsistencies in 'pen' it might be
 noticed either here or in bmi2_define().

 Structure 'pen' can be also obtained via YALMIP as internal input
 for PenBMI.

 Example:
    load didi/pen-f4e.mat
    didi
    bmidata = didi2bmi2(pen,'f4e')
    penm = bmi2_define(bmidata);
    prob = penlab(penm);
    prob.solve();
    ...

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 % This routine converts input structure PEN for PenBMI (as described
0002 % in PenOpt/PenBMI manual Section 5.2) into a structure accepted by
0003 % PenLab via BMI2 or PMI modules, for details see manual or
0004 %    modules/BMI2/bmi2_define.m.
0005 % Note that the convertor doesn't do any heavy checking on the input
0006 % structure. If there were any inconsistencies in 'pen' it might be
0007 % noticed either here or in bmi2_define().
0008 %
0009 % Structure 'pen' can be also obtained via YALMIP as internal input
0010 % for PenBMI.
0011 %
0012 % Example:
0013 %    load didi/pen-f4e.mat
0014 %    didi
0015 %    bmidata = didi2bmi2(pen,'f4e')
0016 %    penm = bmi2_define(bmidata);
0017 %    prob = penlab(penm);
0018 %    prob.solve();
0019 %    ...
0020 %
0021 function [bmidata]=didi2bmi2(pen, name)
0022 
0023   if (nargin<=1)
0024     name='BMI2 from convertor didi2bmi2()';
0025   end
0026 
0027   %%%%%%%%%  Convert the data %%%%%%%%%
0028 
0029   bmidata = [];
0030   bmidata.name = name;
0031 
0032   % no of variables
0033   if (~isfield(pen,'vars') || pen.vars<=0)
0034     error('Input: wrong or missing vars component in pen.');
0035   end
0036   bmidata.Nx = pen.vars;
0037   Nx = pen.vars;
0038 
0039   % if present, copy starting point
0040   if (isfield(pen,'x0'))
0041     if (isempty(pen.x0) || ~isvector(pen.x0) || length(pen.x0)~=Nx)
0042       error('Input: starting point x0 is incompatible.');
0043     end
0044     bmidata.xinit = pen.x0;
0045   end
0046 
0047   % dense vector of the linear part of objective function
0048   if (isfield(pen,'fobj') && ~isempty(pen.fobj))
0049     bmidata.c = pen.fobj;
0050   end
0051 
0052   % if present, quadratic part of the objective function
0053   if (isfield(pen,'q_nzs') && ~isempty(pen.q_nzs) && pen.q_nzs>0)
0054     if (~isfield(pen,'q_row') || ~isfield(pen,'q_col') || ~isfield(pen,'q_val'))
0055       error('Input: incomplete quadratic part of the objective.');
0056     end
0057     H = sparse(pen.q_row+1, pen.q_col+1, pen.q_val,Nx,Nx,pen.Q_nzs);
0058     % only upper triangle, symmetrize
0059     bmidata.H = H + triu(H,1)';
0060   end
0061 
0062   % block of linear constraints stored in 'pen' in the form Bx<=c
0063   if (isfield(pen,'constr') && ~isempty(pen.constr) && pen.constr>0)
0064     if (~isfield(pen,'bi_dim') || ~isfield(pen,'bi_idx') || ...
0065       ~isfield(pen,'bi_val') || ~isfield(pen,'ci'))
0066       error('Input: incomplete linear constraints Bx<=c.');
0067     end
0068     if (any(pen.bi_dim<0))
0069       error('Input: bi_dim has negative components.');
0070     end
0071 
0072     % convert CCS -> CS
0073     nnzB=sum(pen.bi_dim);
0074     brows=[];
0075     for idx=1:pen.constr
0076       brows=[brows;idx*ones(pen.bi_dim(idx),1)];
0077     end
0078     B = sparse(brows,pen.bi_idx+1,pen.bi_val,pen.constr,Nx,nnzB);
0079     bmidata.B = B;
0080     bmidata.ubg = pen.ci;
0081   end
0082 
0083   % matrix constraints
0084   if (isfield(pen,'mconstr') && ~isempty(pen.mconstr) && pen.mconstr>0)
0085     if (~isfield(pen,'msizes') || any(pen.msizes<1))
0086       error('Input: msizes missing or wrong.');
0087     end
0088 
0089     % linear matrix terms - OK?
0090     if (isfield(pen,'ai_dim'))
0091       if (isempty(pen.ai_dim) || any(pen.ai_dim<0) || ...
0092         ~isfield(pen,'ai_idx') || ...
0093         ~isfield(pen,'ai_nzs') || any(pen.ai_nzs<0) || ...
0094         ~isfield(pen,'ai_val') || ~isfield(pen,'ai_col') || ...
0095         ~isfield(pen,'ai_row'))
0096         error('Input: incomplete linear matrix terms A_i^k.');
0097       end
0098     else
0099       % linear SDP terms missing? assume that all are empty
0100       pen.ai_dim=zeros(pen.mconstr,1);
0101       pen.ai_idx=zeros(1,1);
0102       pen.ai_nzs=zeros(1,1);
0103       pen.ai_val=zeros(1,1);
0104       pen.ai_col=zeros(1,1);
0105       pen.ai_row=zeros(1,1);
0106     end
0107 
0108     % bilinear matrix terms - OK?
0109     if (isfield(pen,'ki_dim'))
0110       if (isempty(pen.ki_dim) || any(pen.ki_dim<0) || ...
0111         ~isfield(pen,'ki_idx') || ~isfield(pen,'kj_idx') || ...
0112         ~isfield(pen,'ki_nzs') || any(pen.ki_nzs<0) || ...
0113         ~isfield(pen,'ki_val') || ~isfield(pen,'ki_col') || ...
0114         ~isfield(pen,'ki_row'))
0115         error('Input: incomplete bilinear matrix terms K_ij^k.');
0116       end
0117     else
0118       % bilinear SDP terms missing --> just linear SDP, no higher order matrices
0119       pen.ki_dim=zeros(pen.mconstr,1);
0120       pen.ki_idx=zeros(1,1);
0121       pen.kj_idx=zeros(1,1);
0122       pen.ki_nzs=zeros(1,1);
0123       pen.ki_val=zeros(1,1);
0124       pen.ki_col=zeros(1,1);
0125       pen.ki_row=zeros(1,1);
0126     end
0127 
0128     bmidata.Na = pen.mconstr;
0129     bmidata.A = cell(pen.mconstr,1);
0130 
0131     % copy one matrix constraint at a time
0132     midxAstart=1;          % indices to *_nzs() and *_idx() arrays
0133     midxKstart=1;
0134     idxA=1;                % indices to *_val, *_col, *_row arrays
0135     idxK=1;
0136 
0137     for k=1:pen.mconstr
0138       midxAend=midxAstart+pen.ai_dim(k)-1;
0139       midxKend=midxKstart+pen.ki_dim(k)-1;
0140       nnzAsum=sum(pen.ai_nzs(midxAstart:midxAend));
0141       nnzKsum=sum(pen.ki_nzs(midxKstart:midxKend));
0142 
0143       bmidata.A{k} = copy_mconstr(pen.msizes(k),pen.ai_dim(k),pen.ki_dim(k),...
0144         pen.ai_idx(midxAstart:midxAend), ...
0145         pen.ki_idx(midxKstart:midxKend), pen.kj_idx(midxKstart:midxKend), ...
0146         pen.ai_nzs(midxAstart:midxAend), ...
0147         pen.ai_val(idxA:end), pen.ai_row(idxA:end), pen.ai_col(idxA:end),...
0148         pen.ki_nzs(midxKstart:midxKend), ...
0149         pen.ki_val(idxK:end), pen.ki_row(idxK:end), pen.ki_col(idxK:end));
0150 
0151 
0152       % move indices in *_nzs arrays
0153       midxAstart=midxAend+1;
0154       midxKstart=midxKend+1;
0155       % move indices in *_val arrays
0156       idxA = idxA+nnzAsum;
0157       idxK = idxK+nnzKsum;
0158     end
0159   end
0160 
0161 end
0162 
0163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0164 % create one matrix constraints from PenBMI data
0165 % in the format required in BMI2/PMI
0166 %
0167 % Input:
0168 %   dim - dimension of the matrix constraint
0169 %   nA, nK - number of matrices in linear and bilinear terms
0170 %   A_idx - dim nA, indices of the linear matrices A_i
0171 %   K_idx, K_jdx - dim nK, i and j indices of bilinear matrices K_ij
0172 %   A_nnz - dim nA, number of nonzeros in each given matrix A_i
0173 %   A_val,col,row - dim sum(A_nnz), matries A_i next to each other
0174 %     stored in CS upper triangle format, 0-based indices row/col
0175 %   K_nnz - dim nK, number of nonzeros in each given K_ij
0176 %   K_val,col,row - dim sum(K_nnz), K_ij matrices, same format as A_i
0177 %
0178 function [Ak] = copy_mconstr(dim,nA,nK,A_idx,K_idx,K_jdx,...
0179   A_nnz,A_val,A_row,A_col,K_nnz,K_val,K_row,K_col)
0180 
0181   if (nA==0 && nK==0)
0182     error('Input: neither linear nor bilinear matrices in this constraint.');
0183   end
0184 
0185   if (nK==0)
0186     maxOrder = 1;
0187     Ak.midx = zeros(maxOrder,nA);
0188     Ak.midx(1,:) = A_idx(1:nA);
0189   else
0190     maxOrder = 2;
0191     Ak.midx = zeros(maxOrder,nA+nK);
0192     Ak.midx(1,1:nA) = A_idx(1:nA);   % midx(2,1:nA) = zeroes()
0193     Ak.midx(1,nA+1:end) = K_idx(1:nK);
0194     Ak.midx(2,nA+1:end) = K_jdx(1:nK);
0195   end
0196   
0197   Ak.Q = cell(nA+nK,1);
0198   % copy linear terms
0199   idx = 1;          % index to _val/_row/_col arrays
0200   for midx=1:nA
0201     idxend = idx+A_nnz(midx)-1;
0202     Qi = sparse(A_row(idx:idxend)+1, A_col(idx:idxend)+1, A_val(idx:idxend),...
0203       dim, dim, A_nnz(midx));
0204     % symmetrize, was just upper triangle
0205     Qi = Qi + triu(Qi,1)';
0206     % swap sign, we want Ak >= 0 (pos. def.) and it was neg. def.
0207     Ak.Q{midx} = -Qi;
0208 
0209     idx = idxend+1;
0210   end
0211 
0212   % copy bilinear terms
0213   idx = 1;          % index to _val/_row/_col arrays
0214   for midx=1:nK
0215     idxend = idx+K_nnz(midx)-1;
0216     Qi = sparse(K_row(idx:idxend)+1, K_col(idx:idxend)+1, K_val(idx:idxend),...
0217       dim, dim, K_nnz(midx));
0218     % symmetrize, was just upper triangle
0219     Qi = Qi + triu(Qi,1)';
0220     % swap sign, we want Ak >= 0 (pos. def.) and it was neg. def.
0221     Ak.Q{nA+midx} = -Qi;
0222 
0223     idx = idxend+1;
0224   end
0225 
0226 end
0227

Generated on Mon 26-Aug-2019 10:22:08 by m2html © 2005