斯密特正交化进行QR分解
来源:互联网 发布:怎样加入淘宝客服 编辑:程序博客网 时间:2024/05/29 16:07
矩阵类:
#include<iostream> #include <stdlib.h> #include <math.h> #define iter 60 //迭代次数using namespace std; class Matrix { public: Matrix(const Matrix &rhs)//拷贝构造{if(this != &rhs) {row=rhs.row;col=rhs.col;size=row*col;pmm=new double[size];for(unsigned i=0; i<size; i++)pmm[i]=rhs.pmm[i];}}Matrix(unsigned r,unsigned c):row(r),col(c)//非方阵 { size=r*c; if (size>0){pmm = new double[size]; for(unsigned int j=0;j<size;j++) //init { pmm[j]=0.0; } }elsepmm=NULL;}; Matrix(unsigned n):row(n),col(n)//方阵 { size=n*n; if (size>0){pmm = new double[size]; for(unsigned int j=0;j<size;j++) //init { pmm[j]=0.0; } }elsepmm=NULL;}; ~Matrix(){if (pmm!=NULL) { delete []pmm; } } Matrix &operator=(const Matrix& ); //赋值,必须是成员 friend istream &operator>>(istream&, Matrix&); friend ostream &operator<<(ostream&, Matrix&); friend Matrix operator+(const Matrix&,const Matrix&); friend Matrix operator*(const Matrix&,const Matrix&); double det();Matrix diag(); void sort(); void VectValue(); unsigned getrow(){return row;}unsigned getcolumn(){return col;}double MatrixNorm2();//2范数 double*operator[](int i)//a[i][j]直接访问元素{return pmm+i*row;}private:unsigned row,col,size ; double *pmm;//数组指针 void QR(Matrix&,Matrix&)const; void EigenVect(const Matrix& eigenValue ,Matrix &eigenVector); }; //友元仅仅是指定了访问权限,不是一般意义的函数声明,最好在类外再进行一次函数声明。 istream &operator>>(istream &is, Matrix &obj); ostream &operator<<(ostream &is, Matrix &obj); //对称性运算符,如算术,相等,应该是普通非成员函数。 Matrix operator*( const Matrix&,const Matrix& ); Matrix operator+( const Matrix&,const Matrix& ); double dets(int n, double *&aa){double *bb = new double[(n-1)*(n-1)];//创建n-1阶的代数余子式阵bb int p=0,//判断行是否移动q=0;//代数余子式if(n == 1) {return aa[0]; }double sum=0.0;//sum为行列式的值for(int ai=0;ai<n;ai++) // a的行数把矩阵a(nn)赋值到b(n-1){for(int bi=0;bi<n-1;bi++)//把元素aa[ai][0]代数余子式存到bb[][]{if(ai>bi) //ai行的代数余子式是:小于ai的行,aa与bb阵,同行赋值p=0;else p=1; //大于等于ai的行,取aa阵的ai+1行赋值给阵bb的bi行for(int j=0;j<n-1;j++) //从aa的第二列赋值到第n列{bb[bi*(n-1)+j]=aa[(bi+p)*n+j+1];}}if(ai%2==0) q=1;//因为列数为0,所以行数是偶数时候,代数余子式为-1.else q=(-1);sum+= q* aa[ai*n] *dets(n-1,bb);}return sum;delete []bb;}double Matrix::det(){if(col==row){ return dets(row,pmm) ; }else{cout<<("行列不相等无法计算")<<endl;return 0;}}///////////////////////////////////////////////////////////////////// istream &operator>>(istream &is, Matrix &obj) { for (unsigned i=0; i<obj.size; i++) { is>>obj.pmm[i]; } return is; } ostream &operator<<(ostream &out, Matrix &obj) { for( unsigned i = 0; i < obj.row; i++) //打印逆矩阵 { for( unsigned j = 0; j < obj.col; j++) { cout<< obj.pmm[i*obj.col+j]<<"\t"; } cout<<endl; } return out; } Matrix operator+( const Matrix& lm,const Matrix& rm) { Matrix ret(lm.row,lm.col); for (unsigned i=0;i<ret.size;i++) { ret.pmm[i]=lm.pmm[i] + rm.pmm[i]; } return ret; } Matrix operator*( const Matrix& lm,const Matrix& rm) { if(lm.size==0||rm.size==0||lm.col != rm.row) { Matrix temp(0,0); temp.pmm=NULL;return temp; //数据不合法时候,返回空矩阵 } Matrix ret(lm.row, rm.col); for( unsigned i=0;i<lm.row;i++) { for(unsigned j=0; j< rm.col;j++) { for(unsigned k=0; k< lm.col;k++)//lm.col == rm.row { ret.pmm[i*rm.col+j]+= lm.pmm[i*lm.col+k] * rm.pmm[k*rm.col+j]; } } } return ret; } Matrix& Matrix::operator=( const Matrix& B ) { row=B.row; col=B.col; size=B.size; for (unsigned i=0;i<size;i++) { pmm[i]=B.pmm[i]; } return *this; } //||matrix||_2 求A矩阵的2范数 double Matrix::MatrixNorm2() { double norm = 0; for(unsigned i = 0;i < size;++i) { norm += pmm[i] * pmm[i]; } return (double)sqrt(norm); } void Matrix::sort() { double tem; for (unsigned i=0; i<size;i++) { for (unsigned j=i+1; j<size;j++) { if (pmm[i]<pmm[j]) { tem=pmm[i]; pmm[i]=pmm[j]; pmm[j]=tem; } } } } Matrix Matrix::diag(){ if (row!=col) {Matrix m(0);return m;}Matrix m(row,1);for (unsigned i=0;i<row;i++) { m.pmm[i]=pmm[i*row+i]; } return m; }//----------------------QR分解------------------------------------------- //将A分解为Q和R void Matrix::QR(Matrix &Q,Matrix &R) const { //如果A不是一个二维方阵,则提示错误,函数计算结束 if(row != col ) { printf("ERROE: QR() parameter A is not a square matrix!\n"); return; } const unsigned N = row; double *a=new double[N]; double *b=new double[N]; for(unsigned j = 0 ; j < N;++j) //(Gram-Schmidt) 正交化方法 { for(unsigned i = 0;i < N; ++i) //第j列的数据存到a,b a[i] = b[i] = pmm[i * N + j]; for(unsigned i = 0; i<j; ++i) //第j列之前的列 { R.pmm[i * N + j] = 0; // for(unsigned m = 0;m < N; ++m) { R.pmm[i * N + j] += a[m] * Q.pmm[m *N + i]; //R[i,j]值为Q第i列与A的j列的内积 } for(unsigned m = 0;m < N; ++m) { b[m] -= R.pmm[i * N + j] * Q.pmm[m * N + i]; // } } double norm = 0; for(unsigned i = 0;i < N;++i) { norm += b[i] * b[i]; } norm= (double)sqrt(norm); R.pmm[j*N + j] = norm; //向量b[]的2范数存到R[j,j] for(unsigned i = 0; i < N; ++i) { Q.pmm[i * N + j] = b[i] / norm; //Q 阵的第j列为单位化的b[] } } delete[]a; delete[]b; } //----------已知矩阵的特征值求矩阵特征向量----------------- //eigenValue为矩阵A的特征值, //eigenVector为计算结果即矩阵A的特征向量 void Matrix::EigenVect(const Matrix& eigenValue ,Matrix &eigenVector) { const unsigned NUM = col; double eValue; double sum,midSum,diag; Matrix copym(*this); for(unsigned count = 0; count < NUM;++count) { //计算特征值为eValue,求解特征向量时的系数矩阵 *this=copym; eValue = eigenValue.pmm[count] ; for(unsigned i = 0 ; i < col ; ++i)//A-lambda*I { pmm[i * col + i] -= eValue; } //cout<<*this<<endl; //将 this为阶梯型的上三角矩阵 for(unsigned i = 0 ; i < row - 1 ; ++i) { diag = pmm[i*col + i]; //提取对角元素for(unsigned j = i; j < col; ++j) {pmm[i*col + j] /= diag; //【i,i】元素变为1} for(unsigned j=i+1; j<row; ++j) { diag = pmm[j * col + i]; for(unsigned q = i ; q < col; ++q)//消去第i+1行的第i个元素{ pmm[j*col + q] -= diag*pmm[i*col + q]; } } } //cout<<*this<<endl; //特征向量最后一行元素置为1midSum = eigenVector.pmm[(eigenVector.row - 1) * eigenVector.col + count] = 1; for(int m = row - 2; m >= 0; --m) { sum = 0; for(unsigned j = m + 1;j < col; ++j) { sum += pmm[m * col + j] * eigenVector.pmm[j * eigenVector.col + count]; } sum= -sum / pmm[m * col + m]; midSum += sum * sum; eigenVector.pmm[m * eigenVector.col + count] = sum; } midSum = sqrt(midSum); for(unsigned i = 0; i < eigenVector.row ; ++i) { eigenVector.pmm[i * eigenVector.col + count] /= midSum; //每次求出一个列向量 } } } void Matrix::VectValue() { if (size==0||row!=col) { cout<<"矩阵为空或者非方阵!"<<endl; return; } if (det()==0) { cout<<"非满秩矩阵没法用QR分解计算特征值!"<<endl; return; } const unsigned N=row; Matrix A(*this);//备份矩阵 Matrix Q(N),R(N); /*当迭代次数足够多时,A 趋于上三角矩阵,上三角矩阵的对角元就是A的全部特征值。*/ for(int k = 0;k < iter; ++k) { //cout<<"this:\n"<<*this<<endl; QR(Q,R); *this=R*Q; /*cout<<"Q:\n"<<Q<<endl; cout<<"R:\n"<<R<<endl; */} Matrix eigenValue=diag();//特征值 cout<<"\neigenValue:\n"<<eigenValue<<endl; Matrix eigenVect(N);//特征向量 A.EigenVect (eigenValue,eigenVect); cout<<"\neigenVect:\n"<<eigenVect<<endl; }
测试用的主函数:
#include"matrix.h" #include<iostream> #include <fstream> // std::ifstream using namespace std; int main() { cout<<"输入阶数:"; int N=0; cin>>N; Matrix mm(N); int flag=1; cout<<"屏幕输入矩阵按0,其他数字则从文件mm.txt读入矩阵:"; cin>>flag; cout<<endl; if (flag==0) { cout<<"input matrix:"<<endl; cin>>mm; }else { ifstream ifs; ifs.open ("mm.txt", ifstream::in); ifs>>mm; } mm.VectValue(); system("pause"); }
阅读全文
0 0
- 斯密特正交化进行QR分解
- QR分解-正交矩阵生成
- 【通俗理解线性代数】 -- 施密特正交化与QR分解
- C++ Matrix类(考试太忙了,新增了正交化的QR分解,求逆运算等)
- QR 分解
- QR分解
- QR分解
- QR分解
- QR分解
- 求助QR分解
- OpenCV QR分解
- QR分解如何翻译
- QR,RQ分解
- 【矩阵】RQ/QR 分解
- 正交函数系分解
- matlab qr函数 QR分解
- 矩阵分析中的QR分解
- Householder 变换与 QR 分解
- PHPstorm一些常用的快捷键
- LeetCode 13. Roman to Integer
- Host Profiles Management使用
- stm32完美驱动1.77寸oled裸屏
- jsp生成json并传递给前台html解析后显示传递的信息
- 斯密特正交化进行QR分解
- PAT甲级 1120. Friend Numbers (20)
- hihocoder Challenge 29 A.序列的值
- java GMT时间转换为CST时间
- 对于所有对象都通用的方法
- express-10-登录2
- C++线程同步的四种方式(Windows)
- 【Docker安装】- 卸掉docker参考
- sklearn.metrics.confusion_matrix