0001 function [Contain OK]=BuildMPS(A, b, Aeq, beq, cost, L, U, PbName, varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 if nargin<8 || isempty(PbName)
0088 PbName='GENERIC';
0089 end
0090
0091
0092
0093
0094 idx1=02:03;
0095 idx2=05:12;
0096 idx3=15:22;
0097 idx4=25:36;
0098 idx5=40:47;
0099 idx6=50:61;
0100 idxlist={idx1 idx2 idx3 idx4 idx5 idx6};
0101
0102
0103
0104
0105 Contain=[];
0106 OK = 0;
0107
0108
0109
0110
0111 [neq nvar]=size(Aeq);
0112 [nle sizeA2]=size(A);
0113
0114 if neq==0
0115 nvar=sizeA2;
0116 Aeq=zeros(0,nvar);
0117 elseif nle==0
0118 sizeA2=nvar;
0119 A=zeros(0,nvar);
0120 end
0121
0122
0123
0124
0125 elenamefun = @elename;
0126 eqtnamefun = @eqtname;
0127 varnamefun = @varname;
0128 MPSfilename = '';
0129
0130
0131 iset = [];
0132 bset = [];
0133
0134
0135
0136
0137 parseoptions(varargin{:});
0138
0139 if ~exist('elenames','var')
0140 elenames=arrayfun(elenamefun, (1:nle), 'UniformOutput', false);
0141 end
0142 if ~exist('eqtnames','var')
0143 eqtnames=arrayfun(eqtnamefun, (1:neq), 'UniformOutput', false);
0144 end
0145 if ~exist('varnames','var')
0146 varnames=arrayfun(varnamefun, (1:nvar), 'UniformOutput', false);
0147 end
0148
0149 if nargin<6 || isempty(L)
0150 L=-inf(1,nvar);
0151 elseif isscalar(L)
0152 Lval=L;
0153 L=zeros(1,nvar);
0154 L(:)=Lval;
0155 else
0156 L = reshape(L,1,[]);
0157 end
0158 if nargin<7 || isempty(U)
0159 U=+inf(1,nvar);
0160 elseif isscalar(U)
0161 Uval=U;
0162 U=zeros(1,nvar);
0163 U(:)=Uval;
0164 else
0165 U = reshape(U,1,[]);
0166 end
0167
0168
0169
0170
0171 if length(beq)~=neq || length(b)~=nle || ...
0172 length(cost)~=nvar || ...
0173 length(L)~=nvar || length(U)~=nvar || ...
0174 sizeA2~=nvar
0175 error('BuildMPS:DimensionsUnMatched', ...
0176 'BuildMPS: dimensions do not match');
0177 end
0178
0179
0180
0181
0182 l_name=setfields([],0,'NAME');
0183 l_name=setfields(l_name,3,PbName);
0184
0185
0186
0187
0188 l_rows=setfields([],0,'ROWS');
0189
0190 l_cost=setfields([],1,'N',2,'COST');
0191
0192 l_rows_eq=emptyline(neq);
0193 for m=1:neq
0194 l_rows_eq(m,:)=setfields(l_rows_eq(m,:),1,'E',2,eqtnames{m});
0195 end
0196
0197 l_rows_le=emptyline(nle);
0198 for m=1:nle
0199 l_rows_le(m,:)=setfields(l_rows_le(m,:),1,'L',2,elenames{m});
0200 end
0201
0202 CostAeq = [cost(:)'; Aeq; A];
0203 MustWrite = (CostAeq ~= 0);
0204 NWrite = sum(MustWrite,1);
0205 NLines = sum(ceil(NWrite/2));
0206
0207
0208
0209
0210 l_columns=setfields([],0,'COLUMNS');
0211 l_columnsbody=emptyline(NLines);
0212
0213 c=0;
0214 for n=1:nvar
0215 var=varnames{n};
0216 field=3;
0217 eqtn = find(MustWrite(:,n));
0218 for m=eqtn(:).'
0219 if m==1
0220 colname='COST';
0221 val = cost(n);
0222 elseif m<=1+neq
0223 colname=eqtnames{m-1};
0224 val=Aeq(m-1,n);
0225 else
0226 colname=elenames{m-(1+neq)};
0227 val=A(m-(1+neq),n);
0228 end
0229 if field==3
0230 c=c+1;
0231 l_columnsbody(c,:)=setfields(l_columnsbody(c,:),...
0232 2,var,...
0233 field,colname, ...
0234 field+1,val);
0235 field=5;
0236 else
0237 l_columnsbody(c,:)=setfields(l_columnsbody(c,:),...
0238 field,colname, ...
0239 field+1,val);
0240 field=3;
0241 end
0242 end
0243 end
0244 l_columnsbody(c+1:end,:)=[];
0245
0246
0247
0248
0249 rhs=[beq(:); b(:)];
0250 MustWrite = (rhs ~= 0);
0251 NWrite = sum(MustWrite);
0252 NLines = ceil(NWrite/2);
0253
0254 l_rhs=setfields([],0,'RHS');
0255 l_rhsbody=emptyline(NLines);
0256 c=0;
0257 field=3;
0258 eqt = find(MustWrite);
0259 for m=eqt(:).'
0260 if m<=neq
0261 colname=eqtnames{m};
0262 val=rhs(m);
0263 else
0264 colname=elenames{m-neq};
0265 val=rhs(m);
0266 end
0267 if field==3
0268 c=c+1;
0269 l_rhsbody(c,:)=setfields(l_rhsbody(c,:),...
0270 2,'RHS',...
0271 field,colname, ...
0272 field+1,val);
0273 field=5;
0274 else
0275 l_rhsbody(c,:)=setfields(l_rhsbody(c,:),...
0276 field,colname, ...
0277 field+1,val);
0278 field=3;
0279 end
0280 end
0281 l_rhsbody(c+1:end,:)=[];
0282
0283
0284
0285
0286 l_bound=setfields([],0,'BOUNDS');
0287
0288 VarType=zeros(size(U));
0289
0290
0291
0292 VarType(:)=0;
0293 VarType(iset) = 1;
0294 VarType(bset) = 2;
0295
0296
0297 L(iset) = max(ceil(L(iset)),0);
0298 U(iset) = floor(U(iset));
0299
0300
0301 L(bset) = 0;
0302 U(bset) = 1;
0303
0304 upinf=(U==inf);
0305 loinf=(L==-inf);
0306 lonz=(L~=0) & ~loinf;
0307
0308 BoundType=zeros(size(U));
0309
0310
0311
0312
0313 BoundType(:) = 3;
0314 BoundType(upinf & loinf) = 1;
0315 BoundType(upinf & lonz) = 2;
0316 BoundType(~upinf & lonz) = 4;
0317 BoundType(~upinf & loinf) = 5;
0318 BoundType(~upinf & ~loinf & ~lonz) = 6;
0319 BoundType(upinf & VarType==1) = 7;
0320 BoundType(bset) = 8;
0321
0322 NLines = sum(ismember(BoundType,[1 2 6 7 8])) + ...
0323 sum(ismember(BoundType,[4 5]))*2;
0324 l_boundbody=emptyline(NLines);
0325 c=0;
0326 for n=1:nvar
0327 var=varnames{n};
0328 lo=L(n);
0329 up=U(n);
0330 vtype = VarType(n);
0331 if (vtype==2)
0332 c=c+1;
0333 l_boundbody(c,:)=setfields(l_boundbody(c,:),...
0334 1, 'BV', ...
0335 2, 'BND1', ...
0336 3, var, ...
0337 4, 1);
0338 elseif (up==inf)
0339 if (lo==-inf)
0340 c=c+1;
0341 l_boundbody(c,:)=setfields(l_boundbody(c,:),...
0342 1, 'FR', ...
0343 2, 'BND1', ...
0344 3, var, ...
0345 4, 0);
0346 elseif (lo~=0) || (vtype==1)
0347 c = c+1;
0348 if vtype==1
0349 LOstr = 'LI';
0350 else
0351 LOstr = 'LO';
0352 end
0353 l_boundbody(c,:)=setfields(l_boundbody(c,:),...
0354 1, LOstr, ...
0355 2, 'BND1', ...
0356 3, var, ...
0357 4, lo);
0358
0359 end
0360 else
0361 if lo>-inf
0362 if lo~=0
0363 c=c+1;
0364 if vtype==1
0365 LOstr = 'LI';
0366 else
0367 LOstr = 'LO';
0368 end
0369 l_boundbody(c,:)=setfields(l_boundbody(c,:),...
0370 1, LOstr, ...
0371 2, 'BND1', ...
0372 3, var, ...
0373 4, lo);
0374
0375 end
0376 else
0377 c=c+1;
0378 l_boundbody(c,:)=setfields(l_boundbody(c,:),...
0379 1, 'MI', ...
0380 2, 'BND1', ...
0381 3, var, ...
0382 4, 0);
0383 end
0384
0385
0386 c=c+1;
0387 if vtype==1
0388 HIstr = 'UI';
0389 else
0390 HIstr = 'UP';
0391 end
0392 l_boundbody(c,:)=setfields(l_boundbody(c,:),...
0393 1, HIstr, ...
0394 2, 'BND1', ...
0395 3, var, ...
0396 4, up);
0397 end
0398 end
0399 l_boundbody(c+1:end,:)=[];
0400
0401
0402
0403
0404 l_end=setfields([],0,'ENDATA');
0405
0406
0407
0408
0409 Contain=[l_name; ...
0410 l_rows; ...
0411 l_cost; ...
0412 l_rows_eq; ...
0413 l_rows_le; ...
0414 l_columns; ...
0415 l_columnsbody; ...
0416 l_rhs; ...
0417 l_rhsbody; ...
0418 l_bound; ...
0419 l_boundbody; ...
0420 l_end];
0421
0422 if ~isempty(MPSfilename)
0423
0424
0425
0426 OK = SaveMPS(MPSfilename, Contain);
0427 if ~OK
0428 warning('BuildMPS:SavingFailure', ...
0429 ['BuildMPS: Cannot save ' MPSfilename]);
0430 end
0431 else
0432 OK = 1;
0433 end
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446 function l=emptyline(n)
0447 if nargin<1 || isempty(n)
0448 n=1;
0449 end
0450 l=char(zeros(n,61));
0451 l(:)=' ';
0452 end
0453
0454
0455
0456
0457 function str=num2fixedlengthstr(num, maxlength, roundingflag)
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471 if nargin<2
0472 maxlength=12;
0473 end
0474
0475 if nargin<3
0476 roundingflag=1;
0477 end
0478
0479 if num>=0
0480 fracNDigits=maxlength;
0481 else
0482 fracNDigits=maxlength-1;
0483 end
0484
0485
0486
0487 str=num2str(num,['%0.' num2str(fracNDigits) 'G']);
0488
0489
0490
0491 while length(str)>maxlength
0492 if regexp(str,'^0\.')
0493 str(1)=[];
0494 continue;
0495 end
0496 [istart iend]=regexp(str,'[+-](0)+');
0497 if ~isempty(istart)
0498 str(istart+1:iend)=[];
0499 continue
0500 else
0501 [istart iend]=regexp(str,'E[+]');
0502 if ~isempty(istart)
0503 str(iend)=[];
0504 continue
0505 end
0506 end
0507 idot=find(str=='.',1,'first');
0508 if ~isempty(idot)
0509 iE=find(str=='E',1,'first');
0510 if roundingflag
0511
0512
0513 if ~isempty(iE)
0514 fracNDigits=maxlength-length(str)+iE-idot-1;
0515 str=num2str(num,['%0.' num2str(fracNDigits) 'E']);
0516 else
0517 fracNDigits=maxlength-idot;
0518 str=num2str(num,['%0.' num2str(fracNDigits) 'f']);
0519 end
0520 roundingflag=0;
0521 continue
0522 else
0523
0524 if ~isempty(iE)
0525 str(maxlength-length(str)+iE:iE-1)=[];
0526 return;
0527 else
0528 str(maxlength+1:end)=[];
0529 return;
0530 end
0531 end
0532 end
0533
0534 error('BuildMPS: cannot convert %0.12e to string\n',num);
0535 end
0536
0537 end
0538
0539
0540
0541
0542 function l=setfield(l,field,var)
0543
0544 if isnumeric(var)
0545 var=num2fixedlengthstr(var);
0546 end
0547
0548 if isempty(l)
0549 l=emptyline;
0550 end
0551 if ~isempty(field) && field>0
0552 idx=idxlist{field};
0553 else
0554 idx=1:61;
0555 end
0556 if length(var)>length(idx)
0557 var=var(1:length(idx));
0558 else
0559 idx=idx(1:length(var));
0560 end
0561 l(idx)=var;
0562
0563 end
0564
0565
0566
0567
0568 function l=setfields(l, varargin)
0569 for k=1:2:length(varargin)
0570 l=setfield(l, varargin{k}, varargin{k+1});
0571 end
0572 end
0573
0574
0575
0576
0577 function name=elename(m)
0578 name=['LE' num2str(m)];
0579 end
0580
0581
0582
0583
0584 function name=eqtname(m)
0585 name=['EQ' num2str(m)];
0586 end
0587
0588
0589
0590
0591 function name=varname(n)
0592 name=['X' num2str(n)];
0593 end
0594
0595
0596
0597
0598 function parseoption(strname, value)
0599 if ischar(strname)
0600 strname = strtrim(lower(strname));
0601 switch strname
0602 case 'elenames',
0603 if ~iscell(value) || length(value)~=nle || ...
0604 ~all(cellfun(@ischar, value))
0605 error('BuildMPS:IncorrectEleNames', ...
0606 'BuildMPS: EleNames must be cell of %d strings', nle);
0607 end
0608 elenames = value;
0609 case 'eqtnames',
0610 if ~iscell(value) || length(value)~=neq || ...
0611 ~all(cellfun(@ischar, value))
0612 error('BuildMPS:IncorrectEqtNames', ...
0613 'BuildMPS: EqtNames must be cell of %d strings', neq);
0614 end
0615 eqtnames = value;
0616 case 'varnames',
0617 if ~iscell(value) || length(value)~=nvar || ...
0618 ~all(cellfun(@ischar, value))
0619 error('BuildMPS:IncorrectVarNames', ...
0620 'BuildMPS: VarNames must be cell of %d strings', nvar);
0621 end
0622 varnames = value;
0623 case 'varnamefun',
0624 if ischar(value)
0625 value=str2func(value);
0626 end
0627 if ~isa(value,'function_handle')
0628 error('BuildMPS:IncorrectVarNameFun', ...
0629 'BuildMPS: VarNameFun must be a function');
0630 end
0631 varnamefun = value;
0632 case 'eqtnamefun',
0633 if ischar(value)
0634 value=str2func(value);
0635 end
0636 if ~isa(value,'function_handle')
0637 error('BuildMPS:IncorrectEqtNameFun', ...
0638 'BuildMPS: EqtNameFun must be a function');
0639 end
0640 eqtnamefun = value;
0641 case 'elenamefun',
0642 if ischar(value)
0643 value=str2func(value);
0644 end
0645 if ~isa(value,'function_handle')
0646 error('BuildMPS:IncorrectEleNameFun', ...
0647 'BuildMPS: EleNameFun must be a function');
0648 end
0649 elenamefun = value;
0650 case 'mpsfilename',
0651 if ~ischar(value)
0652 error('BuildMPS:IncorrectMPSfilename', ...
0653 'BuildMPS: MPSfilename must be a string');
0654 end
0655 MPSfilename = value;
0656 case {'i' 'int' 'integer' 'integers'},
0657 iset = value(:);
0658 if any(iset<1 | iset>nvar)
0659 error('Integer set contains invalid index');
0660 end
0661 case {'b' 'bin' 'binary', 'binaries'},
0662 bset = value(:);
0663 if any(bset<1 | bset>nvar)
0664 error('Binary set contains invalid index');
0665 end
0666 otherwise
0667 warning('BuildMPS:UnknownParams', ...
0668 ['BuildMPS: Unknown parameter ' strname]);
0669 end
0670 else
0671 error('BuildMPS:IncorrectCall', ...
0672 'BuildMPS: options must be pair of Name/Value');
0673 end
0674 end
0675
0676
0677
0678
0679 function parseoptions(varargin)
0680 if mod(nargin,2)
0681 error('BuildMPS:IncorrectCall', ...
0682 'BuildMPS: options must be pair of Name/Value');
0683 end
0684
0685
0686
0687 for ivararg=1:2:nargin
0688 parseoption(varargin{ivararg},varargin{ivararg+1});
0689 end
0690 end
0691
0692 end