数学建模各类算法学习笔记(附matlab代码)

对于建模和编程的同学

1、假设很重要(题目中往往不提供数据或者提供很多数据,要恰当假设(即处理数据))

2、标准:假设合理、模型创造性、结果正确、表述清晰

3、十个较常用的(经典)算法:

    3.1、蒙特卡洛(计算机仿真)

    3.2、数据拟合、参数估计(最大似然、最大后验、最小二乘etc.)、插值等

    3.3、线性规划、整数规划、二乘规划等(最优化问题,即最值求解问题,通常用Lingo软件实现)

    3.4、图论算法(网络。选址等问题)

    3.5、动态规划、回溯搜索、分支算法、分支界定etc.

    3.6、对于很难写出目标函数的最优化问题(求最值问题):模拟退火法、神经网络、遗传算法

    3.7、数值分析算法(方程组求解、矩阵运算、函数积分etc.)

    3.8、网格算法和穷举法(搜索最有点、重点讨论模型本身儿请示算法时实用)

4、对于非线性规划问题(求解的目标函数是0/1或是分段函数etc.)

    4.1、目标函数是分段函数的,要把分段函数写成一个函数才能求解. 如何把分段函数写成一个函数?

        4.1.1、有几段就设置几个(组)自变量.(如有三段,则设置x1x2x3)

        4.1.2、将各段的表达式用对应自变量写出并相加(如三段则为f(x) = f1(x1) + f2(x2) + f3(x3) )

        4.1.3、对于2中的表达式设置约束(如0-5001x1为一段500-1000x2为一段,即 x2 > 500时 x1 为0,一种写法是 (x1-500) x2 = 0 )

一些算法的matlab源码参考

https://github.com/HuangCongQing/Algorithms_MathModels

https://github.com/liuzili97/MCM-ICM

往年论文

https://github.com/dick20/MCM-ICM

数据来源

https://max.book118.com/html/2019/0204/6232125043002005.shtm

https://blog.csdn.net/weixin_43102634/article/details/103696632

插值和拟合

插值是用现有数据来预测某个(些)指定点的数据(曲线要经过数据点)

拟合是用一个函数来描述所有现有的数据的规律(曲线不一定要经过数据点)

插值matlab实现

clear;
x = [0, 3, 5, 7, 9, 11, 12, 13, 14, 15];
y = [0, 1.2, 1.7, 2.0, 2.1, 2.0, 1.8, 1.2, 1.0, 1.6];
x1 = 0:0.1:15;
y1 = interp1(x, y, x1, 'spline');   
% one dimension interpolation,
% x1 is the interpolated data,
% spline is the interpolate method, which includes linear,nearst,pchip,spline.
%'linear''nearest''next''previous''pchip''cubic''v5cubic''makima''spline' 默认为 'linear'
plot(x1, y1)

spline为样条差值;linear:线性插值;nearest:最邻近插值;pchic:分段三次艾尔米特插值

interp1表一维线性插值

多项式拟合matlab实现

x = 1790:10:2010;
y = [3.9,5.3,7.2,9.6,12.9,17.1,23.2,31.4,38.6, 50.2,63.0,76.0,92.0,105.7,122.8,131.7,150.7,179.3,203.2,226.5,248.7,281.4,308.7];
plot(x,y,'*');
p = polyfit(x,y,3); % 3 means the number of fitting items,多项式的最高次项
polyval(p, 2020)    % forecast 2010
plot(x, y, '*', x, polyval(p, x)); 
polyval(p, 2016)

线性规划

matlab中可用linprog求解. 以下为官方文档内容

x = linprog(f,A,b) solves min f'*x such that A*x  b.

x = linprog(f,A,b,Aeq,beq) includes equality constraints Aeq*x = beq. Set A = [] and b = [] if no inequalities exist.

层次分析法(Analytic Hierarchy Process)AHP

用于评价模型,但是不建议在整个大的模型上使用(整道题目的模型),因为判断矩阵的主观性比较强

步骤如下:

1、填写判断矩阵

2、注意1中判断矩阵的一致性(希望对角线对称的互为倒数,主对角线上权全为1),可以不一致,但不能不一致太多。检验步骤如下

