%% 通过autocorr和xcorr自相关求周期
clear ;clc
%加载TOP13家供货商240周的供货量数组文件
load FFt.mat;
%使用autocorr函数
Randi = randi([2 14],1,1)
A = FFt([1:96],Randi) ;
len = length(A) ;
[ACF,lags,bounds] = autocorr(A,len-1) ;
subplot(2,1,1) ;
plot(lags(1:end),ACF(1:end)) ;
title('autocorr求S-top13的自相关') ;
%使用xcorr函数
B = A - mean(A) ;%减掉均值
[c,lags] = xcorr(B) ;
d = c ./ c(len) ;%归一化
subplot(2,1,2) ;
plot(lags(len:end),d(len:end)) ;%取中点n为起始的后面n个序列
title('xcorr求S-top13的自相关') ;
from statsmodels.tsa.stattools import acf
# Expected time period
for lag in fft_periods:
# lag = fft_periods[np.abs(fft_periods - time_lag).argmin()]
acf_score = acf(data["value"].values, nlags=lag)[-1]
print(f"lag: {lag} fft acf: {acf_score}")
expected_lags = np.array([timedelta(hours=12)/timedelta(minutes=5), timedelta(days=1)/timedelta(minutes=5), timedelta(days=7)/timedelta(minutes=5)]).astype(int)
for lag in expected_lags:
acf_score = acf(data["value"].values, nlags=lag, fft=False)[-1]
print(f"lag: {lag} expected acf: {acf_score}")
%% 判断TOP13家供货商的供货量(S)是否为周期波动。如果周期波动,求出周期。
clear;clc;
%加载TOP13家供货商240周的供货量数组文件
load FFt.mat;
%将首列的240个周次作为横坐标(Weeks)
weeks = FFt([1:240],1);
%随机生成2到14中的一个整数用以随机择取13个供货商中的一家
Randi = randi([2 14],1,1)
SNumbers = FFt([1:240],Randi);
%绘制该供货商未经fft(傅里叶函数)变换的原始图像并观察是否存在周期此性
plot(weeks,SNumbers)
xlabel('Weeks')
ylabel('SNumbers')
title('FFt Data')
%大致判断该原始图像是否具有周期性
judge = input("请输入观察该供货商的供货量(S)数据是否具有周期性,'是'请输入'1','不是'请输入'0':")
if judge == 1
%如果具有周期性,则使用FFt(傅里叶变换)函数将随机择取的供货商所在列的供货量(S)进行变换
y = fft(SNumbers);
y(1) = [];
plot(y,'ro')
%绘制经过fft(傅里叶函数)变换后的图像
xlabel('real_SNumbers(y)')
ylabel('imag_SNumbers(y)')
title('傅里叶转换')
%变换数据前半部分的幂
n = length(y);
power = abs(y(1:floor(n/2))).^2;
%最大频率
maxfreq = 1/2;
%等距频率网格
freq = (1:n/2)/(n/2)*maxfreq;
plot(freq,power)
xlabel('Weeks/Cycle')
ylabel('Power')
period = 1./freq;
plot(period,power);
%放大最大功率(周次)
xlim([0 240]);
xlabel('Weeks/Cycle')
ylabel('SNumbers')
end
%% 定义Inter2Max函数以备主函数调用
function [posit_x] = Inter2Max(x,a,b)
r_x = size(x,1); % row of x
M = max([a-min(x),max(x)-b]);
posit_x = zeros(r_x,1);
% 初始化posit_x全为0
for i = 1: r_x
if x(i) < a
posit_x(i) = 1-(a-x(i))/M;
elseif x(i) > b
posit_x(i) = 1-(x(i)-b)/M;
else
posit_x(i) = 1;
end
end
end
%% 中间型数据转极大型数据
%定义Mid2Max函数以备主函数调用
function [posit_x] = Mid2Max(x,best)
M = max(abs(x-best));
posit_x = 1 - abs(x-best) / M;
end```
%% 中间型数据转极大型数据
%定义Mid2Max函数以备主函数调用
function [posit_x] = Mid2Max(x,best)
M = max(abs(x-best));
posit_x = 1 - abs(x-best) / M;
end
%% 及小型数据转极大型数据
%定义Min2Max函数以备主函数调用
function [posit_x] = Min2Max(x)
posit_x = max(x) - x;
% posit_x = 1 / x; 如果x全部都大于0,需要这样正向化
end
%% 调用Mid2Max.m和Min2Max.m和Inter2Max.m函数定义正向化函数
function [posit_x] = Positivization(x,type,i)
% 输入变量有三个:
% x:需要正向化处理的指标对应的原始列向量
% type: 指标的类型(1:极小型, 2:中间型, 3:区间型)
% i: 正在处理的是原始矩阵中的哪一列
% 输出变量posit_x表示:正向化后的列向量
if type == 1 %极小型
disp(['第' num2str(i) '列是极小型,正在正向化'] )
posit_x = Min2Max(x); %调用Min2Max函数来正向化
disp(['第' num2str(i) '列极小型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
elseif type == 2 %中间型
disp(['第' num2str(i) '列是中间型'] )
best = input('请输入最佳的那一个值: ');
posit_x = Mid2Max(x,best);
disp(['第' num2str(i) '列中间型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
elseif type == 3 %区间型
disp(['第' num2str(i) '列是区间型'] )
a = input('请输入区间的下界: ');
b = input('请输入区间的上界: ');
posit_x = Inter2Max(x,a,b);
disp(['第' num2str(i) '列区间型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
else
disp('没有这种类型的指标,请检查Type向量中是否有除了1、2、3之外的其他值')
end
end
%% Step1:清空界面,并加载矩阵X
clear;clc %清空界面
load X.mat %加载数据
%% Step2:判断是否需要正向化处理
[n,m] = size(X);%计算矩阵的大小
disp(['共有' num2str(n) '个评价对象, ' num2str(m) '个评价指标']) %输出共有多少个评价对象
JUDGING = input(['这' num2str(m) '个指标是否需要经过正向化处理,需要请输入1 ,不需要输入0: ']);%定义是否需要正向化处理
if JUDGING == 1
Position = input('请输入需要正向化处理的指标所在的列 ');
disp('请输入需要处理的这些列的指标类型(1-极小型, 2-中间型, 3-区间型) ')
TYPE = input('例如:第1列是极小型,第2列是中间型,第3列是区间型,就输入[1,2,3]: ');%同样为了保证代码逻辑的完整性,此处添加正向化的处理步骤
for i = 1 : size(Position,2) %这里需要对这些列分别处理,因此需要知道一共要处理的次数,即循环的次数
X(:,Position(i)) = Positivization(X(:,Position(i)),TYPE(i),Position(i));
end
disp('正向化后的矩阵 X = ')%输出正向化的矩阵
disp(X)
end%以end作为结尾
%% Step3:对正向化后的矩阵进行标准化
Z = X ./ repmat(sum(X.*X) .^ 0.5, n, 1);%利用repmat函数
disp('标准化矩阵 Z = ')%输出标准化矩阵Z
disp(Z)
%% Step4:判断是否需要增加权重
disp("请输入是否需要增加权重向量,需要输入1,不需要输入0")%以此作为增加权重步骤的开始
JUDGING = input('请输入是否需要增加权重: ');%判断是否需要增加权重
if JUDGING == 1%用if 和 for 循环来判断是否需要增加权重
JUDGING = input('使用熵权法确定权重请输入1,否则输入0: ');%确定是否需要用熵权法增加权重
if JUDGING == 1%==是判断符号
if sum(sum(Z<0)) >0 % 如果之前标准化后的Z矩阵中存在负数,则重新对X进行标准化
disp('原来标准化得到的Z矩阵中存在负数,所以需要对X重新标准化')
for i = 1:n%使用for循环
for j = 1:m
Z(i,j) = [X(i,j) - min(X(:,j))] / [max(X(:,j)) - min(X(:,j))];
end
end
disp('X重新进行标准化得到的标准化矩阵Z为: ')
disp(Z)
end
weight = Entropy_Method(Z);
disp('熵权法确定的权重为:')%输出最终权重数据
disp(weight)
else
disp(['如果你有3个指标,你就需要输入3个权重,例如它们分别为0.25,0.25,0.5, 则你需要输入[0.25,0.25,0.5]']);
weight = input(['你需要输入' num2str(m) '个权数。' '请以行向量的形式输入这' num2str(m) '个权重: ']);
OK = 0; % 用来判断用户的输入格式是否正确
while OK == 0
if abs(sum(weight) -1)<0.000001 && size(weight,1) == 1 && size(weight,2) == m % 注意,Matlab中浮点数的比较要小心
OK =1;
else
weight = input('你输入的有误,请重新输入权重行向量: ');
end
end
end
else
weight = ones(1,m) ./ m ; %如果不需要加权重就默认权重都相同,即都为1/m
end
%% Step5:计算与最大值的距离和最小值的距离,并算出得分
D_P = sum([(Z - repmat(max(Z),n,1)) .^ 2 ] .* repmat(weight,n,1) ,2) .^ 0.5; %此为与最大值即最优解的距离
D_N = sum([(Z - repmat(min(Z),n,1)) .^ 2 ] .* repmat(weight,n,1) ,2) .^ 0.5; %此为与最小值即最劣解的距离
S = D_N ./ (D_P+D_N); % 这里得到未归一化的得分
disp('最后的得分为:')
stand_S = S / sum(S)%将数据进行归一化处理,以便于比较。
[sorted_S,index] = sort(stand_S ,'descend')%对各个供应商进行排序,得到最终数据