├── .DS_Store ├── utils ├── .DS_Store ├── exp4.m ├── exp1.m ├── exp3.m ├── exp5.m ├── exp7.m ├── exp10.m ├── exp2.m ├── exp9.m ├── exp8.m ├── exp6.m └── examples_of_problems.md ├── assets ├── .DS_Store └── Max_paraboloid.svg.png ├── README.md ├── armijo_search_method.m ├── LICENSE ├── quadratic_Lagrangian.m ├── damp_newton_method.m ├── gradient_descent_method.m ├── revised_newton_method.m ├── exterior_penalty_method.m ├── fr_conjugate_gradient_method.m ├── trust_region_method.m ├── interior_penalty_method.m ├── l_m_least_squares_method.m ├── trust_region_quadratic_model.m └── genetic_algorithm.m /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Matthew-Lyu/Nonlinear-Numerical-Optimization-Methods/HEAD/.DS_Store -------------------------------------------------------------------------------- /utils/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Matthew-Lyu/Nonlinear-Numerical-Optimization-Methods/HEAD/utils/.DS_Store -------------------------------------------------------------------------------- /assets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Matthew-Lyu/Nonlinear-Numerical-Optimization-Methods/HEAD/assets/.DS_Store -------------------------------------------------------------------------------- /assets/Max_paraboloid.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Matthew-Lyu/Nonlinear-Numerical-Optimization-Methods/HEAD/assets/Max_paraboloid.svg.png -------------------------------------------------------------------------------- /utils/exp4.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | 4 | fun = @(x) x(1)^2 + x(2)^2 -1; 5 | gfun = @(x) [2*x(1); 2*x(2)]; 6 | 7 | x = [2;2]; 8 | d = [-1;-1]; 9 | [mk, alpha, fk, newfk] = armijo_search_method(x, d, fun, gfun); 10 | fprintf('使用Armijo方法搜索步长: alpha = %f\n', alpha); -------------------------------------------------------------------------------- /utils/exp1.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | 4 | fun = @(x) x(1)^2 + 25*x(2)^2; 5 | gfun = @(x) [2*x(1); 50*x(2)]; 6 | 7 | x0=[1; 2]; 8 | [x,val,k] = gradient_descent_method(fun, gfun,x0); 9 | 10 | fprintf('最速梯度下降法求解: x = [%f, %f]\n', x(1), x(2)); 11 | fprintf('最小值: f(x) = %f\n', val); 12 | fprintf('迭代次数: %d\n', k); -------------------------------------------------------------------------------- /utils/exp3.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | 4 | fun = @(x) x(1)^2 + 4 * x(2)^2; 5 | gfun = @(x) [2 * x(1); 8 * x(2)]; 6 | 7 | x0 = [1; 1]; 8 | [x, val, k] = FR_conjugate_gradient_method(fun, gfun, x0); 9 | fprintf('FR共轭梯度法求解: x = [%f, %f]\n', x(1), x(2)); 10 | fprintf('最小值: f(x) = %f\n', val); 11 | fprintf('迭代次数: %d\n', k); -------------------------------------------------------------------------------- /utils/exp5.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | 4 | fun = @(x) 100*(x(1)^2-x(2))^2+(x(1)-1)^2; 5 | gfun = @(x) [400*x(1)*(x(1)^2-x(2))+2*(x(1)-1); -200*(x(1)^2-x(2))]; 6 | hessian = @(x) [1200*x(1)^2-400*x(2)+2, -400*x(1); -400*x(1), 200]; 7 | 8 | x0 = [2; 1]; 9 | [x, val, k] = trust_region_method(fun, gfun, hessian, x0); 10 | 11 | fprintf('信赖域法求解: x = [%f, %f]\n', x(1), x(2)); 12 | fprintf('最小值: f(x) = %f\n', val); 13 | fprintf('迭代次数: %d\n', k); -------------------------------------------------------------------------------- /utils/exp7.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | 4 | % 参数设置 5 | H = 2 * eye(2); 6 | A = [1 1]; 7 | b = 1; 8 | c = zeros(2, 1); 9 | 10 | [x, lam, fval] = quadratic_Lagrangian(H, A, b, c); 11 | 12 | % 检查 x2 是否满足不等式约束 13 | if x(2) > 1/4 14 | % 若 x2 > 1/4,需要调整为边界情况 x2 = 1/4 并解 x1 15 | x(2) = 1/4; 16 | x(1) = 1 - x(2); 17 | fval = 0.5 * x' * H * x + c' * x; % 重新计算最优值 18 | end 19 | 20 | % 输出结果 21 | fprintf('最优解: (%f, %f)\n', x(1), x(2)); 22 | fprintf('最优值: %f\n', fval); -------------------------------------------------------------------------------- /utils/exp10.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | 4 | % 定义目标函数 5 | objectiveFunction = @(x) x .* sin(10 * x) + 1; 6 | 7 | % 遗传算法参数 8 | populationSize = 100; % 种群大小 9 | numGenerations = 1000; % 最大迭代代数 10 | crossoverRate = 0.8; % 交叉概率 11 | mutationRate = 0.05; % 变异概率 12 | tolerance = 1e-6; % 收敛精度 13 | lowerBound = -1; % 变量下界 14 | upperBound = 2.0; % 变量上界 15 | 16 | % 调用遗传算法 17 | [bestSolution, maxFitness] = genetic_algorithm(objectiveFunction, populationSize, numGenerations, crossoverRate, mutationRate, tolerance, lowerBound, upperBound); 18 | 19 | fprintf('最优解: x = %.6f, f(x) = %.6f\n', bestSolution, maxFitness); 20 | -------------------------------------------------------------------------------- /utils/exp2.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | 4 | fun = @(x) x(1)^2 + x(2)^2 - x(1)*x(2)- 10*x(1) - 4*x(2) + 60; 5 | gfun = @(x) [2*x(1) - x(2) - 10; 2*x(2) - x(1) - 4]; 6 | hessian = @(X) [2, -1; -1, 2]; 7 | 8 | x0 = [1; 2]; 9 | [x,val,k] = damp_newton_method(fun, gfun, hessian, x0); 10 | fprintf('阻尼牛顿法求解: x = [%f, %f]\n', x(1), x(2)); 11 | fprintf('最小值: f(x) = %f\n', val); 12 | fprintf('迭代次数: %d\n', k); 13 | 14 | disp(' ') 15 | 16 | [x,val,k] = revised_newton_method(fun, gfun, hessian, x0); 17 | fprintf('修正牛顿法求解: x = [%f, %f]\n', x(1), x(2)); 18 | fprintf('最小值: f(x) = %f\n', val); 19 | fprintf('迭代次数: %d\n', k); 20 | 21 | 22 | -------------------------------------------------------------------------------- /utils/exp9.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | 4 | % 目标函数 5 | fun = @(x) x(1)^2 + x(2)^2; 6 | 7 | % 目标函数的梯度 8 | gfun = @(x) [2 * x(1); 2 * x(2)]; 9 | 10 | % 目标函数的海森矩阵 11 | hessian = @(x) [2, 0; 0, 2]; 12 | 13 | % 约束函数,定义为 x1 - 1 >= 0 14 | cons = @(x) x(1) - 1; 15 | 16 | % 约束的梯度 17 | cons_grad = @(x) [1; 0]; 18 | 19 | % 约束的海森矩阵 20 | cons_hessian = @(x) [0, 0; 0, 0]; 21 | 22 | x0 = [10; 10]; % 初始点 23 | tol = 1e-8; % 精度要求 24 | 25 | [x_opt, f_opt, iter] = interior_penalty_method(fun, gfun, hessian, cons,cons_grad,cons_hessian, x0, tol); 26 | 27 | fprintf('最优解: (%f, %f)\n', x_opt(1), x_opt(2)); 28 | fprintf('最优值: %f\n', f_opt); 29 | fprintf('迭代次数: %d\n', iter); 30 | -------------------------------------------------------------------------------- /utils/exp8.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | 4 | % 目标函数 5 | fun = @(x) x(1)^2 + x(2)^2; 6 | 7 | % 梯度函数 8 | gfun = @(x) [2 * x(1); 2 * x(2)]; 9 | 10 | % 海森矩阵函数 11 | hessian = @(x) [2, 0; 0, 2]; 12 | 13 | % 约束函数 x1 + x2 = 2 14 | cons = @(x) x(1) + x(2) - 2; 15 | 16 | % 约束函数的梯度 17 | cons_grad = @(x) x(1) + x(2) - 2 * [1; 1]; 18 | 19 | % 约束函数的海森矩阵 20 | cons_hessian = @(x) [1, 1; 1, 1]; 21 | 22 | x0 = [10; 10]; % 初始点 23 | tol = 1e-8; % 精度 24 | 25 | [x_opt, f_opt, iter] = exterior_penalty_method(fun, gfun, hessian, cons,cons_grad,cons_hessian, x0, tol); 26 | 27 | fprintf('最优解: (%f, %f)\n', x_opt(1), x_opt(2)); 28 | fprintf('最优值: %f\n', f_opt); 29 | fprintf('迭代次数: %d\n', iter); 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nonlinear-Numerical-Optimization-Methods 2 | 3 | 非线性数值优化方法的Matlab代码仓库,并给出了对应的数值优化问题样例,参见./utils 4 | 5 | 6 | 7 | `gradient_descent_method`:梯度下降法 8 | 9 | `armijo_search_method`:Armijo搜索步长准则 10 | 11 | `damp_newton_method`:阻尼牛顿法 12 | 13 | `revised_newton_method`:修正牛顿法 14 | 15 | `fr_conjugate_gradient_method`:FR共轭梯度法 16 | 17 | `trust_region_method`:信赖域法 18 | 19 | `trust_region_quadratic_model`:光滑牛顿法解决信赖域子问题 20 | 21 | `l_m_least_squares_method`:Levenberg-Marquardt 最小二乘法 22 | 23 | `quadratic_Lagrangian`:拉格朗日二次优化法 24 | 25 | `exterior_penalty_method`:外罚函数法 26 | 27 | `interior_penalty_method`:内罚函数法 28 | 29 | `genetic_algorithm`:遗传算法 30 | 31 | 32 | ## 参考文献 33 | 34 | [1] 非线性最优化理论与方法 (第三版) 王宜举, 修乃华 35 | -------------------------------------------------------------------------------- /armijo_search_method.m: -------------------------------------------------------------------------------- 1 | function [mk, alpha, fk, newfk] = armijo_search_method(xk, dk, fun, grad) 2 | % Armijo准则搜索 3 | % 输入: 4 | % xk: 当前点 5 | % dk: 搜索方向 6 | % fun: 目标函数 7 | % grad: 梯度函数 8 | % 输出: 9 | % mk: 步长指数 10 | % alpha: 步长因子 11 | % fk: 当前点的函数值 12 | % newfk: 新点的函数值 13 | 14 | rho = 0.1; % 步长缩放因子 15 | sigma = 0.2; % Armijo条件系数 16 | m = 0; % 步长指数 17 | mmax = 20; % 最大步长指数 18 | 19 | while (m <= mmax) 20 | if fun(xk + rho^m * dk) <= fun(xk) + sigma * rho^m * grad(xk)' * dk 21 | mk = m; % 更新步长指数 22 | break; 23 | end 24 | m = m + 1; 25 | end 26 | 27 | alpha = rho^mk; % 计算步长因子 28 | newxk = xk + alpha * dk; % 计算新点 29 | fk = fun(xk); % 当前点的函数值 30 | newfk = fun(newxk); % 新点的函数值 31 | end 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Lyu Weichen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /quadratic_Lagrangian.m: -------------------------------------------------------------------------------- 1 | function [x_opt, lam, f_opt] = quadratic_Lagrangian(H, A, b, c) 2 | % 拉格朗日二次规划函数 3 | % 用于求解具有等式约束的二次优化问题。 4 | % 形式为: min f(x) = 0.5*x'*H*x + c'*x, 其中约束条件为 Ax = b。 5 | % 6 | % 输入: 7 | % H - 目标函数中二次项的系数矩阵,应为正定矩阵。 8 | % A - 约束条件中的系数矩阵。 9 | % b - 约束条件中的常数向量。 10 | % c - 目标函数中一次项的系数向量。 11 | % 12 | % 输出: 13 | % x - 最优解向量。 14 | % lam - 拉格朗日乘子向量。 15 | % f_opt - 在x处的目标函数最小值。 16 | 17 | % 计算 H 的逆矩阵 18 | inv_H = inv(H); 19 | 20 | % 计算 A*H^-1*A',即约束矩阵 A,预乘 H 的逆,再后乘 A 的转置 21 | AHA = A * inv_H * A'; 22 | 23 | % 计算 A*H^-1*A' 的逆矩阵 24 | inv_AHA = inv(AHA); 25 | 26 | % 计算 A*H^-1 27 | AiH = A * inv_H; 28 | 29 | % 计算 G 矩阵,用于后续计算最优解向量 x 30 | G = inv_H - AiH' * inv_AHA * AiH; 31 | 32 | % 计算 B 矩阵,用于后续计算拉格朗日乘子 lam 33 | B = inv_AHA * AiH; 34 | 35 | % 计算 C 矩阵,也是用于后续计算拉格朗日乘子 lam 36 | C = -inv_AHA; 37 | 38 | % 计算最优解向量 x 39 | x_opt = B' * b - G * c; 40 | 41 | % 计算拉格朗日乘子向量 lam 42 | lam = B * c - C * b; 43 | 44 | % 计算在 x 处的目标函数值 45 | f_opt = 0.5 * x_opt' * H * x_opt + c' * x_opt; 46 | 47 | end 48 | -------------------------------------------------------------------------------- /utils/exp6.m: -------------------------------------------------------------------------------- 1 | clear 2 | clc 3 | 4 | % 数据 5 | t = [3, 6, 9, 12, 15, 18, 21, 24]; % 时间序列 6 | y = [57.6, 41.9, 31.0, 22.7, 16.6, 12.2, 8.9, 6.5]; % 反应物的量 7 | 8 | x0 = [60; 0.1]; % 随机选择一个合适的起始点 9 | 10 | % 调用 L-M 方法 11 | [x, val, k] = L_M_least_squares_method(@Fk, @JFk, x0); 12 | 13 | % 输出结果 14 | fprintf('拟合参数: a = %.4f, b = %.4f\n', x(1), x(2)); 15 | fprintf('目标函数优化值: %.4f, 迭代次数: %d\n', val, k); 16 | fprintf('拟合函数形式: y = %.2fe^{-%.2ft}\n', x(1), x(2)); 17 | 18 | % 画出数据点和拟合曲线 19 | figure; 20 | scatter(t, y, 'filled'); 21 | hold on; 22 | t_fit = linspace(min(t), max(t), 100); 23 | y_fit = x(1) * exp(-x(2) * t_fit); 24 | plot(t_fit, y_fit, 'r-'); 25 | xlabel('时间 (t)'); 26 | ylabel('反应物的量 (y)'); 27 | title('反应速率数据拟合'); 28 | legend('数据点', '指数衰减拟合'); 29 | hold off; 30 | 31 | function f = Fk(x) 32 | t0 = [3, 6, 9, 12, 15, 18, 21, 24]; 33 | y0 = [57.6, 41.9, 31.0, 22.7, 16.6, 12.2, 8.9, 6.5]; 34 | a = x(1); 35 | b = x(2); 36 | f = y0 - a * exp(-b * t0); 37 | f = f(:); 38 | end 39 | 40 | function jf = JFk(x) 41 | t0 = [3, 6, 9, 12, 15, 18, 21, 24]; 42 | a = x(1); 43 | b = x(2); 44 | jf = [-exp(-b * t0); a * t0 .* exp(-b * t0)]'; 45 | end 46 | 47 | -------------------------------------------------------------------------------- /damp_newton_method.m: -------------------------------------------------------------------------------- 1 | function [x_opt, f_opt, iter] = damp_newton_method(fun, grad, hess, x0) 2 | % 阻尼牛顿法 3 | % 输入: 4 | % fun: 目标函数 5 | % grad: 梯度函数 6 | % hess: 海森矩阵函数 7 | % x0: 初始点 8 | % 输出: 9 | % x_opt: 近似最优解 10 | % f_opt: 最优解对应的函数值 11 | % iter: 迭代次数 12 | 13 | max_iter = 1000; % 最大迭代次数 14 | rho = 0.55; % 阻尼因子 15 | sigma = 0.4; % Armijo条件系数 16 | iter = 0; % 迭代次数 17 | epsilon = 0.01; % 误差阈值 18 | 19 | % 初始化 20 | x = x0; 21 | 22 | while iter < max_iter 23 | % 计算当前点的梯度和海森矩阵 24 | g = feval(grad, x); 25 | H = feval(hess, x); 26 | 27 | % 搜索方向 28 | d = -inv(H) * g; 29 | 30 | % 初始化线搜索参数 31 | m = 0; 32 | mk = 0; 33 | 34 | % 线搜索 35 | while m < 20 36 | if feval(fun, x + rho^m * d) < feval(fun, x) + sigma * rho^m * g' * d 37 | mk = m; % 更新 mk 38 | break; 39 | end 40 | m = m + 1; 41 | end 42 | 43 | % 更新当前点 44 | x = x + rho^mk * d; 45 | iter = iter + 1; 46 | 47 | % 判断停止条件:梯度小于阈值 48 | if norm(g) < epsilon 49 | break; 50 | end 51 | end 52 | 53 | % 输出最优解和最优值 54 | x_opt = x; 55 | f_opt = feval(fun, x); 56 | end 57 | 58 | -------------------------------------------------------------------------------- /gradient_descent_method.m: -------------------------------------------------------------------------------- 1 | function [x_opt, f_opt, iter] = gradient_descent_method(fun, grad_fun, x0) 2 | % 最速梯度下降法 3 | % 输入: 4 | % fun: 目标函数 5 | % grad_fun: 梯度函数 6 | % x0: 初始点 7 | % 输出: 8 | % x_opt: 近似最优解 9 | % f_opt: 最优解对应的函数值 10 | % iter: 迭代次数 11 | 12 | max_iter = 5000; % 最大迭代次数 13 | rho = 0.5; % Armijo线搜索参数 14 | sigma = 0.4; % Armijo线搜索参数 15 | iter = 0; % 迭代次数 16 | epsilon = 0.01; % 误差阈值 17 | 18 | % 初始化 19 | x = x0; 20 | 21 | while(iter < max_iter) 22 | % 计算梯度 23 | g = feval(grad_fun, x); 24 | 25 | % 计算搜索方向为负梯度方向 26 | d = -g; 27 | 28 | % 若梯度范数小于误差阈值,则停止迭代 29 | if(norm(d) < epsilon) 30 | break; 31 | end 32 | 33 | % 初始化线搜索参数 34 | m = 0; 35 | mk = 0; 36 | 37 | % 线搜索确定步长因子 38 | while(m < 20) 39 | % 判断是否满足Armijo条件 40 | if(feval(fun, x + rho^m * d) < feval(fun, x) + sigma * rho^m * g' * d) 41 | mk = m; 42 | break; 43 | end 44 | m = m + 1; 45 | end 46 | 47 | % 更新当前点 48 | x = x + rho^mk * d; 49 | iter = iter + 1; 50 | end 51 | 52 | % 输出最优解和最优值 53 | x_opt = x; 54 | f_opt = feval(fun, x); 55 | end 56 | 57 | -------------------------------------------------------------------------------- /revised_newton_method.m: -------------------------------------------------------------------------------- 1 | function [x_opt, f_opt, iter] = revised_newton_method(fun, grad, hess, x0) 2 | % 修正牛顿法 3 | % 输入: 4 | % fun: 目标函数 5 | % grad: 梯度函数 6 | % hess: 海森矩阵函数 7 | % x0: 初始点 8 | % 输出: 9 | % x_opt: 近似最优解 10 | % f_opt: 最优解对应的函数值 11 | % iter: 迭代次数 12 | 13 | n = length(x0); 14 | max_iter = 1000; % 最大迭代次数 15 | rho = 0.55; % 线搜索参数 16 | sigma = 0.4; % Armijo条件系数 17 | tau = 0.0; % 修正因子 18 | iter = 0; % 迭代次数 19 | epsilon = 0.01; % 误差阈值 20 | 21 | % 初始化 22 | x = x0; 23 | 24 | while iter < max_iter 25 | % 计算当前点的梯度和海森矩阵 26 | g = feval(grad, x); 27 | H = feval(hess, x); 28 | 29 | % 计算修正因子 30 | mu = norm(g) ^ (1 + tau); 31 | 32 | % 构造修正后的海森矩阵 33 | A = H + mu * eye(n); 34 | 35 | % 计算搜索方向 36 | d = -A \ g; 37 | 38 | m = 0; 39 | mk = 0; 40 | 41 | % 线搜索 42 | while m < 100 43 | if feval(fun, x + rho^m * d) < feval(fun, x) + sigma * rho^m * g' * d 44 | mk = m; % 更新 mk 45 | break; 46 | end 47 | m = m + 1; 48 | end 49 | 50 | % 更新当前点 51 | x = x + rho^mk * d; 52 | iter = iter + 1; 53 | 54 | % 判断停止条件:梯度小于阈值 55 | if norm(g) < epsilon 56 | break; 57 | end 58 | end 59 | 60 | % 输出最优解和最优值 61 | x_opt = x; 62 | f_opt = feval(fun, x); 63 | end 64 | -------------------------------------------------------------------------------- /exterior_penalty_method.m: -------------------------------------------------------------------------------- 1 | function [x_opt, f_val, iter] = exterior_penalty_method(fun, gfun, hfun, cons,cons_grad,cons_hessian, x0, tol) 2 | % 外罚函数法用于解决有约束的优化问题。 3 | % 利用惩罚因子将约束条件整合到目标函数中,转换成无约束优化问题解决。 4 | % 输入: 5 | % fun - 目标函数 6 | % gfun - 目标函数的梯度 7 | % hfun - 目标函数的海森矩阵 8 | % cons - 约束函数 9 | % cons_grad - 约束函数的梯度 10 | % cons_hessian - 约束函数的海森矩阵 11 | % x0 - 初始迭代点 12 | % tol - 约束满足的容忍度 13 | % 输出: 14 | % x_opt - 最优解 15 | % f_val - 在x_opt处的目标函数值 16 | % iter - 迭代次数 17 | 18 | M = 1; % 初始惩罚因子,用于控制约束违反的惩罚程度 19 | c = 10; % 惩罚因子的增长率,用于调整每轮迭代后惩罚因子的大小 20 | x = x0; % 初始点设置为输入的初始迭代点 21 | max_iter = 100; % 设置最大迭代次数 22 | iter = 0; 23 | 24 | % 主循环 25 | while iter < max_iter 26 | % 定义外罚函数,结合原始目标函数与约束违反惩罚 27 | penalty_fun = @(x) fun(x) + M * cons(x)^2; 28 | 29 | % 定义外罚函数的梯度,包括原始梯度与约束违反的梯度部分 30 | penalty_grad = @(x) gfun(x) + 2 * M * cons_grad(x); 31 | 32 | % 定义外罚函数的海森矩阵,增加对应的二次项以处理线性约束 33 | penalty_hess = @(x) hfun(x) + 2 * M * cons_hessian(x); 34 | 35 | % 调用阻尼牛顿法来求解无约束优化问题 36 | [x, ~, ~] = damp_newton_method(penalty_fun, penalty_grad, penalty_hess, x); 37 | 38 | % 检查约束是否满足到指定的容忍度 39 | if abs(cons(x)) < tol 40 | break; % 如果满足,则退出循环 41 | else 42 | M = M * c; % 否则增加惩罚因子,更加严格地处理约束违反 43 | end 44 | 45 | iter = iter + 1; % 46 | end 47 | 48 | % 计算最终的函数值并返回解 49 | f_val = fun(x); 50 | x_opt = x; 51 | end 52 | -------------------------------------------------------------------------------- /fr_conjugate_gradient_method.m: -------------------------------------------------------------------------------- 1 | function [x_opt, f_opt, iter] = FR_conjugate_gradient_method(fun, grad, x0) 2 | % FR共轭梯度法 3 | % 输入: 4 | % fun: 目标函数 5 | % grad: 梯度函数 6 | % x0: 初始点 7 | % 输出: 8 | % x_opt: 近似最优解 9 | % f_opt: 最优解对应的函数值 10 | % iter: 迭代次数 11 | 12 | max_iter = 1000; % 最大迭代次数 13 | rho = 0.6; % 线搜索参数 14 | sigma = 0.4; % Armijo条件系数 15 | epsilon = 0.01; % 误差阈值 16 | 17 | n = length(x0); 18 | k = 0; % 迭代次数 19 | 20 | while k < max_iter 21 | % 计算当前点的梯度 22 | g = feval(grad, x0); 23 | 24 | % 计算FR系数 25 | itern = k - (n + 1) * floor(k / (n + 1)) + 1; 26 | 27 | % 计算搜索方向 28 | if itern == 1 29 | d = -g; 30 | else 31 | beta = (g' * g) / (g0' * g0); 32 | d = -g + beta * d0; 33 | gd = g' * d; 34 | if gd >= 0.0 35 | d = -g; 36 | end 37 | end 38 | 39 | % 检验终止条件:梯度小于阈值 40 | if norm(g) < epsilon 41 | break; 42 | end 43 | 44 | % Armijo搜索 45 | m = 0; 46 | mk = 0; 47 | while m < 20 48 | if feval(fun, x0 + rho^m * d) < feval(fun, x0) + sigma * rho^m * g' * d 49 | mk = m; 50 | break; 51 | end 52 | m = m + 1; 53 | end 54 | 55 | % 更新当前点和迭代次数 56 | x0 = x0 + rho^mk * d; 57 | f_opt = feval(fun, x0); 58 | g0 = g; 59 | d0 = d; 60 | k = k + 1; 61 | end 62 | 63 | % 输出最优解和最优值 64 | x_opt = x0; 65 | f_opt = feval(fun, x0); 66 | iter = k; 67 | end 68 | -------------------------------------------------------------------------------- /trust_region_method.m: -------------------------------------------------------------------------------- 1 | function [x_optimal, optimal_value, iterations] = trust_region_method(fun, gfun, Hess, x_initial) 2 | % 信赖域方法求解无约束优化问题 3 | % 输入: 4 | % fun: 目标函数 5 | % gfun: 梯度函数 6 | % Hess: Hessian矩阵函数 7 | % x_initial: 初始点 8 | % 输出: 9 | % x_optimal: 近似最优解 10 | % optimal_value: 目标函数在最优解处的值 11 | % iterations: 迭代次数 12 | 13 | % 设置参数 14 | eta1 = 0.1; 15 | eta2 = 0.75; 16 | dtabar = 2.0; 17 | tau1 = 0.5; 18 | tau2 = 2.0; 19 | epsilon = 1e-6; 20 | 21 | % 初始化 22 | x = x_initial; 23 | delta = 1; 24 | Bk = feval(Hess, x); 25 | 26 | iterations = 0; 27 | while iterations < 100000 28 | gk = feval(gfun, x); 29 | 30 | % 检查梯度是否满足终止条件 31 | if norm(gk) < epsilon 32 | break; 33 | end 34 | 35 | % 解信赖域子问题 36 | [d, val, lambda, ik] = trust_region_quadratic_model(gk, Bk, delta); 37 | 38 | % 计算实际下降量和预测下降量 39 | delta_q = -qk(x, d); 40 | delta_f = fun(x) - fun(x + d); 41 | rk = delta_f / delta_q; 42 | 43 | % 更新信赖域半径 44 | if rk <= eta1 45 | delta = tau1 * delta; 46 | else 47 | if rk >= eta2 && norm(d) == delta 48 | delta = min(tau2 * delta, dtabar); 49 | end 50 | end 51 | 52 | % 更新迭代点 53 | if rk > eta1 54 | x = x + d; 55 | Bk = feval(Hess, x); 56 | end 57 | 58 | iterations = iterations + 1; % 更新迭代次数 59 | end 60 | 61 | x_optimal = x; 62 | optimal_value = fun(x_optimal); 63 | 64 | % 信赖域子问题目标函数 65 | function q_d = qk(x, d) 66 | g_k = feval(gfun, x); 67 | B_k = feval(Hess, x); 68 | q_d = g_k' * d + 0.5 * d' * B_k * d; 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /interior_penalty_method.m: -------------------------------------------------------------------------------- 1 | function [x_opt, f_opt, iter] = interior_penalty_method(fun, grad, hess, cons,cons_grad,cons_hessian, x0, tol) 2 | % 内点罚函数法 3 | % 该方法通过在目标函数中加入障碍项(惩罚项)来确保解不越过约束界限。 4 | % 输入: 5 | % fun - 原始的目标函数 6 | % grad - 原始目标函数的梯度 7 | % hess - 原始目标函数的海森矩阵 8 | % cons - 约束函数 9 | % cons_grad - 约束函数的梯度 10 | % cons_hessian - 约束函数的海森矩阵 11 | % x0 - 优化问题的初始点 12 | % tol - 容忍度,用于控制优化的精度 13 | % 输出: 14 | % x_opt - 最优解 15 | % f_opt - 在最优解处的目标函数值 16 | % iter - 实际迭代次数 17 | 18 | R = 10; % 初始障碍因子,用于控制障碍项的强度 19 | c = 0.7; % 障碍因子的递减系数,用于每轮迭代后减少障碍因子 20 | x = x0; % 设置优化算法的起始点为输入的初始点 21 | max_iter = 100; % 设置最大迭代次数 22 | iter = 0; 23 | 24 | while iter < max_iter 25 | % 定义内点罚函数的障碍项,适用于输入的约束函数 26 | barrier = @(x) -R * log(cons(x)); 27 | % 定义内点罚函数的梯度 28 | barrier_grad = @(x) -R ./ cons(x) .* cons_grad(x); 29 | % 定义内点罚函数的海森矩阵 30 | barrier_hessian = @(x) R * (cons_grad(x) * cons_grad(x)' ./ cons(x).^2 - cons_hessian(x) ./ cons(x)); 31 | 32 | % 定义内点罚函数,结合原始目标函数和障碍项 33 | penalty_fun = @(x) fun(x) + barrier(x); 34 | % 定义内点罚函数的梯度 35 | penalty_grad = @(x) grad(x) + barrier_grad(x); 36 | % 定义内点罚函数的海森矩阵 37 | penalty_hess = @(x) hess(x) + barrier_hessian(x); 38 | 39 | % 使用阻尼牛顿法求解当前无约束优化问题 40 | [x, ~, ~] = damp_newton_method(penalty_fun, penalty_grad, penalty_hess, x); 41 | 42 | % 检查障碍项的绝对值是否已小于容忍度,以判断是否接近约束边界 43 | if abs(barrier(x)) < tol 44 | break; % 若满足容忍度,则终止迭代 45 | else 46 | R = R * c; % 若不满足,递减障碍因子,继续迭代 47 | end 48 | 49 | iter = iter + 1; % 更新迭代次数 50 | end 51 | 52 | % 计算在当前解x处的目标函数值 53 | f_opt = fun(x); 54 | % 返回最优解 55 | x_opt = x; 56 | end -------------------------------------------------------------------------------- /l_m_least_squares_method.m: -------------------------------------------------------------------------------- 1 | function [x_opt, val_opt, itr] = l_m_least_squares_method(Fk, JFk, x0) 2 | % Levenberg-Marquardt 最小二乘法 3 | % 输入: 4 | % x0 - 迭代的初始点 5 | % Fk - 计算 F(x) 的函数句柄 6 | % JFk - 计算雅可比矩阵 F'(x) 的函数句柄 7 | % 输出: 8 | % x - F(x) 最小化时的近似解 9 | % val - 解处 0.5*norm(F(x))^2 的值 10 | % k - 执行的迭代次数 11 | 12 | % 最大迭代次数,防止无限循环 13 | maxk = 100; 14 | % Armijo 规则的参数 15 | rho = 0.55; % 步长减小因子 16 | sigma = 0.4; % 足够减小常数 17 | % 初始 mu 参数,基于残差的范数缩放 18 | muk = norm(feval(Fk, x0)); 19 | % 迭代计数器 20 | itr = 0; 21 | % 梯度范数的收敛容忍度 22 | epsilon = 1e-6; 23 | % 问题的维度(变量数) 24 | n = length(x0); 25 | 26 | % 主迭代循环 27 | while itr < maxk 28 | % 在当前点计算函数值和雅可比矩阵 29 | fk = feval(Fk, x0); % 当前函数值 F(x) 30 | jfk = feval(JFk, x0); % 当前雅可比矩阵 F'(x) 31 | % 计算目标函数 0.5*norm(F(x))^2 的梯度 32 | gk = jfk' * fk; % 梯度计算 33 | 34 | % 解算搜索方向 35 | dk = -(jfk' * jfk + muk * eye(n)) \ gk; % 搜索方向 36 | 37 | % 检查收敛性(梯度范数是否足够小) 38 | if norm(gk) < epsilon, break; end 39 | 40 | % Armijo 线搜索确定步长 41 | m = 0; % 步长指数计数器 42 | mk = 0; % 找到的最佳步长指数 43 | while m < 20 44 | % 在新的候选点评估函数 45 | newf = 0.5 * norm(feval(Fk, x0 + rho^m * dk))^2; 46 | oldf = 0.5 * norm(feval(Fk, x0))^2; 47 | % 检查 Armijo 条件 48 | if newf < oldf + sigma * rho^m * gk' * dk 49 | mk = m; % 接受步长 50 | break; 51 | end 52 | m = m + 1; 53 | end 54 | 55 | % 更新当前点 56 | x0 = x0 + rho^mk * dk; 57 | % 基于新的函数值更新 mu 58 | muk = norm(feval(Fk, x0)); 59 | % 增加迭代次数 60 | itr = itr + 1; 61 | end 62 | 63 | % 输出结果 64 | x_opt = x0; % 最终近似解 65 | val_opt = 0.5 * muk^2; % 解处的目标函数值 66 | end 67 | -------------------------------------------------------------------------------- /trust_region_quadratic_model.m: -------------------------------------------------------------------------------- 1 | %%% 利用光滑牛顿法求解信赖域子问题 %%% 2 | function [d, val, lam, k] = trust_region_quadratic_model(gk, Bk, dta) 3 | % 光滑牛顿法 4 | % 输入: 5 | % gk: 当前点的梯度 6 | % Bk: 当前点的 Hessian 矩阵 7 | % dta: 信赖域半径 8 | % 输出: 9 | % d: 子问题的解 10 | % val: 目标函数在 d 处的值 11 | % lam: 最优拉格朗日乘子 12 | % k: 迭代次数 13 | 14 | n = length(gk); % 计算梯度维度 15 | gamma = 0.05; % 初始参数 16 | epsilon = 1.0e-6; % 停止条件 17 | rho = 0.6; % 步长控制参数 18 | sigma = 0.2; % 用于控制步长的参数 19 | mu0 = 0.05; % 初始步长 20 | lam0 = 0.05; % 初始拉格朗日乘子 21 | d0 = ones(n,1); % 初始解向量 22 | u0 = [mu0, zeros(1,n+1)]'; % 初始辅助向量 23 | z0 = [mu0, lam0, d0']'; % 初始组合向量 24 | k = 0; % 迭代次数 25 | z = z0; 26 | mu = mu0; 27 | lam = lam0; 28 | d = d0; 29 | 30 | while (k <= 150) 31 | % 计算子问题解的残差 32 | dh = dah(mu, lam, d, gk, Bk, dta); 33 | % 判断残差是否满足停止条件 34 | if (norm(dh) < epsilon) 35 | break; 36 | end 37 | % 构建雅可比矩阵和右侧向量 38 | A = JacobiH(mu, lam, d, Bk, dta); 39 | b = beta(mu, lam, d, gk, Bk, dta, gamma) * u0 - dh; 40 | % 求解线性方程组 41 | B = inv(A); 42 | dz = B * b; 43 | dmu = dz(1); 44 | dlam = dz(2); 45 | dd = dz(3:n+2); 46 | m = 0; 47 | mk = 0; 48 | % 用Armijo条件搜索合适的步长 49 | while (m < 20) 50 | dhnew = dah(mu + rho^m * dmu, lam + rho^m * dlam, d + rho^m * dd, gk, Bk, dta); 51 | if (norm(dhnew) <= (1 - sigma * (1 - gamma * mu0) * rho^m) * dh) 52 | mk = m; 53 | break; 54 | end 55 | m = m + 1; 56 | end 57 | alpha = rho^mk; % 更新步长 58 | mu = mu + alpha * dmu; % 更新步长参数 59 | lam = lam + alpha * dlam; % 更新拉格朗日乘子 60 | d = d + alpha * dd; % 更新解向量 61 | k = k + 1; % 迭代次数加一 62 | end 63 | val = gk' * d + 0.5 * d' * Bk * d; % 计算目标函数值 64 | 65 | function p = phi(mu, a, b) 66 | p = a + b - sqrt((a - b)^2 + 4 * mu); % 定义 phi 函数 67 | end 68 | 69 | function dh = dah(mu, lam, d, gk, Bk, dta) 70 | n1 = length(d); 71 | dh(1) = mu; 72 | dh(2) = phi(mu, lam, dta^2 - norm(d)^2); 73 | mh = (Bk + lam * eye(n1)) * d + gk; 74 | for (i = 1:n1) 75 | dh(2 + i) = mh(i); 76 | end 77 | dh = dh(:); 78 | end 79 | 80 | function bet = beta(mu, lam, d, gk, Bk, dta, gamma) 81 | dhh = dah(mu, lam, d, gk, Bk, dta); % 计算残差 82 | bet = gamma * norm(dhh) * min(1, norm(dhh)); % 计算步长控制参数 83 | end 84 | 85 | % 定义雅可比矩阵 86 | function A = JacobiH(mu, lam, d, Bk, dta) 87 | n2 = length(d); 88 | A = zeros(n2 + 2, n2 + 2); 89 | pmu = -4 * mu / sqrt((lam + norm(d)^2 - dta^2)^2 + 4 * mu^2); 90 | thetak = (lam + norm(d)^2 - dta^2) / sqrt((lam + norm(d)^2 - dta^2)^2 + 4 * mu^2); 91 | A = [1, 0, zeros(1, n2); 92 | pmu, 1 - thetak, -2 * (1 + thetak) * d'; 93 | zeros(n2, 1), d, Bk + lam * eye(n2)]; % 构建雅可比矩阵 94 | end 95 | end -------------------------------------------------------------------------------- /utils/examples_of_problems.md: -------------------------------------------------------------------------------- 1 | The following are five typical examples of solving optimization numerical problems. For the solution code, see the path './utils/' 2 | 3 | 1. Using the steepest gradient descent method to solve 4 | $$ 5 | \min f(X)=x_1^2+25 x_2^2 6 | $$ 7 | Initial value $X_0=[1,2]^T, \varepsilon=0.01$. 8 | 9 | 2. Using the Newton's method to solve 10 | $$ 11 | \min f(X)=x_1^2+x_2^2-x_1 x_2-10 x_1-4 x_2+60 12 | $$ 13 | Initial value $X_0=[0,1]^T, \varepsilon=0.01$. 14 | 15 | 3. Using the conjugate gradient method to solve 16 | $$ 17 | \min f(X)=x_1^2+4 x_2^2 18 | $$ 19 | Initial value $X_0=[1,1]^T, \varepsilon=0.01$. 20 | 21 | 4. Given the function 22 | $$ 23 | f(x)=x_1^2+x_2^2-1, 24 | $$ 25 | at the current point $ x=[2,2]$, with a descent direction $ d=[-1,-1]^ T $, use the Armijo search method to obtain an acceptable step length ( $ \rho=0.1 $​ ). 26 | 27 | 5. Solve the unconstrained optimization problem using the trust region metho 28 | $$ 29 | \min _{x \in R^2} f(x)=100\left(x_1^2-x_2\right)^2+\left(x_1-1\right)^2 30 | $$ 31 | This problem has an exact solution $x^*=[1,1]^T, f\left(x^*\right)=0$. 32 | 33 | 6. Solving Using Least Squares Method. When studying the rate of a single-molecule chemical reaction, the following data were obtained: 34 | 35 | | Index | $\mathbf{1}$ | $\mathbf{2}$ | $\mathbf{3}$ | $\mathbf{4}$ | $\mathbf{5}$ | $\mathbf{6}$ | $\mathbf{7}$ | $\mathbf{8}$ | 36 | | :--------------: | :----------: | :----------: | :----------: | :----------: | :----------: | :----------: | :----------: | :----------: | 37 | | $\boldsymbol{t}$ | 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 38 | | $\boldsymbol{y}$ | 57.6 | 41.9 | 31.0 | 22.7 | 16.6 | 12.2 | 8.9 | 6.5 | 39 | 40 | Here, $t$ represents the time elapsed since the start of the experiment, and $y$ represents the amount of reactant produced at time $t$. Based on the above data, determine the empirical formula $y=f(t)$. 41 | 42 | 7. Solve the Quadratic Programming Problem and Write the Lagrangian Function and Analysis Process 43 | $$ 44 | \left\{ 45 | \begin{array}{l} 46 | \min \quad x_1^2 + x_2^2 \\ 47 | \text{s.t. } x_1 + x_2 = 1 \\ 48 | x_2 \leq \frac{1}{4} 49 | \end{array} 50 | \right. 51 | $$ 52 | 53 | 8. Solve the Following Problem Using the Exterior Penalty Function Method with Precision $10^{-8}$ and Initial Point $(10,10)$ 54 | 55 | $$ 56 | \begin{gathered} 57 | \min f(x) = x_1^2 + x_2^2 \\ 58 | \text{s.t. } x_1 + x_2 = 2 59 | \end{gathered} 60 | $$ 61 | 62 | 9. Solve the Following Problem Using the Interior Penalty Function Method with Precision $10^{-8}$ and Initial Point $(10,10)$ 63 | 64 | $$ 65 | \begin{gathered} 66 | \min f(x) = x_1^2 + x_2^2 \\ 67 | \text{s.t. } x_1 - 1 \geq 0 68 | \end{gathered} 69 | $$ 70 | 71 | 10. Use Genetic Algorithm to Find the Maximum Value of the Following Function in the Specified Constraint Set: 72 | 73 | $$ 74 | f(x) = x \sin (10x) + 1 75 | $$ 76 | 77 | The constraint set is $\{x \in \mathbb{R} : x \in [-1, 2]\}$. The solution should be accurate to 6 decimal places. -------------------------------------------------------------------------------- /genetic_algorithm.m: -------------------------------------------------------------------------------- 1 | function [x_opt, maxFitness] = genetic_algorithm(objectiveFunction, populationSize, numGenerations, crossoverRate, mutationRate, tolerance, lowerBound, upperBound) 2 | % 遗传算法 3 | % 输入: 4 | % objectiveFunction - 目标函数,用于计算种群的适应度值。 5 | % populationSize - 种群大小,即种群中个体的数量。 6 | % numGenerations - 迭代次数,算法运行的代数。 7 | % crossoverRate - 交叉率,决定多少比例的个体会进行交叉。 8 | % mutationRate - 变异率,决定多少比例的个体会发生变异。 9 | % tolerance - 收敛容忍度,当种群的适应度变化小于此值时算法停止。 10 | % lowerBound - 搜索空间的下界。 11 | % upperBound - 搜索空间的上界。 12 | % 输出: 13 | % x_opt - 最优解,适应度最高的个体。 14 | % maxFitness - 最大适应度值。 15 | 16 | % 设置二进制编码长度 17 | numBits = 16; 18 | 19 | % 初始化种群:在搜索空间内随机生成初始二进制种群 20 | population = randi([0, 1], populationSize, numBits); 21 | fitness = calculate_fitness(objectiveFunction, population, lowerBound, upperBound, numBits); % 计算每个个体的适应度 22 | 23 | % 初始化最优个体 24 | [maxFitness, bestIndex] = max(fitness); 25 | bestIndividual = population(bestIndex, :); 26 | 27 | for generation = 1:numGenerations 28 | % 选择操作(最优保存策略):保留当前最优个体 29 | newPopulation = population; 30 | newPopulation(1, :) = bestIndividual; 31 | 32 | % 交叉操作:随机选择个体对进行基因交换,产生新的个体 33 | for i = 2:2:populationSize-1 34 | if rand < crossoverRate 35 | crossoverPoint = randi([1, numBits-1]); 36 | newPopulation(i, crossoverPoint+1:end) = population(i+1, crossoverPoint+1:end); 37 | newPopulation(i+1, crossoverPoint+1:end) = population(i, crossoverPoint+1:end); 38 | end 39 | end 40 | 41 | % 变异操作:随机改变个体的某些基因,以增加种群的多样性 42 | for i = 2:populationSize 43 | for j = 1:numBits 44 | if rand < mutationRate 45 | newPopulation(i, j) = 1 - newPopulation(i, j); % 翻转基因位 46 | end 47 | end 48 | end 49 | 50 | % 更新种群和适应度:用新种群替换旧种群,并重新计算适应度 51 | population = newPopulation; 52 | fitness = calculate_fitness(objectiveFunction, population, lowerBound, upperBound, numBits); 53 | 54 | % 更新最优个体 55 | [currentMaxFitness, bestIndex] = max(fitness); 56 | if currentMaxFitness > maxFitness 57 | maxFitness = currentMaxFitness; 58 | bestIndividual = population(bestIndex, :); 59 | end 60 | 61 | % 打印当前代数和最大适应度 62 | fprintf('迭代数 %d: 当前适应度 = %.6f\n', generation, maxFitness); 63 | 64 | % 检查收敛:如果最大和最小适应度之差小于容忍度,则停止迭代 65 | if max(fitness) - min(fitness) < tolerance 66 | break; 67 | end 68 | end 69 | 70 | % 找到最优解:找出适应度最高的个体及其适应度值 71 | x_opt = decode_individual(bestIndividual, lowerBound, upperBound, numBits); 72 | 73 | fprintf('最优解: x = %.6f, f(x) = %.6f\n', x_opt, maxFitness); 74 | end 75 | 76 | % 计算种群的适应度值 77 | function fitness = calculate_fitness(objectiveFunction, population, lowerBound, upperBound, numBits) 78 | populationSize = size(population, 1); 79 | fitness = zeros(populationSize, 1); 80 | for i = 1:populationSize 81 | x = decode_individual(population(i, :), lowerBound, upperBound, numBits); 82 | fitness(i) = objectiveFunction(x); 83 | end 84 | end 85 | 86 | % 将二进制个体解码为连续值 87 | function x = decode_individual(individual, lowerBound, upperBound, numBits) 88 | binaryString = num2str(individual); 89 | binaryValue = bin2dec(binaryString); 90 | x = lowerBound + (upperBound - lowerBound) * (binaryValue / (2^numBits - 1)); 91 | end 92 | --------------------------------------------------------------------------------