对时间序列数据,一般进行一阶或者二阶差分处理,会丢失部分数据信息,但目的是为了增加其稳定性,便于模型建立与分析。
但奇怪的是,在进行了较高阶数的差分运算后居然感觉恢复了很多数据信息(并不像存粹的白噪啊),不胜求解,望指教!
170阶,想想都恐怖,不知道差到哪去了,但是图形上看感觉拟合到原数据去了,随着阶数进一步升高,又开始发散
原理
消去法是增广矩阵化为单位上三角矩阵求解,除此之外,还有另外一种解题思路
那就是:将矩阵A分解成两个三角形矩阵L和U的乘积,其中L为下三角矩阵,U为上三角矩阵,则 :
可以证明,当系数矩阵的各阶顺序主子式不为0时,这样的分为有且仅有一组
在这种思路下,就有三种分解方法,
Doolitte分解法:L是单位下三角矩阵,U是上三角矩阵
Crout分解法:L是下三角矩阵,U是单位上三角矩阵
Cholesky分解法:L和U互为转置矩阵
要进行这样的分解,系数矩阵A就要满足是对称正定矩阵
对称:矩阵中的元素关于对角线对称
正定:矩阵所有的特征值都大于0
三角分解法不需要特别记住什么公式,只需要知道矩阵乘法的运算方式
进行一次逆运算,先计算某一个矩阵的行,在计算另外一个矩阵的列,以此往复。
杜立特尔分解法
//杜立特尔分解法,分解为单位下三角和上三角矩阵
void Doolittle(double *p,int row)
{
int i,j,k,col=row+1;//增广矩阵的列
double sum;//保存求和结果
for(k=0;k<row;k++)//K表示循环次数,也指示矩阵的行和列,即沿对角线移动
{//先计算U矩阵的K行
for(j=k;j<row;j++)//控制U矩阵列的移动
{//从对角线后面开始求,所以下标从k开始
sum=0;//L矩阵固定K行
for(i=0;i<k;i++)//乘到对角线前一个数字
sum+= ( *(p+k*col+i) ) * ( *(p+i*col+j) );
*(p+k*col+j) = ( *(p+k*col+j) ) - sum;
}//End for-j
//计算L矩阵的列
for(i=k+1;i<row;i++)//控制L矩阵行的移动
{//只需要计算对角线下面的元素,所以下标从k+1开始
sum=0;
for(j=0;j<k;j++)//U矩阵固定K列
sum+= ( *(p+i*col+j) ) * ( *(p+j*col+k) );
*(p+i*col+k)=( ( *(p+i*col+k) ) -sum)/( *(p+k*col+k) );
}//End for-i
}//End for-k
for(i=0;i<row;i++) //通过Ly=b求Ux的结果y
{//结果保存在增广矩阵最后一列
sum=0;
for(j=0;j<i;j++)
sum+=( *(p+j*col+row) )*( *(p+i*col+j) );
*(p+i*col+row)-=sum;
}//End for-i
for(i=row-1;i>=0;i--)//通过Ux=y求解x
{
for(j=row-1;j>i;j--)
*(p+i*col+row)-=( *(p+j*col+row) ) * ( *(p+i*col+j) );
( *(p+i*col+row) )/=( *(p+i*col+i) );
}//End for-i
for(i=0;i<row;i++)
{
for(j=0;j<col;j++)
printf("%lf ",*(p+i*col+j));
printf("\n");
}
}
克洛特分解法
//克洛特尔分解法,分解为单位上三角和下三角矩阵
void Crout(double *p,int row)
{
int i,j,k;
int col=row+1;
double sum;
for(k=0;k<row;k++)//先求L矩阵的列
{
for(i=k;i<row;i++)//i控制矩阵L行的移动
{
sum=0;
for(j=0;j<k;j++)//j控制L矩阵列的移动,需要累乘至对角线前一个
sum+= ( *(p+i*col+j) )*( *(p+j*col+k) );
*(p+i*col+k)= ( *(p+i*col+k)-sum );//求L的k列i行
}//End for-i
for(j=k+1;j<row;j++)//求U矩阵的第k行
{//j控制矩阵U列的移动
sum=0;
for(i=0;i<k;i++)//i控制U矩阵行的移动
sum+=( *(p+k*col+i) )*( *(p+i*col+j) );
*(p+k*col+j)=( *(p+k*col+j)-sum )/( *(p+k*col+k) );
}//求U的k行j列
}//End for-k
for(i=0;i<row;i++)
{//通过Ly=b求解结果y
sum=0;
for(j=0;j<i;j++)
sum+=( *(p+i*row+j) )*( *(p+j*col+row) );
*(p+i*col+row)=( (*(p+i*col+row))-sum )/( *(p+i*row+i) );
}//End for-i
for(i=row-1;i>=0;i--)//通过Ux=y求解x
for(j=row-1;j>i;j--)
*(p+i*col+row)-=( *(p+j*col+row) )*( *(p+i*col+j) );
for(i=0;i<row;i++)
{
for(j=0;j<col;j++)
printf("%lf ",*(p+i*col+j));
printf("\n");
}
}
乔里斯基分解法
//乔里斯基分解,分解为两个互为转置矩阵的矩阵
void Cholesky(double *p,int row)
{
int i,j,k;
int col=row+1;
double sum;
for(k=0;k<row;k++)
{
for(j=k;j<row;j++)//先求U的行
{
sum=0;
for(i=0;i<k;i++)
sum+=( *(p+k*col+i)*( *(p+i*col+j) ) );
if(j==k)//对角线部分需要开根号
*(p+k*col+j)=sqrt( ( *(p+k*col+j) )-sum );
else
*(p+k*col+j)=(( *(p+k*col+j))-sum)/( *(p+k*col+k) );
*(p+j*col+k)=*(p+k*col+j);//L和U互为转置,关于对角线对称
}//End for-j
}//End for-k
for(i=0;i<row;i++)
{//通过Ly=b求解结果y
for(j=0;j<i;j++)
*(p+i*col+row)-=( *(p+i*col+j) )*( *(p+j*col+row) );
*(p+i*col+row)/=( *(p+i*col+i) );
}
for(i=row-1;i>=0;i--)
{//通过Ux=y求解结果x
for(j=row-1;j>i;j--)
*(p+i*col+row)-=( *(p+i*col+j) )*( *(p+j*col+row) );
*(p+i*col+row)/=( *(p+i*col+i) );
}
for(i=0;i<row;i++)
{
for(j=0;j<col;j++)
printf("%lf ",*(p+i*col+j));
printf("\n");
}
}