数学建模实战:从投资组合到生产计划,5个案例详解MATLAB intlinprog 求解

在数学建模竞赛和工程优化领域,混合整数线性规划(MILP)因其强大的离散决策能力而备受青睐。MATLAB的 intlinprog 函数作为求解MILP问题的利器,能够高效处理包含整数变量的复杂优化问题。本文将通过五个典型场景,展示如何将实际问题转化为数学模型,并利用 intlinprog 实现求解。

1. 投资组合优化:风险约束下的收益最大化

问题背景 :某投资者有100万元资金,考虑投资于4种金融产品。每种产品的预期收益率、风险系数和最低投资额如下表所示:

产品 预期收益率(%) 风险系数 最低投资额(万元)
A 8 1.2 10
B 6 0.8 15
C 12 1.8 20
D 4 0.5 5

要求整体投资风险系数不超过1.0,且每种产品要么不投,要么至少达到最低投资额。

建模步骤

  1. 定义决策变量:设投资产品A-D的金额为$x_1$-$x_4$(单位:万元),引入0-1变量$y_i$表示是否投资产品i
  2. 目标函数:最大化总收益 $\max 0.08x_1 + 0.06x_2 + 0.12x_3 + 0.04x_4$
  3. 约束条件:
    • 总投资额:$x_1 + x_2 + x_3 + x_4 \leq 100$
    • 风险控制:$1.2x_1 + 0.8x_2 + 1.8x_3 + 0.5x_4 \leq 100$(总风险不超过100万×1.0)
    • 最低投资额约束:
      • $x_1 \geq 10y_1$, $x_1 \leq 100y_1$
      • $x_2 \geq 15y_2$, $x_2 \leq 100y_2$
      • $x_3 \geq 20y_3$, $x_3 \leq 100y_3$
      • $x_4 \geq 5y_4$, $x_4 \leq 100y_4$

MATLAB实现

f = -[0.08; 0.06; 0.12; 0.04]; % 目标函数系数(求最大值转为最小值)
A = [1.2, 0.8, 1.8, 0.5; 1, 1, 1, 1];
b = [100; 100];
Aeq = [];
beq = [];
lb = zeros(8,1);
ub = [100;100;100;100;1;1;1;1];
intcon = 5:8; % y1-y4为整数变量

% 构造不等式约束矩阵
A = [A, zeros(2,4);
     -eye(4), [10;15;20;5].*eye(4);
     eye(4), -100*eye(4)];
b = [b; zeros(4,1); zeros(4,1)];

