Home > utilities > pen2bmi.m

pen2bmi

PURPOSE ^

PEN2BMI converts input structure PEN for PENBMI (as described

SYNOPSIS ^

function [bmidata]=pen2bmi(pen, name)

DESCRIPTION ^

 PEN2BMI converts input structure PEN for PENBMI (as described 
 in PENOPT/PENBMI manual Section 5.2) into a structure accepted by 
 PENLAB via BMI or PMI modules, for details see manual or
    modules/BMI/bmi_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.

 See also yalmip2bmi, example_yalmip, bmi_define

 Example:
    bmi=pen2bmi(pen);
    penm = bmi_define(bmi);
    prob = penlab(penm);
    solve(prob);

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

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

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