前言:欢迎 各位光临 本博客,这里小编带你直接手撕Make/Makefile (自动化构建) ,文章并不复杂,愿诸君耐其心性,忘却杂尘,道有所长!!!!
**🔥个人主页:IF'Maxue-CSDN博客
🎬作者简介:C++研发方向学习者
📖**个人专栏:
《C语言》
《C++深度学习》
《Linux》
《数据结构》
《数学建模》**⭐️人生格言:生活是默默的坚持,毅力是永久的享受。不破不立,远方请直行!
文章目录
-
- 例子一:基础款非线性规划
-
- 第一步:给变量设个初始值
- 第二步:定义线性约束
- [第三步:调用求解函数 fmincon](#第三步:调用求解函数 fmincon)
- [定义目标函数 f1](#定义目标函数 f1)
- [定义非线性约束 nonlfun1](#定义非线性约束 nonlfun1)
- 例子二:带变量范围的非线性规划
- 例子三:燕双鹰打小怪兽(实际应用场景)
- 总结一下
其实非线性规划没那么玄乎,你可以把它理解成线性规划的 "进阶版"------ 当约束条件或目标函数里出现了平方、乘积这类非线性关系时,就该它登场了。它的核心思路是:用函数来灵活表达那些 "变来变去" 的系数,轻松搞定线性规划搞不定的问题。
下面通过三个例子,手把手带你看看它是怎么用的。
例子一:基础款非线性规划
先从简单的开始,假设我们要解决这样一个问题:
目标 :最小化函数 f (x) = x₁² + x₂² + x₃² + 8
约束条件:
- 线性不等式:-x₁ + x₂ - x₃ ≤ 0
- 非线性不等式:x₁ + x₂² + x₃² - 20 ≤ 0
- 非线性等式:-x₁ - x₂² + 2 = 0
第一步:给变量设个初始值
不管解什么方程,先给变量猜个初始值总没错,这里我们让 x₁、x₂、x₃都从 0 开始试:
matlab
matlab
x0 = [0 0 0]; % x0就是初始猜测值
第二步:定义线性约束
线性约束比较 "规矩",可以直接写成矩阵形式。比如 -x₁ + x₂ - x₃ ≤ 0
这个约束:
matlab
matlab
A = [-1, 1, -1]; % 系数矩阵,对应-x₁、+x₂、-x₃
b = [0]; % 右边的常数,即使是0也得写上
第三步:调用求解函数 fmincon
MATLAB 里的 fmincon 是求解这类问题的利器,用法很直接:
matlab
matlab
[x, val] = fmincon(@f1, x0, A, b, [], [], [], [], @nonlfun1);
这里的@f1
和@nonlfun1
是两个关键函数,分别定义目标函数和非线性约束。
定义目标函数 f1
就是把我们要最小化的函数写进去:
matlab
matlab
function f = f1(x)
% x(1)是x₁,x(2)是x₂,x(3)是x₃
f = x(1)^2 + x(2)^2 + x(3)^2 + 8; % 直接照抄目标函数
end
定义非线性约束 nonlfun1
非线性的约束(包括不等式和等式)都放这里:
matlab
matlab
function [c, ceq] = nonlfun1(x)
% c放非线性不等式约束(比如≤0的式子)
c = [x(1) + x(2)^2 + x(3)^2 - 20]; % 对应x₁ + x₂² + x₃² ≤ 20
% ceq放非线性等式约束(比如=0的式子)
ceq = [-x(1) - x(2)^2 + 2]; % 对应-x₁ - x₂² + 2 = 0
end
例子二:带变量范围的非线性规划
再来个稍复杂的,这次给变量加了范围限制,还多了几个约束:
目标 :最小化函数 f (x) = -x₁x₂x₃(其实就是最大化 x₁x₂x₃)
约束条件:
- 线性不等式:-x₁ + x₂ - x₃ ≤ 0
- 线性等式:x₁ - x₂ = 10
- 非线性不等式:x₁ + x₂² + x₃² - 20 ≤ 0、x₁x₂ - x₃ - 1 ≤ 0
- 变量范围:10 ≤ x₁ ≤ 20
关键参数设置
除了初始值和线性不等式,这次多了线性等式和变量范围:
matlab
matlab
x0 = [0 0 0]; % 初始值
% 线性不等式:-x₁ + x₂ - x₃ ≤ 0
A = [-1, 1, -1];
b = [0];
% 线性等式:x₁ - x₂ = 10
Aeq = [1, -1, 0]; % 系数矩阵
beq = [10]; % 常数项
% 变量范围:x₁≥10、≤20,x₂和x₃无限制
lb = [10; -Inf; -Inf]; % 下限
ub = [20; +Inf; +Inf]; % 上限
调用求解函数
参数里加上线性等式和变量范围就行:
matlab
matlab
[x, val] = fmincon(@f2, x0, A, b, Aeq, beq, lb, ub, @nonlfun2);
val = -1 * val; % 因为我们实际想最大化x₁x₂x₃,所以把结果反过来
目标函数和约束函数
目标函数 f2:
matlab
matlab
function f = f2(x)
f = -x(1)*x(2)*x(3); % 最小化这个,等价于最大化x₁x₂x₃
end
非线性约束 nonlfun2(多个约束用分号隔开):
matlab
matlab
function [c, ceq] = nonlfun2(x)
% 多个非线性不等式,用分号分开
c = [x(1) + x(2)^2 + x(3)^2 - 20; % 第一个不等式
x(1)*x(2) - x(3) - 1]; % 第二个不等式
ceq = [-x(1) - x(2)^2 + 2]; % 非线性等式
end
例子三:燕双鹰打小怪兽(实际应用场景)
最后这个例子更贴近实际问题(就像 "燕双鹰打小怪兽" 一样,要考虑各种资源分配)。假设有 12 个变量 xᵢⱼ,我们要在一堆约束下找到最优解。
问题设置
matlab
matlab
x0 = zeros(1,12); % 12个变量,初始值都设为0
% 线性等式约束:前6个变量和后6个变量分别等于特定值
Aeq = [eye(6), eye(6)]; % 系数矩阵
beq = [5;9;4;8;14;11]; % 等式右边的常数
% 线性不等式约束:前6个变量总和≤30,后6个变量总和≤20
A = [ones(1,6), zeros(1,6); % 前6个变量的和
zeros(1,6), ones(1,6)]; % 后6个变量的和
b = [30;20]; % 总和上限
% 变量范围:所有变量都≥0,无上限
lb = zeros(1,12);
ub = repmat(Inf, 1, 12);
求解与目标函数
直接调用 fmincon,这里没有非线性约束,最后一个参数用[]
:
matlab
matlab
[x, val] = fmincon(@f3, x0, A, b, Aeq, beq, lb, ub, []);
目标函数 f3(这里考虑了成本、距离等综合因素):
matlab
matlab
function f = f3(x)
x = x'; % 把行向量转成列向量,方便计算
% 一些固定参数(比如成本系数、距离系数等)
p1 = 3; p2 = 1; k1 = 1; k2 = 3;
a = [1.37 9.45 4.43 6.66 3.14 15.92];
b = [10.21 9.45 8.88 5 16.44 18];
x1 = 4; y1 = 1; x2 = 8; y2 = 9;
% 计算中间变量
tmp_x = x ./ (x + 1);
% 目标函数:综合成本+距离相关成本
f = [repmat(p1, 1, 6), repmat(p2, 1, 6)] * x ...
+ sum(sqrt(sum(([a; b] - repmat([x1; y1], 1, 6)).^2)) .* k1 .* tmp_x(1:6)) ...
+ sum(sqrt(sum(([a; b] - repmat([x2; y2], 1, 6)).^2)) .* k2 .* tmp_x(7:12));
end
总结一下
非线性规划的核心就是:用fmincon
函数,把目标函数、线性约束、非线性约束分开定义,再设置好变量的初始值和范围就行。
记住这几个关键点:
@f
是你要最小化的目标函数A, b
放线性不等式约束(≤)Aeq, beq
放线性等式约束(=)lb, ub
设定变量的上下限@nonlfun
放非线性的不等式(c)和等式(ceq)约束
跟着例子多试几次,你会发现非线性规划其实没那么难~