3、由判断矩阵得到权重(可根据算术平均、几何平均和特征值平均,特征值平均最为常用

matlab代码如下 其中A为通过一致性检验的判断矩阵

%% 方法1:算术平均法求权重
% 第一步:将判断矩阵按照列归一化(每一个元素除以其所在列的和)
Sum_A = sum(A)
[n,n] = size(A)  % 也可以写成n = size(A,1)
% 因为我们的判断矩阵A是一个方阵,所以这里的r和c相同,我们可以就用同一个字母n表示
SUM_A = repmat(Sum_A,n,1)   %repeat matrix的缩写
clc;A
SUM_A
Stand_A = A ./ SUM_A
% 这里我们直接将两个矩阵对应的元素相除即可

% 第二步:将归一化的各列相加(按行求和)
sum(Stand_A,2)

% 第三步:将相加后得到的向量中每个元素除以n即可得到权重向量
disp('算术平均法求权重的结果为:');
disp(sum(Stand_A,2) / n)
% 首先对标准化后的矩阵按照行求和,得到一个列向量
% 然后再将这个列向量的每个元素同时除以n即可(注意这里也可以用./哦)

%% 方法2:几何平均法求权重
% 第一步:将A的元素按照行相乘得到一个新的列向量
clc;A
Prduct_A = prod(A,2)
% prod函数和sum函数类似,一个用于乘,一个用于加  dim = 2 维度是行

% 第二步:将新的向量的每个分量开n次方
Prduct_n_A = Prduct_A .^ (1/n)
% 这里对每个元素进行乘方操作,因此要加.号哦。  ^符号表示乘方哦  这里是开n次方,所以我们等价求1/n次方

% 第三步:对该列向量进行归一化即可得到权重向量
% 将这个列向量中的每一个元素除以这一个向量的和即可
disp('几何平均法求权重的结果为:');
disp(Prduct_n_A ./ sum(Prduct_n_A))

%% 方法3:特征值法求权重
% 第一步:求出矩阵A的最大特征值以及其对应的特征向量
clc
[V,D] = eig(A)    %V是特征向量, D是由特征值构成的对角矩阵(除了对角线元素外,其余位置元素全为0)
Max_eig = max(max(D)) %也可以写成max(D(:))哦~
% 那么怎么找到最大特征值所在的位置了? 需要用到find函数,它可以用来返回向量或者矩阵中不为0的元素的位置索引。
% 那么问题来了,我们要得到最大特征值的位置,就需要将包含所有特征值的这个对角矩阵D中,不等于最大特征值的位置全变为0
% 这时候可以用到矩阵与常数的大小判断运算
D == Max_eig
[r,c] = find(D == Max_eig , 1)
% 找到D中第一个与最大特征值相等的元素的位置,记录它的行和列。

% 第二步:对求出的特征向量进行归一化即可得到我们的权重
V(:,c)
disp('特征值法求权重的结果为:');
disp( V(:,c) ./ sum(V(:,c)) )
% 我们先根据上面找到的最大特征值的列数c找到对应的特征向量,然后再进行标准化。

4、根据权重算出每个备选的得分(excel中按F4即可锁定单元格),得分最高者是好的

Topsis(优劣解距离法)

中心思想↓

matlab实现如下

[n,m] = size(X);
disp(['共有' num2str(n) '个评价对象, ' num2str(m) '个评价指标']) 
Judge = input(['这' num2str(m) '个指标是否需要经过正向化处理,需要请输入1 ,不需要输入0:  ']);

if Judge == 1
    Position = input('请输入需要正向化处理的指标所在的列,例如第2、3、6三列需要处理,那么你需要输入[2,3,6]: '); %[2,3,4]
    disp('请输入需要处理的这些列的指标类型(1:极小型, 2:中间型, 3:区间型) ')
    Type = input('例如:第2列是极小型,第3列是区间型,第6列是中间型,就输入[1,3,2]:  '); %[2,1,3]
    % 注意,Position和Type是两个同维度的行向量
    for i = 1 : size(Position,2)  %这里需要对这些列分别处理,因此我们需要知道一共要处理的次数,即循环的次数
        X(:,Position(i)) = Positivization(X(:,Position(i)),Type(i),Position(i));
    % Positivization是我们自己定义的函数,其作用是进行正向化,其一共接收三个参数
    % 第一个参数是要正向化处理的那一列向量 X(:,Position(i))   回顾上一讲的知识,X(:,n)表示取第n列的全部元素
    % 第二个参数是对应的这一列的指标类型(1:极小型, 2:中间型, 3:区间型)
    % 第三个参数是告诉函数我们正在处理的是原始矩阵中的哪一列
    % 该函数有一个返回值,它返回正向化之后的指标,我们可以将其直接赋值给我们原始要处理的那一列向量
    end
    disp('正向化后的矩阵 X =  ')
    disp(X)
end

%% 第三步:对正向化后的矩阵进行标准化
Z = X ./ repmat(sum(X.*X) .^ 0.5, n, 1);
disp('标准化矩阵 Z = ')
disp(Z)

%% 第四步:计算与最大值的距离和最小值的距离,并算出得分
D_P = sum([(Z - repmat(max(Z),n,1)) .^ 2 ],2) .^ 0.5;   % D+ 与最大值的距离向量
D_N = sum([(Z - repmat(min(Z),n,1)) .^ 2 ],2) .^ 0.5;   % D- 与最小值的距离向量
S = D_N ./ (D_P+D_N);    % 未归一化的得分
disp('最后的得分为:')
stand_S = S / sum(S)
[sorted_S,index] = sort(stand_S ,'descend')
发布了19 篇原创文章 · 获赞 2 · 访问量 5778

猜你喜欢

转载自blog.csdn.net/dongmie1999/article/details/104101962