为什么我会从MILP问题中得到非整数结果?

问题描述 投票:1回答:1

我有一个用于饮食线性编程问题的matlab脚本。我正在尝试将linearprog或(intlinprog)的结果与工具箱CPLEX为IBM Matlab提供的cplexlp(或cplexmilp)函数的结果进行比较这是脚本

    %% Defining Variables 
clear;clc
Pnames = ["BEEF";
                    "CHK";
                    "FISH";
                    "HAM";
                    "MCH";
                    "MTL";
                    "SPG";
                    "TUR" ];
Packs = optimvar('Packs',Pnames,'Type','integer');
Packs.LowerBound = 2*ones(length(Pnames),1);
Packs.UpperBound = 10*ones(length(Pnames),1);
%% Setting the problem data
CostPerPack = [3.19;2.59;2.29;2.89;1.89;1.99;1.99;2.49];
VitA = [60;8;8;40;15;70;25;60];
VitC = [20;0;10;40;35;30;50;20];
VitB1 = [10;20;15;35;15;15;25;15];
VitB2 = [15;20;10;10;15;15;15;10];
NA = [938;2180;945;278;1182;896;1329;1397];
CAL = [295;770;440;430;315;400;370;450];
% Amount Per package table
TAMT = table(VitA,VitC,VitB1,VitB2,NA,CAL,...
    'VariableNames',{'A','C','B1','B2','NA','CAL'},...
    'RowNames',Pnames);
%% Objective 
TotCost = sum(CostPerPack .* Packs); % Objective 
obj = TotCost;
%% Constraints 
prob = optimproblem('Objective',obj,'ObjectiveSense','min');
prob.Constraints.c1 = sum(VitA.*Packs) >= 700;
prob.Constraints.c1a = sum(VitA.*Packs) <= 20000;
prob.Constraints.c2 = sum(VitC.*Packs) >= 700;
prob.Constraints.c2a = sum(VitC.*Packs) <= 20000;
prob.Constraints.c3 = sum(VitB1.*Packs) >= 700;
prob.Constraints.c3a = sum(VitB1.*Packs) <= 20000;
prob.Constraints.c4 = sum(VitB2.*Packs) >= 700;
prob.Constraints.c4a = sum(VitB2.*Packs) <= 20000;
prob.Constraints.c5 = sum(NA.*Packs) >= 0;
prob.Constraints.c5a = sum(NA.*Packs) <= 40000;
prob.Constraints.c5 = sum(CAL.*Packs) >= 16000;
prob.Constraints.c5a = sum(CAL.*Packs) <= 24000;
%% Putting the problem together and solving
problem = prob2struct(prob);
% LP
% [sol,fval,exitflag,output1] = linprog(problem);
% [sol2,fval2,exitflag2,output2] = cplexlp(problem);
% MILP problem
[sol,fval,exitflag,output1] = intlinprog(problem);
[sol2,fval2,exitflag2,output2] =cplexmilp(problem);
%% Display 
disp('Linear Prog function results')
if (~isempty(sol) )
T1 = table(sol,sol.*VitA,sol.*VitC,sol.*VitB1,sol.*VitB2,sol.*NA,sol.*CAL,sol.*CostPerPack,...
    'VariableNames',{'NuofPacks','PerVitA','PerVitC','PerVitB1','PerVitB2','NA','CAL','Cost'},...
    'RowNames',Pnames);
sumrow = array2table(sum(T1.Variables),...
    'VariableNames',...
    {'NuofPacks','PerVitA','PerVitC','PerVitB1','PerVitB2','NA','CAL','Cost'},...
    'RowNames',"Sum");
T1 = [T1;sumrow];
disp(T1)
else
    disp(['No feasible Solution with exit flag = ' ,num2str(exitflag)])
end
%% Display Cplex
disp('Cplex function results')
if (~isempty(sol2) )
T2 = table(sol2,sol2.*VitA,sol2.*VitC,sol2.*VitB1,sol2.*VitB2,sol2.*NA,sol2.*CAL,sol2.*CostPerPack,...
    'VariableNames',{'NuofPacks','PerVitA','PerVitC','PerVitB1','PerVitB2','NA','CAL','Cost'},...
    'RowNames',Pnames);
sumrow2 = array2table(sum(T2.Variables),...
    'VariableNames',...
    {'NuofPacks','PerVitA','PerVitC','PerVitB1','PerVitB2','NA','CAL','Cost'},...
    'RowNames',"Sum");
T2 = [T2;sumrow2];
disp(T2)
else
    disp(['No feasible Solution with exit flag = ' ,num2str(exitflag2)])
end

以及此处的Cplex函数结果

NuofPacks    PerVitA    PerVitC    PerVitB1    PerVitB2     NA       CAL       Cost 
        _________    _______    _______    ________    ________    _____    ______    ______

BEEF          2         120         40          20        30        1876       590      6.38
CHK          10          80          0         200       200       21800      7700      25.9
FISH          2          16         20          30        20        1890       880      4.58
HAM           2          80         80          70        20         556       860      5.78
MCH          10         150        350         150       150       11820      3150      18.9
MTL          10         700        300         150       150        8960      4000      19.9
SPG      7.3333      183.33     366.67      183.33       110        9746    2713.3    14.593
TUR           2         120         40          30        20        2794       900      4.98
Sum      45.333      1449.3     1196.7      833.33       700       59442     20793    101.01

从intlinprog获得的MILP的结果似乎很好,但是从cplexmilp中获得SPG软件包的非整数值。有人可以帮我知道这里的问题吗?在此先感谢

matlab cplex mixed-integer-programming
1个回答
0
投票

问题如下:当您调用problem = prob2struct(prob);时,来自prob的完整性信息会被带入problem.intcon,但不幸的是,它不会被带入cplex。

此问题以前出现过,但由于有一个简单的解决方法,因此无法在cplex中直接解决:替换呼叫

[sol2,fval2,exitflag2,output2] =cplexmilp(problem);

with

[sol2,fval2,exitflag2,output2] = ...
    cplexmilp(problem.f, problem.Aineq, problem.bineq, problem.Aeq, ...
              problem.beq, [], [], [], problem.lb, problem.ub, ...
              intcon_ctype(length(problem.lb),problem.intcon));

其中intcon_ctype函数为:

function ctype = intcon_ctype(numvars, intcon)
   ctype = char(ones(1, numvars) * 'C');
   for i = 1:length(intcon)
      ctype(intcon(i)) = 'I'
   end
end

注意,这是非常简单的intcon_ctype转换函数。如果变量是二进制的,则可能要检查lb / ub值并将类型设置为'B',可以指定半连续变量,等等。

© www.soinside.com 2019 - 2024. All rights reserved.