目录
前言
在MATLAB中,多目标规划问题通常涉及在多个相互冲突的目标之间找到最佳的权衡。这些目标可能由一组不等式和等式约束定义。
*内容有误之处,敬请评论或者联系修改
一、多目标规划定义
- 多目标规划涉及的是多于一个目标函数的优化问题。这些目标函数可能是相互冲突的,也就是说,一个目标函数的优化可能会导致另一个目标函数的性能下降。
- 一般形式:
f (x) = [ f(x1),f(x2),...]
min f (x)
- 多目标规划规划采用的算法有加权和法、序贯法、NSGA—II(基于遗传算法)、MOGA(基于遗传算法)、MOPSO(基于粒子群优化)等。本文主要介绍加权和法以及序贯法。
二、应用范围
fgoalattain
:用于目标实现多目标优化。gamultiobj
:用于遗传算法的多目标优化。paretosearch
:用于寻找Pareto最优解的多目标优化。
在数学建模方面,多目标规划优化技术被用于解决涉及多个冲突目标的问题,如在机械设计中的结构优化、参数优化,以及在自动控制领域的控制系统设计。
在这些应用中,多目标优化算法能够同时考虑多个目标函数,并寻找一组最优解,以平衡各个目标之间的矛盾。在供应链管理领域,平衡库存成本和客户满意度的优化问题;在能源管理中,平衡能源效率和成本的最小化;在物流路径规划中,寻找满足最短路径和最低成本的最优路径。这些应用都体现了MATLAB中多目标规划优化技术的实用性和有效性。
三、思路分析
1.加权和法
加权和法将多个目标函数加权求和作为单目标函数,而Tchebycheff法则则通过最大化各目标函数的加权值来构建单目标问题。本质上是将多目标问题转化为单目标求解
步骤:
-
定义目标函数和: 假设有两个目标函数f1和f2,其中 ( x ) 是决策变量向量。
% 定义目标函数 function [f1, f2] = objectives(x) % 目标函数:最小化 x1^2 + x2^2 和 (x1-1)^2 + x2^2 f1 = x(1)^2 + x(2)^2; f2 = (x(1) - 1)^2 + x(2)^2; end
-
定义加权和目标函数: 使用权重向量将多个目标函数组合成单个加权和目标函数 F。
% 定义加权和目标函数 function F = weighted_sum_objective(x) [f1, f2] = objectives(x); w = [0.5, 0.5]; % 权重系数 F = w(1) * f1 + w(2) * f2; end
- 定义约束条件:此处只是简单说明,做简单处理。
% 定义约束条件函数(如果有)
function [c, ceq] = constraints(x)
c = []; % 无不等式约束
ceq = x(1)^2 + x(2)^2 - 1; % 非线性等式约束:x1^2 + x2^2 = 1
end
- 优化求解:通过赋予权重后,可以考虑直接用线性fmincon函数。
% 主程序
% 求解优化问题
options = optimoptions('fmincon', 'Algorithm', 'interior-point', 'Display', 'iter-detailed');
x0 = [0, 0]; % 初始猜测值
[x_opt, F_opt, exitflag, output] = fmincon(@weighted_sum_objective, x0, [], [], [], [], [], [], @constraints, options);
% 输出优化结果
disp(['最优解 x_opt: [' num2str(x_opt) ']']);
disp(['最优目标函数值 F_opt: ' num2str(F_opt)]);
disp(['迭代次数: ' num2str(output.iterations)]);
2.序贯法
序贯法是一种将多目标问题分解为一系列单目标子问题的方法。通常是通过优先级、权重或顺序来逐个优化每个目标函数或子目标函数。一种常见的序贯法是分层方法,其中在每个阶段优化一个子目标函数,并且考虑前一阶段的优化结果作为约束条件。这种方法有助于处理复杂的多目标问题,并可能导致更好的全局解。
正负偏差变量(s^+、s^-)的定义:用于处理约束条件的松弛,允许某些约束条件有一定程度的违反,同时对这些违反进行惩罚。与松弛变量和剩余变量区分开来。
正偏差变量——sp:约束条件被超过的量。
负偏差变量——sm:约束条件被低于的量。
举例:你卖苹果想卖100(目标值),假设实际获利80,那么sp=0,sm=20,即低于约束条件目标值20;同理,假设实际获利120,那么sp=20,sm=0,即超过约束条件目标值20。
举例: min。。。。。。。。。
s.t. x1+2x2=1 x1+2x2+ s^-1 - s^+1 = 0
x1-x2<2 转为:x1-x2+ s^-2 - s^+2 = 0
x1+x2>0.3 x1+x2 + s^-3 - s^+3 = 0
注意:在题干中,有必须满足的条件是不能使用正负偏差变量进行约束的;
在计算时,采用序贯算法,一般来说约束条件的优先级越大的首先进行迭代:
f1=min(s^-1 + s^+1)----f2=f1+min(s^+2)----f3=f2+min(s^-3)
注意上述举例中不等号与目标函数的关系。
先举一个正负偏差变量的使用:
clc;
clear;
% 定义变量
x = optimvar('x', 2, 'LowerBound', 0); % 优化变量 x,两个变量,下界为0
sp = optimvar('sp', 'LowerBound', 0); % 正偏差变量 sp,下界为0
sm = optimvar('sm', 'LowerBound', 0); % 负偏差变量 sm,下界为0
% 创建优化问题
p = optimproblem('ObjectiveSense', 'min'); % 设置为最小化问题
% 目标函数:x1 + x2 + sp + sm
p.Objective = x(1) + x(2) + sp + sm;
% 约束条件:2*x1 + 3*x2 + sp - sm == 6
p.Constraints.cons1 = 2*x(1) + 3*x(2) + sm - sp == 6;
% 求解优化问题
[sx, fval] = solve(p);
% 显示结果
fprintf('优化目标值: %.4f\n', fval);
fprintf('优化变量 x: %.4f, %.4f\n', sx.x);
fprintf('正偏差变量 sp: %.4f\n', sx.sp);
fprintf('负偏差变量 sm: %.4f\n', sx.sm);
再举一个松弛变量和剩余变量的使用:
clc;
clear;
% 定义变量
x = optimvar('x', 2, 'LowerBound', 0); % 优化变量 x,两个变量,下界为0
slack = optimvar('slack', 'LowerBound', 0); % 松弛变量 slack,下界为0
surplus = optimvar('surplus', 'LowerBound', 0); % 剩余变量 surplus,下界为0
% 创建优化问题
p = optimproblem('ObjectiveSense', 'min'); % 设置为最小化问题
% 目标函数:x1 + x2
p.Objective = x(1) + x(2);
% 约束条件
p.Constraints.cons1 = 2*x(1) + 3*x(2) + slack == 6; % 小于等于约束
p.Constraints.cons2 = 3*x(1) + 4*x(2) - surplus == 10; % 大于等于约束
% 求解优化问题
[sx, fval] = solve(p);
% 显示结果
fprintf('优化目标值: %.4f\n', fval);
fprintf('优化变量 x: %.4f, %.4f\n', sx.x);
fprintf('松弛变量 slack: %.4f\n', sx.slack);
fprintf('剩余变量 surplus: %.4f\n', sx.surplus);
以下代码是采用序贯法对于多目标案例进行优先排序后的结果:
clc;
clear;
% 定义变量和参数
x = optimvar('x', 3, 'LowerBound', 0); % 优化变量 x,三个变量,下界为0
sp = optimvar('sp', 5, 'LowerBound', 0); % 正偏差变量 sp,五个变量,下界为0
sm = optimvar('sm', 5, 'LowerBound', 0); % 负偏差变量 sm,五个变量,下界为0
% 创建优化问题
p = optimproblem('ObjectiveSense', 'min'); % 设置优化问题为最小化问题
% 添加约束条件
p.Constraints.con1 = 3*sum(x) <= 20; % 第一个约束条件
p.Constraints.con2 = [100*x(1) + 150*x(2) + 200*x(3) + sm(1) - sp(1) == 2500
x(1) - 2*x(2) + 3*x(3) + sm(2) - sp(2) == 5
3*x(1) + 4*x(2) + sm(3) - sp(3) == 18
2*x(2) + 3*x(3) + sm(4) - sp(4) == 12
x(1) + 2*x(3) + sm(5) - sp(5) == 10];
% 多目标函数定义
mobj = [sm(1); sp(2) + sm(2); 2*sp(3) + 2*sm(3); sp(4) + 2*sm(5)]; % 多个目标函数的线性组合
goal = 10000 * ones(4, 1); % 初始目标值,长度为4的列向量,每个元素初始为10000(足够宽松的约束条件一般不会对跌代造成影响)
% 循环优化每个目标函数
for i = 1:4
p.Constraints.cons3 = mobj <= goal; % 更新目标约束条件
p.Objective = mobj(i); % 设置当前优化目标
% 解决优化问题
[sx, fval] = solve(p);
% 显示优化结果
fprintf('第%d级目标计算结果如下:\n', i)
fprintf('优化变量 x: %.4f, %.4f, %.4f\n', sx.x)
fprintf('优化目标值: %.4f\n', fval)
% 更新目标值
goal(i) = fval;
end
四、典型案例
一家物流公司希望优化货物的运输,以最小化运输成本和时间。假设公司有两个配送中心,每个配送中心都有不同的运费和运输时间。物流公司需要决定每个配送中心的货物分配,以同时最小化总运输成本和总运输时间,并且满足各配送中心的容载约束。
具体参数:
- 配送中心1的运输成本系数:
[2, 3, 1, 4]
- 配送中心2的运输成本系数:
[3, 1, 5, 2]
- 配送中心1的运输时间系数:
[4, 2, 3, 1]
- 配送中心2的运输时间系数:
[2, 5, 1, 3]
- 各配送中心的最大运力(货物重量约束):
[10, 8, 7, 12]
约束条件:
- 总货物量不能超过各配送中心的最大运力。
- 每个配送中心的货物分配量必须大于等于0。
优化目标:
- 最小化总运输成本。
- 最小化总运输时间。
clc; % 清除命令窗口
clear; % 清除工作区变量
% 定义不等式约束矩阵和向量
A = [1 0 0 0;
0 1 0 0;
0 0 1 0;
0 0 0 1]; % 不等式约束系数矩阵 (每个变量必须大于等于0)
b = [10; 8; 7; 12]; % 不等式约束常数项向量 (各配送中心的最大运力)
% 定义两个目标函数的系数
cost1 = [2 3 1 4]; % 配送中心1的运输成本系数
cost2 = [3 1 5 2]; % 配送中心2的运输成本系数
time1 = [4 2 3 1]; % 配送中心1的运输时间系数
time2 = [2 5 1 3]; % 配送中心2的运输时间系数
% 求解第一个目标函数的最优解(总运输成本)
[x_cost, min_cost] = linprog(cost1 + cost2, A, b, [], [], zeros(4, 1));
disp("总运输成本的最优值:" + min_cost); % 打印总运输成本的最优值
% 求解第二个目标函数的最优解(总运输时间)
[x_time, min_time] = linprog(time1 + time2, A, b, [], [], zeros(4, 1));
disp("总运输时间的最优值:" + min_time); % 打印总运输时间的最优值
% 目标goal的值
F = [min_cost; min_time];
% 定义联合目标函数
fun = @(x) [cost1*x + cost2*x; time1*x + time2*x];
% 设置加权因子
weight = [1, 1]; % 设置两个目标函数同等重要
% 使用fgoalattain求解加权后的联合优化问题
options = optimoptions('fgoalattain', 'Display', 'iter'); % 可选,用于显示迭代信息
[x, fval, attainfactor] = fgoalattain(fun, rand(4, 1), F, weight, A, b, [], [], zeros(4, 1), [], [], options);
% 显示结果
disp("加权后目标函数的最优解:");
disp(x);
disp("加权后目标函数的最优值:");
disp(fval);
disp("达到因子:");
disp(attainfactor);
解释:
- 定义约束:矩阵
A
和向量b
定义了每个配送中心的最大运力。 - 定义目标函数:
cost1
,cost2
分别表示两个配送中心的运输成本系数;time1
,time2
分别表示两个配送中心的运输时间系数。 - 求解单目标优化问题:使用
linprog
分别求解最小化总运输成本和最小化总运输时间的单目标优化问题。 - 定义联合目标函数:将两个目标函数合并为一个联合目标函数。
- 设置加权因子:设置两个目标函数的加权因子,表示它们的重要性相同。
- 求解多目标优化问题:使用
fgoalattain
函数求解加权后的多目标优化问题,并输出最优解、最优值和达到因子。
五、注意
- 初始化:选择良好的初始种群或初始解可以加快收敛速度。
- 停止准则:设置合理的停止准则(如最大迭代次数、目标变化量等),避免过长时间的计算。
- 多次运行:通过多次运行优化算法,观察解的稳定性和一致性。
总结
在进行多目标规化优化时,一是要找到目标的优先级,必要性和非必要性;二是要选择合适的算法,将多目标转化为单目标,或者采用其他办法。