#include <stdio.h>
#include <math.h>
#include <iostream>
#define PrecisionLevel 1.0e-12 //迭代精度
double Z[6][6];//將Z聲明爲全局變量,便於後面操作
double** CreateMatrix(int m,int n);
void DestroyMatrix(double**A,int m,int n);
bool GaussElimination(double **A,int n,double* b);
double InfiniteNorm(double*b,int n);
void CoefficientMatrix(double* x,int m,double* y,int n,double** z,int k1,int k2,double** C);
double P_Value(double **C,int k,double x,double y);
double** SurfaceFitting(int& k);
//-----------------------------------------------
//生成一個m*n矩陣
double** CreateMatrix(int m,int n)
{
double** A;
int i;
A=new double* [m];
for(i=0;i<m;i++)
A[i]=new double[n];
return A;
}
//-----------------------------------------------
//釋放m*n矩陣
void DestroyMatrix(double** A,int m,int n)
{
int i;
for(i=0; i<m; i++)
delete[]A[i];
delete[]A;
}
//-----------------------------------------------
//列主元Guass削去法求解線性方程組,A*x=b
bool GaussElimination(double** A,int n,double* b)
{
double m,sum,max,temp;
int i,j,k,l;
for(i=0; i<n-1; i++)
{
max=A[i][i];
l=i;
for(j=i; j<n; j++) //尋找列主元
if(fabs(A[i][j])>max)
{
max=fabs(A[i][j]);
l=j;
}
if(l!=i) //判斷並換行
{
for(j=i; j<n; j++)
{
temp=A[i][j];
A[i][j]=A[l][j];
A[l][j]=temp;
}
temp=b[i];
b[i]=b[l];
b[l]=temp;
}
if(A[i][i]==0)
{
printf("第%d個主元素爲0!\n",i);
return false;
}
for(j=i+1; j<n; j++) //消元
{
m=A[j][i]/A[i][i];
for(k=i+1;k<n;k++)
A[j][k]=A[j][k]-A[i][k]*m;
b[j]=b[j]-b[i]*m;
}
}
if(A[n-1][n-1]==0)
{
printf("第%d個主元素爲0!\n",n);
return false;
}
//迴帶求解,用b來存儲解x
b[n-1]=b[n-1]/A[n-1][n-1];
for(i=n-2; i>=0; i--)
{
sum=0;
for(j=i+1; j<n; j++)
sum+=A[i][j]*b[j];
b[i]=(b[i]-sum)/A[i][i];
}
return true;
}
//-----------------------------------------------
//計算向量的無窮範數
double InfiniteNorm(double* b,int n)
{
double max;
int i;
max=b[0];
for(i=1; i<n; i++)
{
if(fabs(b[i])>max)
max=fabs(b[i]);
}
return max;
}
//-----------------------------------------------
//分片二次代數插值,z=z(u,t)
double PiecewiseInterpolation(double t,double u)
{
double pnm=0.0;
int i,j;
bool flag=false; //判斷t和u是否在插值區間內的標誌
for(i=0; i<6; i++)
{
if((u>0.4*i-0.4/2)&&(u<=0.4*i+0.4/2))
for(j=0;j<6;j++)
{
if((t>0.2*j-0.2/2)&&(t<=0.2*j+0.2/2))
{
flag=true;
break;
}
}
if(flag)
break;
}
if(!flag)
{
printf("u=%e,t=%e is not in the expected interval\n",u,t);
return 0;
}
if(i==0) //邊界的處理
{
i=1;
if(j==0)
j=1;
else if(j==5)
j=4;
}
else if(i==5)
{
i=4;
if(j==0)
j=1;
else if(j==5)
j=4;
}
pnm=Z[j-1][i-1]*((u-0.4*i)*(u-0.4*(i+1))*(t-0.2*j)*(t-0.2*(j+1)))/((-0.4)*(-0.8)*(-0.2)*(-0.4))
+Z[j][i-1]*((u-0.4*i)*(u-0.4*(i+1))*(t-0.2*(j-1))*(t-0.2*(j+1)))/((-0.4)*(-0.8)*(0.2)*(-0.2))
+Z[j+1][i-1]*((u-0.4*i)*(u-0.4*(i+1))*(t-0.2*(j-1))*(t-0.2*j))/((-0.4)*(-0.8)*(0.2)*(0.4))
+Z[j-1][i]*((u-0.4*(i-1))*(u-0.4*(i+1))*(t-0.2*j)*(t-0.2*(j+1)))/((-0.4)*(0.4)*(-0.2)*(-0.4))
+Z[j][i]*((u-0.4*(i-1))*(u-0.4*(i+1))*(t-0.2*(j-1))*(t-0.2*(j+1)))/((-0.4)*(0.4)*(0.2)*(-0.2))
+Z[j+1][i]*((u-0.4*(i-1))*(u-0.4*(i+1))*(t-0.2*(j-1))*(t-0.2*j))/((-0.4)*(0.4)*(0.2)*(0.4))
+Z[j-1][i+1]*((u-0.4*(i-1))*(u-0.4*i)*(t-0.2*j)*(t-0.2*(j+1)))/((0.8)*(0.4)*(-0.2)*(-0.4))
+Z[j][i+1]*((u-0.4*(i-1))*(u-0.4*i)*(t-0.2*(j-1))*(t-0.2*(j+1)))/((0.8)*(0.4)*(0.2)*(-0.2))
+Z[j+1][i+1]*((u-0.4*(i-1))*(u-0.4*i)*(t-0.2*(j-1))*(t-0.2*j))/((0.8)*(0.4)*(0.2)*(0.4));
return pnm;
}
//-----------------------------------------------
//求解非線性方程組,給定x和y,求解出t,u,v,w
void NonlinearEquationSolver(double x,double y,double* X)
{
double x2[4]; //x2=[t u v w]'
double del_x2[4];
double** G=CreateMatrix(4,4); //調用CreateMatrix函數,構建矩陣
int i,j,k;
for(i=0; i<4; i++)
{
del_x2[i]=0;
x2[i]=1.0; //給定初值
}
k=0; //解非線性方程組的迭代次數
do
{
k++;
for(i=0; i<4; i++)
x2[i] = x2[i]+del_x2[i];
//計算Jacobi矩陣F',即G
for(i=0; i<4; i++)
for(j=0; j<4; j++)
G[i][j]=1.0;
G[0][0]=-0.5*sin(x2[0]);
G[1][1]=0.5*cos(x2[1]);
G[2][0]=0.5;
G[2][2]=-sin(x2[2]);
G[3][1]=0.5;
G[3][3]=cos(x2[3]);
//計算F,即-del_x2
del_x2[0]=-(0.5*cos(x2[0])+x2[1]+x2[2]+x2[3]-x-2.67);
del_x2[1]=-(x2[0]+0.5*sin(x2[1])+x2[2]+x2[3]-y-1.07);
del_x2[2]=-(0.5*x2[0]+x2[1]+cos(x2[2])+x2[3]-x-3.74);
del_x2[3]=-(x2[0]+0.5*x2[1]+x2[2]+sin(x2[3])-y-0.79);
GaussElimination(G,4,del_x2); //調用GaussElimination函數計算線性方程組F'*del_x=-F,解del_x即del_x2
}while(fabs(InfiniteNorm(del_x2,4)/InfiniteNorm(x2,4))>PrecisionLevel); //調用InfiniteNorm函數計算向量的無窮範數
for(i=0;i<4;i++)
X[i]=x2[i];
DestroyMatrix(G,4,4);
}
//-----------------------------------------------
//求方陣的逆矩陣
bool InverseMatrix(double** A,int n)
{
double* b;
double** A1=CreateMatrix(n,n);
double** A2=CreateMatrix(n,n);
b=new double[n];
int i,j,k;
for(k=0; k<n; k++)
{
for(i=0; i<n; i++)
for(j=0; j<n; j++)
A1[i][j]=A[i][j];
for(i=0; i<n; i++)
if(i==k)
b[i]=1;
else
b[i]=0;
if(!GaussElimination(A1,n,b))
return false;
for(i=0; i<n; i++)
A2[i][k]=b[i];
}
for(i=0; i<n; i++)
for(j=0; j<n; j++)
A[i][j]=A2[i][j];
DestroyMatrix(A1,n,n);
DestroyMatrix(A2,n,n);
delete[]b;
return true;
}
//-----------------------------------------------
//計算擬合曲面係數矩陣c_rs
void CoefficientMatrix(double* x,int m,double* y,int n,double** z,int k1,int k2,double** C)
{
double** G=CreateMatrix(n,k2+1);
double** B=CreateMatrix(m,k1+1);
double** A1=CreateMatrix(k1+1,k1+1);
double** A2=CreateMatrix(k2+1,k2+1);
double** A3=CreateMatrix(k1+1,m);
double** A4=CreateMatrix(n,k2+1);
double* temp=new double[n];
int i,j,r,s;
for(i=0; i<n; i++)
for(j=0; j<k2+1; j++)
G[i][j]=pow(y[i],j); //調用math庫函數pow計算y[i]的j次方,構建基函數組
for(i=0; i<m; i++)
for(j=0; j<k1+1; j++)
B[i][j]=pow(x[i],j);
//A1=B'*B
for(i=0; i<k1+1; i++)
for(j=0; j<k1+1; j++)
{
A1[i][j]=0;
for(r=0; r<m; r++)
A1[i][j]+=B[r][i]*B[r][j];
}
InverseMatrix(A1,k1+1); //調用InverseMatrix函數,求矩陣的逆
//A2=G'*G
for(i=0; i<k2+1; i++)
for(j=0; j<k2+1; j++)
{
A2[i][j]=0;
for(r=0; r<n; r++)
A2[i][j]+=G[r][i]*G[r][j];
}
InverseMatrix(A2,k2+1);
//A3=A1*B'=(B'B)*B'
for(i=0; i<k1+1; i++)
for(j=0; j<m; j++)
{
A3[i][j]=0;
for(r=0; r<k1+1; r++)
A3[i][j]+=A1[i][r]*B[j][r];
}
//A4=G*A2=G*(G'*G)
for(i=0; i<n; i++)
for(j=0; j<k2+1; j++)
{
A4[i][j]=0;
for(r=0; r<k2+1; r++)
A4[i][j]+=G[i][r]*A2[r][j];
}
//C=A3*U*A4
for(i=0; i<k1+1; i++)
for(j=0; j<k2+1; j++)
{
C[i][j]=0;
for(r=0; r<n; r++)
{
temp[r]=0;
for(s=0; s<m; s++)
temp[r]+=A3[i][s]*z[s][r];
C[i][j]+=temp[r]*A4[r][j];
}
}
delete[]temp;
DestroyMatrix(G,n,k2+1);
G=NULL;
DestroyMatrix(B,m,k1+1);
B=NULL;
DestroyMatrix(A1,k1+1,k1+1);
A1=NULL;
DestroyMatrix(A2,k2+1,k2+1);
A2=NULL;
DestroyMatrix(A3,k1+1,m);
A3=NULL;
DestroyMatrix(A4,n,k2+1);
A4=NULL;
}
//-----------------------------------------------
//計算p(x,y)值
double P_Value(double **C,int k,double x,double y)
{
double sum=0.0;
int r,s;
for(r=0; r<=k; r++)
for(s=0; s<=k; s++)
sum+=C[r][s]*pow(x,r)*pow(y,s);
return sum;
}
//-----------------------------------------------
//曲面擬合
double** SurfaceFitting(int& k)
{
int i,j;
double x1[11];
double y1[21];
double y[4]; //用於存儲非線性方程組的解y=[t u v w]'
double** F=CreateMatrix(11,21); //調用CreateMatrix函數創建矩陣
//--------以下求解問題的第(1)問--------
for(i=0; i<11; i++) //計算xi,yj
x1[i]=0.08*i;
for(j=0; j<21; j++)
y1[j]=0.5+0.05*j;
printf("數表xi,yj,f(xi,yj)\n");
for(i=0;i<11;i++)
{
for(j=0;j<21;j++)
{
NonlinearEquationSolver(x1[i],y1[j],y); //調用NonlinearEquationSolver函數,求解非線性方程,返回解y,即求用於插值t和u
F[i][j]=PiecewiseInterpolation(y[0],y[1]); //調用PiecewiseInterpolation函數,進行分片二次插值求f(xi,yj)
printf("%f %f %20.12e\n",x1[i],y1[j],F[i][j]);
}
}
//--------以上求解問題的第(1)問--------
printf("\n");
//--------以下求解問題的第(2)問和第(3)問--------
double sum;
double** C;
for(k=1; ;k++)
{
C=CreateMatrix(k+1,k+1);
CoefficientMatrix(x1,11,y1,21,F,k,k,C); //調用CoefficientMatrix函數,計算曲面擬合係數C_rs
sum=0; //對結果進行驗證
for(i=0; i<11; i++)
for(j=0; j<21; j++) //調用P_Value函數,計算p(x,y),然後計算誤差平方和sigma
sum+=(F[i][j]-P_Value(C,k,x1[i],y1[j]))*(F[i][j]-P_Value(C,k,x1[i],y1[j]));
printf("k=%d sigma=%.12e\n",k,sum); //顯示選擇過程中和達到精度要求時的k和sigma
if(sum<=1.0e-7)
break;
if(k>7)
break;
DestroyMatrix(C,k+1,k+1);
C=NULL;
}
//--------以上求解問題的第(2)問和第(3)問--------
DestroyMatrix(F,11,21);
return C;
}
//-----------------------------------------------
//主函數
void main()
{
double **C;
int i,j,k;
double X[4];
//初始化Z矩陣(二維數表)
Z[0][0]=-0.5; Z[0][1]=-0.34; Z[0][2]=0.14; Z[0][3]=0.94; Z[0][4]=2.06; Z[0][5]=3.5;
Z[1][0]=-0.42; Z[1][1]=-0.5; Z[1][2]=-0.26; Z[1][3]=0.3; Z[1][4]=1.18; Z[1][5]=2.38;
Z[2][0]=-0.18; Z[2][1]=-0.5; Z[2][2]=-0.5; Z[2][3]=-0.18; Z[2][4]=0.46; Z[2][5]=1.42;
Z[3][0]=0.22; Z[3][1]=-0.34; Z[3][2]=-0.58; Z[3][3]=-0.5; Z[3][4]=-0.1; Z[3][5]=0.62;
Z[4][0]=0.78; Z[4][1]=-0.02; Z[4][2]=-0.5; Z[4][3]=-0.66; Z[4][4]=-0.5; Z[4][5]=-0.02;
Z[5][0]=1.5; Z[5][1]=0.46; Z[5][2]=-0.26; Z[5][3]=-0.66; Z[5][4]=-0.74; Z[5][5]=-0.5;
C=SurfaceFitting(k); //調用SurfaceFitting函數求曲面擬合係數C_rs
printf("\n係數矩陣C的計算結果:\n");
for(i=0; i<=k; i++)
{
for(j=0;j<=k;j++)
printf("%20.12e ",C[i][j]);
printf("\n");
}
//--------以下求解問題的第(4)問--------
printf("\n檢驗p(x,y)逼近f(x,y)的效果:\n");
printf("\n數表xi*,yj*,f(xi*,yj*),p(xi*,yj*):\n");
for(i=1; i<=8; i++)
for(j=1; j<=5; j++)
{
NonlinearEquationSolver(0.1*i,0.5+0.2*j,X);
printf("%f %f %20.12e %20.12e\n",0.1*i,0.5+0.2*j,PiecewiseInterpolation(X[0],X[1]),P_Value(C,k,0.1*i,0.5+0.2*j));
}
//--------以上求解問題的第(4)問--------
DestroyMatrix(C,k+1,k+1);
system("pause");
}
//-----------------------------------------------
數值分析
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.