代码语言
.
CSharp
.
JS
Java
Asp.Net
C
MSSQL
PHP
Css
PLSQL
Python
Shell
EBS
ASP
Perl
ObjC
VB.Net
VBS
MYSQL
GO
Delphi
AS
DB2
Domino
Rails
ActionScript
Scala
代码分类
文件
系统
字符串
数据库
网络相关
图形/GUI
多媒体
算法
游戏
Jquery
Extjs
Android
HTML5
菜单
网页交互
WinForm
控件
企业应用
安全与加密
脚本/批处理
开放平台
其它
【
Java
】
实现灰色马尔科夫算法
作者:
郑岸以
/ 发布于
2014/10/8
/
652
使用马尔科夫链对GM(1,1)模型进行修正,其中包含残差修正代码,但是结果中未使用残差修正,仅使用马尔科夫链进行修正,代码中区间的选取和最后预测值的修正使用者可以根据自己需要进行修改
import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.lang.Math.* ; import java.util.*; public class new_Marcof { static double a=0,b=0,a_error=0,b_error=0; static protected void Cal_param(int num,double arr[]){ double []arr1=new double[num];//经过一次累加数组 double sum=0; for(int i=0;i<num;i++) { sum+=arr[i]; arr1[i]=sum; //System.out.println("arr1["+i+"]="+arr1[i]+";");//同上 } double []arr2=new double [num-1];//arr1的紧邻均值数组 for(int i=0;i<num-1;i++) { arr2[i]=(double)(arr1[i]+arr1[i+1])/2; //System.out.println("arr2["+i+"]="+arr2[i]+";");//同上 } /* * 下面建立 向量B和YN求解待估参数向量, 即求参数a,b */ /* 下面建立向量B, B是5行2列的矩阵, 相当于一个二维数组。 */ double[][]B=new double[num-1][2]; for(int i=0;i<num-1;i++) { for(int j=0;j<2;j++) { if(j==1) B[i][j]=1; else B[i][j]=-arr2[i]; //System.out.println("B["+i+"]["+j+"]="+B[i][j]+";"); } } /* 下面建立向量YN*/ double [][]YN=new double[num-1][1]; for(int i=0;i<num-1;i++) { for(int j=0;j<1;j++) { YN[i][j]=arr[i+1]; //System.out.println("YN["+i+"]["+j+"]="+YN[i][j]+";"); } } /* B的转置矩阵BT,2行5列的矩阵 */ double[][]BT=new double[2][num-1]; for(int i=0;i<2;i++) { for(int j=0;j<num-1;j++) { BT[i][j]=B[j][i]; //System.out.println("BT["+i+"]["+j+"]="+BT[i][j]+";"); } } /* 将BT和B的乘积所得到的结果记为数组B2T,则B2T是一个2*2的矩阵*/ double [][]B2T=new double [2][2]; for(int i=0;i<2;i++){//rows of BT { for(int j=0;j<2;j++)//cloums of B { for(int k=0;k<num-1;k++)//cloums of BT=rows of B { B2T[i][j]=B2T[i][j]+BT[i][k]*B[k][j]; } //System.out.println("B2T["+i+"]["+j+"]="+B2T[i][j]+";"); } } } /*下面求B2T的逆矩阵,设为B_2T,怎么适用于一般的矩阵?*/ double [][]B_2T=new double [2][2]; B_2T[0][0]=(1/(B2T[0][0]*B2T[1][1]-B2T[0][1]*B2T[1][0]))*B2T[1][1]; B_2T[0][1]=(1/(B2T[0][0]*B2T[1][1]-B2T[0][1]*B2T[1][0]))*(-B2T[0][1]); B_2T[1][0]=(1/(B2T[0][0]*B2T[1][1]-B2T[0][1]*B2T[1][0]))*(-B2T[1][0]); B_2T[1][1]=(1/(B2T[0][0]*B2T[1][1]-B2T[0][1]*B2T[1][0]))*B2T[0][0]; for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { //System.out.println("B_2T["+i+"]["+j+"]="+B_2T[i][j]+";"); } } /*根据以上所求的各已知量下面求待估参数的未知量a和b,待估向量矩阵等于B_2T*BT*YN 下面我们分别求这些矩阵的乘积,首先求B_2T*BT,令B_2T*BT的乘积为A矩阵,则A就是一个2*5的矩阵*/ /* * * * * 下面先求A矩阵*/ double [][]A=new double[2][num-1]; for(int i=0;i<2;i++){//rows of B_2T { for(int j=0;j<num-1;j++)//cloums of BT { for(int k=0;k<2;k++)//cloums of B_2T=rows of BT { A[i][j]=A[i][j]+B_2T[i][k]*BT[k][j]; } //System.out.println("A["+i+"]["+j+"]="+A[i][j]+";"); } } } /* * * * 下面求A和YN矩阵的乘积,令乘积为C矩阵,则C就是一个2*1的矩阵*/ double [][]C=new double[2][1]; for(int i=0;i<2;i++){//rows of A { for(int j=0;j<1;j++)//cloums of YN { for(int k=0;k<num-1;k++)//cloums of A=rows of YN { C[i][j]=C[i][j]+A[i][k]*YN[k][j]; } //System.out.println("C["+i+"]["+j+"]="+C[i][j]+";"); } } } /*根据以上所得则a=C[0][0],b=C[1][0];*/ a=C[0][0]; b=C[1][0]; //System.out.println("a="+a+";"+"b="+b+";"); //System.out.println("b/a="+b/a); /* * * * */ } static protected void Cal_errorpm(int num,double arr[]){ double []arr1=new double[num];//经过一次累加数组 double sum=0; for(int i=0;i<num;i++) { sum+=arr[i]; arr1[i]=sum; //System.out.println("arr1["+i+"]="+arr1[i]+";");//同上 } double []arr2=new double [num-1];//arr1的紧邻均值数组 for(int i=0;i<num-1;i++) { arr2[i]=(double)(arr1[i]+arr1[i+1])/2; //System.out.println("arr2["+i+"]="+arr2[i]+";");//同上 } /* * 下面建立 向量B和YN求解待估参数向量, 即求参数a,b */ /* 下面建立向量B, B是5行2列的矩阵, 相当于一个二维数组。 */ double[][]B=new double[num-1][2]; for(int i=0;i<num-1;i++) { for(int j=0;j<2;j++) { if(j==1) B[i][j]=1; else B[i][j]=-arr2[i]; //System.out.println("B["+i+"]["+j+"]="+B[i][j]+";"); } } /* 下面建立向量YN*/ double [][]YN=new double[num-1][1]; for(int i=0;i<num-1;i++) { for(int j=0;j<1;j++) { YN[i][j]=arr[i+1]; //System.out.println("YN["+i+"]["+j+"]="+YN[i][j]+";"); } } /* B的转置矩阵BT,2行5列的矩阵 */ double[][]BT=new double[2][num-1]; for(int i=0;i<2;i++) { for(int j=0;j<num-1;j++) { BT[i][j]=B[j][i]; //System.out.println("BT["+i+"]["+j+"]="+BT[i][j]+";"); } } /* 将BT和B的乘积所得到的结果记为数组B2T,则B2T是一个2*2的矩阵*/ double [][]B2T=new double [2][2]; for(int i=0;i<2;i++){//rows of BT { for(int j=0;j<2;j++)//cloums of B { for(int k=0;k<num-1;k++)//cloums of BT=rows of B { B2T[i][j]=B2T[i][j]+BT[i][k]*B[k][j]; } //System.out.println("B2T["+i+"]["+j+"]="+B2T[i][j]+";"); } } } /*下面求B2T的逆矩阵,设为B_2T,怎么适用于一般的矩阵?*/ double [][]B_2T=new double [2][2]; B_2T[0][0]=(1/(B2T[0][0]*B2T[1][1]-B2T[0][1]*B2T[1][0]))*B2T[1][1]; B_2T[0][1]=(1/(B2T[0][0]*B2T[1][1]-B2T[0][1]*B2T[1][0]))*(-B2T[0][1]); B_2T[1][0]=(1/(B2T[0][0]*B2T[1][1]-B2T[0][1]*B2T[1][0]))*(-B2T[1][0]); B_2T[1][1]=(1/(B2T[0][0]*B2T[1][1]-B2T[0][1]*B2T[1][0]))*B2T[0][0]; for(int i=0;i<2;i++) { for(int j=0;j<2;j++) { //System.out.println("B_2T["+i+"]["+j+"]="+B_2T[i][j]+";"); } } /*根据以上所求的各已知量下面求待估参数的未知量a和b,待估向量矩阵等于B_2T*BT*YN 下面我们分别求这些矩阵的乘积,首先求B_2T*BT,令B_2T*BT的乘积为A矩阵,则A就是一个2*5的矩阵*/ /* * * * * 下面先求A矩阵*/ double [][]A=new double[2][num-1]; for(int i=0;i<2;i++){//rows of B_2T { for(int j=0;j<num-1;j++)//cloums of BT { for(int k=0;k<2;k++)//cloums of B_2T=rows of BT { A[i][j]=A[i][j]+B_2T[i][k]*BT[k][j]; } //System.out.println("A["+i+"]["+j+"]="+A[i][j]+";"); } } } /* * * * 下面求A和YN矩阵的乘积,令乘积为C矩阵,则C就是一个2*1的矩阵*/ double [][]C=new double[2][1]; for(int i=0;i<2;i++){//rows of A { for(int j=0;j<1;j++)//cloums of YN { for(int k=0;k<num-1;k++)//cloums of A=rows of YN { C[i][j]=C[i][j]+A[i][k]*YN[k][j]; } //System.out.println("C["+i+"]["+j+"]="+C[i][j]+";"); } } } /*根据以上所得则a=C[0][0],b=C[1][0];*/ a_error=C[0][0]; b_error=C[1][0]; //System.out.println("a="+a+";"+"b="+b+";"); //System.out.println("b/a="+b/a); /* * * * */ } static protected void Cal_Res(double arr[]){ // System.out.println("输入要预测的年数:"); // Scanner scan=new Scanner(System.in); // int year=scan.nextInt(); int year=7; // System.out.println("输入数据个数:"); // Scanner Scan=new Scanner(System.in); // int num=Scan.nextInt(); int num=12; // int num2=num+year; // arr=new double[num];//{2.67,3.13,3.25,3.36,3.56,3.72};//原始数组 // for(int i=0;i<num;i++){ // arr[i]=Scan.nextDouble(); // } double Y=0; double []new_arr=new double[num]; double []new_err=new double[num]; double []my_arr=new double[num+8]; double []my_arr2=new double[num+8]; Cal_param(num, arr); // System.out.println("a为 "+a+" b为 "+b); // Scanner x=new Scanner(System.in);//构造一个Scanner对象,其传入参数为System.in /*输入到特定文件中*/ FileOutputStream f1=null; FileOutputStream f1_error=null; OutputStreamWriter osw1=null; OutputStreamWriter osw1_err=null; PrintWriter pw1=null; PrintWriter pw1_error=null; try { f1 = new FileOutputStream("D:\\data1.txt"); f1_error=new FileOutputStream("D:\\data1_error.txt"); pw1=new PrintWriter(f1); pw1_error=new PrintWriter(f1_error); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } /*计算预测数据*/ System.out.println("原预测数据为:"); pw1.println("原预测数据为:"); for(int i=0;i < num+8; i++) { if (i == 0) Y = arr[0]; else Y = (arr[0] - b / a) * (Math.exp(-a * (i)) - Math.exp(-a * (i - 1)));// 2.67 // 3.13 // 3.25 // 3.36 // 3.56 // 3.72 my_arr[i] = Y; System.out.print(my_arr[i] + " "); pw1.print(my_arr[i]+" "); } pw1.println(); System.out.println(""); /*计算绝对误差*/ System.out.println("原预测(绝对)误差为:"); pw1_error.println("原预测(绝对)误差为:"); // System.out.println(num); for(int i=0;i<num;i++){ new_arr[i]=my_arr[i]-arr[i]; System.out.print(new_arr[i]+" "); pw1_error.print(new_arr[i]+" "); } pw1_error.println(); System.out.println(); System.out.println("平均相对误差为:"); pw1_error.println("平均相对误差为:"); double xiangdui=0; for(int i=0;i<num;i++){ xiangdui=xiangdui+Math.abs(new_arr[i]/arr[i]); } xiangdui=xiangdui/num; System.out.print(xiangdui+" "); pw1_error.println(xiangdui+" "); System.out.println(); System.out.println("相对标准差为:"); pw1_error.println("相对标准差为:"); double biaozhun=0; for(int i=0;i<num;i++){ biaozhun=biaozhun+(new_arr[i]/arr[i])*(new_arr[i]/arr[i]); } biaozhun=Math.sqrt(biaozhun/num); System.out.print(biaozhun+" "); pw1_error.println(biaozhun+" "); Cal_errorpm(num, new_arr); // System.out.println("erroa为 "+a_error+" errorb为 "+b_error); double new_Y=0,param=0; xiangdui=0; biaozhun=0; /*计算修正后误差并存储修正后预测值*/ System.out.println(); System.out.println("修正后预测值为 "); pw1.println("修正后预测值为"); System.out.println(a_error+" "+b_error); for(int k2=0;k2<num+8;k2++){ if(k2+1>=2) param=1; else param=0; my_arr2[k2]=(arr[0]-b/a)*(Math.exp(-a*(k2))-Math.exp(-a*(k2-1)))+param*(-a_error)*(new_arr[0]-b_error/a_error)*(Math.exp(-a_error*(k2-1))-Math.exp(-a_error*(k2-2))); if(k2==0){ my_arr2[k2]=arr[k2]; } System.out.print(my_arr2[k2]+" "); pw1.print(my_arr2[k2]+" "); } System.out.println(""); System.out.println("修正后误差为 "); pw1_error.println("修正后误差为:"); for(int k2=0;k2<num;k2++){ new_err[k2]=my_arr2[k2]-arr[k2]; System.out.print(new_err[k2]+" "); pw1_error.print(new_err[k2]+" "); } pw1_error.println(); System.out.println(); System.out.println("修正后平均相对误差为: "); pw1_error.println("修正后平均相对误差为:"); for(int k2=0;k2<num;k2++){ xiangdui=xiangdui+Math.abs(new_err[k2]/arr[k2]); } xiangdui=xiangdui/num; System.out.print(xiangdui+" "); pw1_error.println(xiangdui+" "); System.out.println(); System.out.println("修正后相对标准差为: "); pw1_error.println("修正后相对标准差为:"); for(int k2=0;k2<num;k2++){ biaozhun=biaozhun+(new_err[k2]/arr[k2])*(new_arr[k2]/arr[k2]); } biaozhun=biaozhun/num; System.out.print(biaozhun+" "); pw1_error.println(biaozhun+" "); // System.out.println(""); /*引入马尔科夫*/ int num2=num-year; /*计算相对误差*/ double relat_error[]=new double[num2]; for(int k2=0;k2<num2;k2++){ relat_error[k2]=(my_arr[k2]-arr[k2])/arr[k2]; } /*为相对误差划分四个区间*/ double temp_max=relat_error[0]; double temp_min=relat_error[0]; for(int k=1;k<num2;k++){ if(relat_error[k]>temp_max) temp_max=relat_error[k]; if(relat_error[k]<temp_min) temp_min=relat_error[k]; } double temp=(temp_max-temp_min)/4; double qujian[]=new double[5]; qujian[4]=temp_max-temp; qujian[3]=qujian[4]-temp; qujian[2]=qujian[3]-temp; qujian[1]=temp_min; qujian[0]=0; /*每个区间的均值*/ double Flag_mean[]=new double[5]; for(int k=1;k<5;k++){ if(k==4) { Flag_mean[k]=(qujian[k]+temp_max)*0.5;} else {Flag_mean[k]=(qujian[k]+qujian[k+1])*0.5;} } /*为预测误差计算所处区间*/ int Flag_error[]=new int[num2]; double Flag_sum[]=new double[5]; for(int k=0;k<5;k++){ Flag_sum[k]=0; } for(int k=0;k<num2;k++){ if((new_err[k]>=qujian[1])&&(new_err[k]<qujian[2])) { Flag_error[k]=1; Flag_sum[1]=Flag_sum[1]+1; } if((new_err[k]>=qujian[2])&&(new_err[k]<qujian[3])) { Flag_error[k]=2; Flag_sum[2]=Flag_sum[2]+1; } if((new_err[k]>=qujian[3])&&(new_err[k]<qujian[4])) { Flag_error[k]=3; Flag_sum[3]=Flag_sum[3]+1; } if((new_err[k]>=qujian[4])&&(new_err[k]<=temp_max)) { Flag_error[k]=4; Flag_sum[4]=Flag_sum[4]+1; } } /*P1矩阵建立*/ double P1[][]=new double[5][5]; for(int k=1;k<5;k++){ for(int k2=1;k2<5;k2++){ for(int k3=0;k3<num2-1;k3++) { if((Flag_error[k3]==k)&&(Flag_error[k3+1]==k2)) P1[k][k2]=P1[k][k2]+1; } } } for(int k=1;k<5;k++){ for(int k2=1;k2<5;k2++){ P1[k][k2]=P1[k][k2]/Flag_sum[k]; } } /*P2*/ double P2[][]=new double[5][5]; for(int k=1;k<5;k++){ for(int k2=1;k2<5;k2++){ for(int k3=0;k3<num2-2;k3++) { if((Flag_error[k3]==k)&&(Flag_error[k3+2]==k2)) P2[k][k2]=P2[k][k2]+1; } } } for(int k=1;k<5;k++){ for(int k2=1;k2<5;k2++){ P2[k][k2]=P2[k][k2]/Flag_sum[k]; } } /*P3*/ double P3[][]=new double[5][5]; for(int k=1;k<5;k++){ for(int k2=1;k2<5;k2++){ for(int k3=0;k3<num2-3;k3++) { if((Flag_error[k3]==k)&&(Flag_error[k3+3]==k2)) P3[k][k2]=P3[k][k2]+1; } } } for(int k=1;k<5;k++){ for(int k2=1;k2<5;k2++){ P3[k][k2]=P3[k][k2]/Flag_sum[k]; } } /*P4*/ double P4[][]=new double[5][5]; for(int k=1;k<5;k++){ for(int k2=1;k2<5;k2++){ for(int k3=0;k3<num2-4;k3++) { if((Flag_error[k3]==k)&&(Flag_error[k3+4]==k2)) P4[k][k2]=P4[k][k2]+1; } } } for(int k=1;k<5;k++){ for(int k2=1;k2<5;k2++){ P4[k][k2]=P4[k][k2]/Flag_sum[k]; } } /*计算每年的误差状态预测*/ int statu[]=new int[num+8]; double temp_new[]=new double[5]; for(int k=0;k<num2;k++){ statu[k]=Flag_error[k]; } for(int k=num2;k<num+8;k++){ int t=statu[k-1]; for(int i=1;i<5;i++){ temp_new[i]=temp_new[i]+P1[t][i]; } t=statu[k-2]; for(int i=1;i<5;i++){ temp_new[i]=temp_new[i]+P2[t][i]; } t=statu[k-3]; for(int i=1;i<5;i++){ temp_new[i]=temp_new[i]+P3[t][i]; } t=statu[k-4]; for(int i=1;i<5;i++){ temp_new[i]=temp_new[i]+P4[t][i]; } /*寻找temp_new中的最大值*/ double tt=temp_new[1]; int index=1; for(int i=2;i<5;i++){ if(tt<temp_new[i]){ tt=temp_new[i]; index=i; } } statu[k]=index; } /*提取原预测值并计算新的预测值*/ double newmy_arr2[]=new double[num+8]; for(int i=num2;i<num+8;i++){ double num_randm; num_randm=Math.random()*temp+qujian[statu[i]]; // newmy_arr2[i]=my_arr[i]/(1-num_randm); // if(new_err[i]>0) // newmy_arr2[i]=my_arr[i]/(1+Flag_mean[statu[i]]); // else newmy_arr2[i]=my_arr2[i]/(1-Flag_mean[statu[i]]); } System.out.println(); System.out.println("利用马尔科夫修正得到的预期值为:"); pw1.println(); pw1.println("利用马尔科夫修正得到的预期值为:"); for(int i=num2;i<num+8;i++){ System.out.print(newmy_arr2[i]+" "); pw1.print(newmy_arr2[i]+" "); }//计算预期值 System.out.println(); System.out.println("误差为"); pw1_error.println(); pw1_error.println("误差为:"); double newmy_erro[]=new double[num]; for(int i=num2;i<num;i++){ newmy_erro[i]=newmy_arr2[i]-arr[i]; System.out.print( newmy_erro[i]+" "); pw1_error.append( newmy_erro[i]+" "); } System.out.println(); System.out.println("平均相对误差为:"); pw1_error.println(); pw1_error.println("平均相对误差为:"); xiangdui=0; biaozhun=0; for(int i=num2;i<num;i++){ xiangdui=xiangdui+Math.abs(newmy_erro[i]/arr[i]); } xiangdui=xiangdui/year; System.out.print(xiangdui+" "); pw1_error.println(xiangdui+" "); System.out.println(); System.out.println("平均相对标准差为:"); pw1_error.println("平均相对标准差为:"); for(int i=0;i<num;i++){ biaozhun=biaozhun+(newmy_erro[i]/arr[i])*(newmy_erro[i]/arr[i]); } biaozhun=Math.sqrt(biaozhun/year); System.out.print(biaozhun+" "); pw1_error.println(biaozhun+" "); pw1_error.println(); pw1.println(); pw1.close(); pw1_error.close(); System.out.println(); } public static void main(String[] args) { // TODO Auto-generated method stub /*输入数据*/ System.out.println("输入数据"); Scanner scan=new Scanner(System.in); double AArray[][]=new double[9][13]; int k=1; for(int i=1;(i<=12)&&(k<=8);i++){ AArray[k][i]=scan.nextDouble(); if(i%12==0) { k=k+1;i=0;} } // for(int i=1;i<9;i++){ // for(int j=1;j<14;j++){ // System.out.print(AArray[i][j]+" "); // // } // System.out.println(); // } // double arr[]=new double[12]; // for(int i=1;(i<=13)&&(k<=8);i++){ // arr[i-1]=AArray[k][i]; // if (i % 13 == 0) { // k = k + 1; // i = 0; // System.out.println("第一组数据:"); // Cal_Res(arr); // } // // } for(int i=1;i<=8;i++){ for(int j=1,k1=0;j<=12;j++,k1++){ arr[k1]=AArray[i][j]; } System.out.println(); System.out.println("第"+i+"组原数据为:"); for(int k2=0;k2<12;k2++) System.out.print(arr[k2]+" "); System.out.println(); System.out.println("第"+i+"组要求数据为:"); Cal_Res(arr); } } }
试试其它关键字
马尔科夫
马尔科夫算法
同语言下
.
List 切割成几份 工具类
.
一行一行读取txt的内容
.
Java PDF转换成图片并输出给前台展示
.
java 多线程框架
.
double类型如果小数点后为零则显示整数否则保留两位小
.
将图片转换为Base64字符串公共类抽取
.
sqlParser 处理SQL(增删改查) 替换schema 用于多租户
.
JAVA 月份中的第几周处理 1-7属于第一周 依次类推 29-
.
java计算两个经纬度之间的距离
.
输入时间参数计算年龄
可能有用的
.
C#实现的html内容截取
.
List 切割成几份 工具类
.
SQL查询 多列合并成一行用逗号隔开
.
一行一行读取txt的内容
.
C#动态修改文件夹名称(FSO实现,不移动文件)
.
c# 移动文件或文件夹
.
c#图片添加水印
.
Java PDF转换成图片并输出给前台展示
.
网站后台修改图片尺寸代码
.
处理大图片在缩略图时的展示
郑岸以
贡献的其它代码
(
8
)
.
数据库表生成Model
.
实现灰色马尔科夫算法
.
实现带残差修正的灰色算法
.
矩阵伴随矩阵的java实现
.
实现拉格朗日插值法
.
实现牛顿插值法
.
实现高斯赛德尔算法解线性方程组
.
实现SOR算法解线性方程组
Copyright © 2004 - 2024 dezai.cn. All Rights Reserved
站长博客
粤ICP备13059550号-3