线性整数规划的三道经典例题

一、背包问题

1.模型建立

2.代码实现

c = -[540 200 180 350 60 150 280 450 320 120];  % 目标函数的系数矩阵(最大化问题记得加负号)
intcon=[1:10];  % 整数变量的位置(一共10个决策变量,均为0-1整数变量)
A = [6 3 4 5 1 2 3 5 4 2];  b = 30;   % 线性不等式约束的系数矩阵和常数项向量(物品的重量不能超过30)
Aeq = []; beq =[];  % 不存在线性等式约束
lb = zeros(10,1);  % 约束变量的范围下限
ub = ones(10,1);  % 约束变量的范围上限
%最后调用intlinprog()函数
[x,fval]=intlinprog(c,intcon,A,b,Aeq,beq,lb,ub)
fval = -fval

二、指派问题

1.模型建立

2.代码实现

(1)输入目标函数系数

clear;clc
c = [66.8 75.6 87 58.6 57.2 66 66.4 53 78 67.8 84.6 59.4 70 74.2 69.6 57.2 67.4 71 83.8 62.4]'; % 目标函数的系数矩阵(先列后行的写法)
intcon = [1:20]; % 整数变量的位置(一共20个决策变量,均为0-1整数变量)

(2)输入不等式约束

这里着重讲一下约束怎么写,这里的变量有20个,已经很男写了,在运用中可能会有更多,因此一个一个打是不太现实的,可以先将矩阵初始化,然后利用循环添加数值

% 线性不等式约束的系数矩阵和常数项向量(每个人只能入选四种泳姿之一,一共五个约束)
A = [1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
       0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0;
       0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0;
       0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0;
       0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1];
% A=zeros(5,20)
% j=1
% for i=1:5
%     A(i,j:j+3)=1
%     j=j+4
% end
b = [1;1;1;1;1];

(3)输入等式约束

每个项目只能由一名队员参加,在约束的体现上就是由4个单位矩阵拼接

Aeq = [1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0;
          0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0;
          0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0;
          0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1];
% Aeq = [eye(4),eye(4),eye(4),eye(4),eye(4)];  % 或者写成 repmat(eye(4),1,5)  
beq = [1;1;1;1];
lb = zeros(20,1);  % 约束变量的范围下限
ub = ones(20,1);

(4)调用函数求解

最终我们得到的是一个列向量,我们想将其转化为矩阵形式,但是reshape函数是按列将向量进行填充的,我们想要的是按行进行填充的效果。
如果直接将其转化为5行4列的矩阵会得到到错误的结果,因此先将其转成4行5列的矩阵,再将其转置即可

[x,fval] = intlinprog(c,intcon,A,b,Aeq,beq,lb,ub)
% reshape(x,4,5)'
%      0     0     0     1    甲自由泳
%      1     0     0     0    乙蝶泳
%      0     1     0     0    丙仰泳
%      0     0     1     0    丁蛙泳
%      0     0     0     0    戊不参加

三、钢管切割问题

1.问题分析

因为原材料的长度一共6.9m,我们可以先找到一种简单的,能够直接满足需求切割方式,然后再用枚举法找出比这种切割方式更好(剩余材料更少)的方法,进行整数规划求解。
原材料一共6.9m,用一根原材料可以切割2.9m,2.1m 和 1m 的圆钢各一根,这样需要100根原材料就可以达到我们的需求了。但我们知道,这样的方式是有很多浪费的,因为用这种方式所得的料头(剩余材料长度)为0.9m,这样做100次岂不是浪费了90m的原材料,这种方法难道没有意义了吗?
之所以提出这种不那么好但是有用的方法,就是以这种方法为基础,找出所有优于这种方法的切割方法,然后利用这些方法进行规划求解。

2.模型建立

(1)利用枚举法找到料头小于等于0.9的切割方法

(2)得到目标函数与约束

3.代码实现

(1)枚举法找出同一个原材料上所有的切割方法

由于6.9m的原材料最多只能切两根2.9m的圆钢,因此i的取值为0,1,2。其余同理,找出料头小于等于0.9m的满足要求的切割方法,进行输出

for i = 0: 2  % 2.9m长的圆钢的数量
    for j = 0: 3  % 2.1m长的圆钢的数量
        for k = 0:6   % 1m长的圆钢的数量
            if 2.9*i+2.1*j+1*k >= 6 && 2.9*i+2.1*j+1*k <= 6.9
                disp([i, j, k])
            end
        end
    end
end

(2)线性整数规划问题的求解

我们把这7种切割方法设为x1,x2.....,目标函数就是使用原材料的数目最小,而这7项求和即为原材料的数目。
不等式约束要求每种切割的原钢数目要大于等于100

c = ones(7,1);  % 目标函数的系数矩阵
intcon=[1:7];  %  整数变量的位置(一共7个决策变量,均为整数变量)
A = -[1 2 0 0 0 0 1;  
         0 0 3 2 1 0 1;
         4 1 0 2 4 6 1];  % 线性不等式约束的系数矩阵
b = -[100 100 100]'; %  线性不等式约束的常数项向量
lb = zeros(7,1); % 约束变量的范围下限
[x,fval]=intlinprog(c,intcon,A,b,[],[],lb)
posted @ 2024-08-11 20:12  卢宇博  阅读(11)  评论(0编辑  收藏  举报