对于建模和编程的同学
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求解. 以下为官方文档内容
solves min x
= linprog(f
,A
,b
)f'*x
such that A*x
≤ b
.
includes equality constraints x
= linprog(f
,A
,b
,Aeq
,beq
)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')