数学建模优化及算法总结

一.模型优化

1.线性规划
目标函数和约束条件都是线性的最优化方法称为线性最优化,也称为线性规划问题。Matlab 中线性规划的标准形式为
\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad m i n x x = f T x \mathop{minx}\limits_{x} = f^{T}x xminx=fTx
s . t = { A ⋅ x ≤ b , A e q ⋅ x = b e q , l b ≤ x ≤ u b . s.t = \left\{\begin{array}{l} A \cdot x \leq b, \\Aeq \cdot x = beq, \\lb \leq x \leq ub. \end{array}\right. s.t=Axb,Aeqx=beq,lbxub.
通常称 x x x 为决策变量, f f f 为价值系数。
Matlab 中求解线性规划的命令为
[ x , f v a l ] = l i n p r o g ( f , A , b , A e q , b e q , l b , u b ) [x,fval] = linprog(f, A, b, Aeq, beq, lb, ub) [x,fval]=linprog(f,A,b,Aeq,beq,lb,ub)
其中 A A A b b b 对应线性不等式约束, A e q Aeq Aeq b e q beq beq 对应线性等式约束, l b lb lb u b ub ub 分别为决策向量的下界向量和上界向量。

下面以一个例题来说明如何求解线性规划问题。
假设目标函数为
\qquad\qquad\qquad\qquad\qquad\qquad m i n z = 13 x 1 + 9 x 2 + 10 x 3 + 11 x 4 + 12 x 5 + 8 x 6 minz = 13x_{1} + 9x_{2} + 10x_{3} + 11x_{4} +12x_{5} + 8x_{6} minz=13x1+9x2+10x3+11x4+12x5+8x6
约束条件为
s . t = { x 1 + x 4 = 400 , x 2 + x 5 = 600 , x 3 + x 6 = 500 , 0.4 x 1 + 1.1 x 2 + x 3 ≤ 800 , 0.5 x 4 + 1.2 x 5 + 1.3 x 6 ≤ 900 , x i ≥ 0 , i = 1 , 2 , . . . , 6. s.t = \left\{\begin{array}{l} x_{1} + x{4} = 400, \\x_{2} + x_{5} = 600, \\x_{3} + x_{6} = 500, \\0.4x_{1} + 1.1x_{2} + x_{3} \leq 800, \\0.5x_{4} + 1.2x_{5} + 1.3x_{6} \leq 900, \\x_{i} \geq 0, i = 1, 2,...,6. \end{array}\right. s.t=x1+x4=400,x2+x5=600,x3+x6=500,0.4x1+1.1x2+x3800,0.5x4+1.2x5+1.3x6900,xi0,i=1,2,...,6.
首先,注意到目标函数有6个系数,我们改写为
\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad m i n z = ( 13 9 10 11 12 8 ) X minz = (13\quad9\quad10\quad11\quad12\quad8)X minz=(1391011128)X
接着处理不等式约束的两个式子 0.4 x 1 + 1.1 x 2 + x 3 ≤ 800 0.4x_{1} + 1.1x_{2} + x_{3} \leq 800 0.4x1+1.1x2+x3800 0.5 x 4 + 1.2 x 5 + 1.3 x 6 ≤ 900 0.5x_{4} + 1.2x_{5} + 1.3x_{6} \leq 900 0.5x4+1.2x5+1.3x6900,这里有 2 条式子以及 6 个决策变量,于是我们要构造一个 2 行 6 列的矩阵
( 0.4 1.1 1 0 0 0 0 0 0 0.5 1.2 1.3 ) X ≤ ( 800 900 ) \begin{pmatrix} 0.4 & 1.1 & 1 & 0 & 0 & 0\\ 0 & 0 & 0 & 0.5 & 1.2 & 1.3\\ \end{pmatrix}X \leq \begin{pmatrix}800\\900\end{pmatrix} (0.401.101000.501.201.3)X(800900)
最后来处理等式约束的三个式子 x 1 + x 4 = 400 x_{1} + x{4} = 400 x1+x4=400 x 2 + x 5 = 600 x_{2} + x_{5} = 600 x2+x5=600 以及 x 3 + x 6 = 500 x_{3} + x_{6} = 500 x3+x6=500,由于这里有 3 条式子以及 6 个决策变量,于是我们要构造一个 3 行 6 列的矩阵
( 1 0 0 1 0 0 0 1 0 0 1 0 0 0 1 0 0 1 ) X = ( 400 600 500 ) \begin{pmatrix} 1 & 0 & 0 & 1 & 0 & 0\\ 0 & 1 & 0 & 0 & 1 & 0\\ 0 & 0 & 1 & 0 & 0 & 1\\ \end{pmatrix}X = \begin{pmatrix}400\\600\\500\end{pmatrix} 100010001100010001X=400600500

Matlab 求解的代码如下

f = [13 9 10 11 12 8];
A = [0.4 1.1 1 0 0 0; 0 0 0 0.5 1.2 1.3];
b = [800; 900];
Aeq = [1 0 0 1 0 0; 0 1 0 0 1 0; 0 0 1 0 0 1];
beq = [400; 600; 500];
lb = zeros(6, 1);
ub = [];
[x,fval] = linprog(f, A, b, Aeq, beq, lb, ub)

下面再来看一个例子:
在这里插入图片描述

clc,clear,close all
%% 选择优化求解器,线性规划求解可由linprog实现
 
%% 将所有变量合并为一个向量,共16个变量
variables = {
    
    'I1','I2','HE1','HE2','LE1','LE2','C','BF1','BF2','HPS','MPS','LPS','P1','P2','PP','EP'}
N = length(variables)
for v = 1:N
    eval([variables{
    
    v}, '=', num2str(v), ';']) %将I1到EP映射为116
end
 
%% 设置上下限约束(lb<=x<=ub)
% 设置下限约束,即lb<=x
lb = zeros(size(variables)); % 1x16的矩阵,每个数都是0
lb([P1, P2, MPS, LPS]) = [2500, 3000, 271536, 100623];
% 设置上限约束,即x<=ub
ub = Inf(size(variables)); % 16的矩阵,每个数都是无穷大
ub([P1, P2, I1, I2, C, LE2]) = [6250, 9000, 192000, 244000, 62000, 142000];
 
%% 创建线性不等式约束(A*x<=b)
A = zeros(3,16); % 3x16的矩阵,每个数均为0,为什么是3x16,因为约束条件有3个不等式

% 由不等式I1-HE1<=132000得到下面一行代码
A(1, I1) = 1;
A(1, HE1) = -1;
b(1) = 132000;

% 由不等式-EP-PP<=12000得到下面一行代码
A(2, EP) = -1;
A(2, PP) = -1;
b(2) = -12000;

% 由不等式-P1-P2-PP<=-24550得到下面一行代码
A(3, [P1, P2, PP]) = [-1, -1, -1];
b(3) = -24550;
 
%% 创建线性等式约束(Aeq*x=beq)
Aeq = zeros(8,16);
beq = zeros(8,1) % 约束条件中共有8个等式

% 把等式I2=LE2+HE2转化为LE2+HE2-I2=0后,得到下面一行代码
Aeq(1, [LE2, HE2, I2]) = [1, 1, -1];
Aeq(2, [LE1, LE2, BF2, LPS]) = [1, 1, 1, -1];
Aeq(3, [I1, I2, BF1, HPS]) = [1, 1, 1, -1];
Aeq(4, [C, MPS, LPS, HPS]) = [1, 1, 1, -1];
Aeq(5, [LE1, HE1, C, I1]) = [1, 1, 1, -1];
Aeq(6, [HE1, HE2, BF1, BF2, MPS]) = [1, 1, 1, -1, -1];
Aeq(7, [HE1, LE1, C, P1, I1]) = [1267.8, 1251.4, 192, 3413, -1359.8];
Aeq(8, [HE2, LE2, P2, I2]) = [1267.8, 1251.4, 3413, -1359.8];
 
%% 创建目标函数
f = zeros(size(variables));
% 由目标函数0.002614HPS + 0.0239PP + 0.009825EP
f([HPS, PP, EP]) = [0.002614, 0.0239, 0.009825];
 
%% 由linprog实现线性规划问题求解
options = optimoptions('linprog', 'Algorithm', 'dual-simplex');
% 将前面已经确定的各个参数传入linprog()[x, fval] = linprog(f, A, b, Aeq, beq, lb, ub, options);
for d = 1:N
    fprintf('%12.2f\t%s\n', x(d), variables{
    
    d})
end

2.整数规划
数学规划中的变量(部分或全部)限制为整数时,称为整数规划。

2.1 0 − 1 0 - 1 01型整数规划
0 − 1 0 - 1 01 型整数规划中某个变量 x j x_{j} xj 只能取值 0 或 1。
求解 0 − 1 0 - 1 01 型整数规划可以使用 Matlab 的 i n t l i n p r o g intlinprog intlinprog 函数, i n t l i n p r o g intlinprog intlinprog函数参数如下
i n t l i n p r o g ( f , i n t c o n , A , b , A e q , b e q , l b , u b ) intlinprog(f, intcon, A, b, Aeq, beq, lb, ub) intlinprog(f,intcon,A,b,Aeq,beq,lb,ub)
其中 f f f 为目标函数各变量的系数, i n t c o n intcon intcon 为只能取 0 − 1 0 - 1 01 的变量的下标数值, A A A b b b 对应线性不等式约束, A e q Aeq Aeq b e q beq beq 对应线性等式约束, l b lb lb u b ub ub 分别为决策向量的下界向量和上界向量。
下面用一个例子来说明如何求解 0 − 1 0 - 1 01 整数规划问题。
假设目标函数为
\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad m a x z = 3 x 1 − 2 x 2 + 5 x 3 maxz = 3x_{1} - 2x_{2} + 5x_{3} maxz=3x12x2+5x3
约束条件为
s . t = { x 1 + 2 x 2 − x 3 ≤ 2 , x 1 + 4 x 2 + x 3 ≤ 4 , x 1 + x 2 ≤ 3 , 4 x 2 + x 3 ≤ 6 , 0.5 x 4 + 1.2 x 5 + 1.3 x 6 ≤ 900 , x 1 , x 2 , x 3 = 0 或 1. s.t = \left\{\begin{array}{l} x_{1} + 2x_{2} - x_{3} \leq 2, \\x_{1} + 4x_{2} + x_{3} \leq 4, \\x_{1} + x_{2} \leq 3, \\4x_{2} + x_{3} \leq 6, \\0.5x_{4} + 1.2x_{5} + 1.3x_{6} \leq 900, \\x_{1},x_{2},x_{3} = 0 或 1. \end{array}\right. s.t=x1+2x2x32,x1+4x2+x34,x1+x23,4x2+x36,0.5x4+1.2x5+1.3x6900,x1,x2,x3=01.
求解的 Matlab 代码如下
因为这里 x 1 , x 2 , x 3 x_{1},x_{2},x_{3} x1,x2,x3 都只能取 0 或 1,因此 i n t c o n intcon intcon [ 1 , 2 , 3 ] [1,2,3] [1,2,3]

f = [-3; 2; -5];
intcon = [1, 2, 3];
A = [1 2 -1; 1 4 1; 1 1 0; 0 4 1]; % 四个不等式中的变量系数
b = [2; 4; 3; 6]; % 约束条件中不等式右边的常数
lb = [0, 0, 0]; % x1,x2,x3=0
ub = [1, 1, 1]; % x1,x2,x3=1
Aeq = [0, 0, 0];
beq = 0;
x = intlinprog(f, intcon, A, b, Aeq, beq, lb, ub)

3.多目标规划

二.插值与拟合

插值:已知若干点 ( x i , y i ) (x_{i},y_{i}) (xi,yi),构造一个过所有已知点的函数 y = f ( x ) y = f(x) y=f(x)
拟合:已知一些点,寻找一个函数曲线,使其与所有已知的数据点最为接近。
通常在已知数据较少时使用插值,数据较多时使用拟合。
首先是插值算法
1.拉格朗日插值
Matlab 代码:

function y1 = Lagrange(x, y, x1);
% x   插值节点
% y   被插值函数在节点x处的函数值
% x1  待插值节点
% y1  待插值节点的插值结果
n = length(x); % 数据点个数
m = length(x1); % 待插值点数
for k = 1:m
    z = x1(k);
    sum = 0.0;
    for i = 1:n
        prod = 1.0;
        for j = 1:n
            if j ~= i
                prod = prod * (z - x(j)) / (x(i) - x(j));
            end
        end
        sum = sum + prod * y(i);
    end
    y1(k) = sum;
end              

测试样例:

clear all 
clc
% 人口数据
T = 1:30;  % +1970=年份
P = [33815 33981 34004 34165 34212 34327 34344 34458 34498 34476 34483 34488 34513 34497 34511 34520 34507 34509 34521 34513 34515 34517 34519 34519 34521 34521 34523 34525 34525 34527];%人口
plot(T, P, 'r o')% 只画数据点
hold on
x1 = 1.5 : 30.5; 
y1 = Lagrange(T, P, x1);
plot(x1, y1, 'b +')
axis([0 30 33600 34800])
title('拉格朗日插值&人口预测模型')

2.牛顿插值
Matlab 代码:

%newton.m
%求牛顿插值多项式、差商、插值及其误差估计的MATLAB主程序
%输入的量:X是n+1个节点(x_i,y_i)(i = 1,2, ... , n+1)横坐标向量,Y是纵坐标向量,
%x是以向量形式输入的m个插值点,M在[a,b]上满足|f~(n+1)(x)|≤M
%注:f~(n+1)(x)表示f(x)的n+1阶导数
%输出的量:向量y是向量x处的插值,误差限R,n次牛顿插值多项式L及其系数向量C,
%差商的矩阵A
function[y, R, A, C, L] = newton(X, Y, x, M)
n = length(X);
m = length(x);
for t = 1 : m
    z = x(t);
    A = zeros(n, n);
    A(:,1) = Y';
    s = 0.0; p = 1.0; q1 = 1.0; c1 = 1.0;
        for j = 2 : n
            for i = j : n
                A(i,j) = (A(i,j-1) - A(i-1,j-1))/(X(i) - X(i-j+1));
            end
            q1 = abs(q1 * (z - X(j-1))); % 余项计算中的差值连乘项
            c1 = c1 * j; % 余项计算中的分母,阶乘
        end
        C = A(n, n); q1 = abs(q1 * (z-X(n)));
        for k = (n - 1) : -1 : 1
            C = conv(C, poly(X(k))); 
            % poly函数把根转换为求得此根的多项式,X(k)是一个数,所以转换为一次多项式,得到其系数向量
            % conv函数的输入是多项式的系数向量时,相当于直接相乘
            d = length(C);
            C(d) = C(d) + A(k, k);%在最后一维,也就是常数项加上新的差商
        end
        y(t) = polyval(C, z); % 插值结果
        R(t) = M * q1 / c1; % 用M代替f~(n+1)(x),即f(x)的n+1阶导数,这样求得的余项比真实值略大
end
L = vpa(poly2sym(C), 3);% vpa让输出结果系数为小数而非分数,3表示用3位小数

测试样例1:

clear all 
clc
X = [0 pi/6 pi/4 pi/3 pi/2];  
Y = [0 0.5 0.7071 0.8660 1];  
x = linspace(0,pi,50);  
M = 1;  
[y, R, A, C, L] = newton(X, Y, x, M); 
y1 = sin(x);  
errorbar(x, y, R, '.g')  
hold on  
plot(X, Y, 'or', x, y, '.k', x, y1, '-b');  
legend('误差', '样本点', '牛顿插值估算', 'sin(x)'); 

测试样例2:

X = [0.4 0.55 0.65 0.80 0.90 1.05];
Y = [0.41075 0.57815 0.69675 0.88811 1.02652 1.25386];
x = 0.4 : 0.01 : 1.05;
M = 1;  
[y, R, A, C, L] = newton(X, Y, x, M);   
errorbar(x, y, R, '.g')  
hold on  
plot(X, Y, 'or', x, y, '.k');  
legend('误差', '样本点', '牛顿插值估算'); 

接着是拟合算法
1.最小二乘法线性拟合
Matlab 代码:

clear;clc
load  data1
plot(x, y, 'o')
% 给x和y轴加上标签
xlabel('x的值')
ylabel('y的值')
n = size(x,1);
k = (n * sum(x.*y) - sum(x) * sum(y)) / (n * sum(x.*x) - sum(x) * sum(x))
b = (sum(x.*x) * sum(y) - sum(x) * sum(x.*y)) / (n * sum(x.*x) - sum(x) * sum(x))
hold on % 继续在之前的图形上来画图形
grid on % 显示网格线

% % 画出y=kx+b的函数图像 plot(x,y)
% % 传统的画法:模拟生成x和y的序列,比如要画出[0,5]上的图形
% x = 0: 0.1 :5  % 间隔设置的越小画出来的图形越准确
% y = k * x + b  % k和b都是已知值
% plot(x,y,'-')

f = @(x) k * x + b;
fplot(f, [min(x) - 1, max(x) + 1]);
legend('样本数据', '拟合函数', 'location', 'SouthEast')


% 匿名函数的基本用法。
% handle = @(arglist) anonymous_function
% 其中handle为调用匿名函数时使用的名字。
% arglist为匿名函数的输入参数,可以是一个,也可以是多个,用逗号分隔。
% anonymous_function为匿名函数的表达式。
% 举个小例子
% % >> z=@(x,y) x^2+y^2; 
% % >> z(1,2) 
% % ans =  5
% fplot函数可用于画出匿名函数的图形。
% fplot(f,xinterval) 将在指定区间绘图。将区间指定为 [xmin xmax] 形式的二元素向量。

y_hat = k * x + b; % y的拟合值
SSR = sum((y_hat - mean(y)).^2)  % 回归平方和
SSE = sum((y_hat - y).^2) % 误差平方和
SST = sum((y - mean(y)).^2) % 总体平方和
SST - SSE - SSR  % 非常小的数,接近0
R_2 = SSR / SST % 拟合优度

三.算法

多元线性回归:求一个变量与两个及以上其他变量的线性关系的方法
Python求解代码如下

import numpy as np
from sklearn import linear_model

"""
scikit-learn
"""

Y = np.array([89, 91, 93, 95, 97])
X = np.array([[87, 72, 83, 90],
              [89, 76, 88, 93],
              [89, 74, 82, 91],
              [92, 71, 91, 89],
              [93, 76, 89, 94]])
m = np.alen(X)
ones = np.ones(m)
X = np.column_stack((ones, X))

model = linear_model.LinearRegression()
model.fit(X, Y)
x_predict = np.array([[1, 88, 73, 87, 92]])
result = model.predict(x_predict)
print(model.intercept_)
print(model.coef_)
print("Predit result: ", result)

这里求得的 y y y x x x 的关系式为 y = x ⋅ θ y = x \cdot \theta y=xθ,其中

x = [ 1 87 72 83 90 1 89 76 88 93 1 89 74 82 91 1 92 71 91 89 1 93 76 89 94 ] x = \begin{bmatrix} 1 & 87 & 72 & 83 & 90\\ 1 & 89 & 76 & 88 & 93\\ 1 & 89 & 74 & 82 & 91\\ 1 & 92 & 71 & 91 & 89\\ 1 & 93 & 76 & 89 & 94 \end{bmatrix} x=111118789899293727674717683888291899093918994 θ = [ θ 0 θ 1 θ 2 θ 3 θ 4 ] = [ − 19.5 1.6875 0.375 − 0.3125 − 0.4375 ] \theta = \begin{bmatrix}\theta_{0}\\\theta_{1}\\\theta_{2}\\\theta_{3}\\\theta_{4}\end{bmatrix} = \begin{bmatrix}-19.5\\1.6875\\0.375\\-0.3125\\-0.4375\end{bmatrix} θ=θ0θ1θ2θ3θ4=19.51.68750.3750.31250.4375.

该程序输出的 i n t e r c e p t intercept intercept 代表 θ 0 \theta_{0} θ0 c o e f coef coef_代表 θ 1 到 θ 4 \theta_{1} 到 \theta_{4} θ1θ4

四.Matlab常用函数总结

Matlab导入Excel数据:

P = xlsread('3.xlsx', 'A2:A402');
%3.xlsx中A2到A402的数据导入并赋给变量P

Matlab二次拟合:

y = polyfit(自变量, 因变量, 2);
z = polyval(y, 自变量);
plot(自变量, 因变量, '.', 自变量, z, 'b');

未完待续

参考博客 https://blog.csdn.net/qq_41149269/article/details/84202777
https://blog.csdn.net/sinat_31790817/article/details/79884618
https://blog.csdn.net/qq_36607894/article/details/100012334

猜你喜欢

转载自blog.csdn.net/qq_18431031/article/details/108095558