int EVqr(MAT &A,double tol,int maxiter){ int iter = 0 ; MAT T(A); MAT R(A.dim()), Q(A.dim()); //since we are not able to access column of a matrix easily, so we access row of matrices as substitute. do{ //QR decomposition QRDecomp(T,Q,R); T = R * Q; iter++; }while( (iter < maxiter) && (QRerror(T) > tol) ); printf("Largest 3 eigenvalues: "); for (int i = 0; i < 3; i++) printf(" %lf;",T[i][i]); printf("\nSmallest 3 eigenvalues: "); for (int i = A.dim()-1; i > A.dim()-4; i--) printf(" %lf;",T[i][i]); //printf("\niter %d\nerror: %E\n",iter,QRerror(A_k)); return iter; }
double invPowerShift(MAT &A, double omega, VEC q, int maxIter){ int k = 1; //I: identity matrix; LU: LU in-place; MAT I(A.dim()), LU(A.dim()), shiftedA(A.dim()); //q: VEC z(A.dim()), temp(A.dim()),r(A.dim()), u(A.dim()), w(A.dim()); double lambdaN= 100.0, newlambdaN=0.0, tol = 1.0; //Form identity matrix for (int i =0; i < A.dim(); i++){ I[i][i] = 1; } shiftedA = A-(omega*I); LU = luFact(shiftedA); //LU in-place decomposition while( (k < maxIter) && tol >= 0.000000001 ){ temp = fwdSubs(LU,q); //forward substitution z = bckSubs(LU,temp);//backward substitution q = z/l2norm(z); lambdaN = q * A * q; r = A * q - lambdaN * q; u = q * A; w = u/l2norm(u); tol = l2norm(r)/std::abs(w*q); } //printf("Iteration: %d\n",k); return lambdaN; }
VEC fwdSubs(MAT &m1, VEC b) { VEC y(b); for(int i = 0 ; i < m1.dim() ; i++) y[i] = b[i]; for(int i = 0 ; i < m1.dim() ; i++){ for(int j = i+1 ; j<m1.dim() ; j++){ y[j] -= m1[j][i] * y[i]; } } return y; }
VEC fwdSubs(MAT &m1,VEC b)//fwdSubs must be modified from the one used by LU Decomposition { VEC y = b; //y[0]=b[0]/m1[0][0]; for(int i=0; i<m1.dim();i++){ //y[i]/=m1[i][i];//Add this step for modification about Cholesky method for(int j=i+1; j<m1.dim(); j++) y[j] -= m1[j][i]*y[i]; } return y; }
VEC bckSubs(MAT &m1,VEC y){ VEC x(y); for(int i = 0 ; i < m1.dim() ; i++) x[i] = y[i]; for(int i = m1.dim()-1 ; i >= 0 ; i--){ x[i] /= m1[i][i]; for(int j = i-1 ; j >= 0 ; j--){ x[j] -= m1[j][i] *x[i]; } } return x; }
VEC fwdSubs1(MAT &m1, VEC b) { VEC y(b); for(int i = 0 ; i < m1.dim() ; i++) y[i] = b[i]; for(int i = 0 ; i < m1.dim() ; i++){ y[i] /= m1[i][i]; //because the diagonal elements are not 1's, modify by adding this line for(int j = i+1 ; j<m1.dim() ; j++){ y[j] -= m1[j][i] * y[i]; } } return y; }
VEC operator*(VEC &v1,MAT &m1) { VEC v2(m1.n); for(int i = 0; i <m1.dim();i++){ v2[i]=0; for(int j = 0; j<m1.dim();j++){ v2[i]+=v1[j]*m1[j][i]; } } return v2; }
double ConvErr(MAT A){ //find the maximum among the elements just below the diagonal double error = 0; for(int i=1;i<A.dim();i++){ error = max(error,fabs(A[i][i-1])); } return error; }
double invpower(MAT A,VEC q,int maxiter,double eps,double &v,int aw){ double tol = 1+eps; int k=0; int n=A.dim(); VEC y(n); VEC z(n); VEC r(n); VEC Aq(n); VEC u(n); VEC w(n); MAT A1(n); MAT S(n); for(int i=0;i<n;i++){ S[i][i] = aw; //define the shifting matrix } A1 = A-S; luFact(A1); //use LU to solve the equation while((tol>=eps) && (k<=maxiter)){ k = k+1; y = fwdSubs(A1,q); //forward subsitution z = bckSubs(A1,y); //backward substitution q = z/norm2(z); Aq = A*q; v = q*Aq; r = Aq - v*q; u = Aq; w = u/norm2(u); tol = norm2(r)/fabs(q*w); } printf("accuracy of lambda min = %e\n",norm2(r)); return k; }
double power(MAT A,VEC q,int maxiter,double eps,double &v){ double tol = 1 + eps; int k = 0; int n = A.dim(); VEC z(n); VEC r(n); VEC Aq(n); VEC u(n); VEC w(n); while((tol>=eps) && (k<=maxiter)){ Aq = A*q; k = k+1; q = Aq/norm2(Aq); Aq = A*q; v = q*Aq; r = Aq-v*q; u = Aq; w = u/norm2(u); tol = norm2(r)/fabs(q*w); } printf("accuracy of lambda max = %e\n",norm2(r)); //set 2-norm error of residue as accuracy term return k; }
// A = Q * R QR Decomposition void QRDecomp(MAT &A,MAT &Q, MAT &R){ int n=A.dim(); MAT AT(A.tpose()); MAT QT(Q.tpose()); VEC S(n); //sum vector R[0][0]=sqrt(AT[0]*AT[0]); //initial R QT[0]=AT[0]/R[0][0]; //initial Q for(int j=1;j<n;j++){ for(int i=0;i<n;i++){ S[i] = 0; } //initialization of sum vector for(int i=0;i<=j;i++){ R[i][j] = QT[i]*AT[j]; } for(int i=0;i<=j-1;i++){ S = S + R[i][j]*QT[i]; //do the summation } S = AT[j] - S; R[j][j]=sqrt(S*S); QT[j] = S/R[j][j]; } Q=QT.tpose(); }
int EVqrShifted(MAT &A,double mu, double tol,int maxiter){ int n=A.dim(); int k=0; double err=10; MAT Q(n),R(n),T(A); while(err>tol && k<maxiter){ for(int i=0;i<n;i++){ //subtract mu*I before QR factorization T[i][i] = T[i][i] - mu; } QRDecomp(T,Q,R); //QR factorization T=R*Q; //matrix multiplication for(int i=0;i<n;i++){ //add mu*I back T[i][i] = T[i][i] + mu; } err = ConvErr(T); k++; } printf("the three largest EV:\n"); printf("%lf %lf %lf\n",T[0][0],T[1][1],T[2][2]); printf("the three smallest EV:\n"); printf("%lf %lf %lf\n",T[n-1][n-1],T[n-2][n-2],T[n-3][n-3]); printf("iter = %d\n",k); printf("error = %e\n",err); A=T; return k; }
double invPowerShift(MAT &A, double omega, VEC q, int maxIter){ int k = 1; //I: identity matrix; LU: LU in-place; iLU: LU in-place for invA; invA: inverse of A MAT I(A.dim()), LU(A.dim()),iLU(A.dim()), invA = inverse(A), shiftedA(A.dim()); //q: VEC z(A.dim()), temp(A.dim());// q(A.dim()),iq(A.dim()), iz(A.dim()), double lambdaN= 100.0, newlambdaN=0.0; //Form identity matrix for (int i =0; i < A.dim(); i++){ I[i][i] = 1; } shiftedA = A-(omega*I); LU = luFact(shiftedA); //LU in-place decomposition //iLU = luFact(invA-(w*I)); //LU in-place decomposition while( (k < maxIter) && (std::abs(newlambdaN - lambdaN) >= 10E-9) ){ lambdaN = newlambdaN; temp = fwdSubs(LU,q); //forward substitution z = bckSubs(LU,temp);//backward substitution q = z/l2norm(z); newlambdaN = q * A * q; /* temp = fwdSubs(iLU,iq); //forward substitution iz = bckSubs(iLU,temp);//backward substitution iq = iz / l2norm(iz); imu = iq * invA * iq; //newCond = mu/imu; */ } printf("Iteration: %d\n",k); return newlambdaN; }
double powerMethod(MAT &A, VEC q, int maxIter){ VEC z(A.dim()), r(A.dim()), u(A.dim()), w(A.dim()); MAT A_k(A.dim()); double lambda1, tol= 1.0; //double new_lambda int iter = 0; while( (iter < maxIter) && (tol >= 0.000000001) ){ z = A * q; iter++; q = z/l2norm(z); lambda1 = q * A * q; r = A * q - lambda1 * q; u = q * A; w = u/l2norm(u); tol = l2norm(r)/std::abs(w*q); } return lambda1; }
VEC bckSubs(MAT &m1,VEC b)//b as y { int i,j,k; VEC x=b; for(i=m1.dim()-1 ;i>=0 ;i--){ x[i] /= m1[i][i]; for(j=i-1; j>=0; j--) x[j] -= m1[j][i] * x[i]; } return x; }
double invPowerShift(MAT &A, double omega, VEC q, int maxIter){ int k = 1; //I: identity matrix; LU: LU in-place; MAT I(A.dim()), LU(A.dim()), shiftedA(A.dim()); //q: VEC z(A.dim()), temp(A.dim());// q(A.dim()) double lambdaN = 100.0, newlambdaN=0.0; //Form identity matrix for (int i =0; i < A.dim(); i++){ I[i][i] = 1; } shiftedA = A-(omega*I); LU = luFact(shiftedA); //LU in-place decomposition while( (k < maxIter) && (std::abs(newlambdaN - lambdaN) >= 0.000000001) ){ lambdaN = newlambdaN; temp = fwdSubs(LU,q); //forward substitution z = bckSubs(LU,temp);//backward substitution q = z/l2norm(z); newlambdaN = q * A * q; } printf("Iteration: %d\n",k); return newlambdaN; }
int gaussSeidel(MAT &A,VEC b,VEC &x,int maxIter,double tol) { int k = 0; double theta=0.0; VEC newx(A.dim()),ans(A.dim()),temp(A.dim()); MAT LU(A.dim()),a = A; LU = luFact(a); //LU in-place decomposition temp=fwdSubs(LU,b); //forward substitution ans= bckSubs(LU,temp);//backward substitution while( k < maxIter) { x = newx; for(int i=0; i< A.dim(); i++) { theta = 0.0; for(int j=0; j < A.dim();j++){ if(i!=j){ theta += (A[i][j]*newx[j]); } } newx[i]= (b[i]-theta)/A[i][i]; } k++; if (linfnorm(newx - x) < tol) break; } printf("Diffrence w.r.t. hw4: %E\n",linfnorm(newx-ans)); return k; }
int cg(MAT &A,VEC b,VEC &x,int maxIter, double tol) { //A_p: A * p VEC A_p(A.dim()); int node = std::sqrt(A.dim()); //p: search direction; VEC p(A.dim()), r(A.dim()), newr(A.dim()), newx(A.dim());//,ans(A.dim()),temp(A.dim()); //MAT LU(A.dim()),a = A; //r2: rT * r double alpha, beta, r2, newr2, err;//,g; //g = (double)(node-1)/2000.0; int iter = 0;// /* LU = luFact(a); //LU in-place decomposition temp=fwdSubs(LU,b); //forward substitution ans= bckSubs(LU,temp);//backward substitution */ //Initial condition for CGM p = r = b - (A * x); r2 = r * r; while(iter < maxIter) { A_p = A * p; alpha = r2 / (p * A_p); newx = x + (alpha * p); err = std::sqrt(r2/A.dim()); if ( err < tol ) break; newr = r - (alpha * A_p); newr2 = newr * newr; beta = newr2 / r2; p = newr + beta * p; //Re-initialization for next iteration x = newx; r = newr; r2 = newr2; ////////////////////////////////////// iter++; } //printf("cg:Vne: %lf; Vsw: %lf; Vse: %lf; R:%lf\n",newx[node-1],newx[(node-1)*node],newx[node*node-1], std::abs( 1/(g*(newx[0]-newx[1])+g*(newx[0]-newx[node] )) ) ); //printf("LU:Vne: %lf; Vsw: %lf; Vse: %lf; R:%lf\n",ans[node-1],ans[(node-1)*node],ans[node*node-1], std::abs( 1/(g*(ans[0]-ans[1])+g*(ans[0]-ans[node] )) ) ); //printf("Difference w.r.t. hw4: %E\n",linfnorm(ans - newx)); return iter; }
int cg(MAT &A,VEC b,VEC &x,int maxIter,double tol){ int n = A.dim(); int k = 0; VEC x_next(n); VEC r_next(n); VEC p_next(n); VEC r(n); VEC p(n); MAT L(n); VEC cpr(n); double alpha,beta; double err; double diff; r = b - A*x; //initial condition p = r; while(k<maxIter){ //conjugate gradient decent alpha = (r*r)/(p*(A*p)); x_next = x + alpha*p; r_next = r - alpha*(A*p); beta = (r_next*r_next)/(r*r); p_next = r_next + beta*p; k++; x = x_next; //assign to the x,r,p of the next iteration r = r_next; p = p_next; err = pow((r*r)/n,0.5); if(err<tol) //see if the error is smaller than the defined tolerance. if so, break out of the loop break; } diff = 0; //the answer from hw4 L = cholesky(A); //in-place Cholesky Decomposition cpr = choSolve(L,b); //solve the linear system by forward and backward substitution //use the same method to compute the error between hw4 and hw5, see if < 10^-7. if not, decrease the tol for(int i=0;i<n;i++){ diff = max(diff,fabs(x[i]-cpr[i])); //use infinity norm to compute the error } printf("error between hw4 and hw6(infinity-norm): %e\n",diff); return k; }
int EVqr(MAT &A,double tol,int maxiter){ int n=A.dim(); int k=0; double err=10; MAT Q(n),R(n),T(A); while(err>tol && k<maxiter){ QRDecomp(T,Q,R); //QR factorization T=R*Q; //matrix multiplication err = ConvErr(T); //get the error term in each iteration k++; } printf("the three largest EV:\n"); printf("%lf %lf %lf\n",T[0][0],T[1][1],T[2][2]); printf("the three smallest EV:\n"); printf("%lf %lf %lf\n",T[n-1][n-1],T[n-2][n-2],T[n-3][n-3]); printf("iter = %d\n",k); printf("error = %e\n",err); A=T; return k; }
int EVqrShifted(MAT &A,double mu,double tol,int maxiter){ int iter = 0 ; MAT T(A); MAT R(A.dim()), Q(A.dim()),muI(A.dim()); //since we are not able to access column of a matrix easily, so we access row of matrices as substitute. for (int i =0 ; i < A.dim(); i++) muI[i][i] = mu; do{ for(int i=0;i<A.dim();i++){ //subtract mu*I before QR factorization T[i][i] = T[i][i] - mu; } //QR decomposition QRDecomp(T,Q,R); T = R * Q; //QR decomposition ends for(int i=0;i<A.dim();i++){ //add mu*I back T[i][i] = T[i][i] + mu; } iter++; }while( (iter < maxiter) && (QRerror(T) > tol) ); printf("Largest 3 eigenvalues: "); for (int i = 0; i < 3; i++) printf(" %lf;",T[i][i]); printf("\nSmallest 3 eigenvalues: "); for (int i = A.dim()-1; i > A.dim()-4; i--) printf(" %lf;",T[i][i]); //printf("\niter %d\nerror: %E\n",iter,QRerror(A_k)); return iter; }
VEC choSolve(MAT &L,VEC b) { VEC x(b); //forward substitutions for (int i=0; i<x.len(); i++) { x[i] /= L[i][i]; for (int j=i+1; j<L.dim(); j++) x[j] -= L[j][i]*x[i]; } //backward substitutions for (int i=(x.len()-1); i>=0; i--) { x[i] /= L[i][i]; for (int j=i-1; j>=0; j--) x[j] -= L[i][j]*x[i]; } return x; }
MAT inverse(MAT &A) { VEC temp(A.dim()); // I: identity matrix; inv: inverse of A; LU: LU in-place MAT LU(A.dim()), a = A, I(A.dim()), inv(A.dim()); LU = luFact(a); //LU in-place decomposition // Form identity matrix for (int i =0; i < A.dim(); i++){ I[i][i] = 1; } // solve inverse of A. Answer is stored row by row for (int i = 0; i< A.dim(); i++){ temp=fwdSubs(LU,I[i]); //forward substitution inv[i]= bckSubs(LU,temp);//backward substitution } // we need the result of inverse() column by column, so return transpose matrix of inv return inv.tpose(); }
double QRerror(MAT &A){ double max = std::abs(A[1][0]); for (int i = 2; i< A.dim(); i++) max = std::max(std::abs(A[i][i-1]),max); return max; }
int jacobi(MAT &A,VEC b,VEC &x, int maxIter, double tol){ int n = A.dim(); VEC S(n); //summation vector VEC G(n); //diagonal of A VEC tmp(n); //save the x before iterative method MAT L(n); VEC cpr(n); //the result of hw4 //iterative int k=0; double err1; double err2; double errinf; double diff1,diff2,diffinf; while(k<maxIter){ for(int i=0;i<n;i++){ S[i] = 0; //initialize the sum vector to 0 } for(int i=0;i<n;i++){ G[i] = A[i][i]; //save the previous vector x to tmp(for comparison between iteration k and k+1) tmp[i] = x[i]; for(int j=0;j<n;j++){ if(j!=i){ S[i] = S[i] + A[i][j]*x[j]; //sum the Aij*xj, where i is not equal to j } } } for(int i=0;i<n;i++){ x[i] = (1/G[i])*(b[i]-S[i]); //compute the new solution of x at iteration k } k++; //after each iteration, k=k+1 err1 = 0; //1-norm err2 = 0; //2-norm errinf = 0; //infinity-norm for(int i=0;i<n;i++){ err1 += fabs(x[i] - tmp[i]); //sum of absolute error err2 += pow(x[i] - tmp[i], 2); //sum of square error errinf = max(errinf,fabs(x[i]-tmp[i])); //take the maximum absolute difference as error } //max(a,b) defined on the top err2 = pow(err2,0.5); //find the square root of err2 and get the 2-norm //you can change err1 to err2 or errinf to get different number of iterations k based on which p-norm you preferred if(err1<tol){ break; } } diff1 = 0; diff2 = 0; diffinf = 0; //the answer from hw4 L = cholesky(A); //in-place Cholesky Decomposition cpr = choSolve(L,b); //solve the linear system by forward and backward substitution //use the same method to compute the error between hw4 and hw5, see if < 10^-7. if not, decrease the tol for(int i=0;i<n;i++){ diff1 += fabs(x[i] - cpr[i]); diff2 += pow(x[i] - cpr[i], 2); diffinf = max(diffinf,fabs(x[i]-cpr[i])); } diff2 = pow(diff2,0.5); printf("error between hw4 and hw5(1-norm 2-norm infinity-norm): %e %e %e\n",diff1,diff2,diffinf); return k; }
int gaussSeidel(MAT &A,VEC b,VEC &x,int maxIter,double tol) { int n = A.dim(); VEC S(n); VEC G(n); VEC tmp(n); MAT L(n); VEC cpr(n); //iterative int k=0; double err1; double err2; double errinf; double diff1,diff2,diffinf; while(k<maxIter){ for(int i=0;i<n;i++){ S[i] = 0; } for(int i=0;i<n;i++){ G[i] = A[i][i]; tmp[i] = x[i]; for(int j=0;j<n;j++){ if(j!=i){ S[i] = S[i] + A[i][j]*x[j]; } } x[i] = (1/G[i])*(b[i]-S[i]); //both x[i] and S[i] are computed in the same for loop, so some updated values are used in the current iteration } k++; err1 = 0; err2 = 0; errinf = 0; for(int i=0;i<n;i++){ err1 += fabs(x[i] - tmp[i]); err2 += pow(x[i] - tmp[i], 2); errinf = max(errinf,fabs(x[i]-tmp[i])); } err2 = pow(err2,0.5); if(err1<tol){ break; } } diff1 = 0; diff2 = 0; diffinf = 0; //the answer from hw4 L = cholesky(A); //in-place Cholesky Decomposition cpr = choSolve(L,b); //solve the linear system by forward and backward substitution //use the same method to compute the error between hw4 and hw5, see if < 10^-7. if not, decrease the tol for(int i=0;i<n;i++){ diff1 += fabs(x[i] - cpr[i]); diff2 += pow(x[i] - cpr[i], 2); diffinf = max(diffinf,fabs(x[i]-cpr[i])); } diff2 = pow(diff2,0.5); printf("error between hw4 and hw5(1-norm 2-norm infinity-norm): %e %e %e\n",diff1,diff2,diffinf); return k; }
int sgs(MAT &A,VEC b,VEC &x,int maxIter,double tol) { int n = A.dim(); VEC S(n); VEC G(n); VEC tmp(n); MAT L(n); VEC cpr(n); //iterative int k=0; double err1; double err2; double errinf; double diff1,diff2,diffinf; while(k<maxIter){ for(int i=0;i<n;i++){ S[i] = 0; } //forward gauss-seidel //compute vector x from x[0] to x[n-1] for(int i=0;i<n;i++){ G[i] = A[i][i]; tmp[i] = x[i]; for(int j=0;j<n;j++){ if(j!=i){ S[i] = S[i] + A[i][j]*x[j]; } } x[i] = (1/G[i])*(b[i]-S[i]); } //backward gauss-seidel //use the reslults of forward gauss-seidel to compute vector x //direction : from x[n-1] to x[0] for(int i=0;i<n;i++){ S[i] = 0; //we also need to initialize the sum vector. } for(int i=n-1;i>=0;i--){ for(int j=n-1;j>=0;j--){ if(j!=i){ S[i] = S[i] + A[i][j]*x[j]; } } x[i] = (1/G[i])*(b[i]-S[i]); } k++; err1 = 0; err2 = 0; errinf = 0; for(int i=0;i<n;i++){ err1 += fabs(x[i] - tmp[i]); err2 += pow(x[i] - tmp[i], 2); errinf = max(errinf,fabs(x[i]-tmp[i])); } err2 = pow(err2,0.5); if(err1<tol){ break; } } diff1 = 0; diff2 = 0; diffinf = 0; //the answer from hw4 L = cholesky(A); //in-place Cholesky Decomposition cpr = choSolve(L,b); //solve the linear system by forward and backward substitution //use the same method to compute the error between hw4 and hw5, see if < 10^-7. if not, decrease the tol for(int i=0;i<n;i++){ diff1 += fabs(x[i] - cpr[i]); diff2 += pow(x[i] - cpr[i], 2); diffinf = max(diffinf,fabs(x[i]-cpr[i])); } diff2 = pow(diff2,0.5); printf("error between hw4 and hw5(1-norm 2-norm infinity-norm): %e %e %e\n",diff1,diff2,diffinf); return k; }