[x, fval] = intlinprog(f, intcon, A, b, Aeq, beq, lb, ub);
disp(['最优投资方案:', num2str(x(1:4)'), '万元']);
disp(['预期最大收益:', num2str(-fval), '万元']);

2. 生产计划优化:多产品多约束排产

问题场景 :某工厂生产三种产品,需要经过两道工序。每种产品在各工序的加工时间、利润及市场需求如下:

产品 工序1(小时) 工序2(小时) 利润(元) 最大需求
P1 2 3 120 50
P2 4 1 150 30
P3 3 2 180 20

工厂每月可用工时为:工序1-200小时,工序2-150小时。要求至少生产每种产品10件。

数学模型

  • 变量:$x_i$为产品i的生产量(整数)
  • 目标:$\max 120x_1 + 150x_2 + 180x_3$
  • 约束:
    • $2x_1 + 4x_2 + 3x_3 \leq 200$
    • $3x_1 + x_2 + 2x_3 \leq 150$
    • $10 \leq x_1 \leq 50$
    • $10 \leq x_2 \leq 30$
    • $10 \leq x_3 \leq 20$

MATLAB求解

f = -[120; 150; 180]; % 目标系数
A = [2,4,3; 3,1,2];
b = [200;150];
lb = [10;10;10];
ub = [50;30;20];
intcon = 1:3; % 全部变量为整数

[x, fval] = intlinprog(f, intcon, A, b, [], [], lb, ub);
disp(['最优生产计划:P1=',num2str(x(1)),' P2=',num2str(x(2)),' P3=',num2str(x(3))]);
disp(['最大利润:', num2str(-fval), '元']);

3. 运输优化:多仓库多需求点配送

问题描述 :某公司有3个仓库和4个销售点,运输成本、供应量和需求量如下:

运输成本矩阵(元/吨):

[8  6 10 9;
 9 12 13 7;
 14 9 16 5]

仓库供应量:[50; 60; 40]吨
销售点需求量:[30; 45; 25; 50]吨

要求每个销售点只能由1个仓库供货(全有或全无)。

建模要点

  1. 引入0-1变量$y_{ij}$表示仓库i是否向销售点j供货
  2. 连续变量$x_{ij}$表示实际运输量
  3. 约束:
    • 供应限制:$\sum_j x_{ij} \leq \text{供应量}_i$
    • 需求限制:$\sum_i x_{ij} = \text{需求量} j \times y {ij}$
    • 单一来源:$\sum_i y_{ij} = 1$

MATLAB实现

cost = [8 6 10 9; 9 12 13 7; 14 9 16 5];
supply = [50;60;40];
demand = [30;45;25;50];

f = [cost(:); zeros(12,1)]; % xij在前,yij在后
intcon = 13:24; % yij为整数变量

% 构造约束矩阵
A = zeros(19,24);
b = zeros(19,1);

% 供应约束
for i = 1:3
    A(i, (i-1)*4+(1:4)) = 1;
    b(i) = supply(i);
end

% 需求约束
for j = 1:4
    A(3+j, (1:3)*4-4+j) = 1;
    A(3+j, 12+j) = -demand(j);
    beq(j) = 0;
end

% 单一来源约束
for j = 1:4
    A(7+j, 12+j:4:24) = 1;
    beq(4+j) = 1;
end

lb = zeros(24,1);
ub = [repmat(supply,4,1); ones(12,1)];

[x, fval] = intlinprog(f, intcon, A, b, Aeq, beq, lb, ub);

4. 排班优化:医院护士调度系统

场景 :某医院需要为护士排班,满足每日需求:

  • 早班(8:00-16:00):最少8人
  • 中班(16:00-24:00):最少5人
  • 夜班(0:00-8:00):最少3人

护士工作规则:

  1. 连续工作不超过2班
  2. 工作后至少休息1班
  3. 每人每周工作不超过40小时

整数规划模型

  • 变量:$x_{d,s,t}$(第d天第s班次类型t的护士数,t=1新上班,t=2连续第二班)
  • 目标:最小化总护士数
  • 约束:
    • 满足各班次需求
    • 连续性约束
    • 休息约束
    • 工作时间约束

MATLAB关键代码

% 定义7天3班次的变量
num_days = 7;
shifts_per_day = 3;
total_shifts = num_days * shifts_per_day;

% 构建目标函数:最小化总护士数
f = ones(1, total_shifts * 2); % 每种班次类型都有变量

% 构建需求约束
A = [];
b = [];
for d = 1:num_days
    for s = 1:shifts_per_day
        % 每班次总人数 >= 需求
        shift_idx = (d-1)*shifts_per_day + s;
        constr = zeros(1, total_shifts*2);
        constr([shift_idx, shift_idx+total_shifts]) = -1; % x1+x2 >= demand
        A = [A; constr];
    end
end
b = -[repmat([8;5;3], num_days, 1)]; % 需求向量

% 添加连续性、休息和工作时间约束...

5. 设施选址:物流中心最优布局

问题 :某物流公司需要在10个候选地点中选择3个建立配送中心,满足15个客户点的需求。已知:

  • 每个候选中心的建设成本
  • 每个客户点的需求量
  • 从各候选中心到客户点的运输成本

目标是最小化总成本(建设成本+运输成本)。

建模技巧

  1. 使用0-1变量表示是否选择某候选点
  2. 连续变量表示从各中心到客户的运输量
  3. 添加逻辑约束确保只有被选中的中心才能供货

MATLAB实现框架

% 参数初始化
fixed_cost = [120, 150, 180, 90, 200, 130, 110, 160, 140, 170]; % 建设成本
transport_cost = rand(10,15); % 运输成本矩阵
demand = randi([10,50],1,15); % 客户需求

% 变量设置
num_warehouses = 10;
num_customers = 15;
total_vars = num_warehouses + num_warehouses*num_customers;

f = [fixed_cost, transport_cost(:)']; % 目标函数系数
intcon = 1:num_warehouses; % 选址变量为整数

% 约束条件构建
A = [];
b = [];
Aeq = zeros(num_customers, total_vars);
beq = demand';

% 每个客户需求必须满足
for c = 1:num_customers
    Aeq(c, num_warehouses+c:num_warehouses:end) = 1;
end

% 只有被选中的仓库才能供货
counter = 1;
A = zeros(num_warehouses*num_customers, total_vars);
for w = 1:num_warehouses
    for c = 1:num_customers
        A(counter, num_warehouses + (w-1)*num_customers + c) = 1;
        A(counter, w) = -demand(c);
        counter = counter + 1;
    end
end
b = zeros(size(A,1),1);

% 选择恰好3个仓库
Aeq = [Aeq; ones(1,num_warehouses), zeros(1,num_warehouses*num_customers)];
beq = [beq; 3];

[x, fval] = intlinprog(f, intcon, A, b, Aeq, beq, zeros(total_vars,1), []);

高级技巧与注意事项

  1. 模型简化 :对于大规模问题,可考虑:

    • 预处理消除冗余变量
    • 分解为多个子问题
    • 使用启发式算法获取初始解
  2. 求解加速

    options = optimoptions('intlinprog',...
        'Heuristics','advanced',...
        'CutGeneration','intermediate',...
        'IntegerPreprocess','advanced');
    
  3. 结果验证 :检查 exitflag 确认求解状态:

    • 1:最优解找到
    • 2:达到整数可行点
    • 0:达到最大迭代次数
  4. 敏感性分析 :通过 lambda 结构体获取影子价格,分析约束松紧程度

混合整数规划在数学建模中应用广泛,从最初的简单生产计划到复杂的物流网络设计, intlinprog 提供了强大的求解能力。实际应用中,良好的模型构建往往比算法选择更重要——合理的变量定义、有效的约束简化能显著提升求解效率。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