Numerical Analysis - Lab
Index
- Lab2 - Direct Methods for Solving Linear Equations
- Lab3 - Inverse Power Method to Solve Eigenvalue
- Lab4 - Jacobi Method to Solve Eigenvalue
- Lab 5 - Cubic Spline Interpolation
- Lab 6 - FFT & IFFT]
- Lab 7 - Romberg Integral
Lab2 - Direct Methods for Solving Linear Equations
Description
Use C/C++, implement the following algorithms:
- Gaussian Elimination
- Doolittle Decomposition
Implement
Predefinition and Useful functions
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;
#define SUCCESS 0
#define FAILURE 1
#define INPUTPATH "./InputData.txt"
typedef int Status;
typedef double* Vector;
typedef double** Matrix;
Status PrintMatrix(int n, Matrix A){
/*
*
= FUNCTION
* Name: PrintMatrix
* Description: Print the Matrix A to the terminal. n is the Dimension of A.
*
=
*/
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
printf("%.2lf\t", A[i][j]);
}
printf("\n");
}
return SUCCESS;
}
Status PrintVector(int n, Vector v){
/*
*
= FUNCTION
* Name: PrintVector
* Description: Print the Vector v to the terminal(in row form). n is the Dimension of v.
*
=
*/
for(int i = 0; i < n; i++)
printf("%.2lf\t", v[i]);
printf("\n");
return SUCCESS;
}
Input
Using a file to input is the most stable way. Two key functions here: getline and strtod.
Status ReadFromInput(int& n, Matrix& A, Vector& b, bool PrintResult){
/*
*
= FUNCTION
* Name: ReadFromInput
* Description: Read data from input file. File Format:
* The first line indicates n.
* The next n line is the Matrix A, separated by space.
* The last line is the vector b, separated by space.
*
* It's recommended that the number are written in demical.
* e.g. Use "1.0", not "1".
*
=
*/
ifstream inputfile;
inputfile.open(INPUTPATH);
string str;
char* endptr;
if(inputfile.is_open()){
getline(inputfile, str); //Reading n.
n = stoi(str);
A = new Vector[n];
for(int i = 0; i < n; i++){
A[i] = new double[n];
}
b = new double[n];
for(int i = 0; i < n; i++){ // Reading A.
getline(inputfile, str);
char SameAsStr[str.length() + 1]; //* Convert str to char* type for
strcpy(SameAsStr, str.c_str()); //* the strtod function.
for(int j = 0; j < n; j++){
A[i][j] = strtod(SameAsStr, &endptr);
strcpy(SameAsStr, endptr);
}
}
getline(inputfile, str); // Reading b.
char SameAsStr[str.length() + 1]; //* Convert str to char* type for
strcpy(SameAsStr, str.c_str()); //* the strtod function.
for(int j = 0; j < n; j++){
b[j] = strtod(SameAsStr, &endptr);
strcpy(SameAsStr, endptr);
}
inputfile.close();
if(PrintResult){
printf("Matrix A:\n");
PrintMatrix(n, A);
printf("Vector b:\n");
PrintVector(n, b);
printf("\n");
}
}
else{
printf("Input Error, please check.\n");
return FAILURE;
}
return SUCCESS;
}
Solving Triangular-Form Equations
LTM Solve Algorithm and UTM Solve Algorithm is symmetric. So we just call UpperSolve function when implementing LowerSolve.
Status UpperSolve(int n, Matrix A, Vector b, Vector x){
/*
*
= FUNCTION
* Name: UpperSolve
* Description: When A is an Upper Triangular Matrix, use elimination, solve Ax == b.
* Parameter: n is D[A]. x is the solution.
*
=
*/
for(int i = 0; i < n; i++){
for(int j = 0; j < i; j++){
if(abs(A[i][j]) > 0.000001){
printf("This Matrix is not a Upper Triangular Matrix.\n");
return FAILURE;
}
}
}
for(int i = n - 1; i > -1; i--){
if(A[i][i] == 0){
printf("This entry have infinity solutions.\n");
return FAILURE;
}
double InPathe = b[i];
for(int j = n - 1; j > i; j--){
InPathe -= A[i][j] * x[j];
}
x[i] = InPathe / A[i][i];
}
return SUCCESS;
}
Status LowerSolve(int n, Matrix A, Vector b, Vector x){
/*
*
= FUNCTION
* Name: LowerSolve
* Description: When A is an Lower Triangular Matrix, use elimination, solve Ax == b.
* Parameter: n is D[A]. x is the solution.
*
=
*/
Matrix TempA = new Vector[n];
for(int i = 0; i < n; i++){
TempA[i] = new double[n];
}
Vector Tempb = new double[n];
Vector Tempx = new double[n];
for(int i = 0; i < n; i++){
Tempb[i] = b[n - 1 - i];
for(int j = 0; j < n; j++)
TempA[i][j] = A[n - 1 - i][n - 1 - j];
}
if(UpperSolve(n, TempA, Tempb, Tempx)){
printf("This Matrix is not a Lower Triangular Matrix.\n");
return FAILURE;
}
for(int i = 0; i < n; i++)
x[i] = Tempx[n - 1 - i];
return SUCCESS;
}
Gaussian Method
Status ChoosePivot(int n, Matrix A, Vector b, int ProcessingColumn){
/*
*
= FUNCTION
* Name: ChoosePivot
* Description: Choose the Pivot of Processing Column, do the exchange.
*
=
*/
double MaxAbs = abs(A[ProcessingColumn][ProcessingColumn]);
int MaxAbsRow = ProcessingColumn;
for(int i = ProcessingColumn + 1; i < n; i++){
if(abs(A[i][ProcessingColumn]) > MaxAbs){
MaxAbs = abs(A[i][ProcessingColumn]);
MaxAbsRow = i;
}
}
double temp = 0;
for(int j = 0; j < n; j++){
temp = A[ProcessingColumn][j]; A[ProcessingColumn][j] = A[MaxAbsRow][j]; A[MaxAbsRow][j] = temp;
}
temp = b[ProcessingColumn]; b[ProcessingColumn] = b[MaxAbsRow]; b[MaxAbsRow] = temp;
return SUCCESS;
}
Status GaussMethod(int n, Matrix A, Vector b, Vector x){
/*
*
= FUNCTION
* Name: GaussMethod
* Description:
*
=
*/
for(int k = 0; k < n; k++){
ChoosePivot(n, A, b, k);
//
set the condition to non-zero to display eliminating process.
==
if(1){
printf("ChoosePivot #%d\n", k);
printf("Matrix A:\n");
PrintMatrix(n, A);
printf("Vector b:\n");
PrintVector(n, b);
printf("\n");
}
//
if(abs(A[k][k]) < 0.0000000001){
printf("This pivot can't be den.\n");
return FAILURE;
}
for(int i = k + 1; i < n; i++){
double Coefficient = A[i][k] / A[k][k];
for(int j = k; j < n; j++)
A[i][j] -= Coefficient * A[k][j];
b[i] -= Coefficient * b[k];
}
}
printf("Matrix After Elimination:\n");
PrintMatrix(n, A);
printf("Vector After Elimination:\n");
PrintVector(n, b);
UpperSolve(n, A, b, x);
printf("The solution is:\n");
PrintVector(n, x);
return SUCCESS;
}
LU Decomposition and Doolittle Method
Status LUDecomposition(int n, Matrix A, Matrix L, Matrix U){
/*
*
= FUNCTION
* Name: LUDecomposition
* Description: Do Doolittle decompose: A = LU, return via param L and U.
*
=
*/
for(int i = 0; i < n; i++){
for(int j = 0; j < i + 1; j++){
L[i][j] = A[i][j];
}
for(int j = i + 1; j < n; j++)
L[i][j] = 0;
}
for(int i = 0; i < n; i++){
for(int j = 0; j < i; j++)
U[i][j] = 0;
for(int j = i; j< n; j++)
U[i][j] = A[i][j];
}
for(int k = 0; k < n; k++){
for(int j = k; j < n; j++){
for(int r = 0; r < k; r++)
U[k][j] -= L[k][r] * U[r][j];
}
for(int i = k; i < n; i++){
for(int r = 0; r < k; r++)
L[i][k] -= L[i][r] * U[r][k];
if(U[k][k] == 0){
printf("Divided by 0.\n");
return FAILURE;
}
L[i][k] /= U[k][k];
}
}
return SUCCESS;
}
Status DoolittleMethod(int n, Matrix A, Vector b, Vector x){
/*
*
= FUNCTION
* Name: DoolittleMethod
* Description: Using DoolittleMethod to Solve Ax == b,
*
=
*/
Matrix L = new Vector[n];
for(int i = 0; i < n; i++){
L[i] = new double[n];
}
Matrix U = new Vector[n];
for(int i = 0; i < n; i++){
U[i] = new double[n];
}
Vector y = new double[n];
LUDecomposition(n, A, L, U);
printf("L:\n");
PrintMatrix(n, L);
printf("U:\n");
PrintMatrix(n, U);
LowerSolve(n, L, b, y);
UpperSolve(n, U, y, x);
printf("\n");
PrintVector(n, x);
return SUCCESS;
}
Calculate Error
Status CalculateError(int n, Matrix A, Vector x, Vector b){
/*
*
= FUNCTION
* Name: CalculateError
* Description: Using 2-Norm to Calculate Norm(Ax - b).
*
=
*/
Vector t = new double[n]; //t = Ax - b.
double Sum = 0;
for(int k = 0; k < n; k++){
t[k] = -b[k];
for(int j = 0; j < n; j++)
t[k] += A[k][j] * x[j];
Sum += t[k] * t[k];
}
double Error = sqrt(Sum);
printf("The Error Vector is:\n");
PrintVector(n, t);
printf("Error = %.12lf\n", Error);
return SUCCESS;
}
Main Function - Calling the Functions implemented above
int main(){
Matrix A = NULL;
Vector b = NULL;
int n = 0;
ReadFromInput(n, A, b, 1);
Vector x = NULL;
x = new double[n];
switch(1){
case 1:
GaussMethod(n, A, b, x);
break;
case 2:
DoolittleMethod(n, A, b, x);
break;
default:
printf("Invalid Argument.\n");
exit(1);
}
ReadFromInput(n, A, b, 0);
CalculateError(n, A, x, b);
return 0;
}
Result
Example 1
Using Gaussian Method:
$ g++ DecompositionMethod.cpp -o De.out $ ./De.out Matrix A: 0.11110.12500.14290.16670.2000 0.12500.14290.16670.20000.2500 0.14290.16670.20000.25000.3333 0.16670.20000.25000.33330.5000 0.20000.25000.33330.50001.0000 Vector b: 1.00001.00001.00001.00001.0000
Matrix After Elimination: 0.20000.25000.33330.50001.0000 0.0000-0.0139-0.0423-0.1111-0.3556 0.00000.0000-0.0024-0.0167-0.1200 0.00000.0000-0.00000.00080.0152 0.00000.00000.00000.0000-0.0007 Vector After Elimination: 1.00000.4444-0.1000-0.0190-0.0036 The solution is: 629.9978 -1119.9957 629.9972 -119.9994 5.0000
The Error Vector is: -0.0000-0.00000.0000-0.0000-0.0000 Error = 0.000000000000
Using Doolittle Method:
$ g++ DecompositionMethod.cpp -o De.out $ ./De.out Matrix A: 0.11110.12500.14290.16670.2000 0.12500.14290.16670.20000.2500 0.14290.16670.20000.25000.3333 0.16670.20000.25000.33330.5000 0.20000.25000.33330.50001.0000 Vector b: 1.00001.00001.00001.00001.0000
L: 1.00000.00000.00000.00000.0000 1.12501.00000.00000.00000.0000 1.28572.66671.00000.00000.0000 1.50005.60005.25001.00000.0000 1.800011.200021.000012.00001.0000 U: 0.11110.12500.14290.16670.2000 0.00000.00220.00600.01250.0250 0.00000.00000.00050.00240.0095 0.00000.00000.00000.00080.0100 0.00000.00000.00000.00000.0400 x: 629.9978 -1119.9957 629.9972 -119.9994 5.0000 The Error Vector is: -0.00000.0000-0.0000-0.00000.0000 Error = 0.000000000000
We don’t have much error here…thanks to the double precision floating point type.
Example 2
Using Gaussian Method:
$ g++ DecompositionMethod.cpp -o De.out $ ./De.out Matrix A: 7.20002.3000-4.40000.5000 1.30006.3000-3.50002.8000 5.60000.90008.1000-1.3000 1.50000.40003.70005.9000 Vector b: 15.10001.800016.600036.9000
Matrix After Elimination: 7.20002.3000-4.40000.5000 0.00005.8847-2.70562.7097 0.00000.000011.1135-1.2796 0.00000.00000.00006.3596 Vector After Elimination: 15.1000-0.92644.715631.7982 The solution is: 3.0000-2.00001.00005.0000 The Error Vector is: -0.0000-0.0000-0.00000.0000 Error = 0.000000000000
Using Doolittle Method:
$ g++ DecompositionMethod.cpp -o De.out $ ./De.out Matrix A: 7.20002.3000-4.40000.5000 1.30006.3000-3.50002.8000 5.60000.90008.1000-1.3000 1.50000.40003.70005.9000 Vector b: 15.10001.800016.600036.9000
L: 1.00000.00000.00000.0000 0.18061.00000.00000.0000 0.7778-0.15111.00000.0000 0.2083-0.01350.41211.0000 U: 7.20002.3000-4.40000.5000 0.00005.8847-2.70562.7097 0.00000.000011.1135-1.2796 0.00000.00000.00006.3596 x: 3.0000-2.00001.00005.0000 The Error Vector is: -0.0000-0.0000-0.00000.0000 Error = 0.000000000000
Summary
For the 1st example, when the true input are fractions, we still have some larger error because I use an file to input, and introduced function strtod. So I don’t even have a way to represent fractions as accurate as a double type - What I can do is just input more digits, as an approximate value.
Finally, in these two examples, our error is eliminated below $10^{-12}$. We can say our programs works well.
Lab3 - Inverse Power Method to Solve Eigenvalue
Description
Solve the minimal eigenvalue and its eigenvector of a given matrix.
Code
Note: Lab3 referenced the code through “Lab2.h”
/*
*
=
*
* Filename: Inverse-Power-Method.cpp
*
* Description: Use inverse power method to calculate the minimal eigenvalue.
*
* Version: 1.0
* Created: 04/08/2022 02:35:07 UTC
* Revision: none
* Compiler: gcc
*
* Author: CuSO4_Deposit
*
*
=
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include "../Lab2/Lab2.h"
using namespace std;
#define SUCCESS 0
#define FAILURE 1
#define INPUTPATH "./InputData.txt"
typedef int Status;
typedef double* Vector;
typedef double** Matrix;
Status Matrix_Multiplication(int A_m, int A_n, int B_m, int B_n, Matrix A, Matrix B, Matrix Result){
/*
*
= FUNCTION
* Name: Matrix_Multiplication
* Description: Calculate the multiplication of A and B. A has m rows and n cols.
*
=
*/
if(A_n != B_m){
printf("A and B can't multiply.\n");
return FAILURE;
}
for(int i = 0; i < A_m; i++){
for(int j = 0; j < B_n; j++){
Result[i][j] = 0;
for(int k = 0; k < A_n; k++)
Result[i][j] += A[i][k] * B[k][j];
}
}
return SUCCESS;
}
Status IPM_Iteration(int n, Matrix A, double& eigenvalue, Vector eigenvector){
/*
*
= FUNCTION
* Name: IPM_Iteration
* Description: Do the iteration of inverse power method to A.
*
=
*/
Vector x = new double[n];
//double value = sqrt(double(1) / n);
double value = 1;
for(int i = 0; i < n; i++)
x[i] = 1;
Vector x_prior = new double[n];
for(int i = 0; i < n; i++)
x_prior[i] = value;
Vector temp = new double[n];
for(int i = 0; i < n; i++)
temp[i] = 1;
Matrix L = new Vector[n];
for(int i = 0; i < n; i++)
L[i] = new double[n];
Matrix U = new Vector[n];
for(int i = 0; i < n; i++)
U[i] = new double[n];
LUDecomposition(n, A, L, U);
double error = 10;
double Max_prior = value;
double Max = 0;
int x_idx = 0;
int x_prior_idx = 0;
bool indexFlag = 0;
double eigenvalue_prior;
int iter_counter = 0;
while(error > pow(10, -5) indexFlag == 0){
printf("\n");
printf("Iteration #%d:\n", ++iter_counter);
LowerSolve(n, L, x_prior, temp); // Now temp is the temp vector to solve equation.
UpperSolve(n, U, temp, x); //
printf("x[%d] =\n", iter_counter);
PrintVector(n, x);
Max = x[0]; x_idx = 0;
for(int i = 1; i < n; i++) // Find max entry in x(not normalized)
if(x[i] > Max){
Max = x[i];
x_idx = i;
}
//error = abs(Max - Max_prior);
printf("Error = %lf.\n", error);
if(x_idx == x_prior_idx)
indexFlag = 1;
else indexFlag = 0;
for(int i = 0; i < n; i++) //* Update data (x -> x_prior)
x_prior[i] = x[i] / Max; //*
Max_prior = Max; x_prior_idx = x_idx; //*
printf("Y[%d] =\n", iter_counter);//*
PrintVector(n, x_prior);
eigenvalue_prior = eigenvalue;
eigenvalue = 1 / x[x_idx];
error = abs(eigenvalue - eigenvalue_prior);
printf("Estimated EV = %lf\n", eigenvalue);
}
for(int i = 0; i < n; i++)
eigenvector[i] = x_prior[i];
return SUCCESS;
}
int main(){
Matrix A = NULL;
int n = 0;
ReadFromInput(n, A, 1);
double EValue;
Vector EVector = new double[n];
IPM_Iteration(n, A, EValue, EVector);
printf("EigenValue = %lf\n", EValue);
printf("EigenVector:\n");
PrintVector(n, EVector);
return 0;
}
Result
Example 1
Raw Output:
$ ./Inverse-Power-Method.out Matrix A: 0.11110.12500.14290.16670.2000 0.12500.14290.16670.20000.2500 0.14290.16670.20000.25000.3333 0.16670.20000.25000.33330.5000 0.20000.25000.33330.50001.0000
Iteration #1: x[1] = 629.9978-1119.9957629.9972-119.99945.0000 Error = 10.000000. Y[1] = 1.0000-1.77781.0000-0.19050.0079 Estimated EV = 0.001587
Iteration #2: x[2] = 260004.0147-529506.9293348753.7531-80203.06204226.2173 Error = 0.001587. Y[2] = 0.7455-1.51831.0000-0.23000.0121 Estimated EV = 0.000003
Iteration #3: x[3] = 226394.6541-461628.5632304559.4849-70212.33383714.5607 Error = 0.001584. Y[3] = 0.7434-1.51571.0000-0.23050.0122 Estimated EV = 0.000003 EigenValue = 0.000003 EigenVector: 0.7434-1.51571.0000-0.23050.0122
Iteration # i
$X^{(i)}$
$Y^{(i)}$
$\lambda$
1
629.9978 -1119.9957 629.9972 -119.9994 5.0000
1.0000 -1.7778 1.0000 -0.1905 0.0079
0.001587
2
260004.0147 -529506.9293 348753.7531 -80203.0620 4226.2173
0.7455 -1.5183 1.0000 -0.2300 0.0121
0.000003
3
226394.6541 -461628.5632 304559.4849 -70212.3338 3714.5607
0.7434 -1.5157 1.0000 -0.2305 0.0122
0.000003
Iteration Process
Example 2
Raw Output:
$ ./Inverse-Power-Method.out Matrix A: 4.0000-1.00001.00003.0000 16.0000-2.0000-2.00005.0000 16.0000-3.0000-1.00007.0000 6.0000-4.00002.00009.0000
Iteration #1: x[1] = 0.00002.0000-0.00001.0000 Error = 10.000000. Y[1] = 0.00001.0000-0.00000.5000 Estimated EV = 0.500000
Iteration #2: x[2] = -0.62505.6250-2.37503.5000 Error = 0.500000. Y[2] = -0.11111.0000-0.42220.6222 Estimated EV = 0.177778
Iteration #3: x[3] = -0.93338.0778-3.43335.0444 Error = 0.322222. Y[3] = -0.11551.0000-0.42500.6245 Estimated EV = 0.123796
Iteration #4: x[4] = -0.93628.0899-3.44385.0543 Error = 0.053981. Y[4] = -0.11571.0000-0.42570.6248 Estimated EV = 0.123611
Iteration #5: x[5] = -0.93678.0938-3.44555.0568 Error = 0.000186. Y[5] = -0.11571.0000-0.42570.6248 Estimated EV = 0.123551
Iteration #6: x[6] = -0.93678.0939-3.44555.0568 Error = 0.000059. Y[6] = -0.11571.0000-0.42570.6248 Estimated EV = 0.123551 EigenValue = 0.123551 EigenVector: -0.11571.0000-0.42570.6248
Iteration # i
X^{(i)}
Y^{(i)}
$\lambda$
1
0.0000 2.0000 -0.0000 1.0000
0.0000 1.0000 -0.0000 0.5000
0.500000
2
-0.6250 5.6250 -2.3750 3.5000
-0.1111 1.0000 -0.4222 0.6222
0.177778
3
-0.9333 8.0778 -3.4333 5.0444
-0.1155 1.0000 -0.4250 0.6245
0.123796
4
-0.9362 8.0899 -3.4438 5.0543
-0.1157 1.0000 -0.4257 0.6248
0.123611
5
-0.9367 8.0938 -3.4455 5.0568
-0.1157 1.0000 -0.4257 0.6248
0.123551
6
-0.9367 8.0939 -3.4455 5.0568
-0.1157 1.0000 -0.4257 0.6248
0.123551
Iteration Process
Analysis
The smaller the minimal eigenvalue is, the faster the iteration converges. In example 1(iterated 3 times), eigenvalue is 0.000003, much smaller than 0.123 in ex2(iterated 6 times).
Lab4 - Jacobi Method to Solve Eigenvalue
Description
Solve all eigenvalues of a given matrix, using Jacobi method.
Code
Note: Lab4 referenced the code through “Lab2.h”, it’s code is here.
/*
*
=
*
* Filename: JacobiMethod.cpp
*
* Description: Solve n Eigenvalues of a given matrix.
*
* Version: 1.0
* Created: 04/25/2022 14:41:30 UTC
* Revision: none
* Compiler: gcc
* Author: CuSO4_Deposit
*
=
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include <ctime>
#include "..\Lab2\Lab2.h"
using namespace std;
#define SUCCESS 0
#define FAILURE 1
#define INPUTPATH "./InputData.txt"
Status GenerateRandomMatrix(int n, Matrix A){
/*
*
= FUNCTION
* Name: GenerateRandomMatrix
* Description: Generate a random symmetry matrix, where each entry ranges from 0 to 1.
*
=
*/
srand(time(0));
for(int i = 0; i < n; i++)
for(int j = i; j < n; j++){
A[i][j] = rand()%10001 / 10000.0;
A[j][i] = A[i][j];
}
return SUCCESS;
}
bool CheckSymmetry(int n, Matrix A){
/*
*
= FUNCTION
* Name: CheckSymmetry
* Description: if A is symmetry, return 1, otherwise return 0.
*
=
*/
for(int i = 0; i < n; i++){
for(int j = i + 1; j < n; j++){
if(A[i][j] != A[j][i])
return false;
}
}
return true;
}
double NonDiagSquareSum(int n, Matrix A){
/*
*
= FUNCTION
* Name: NonDiagSum
* Description: return the sum of non-diagonal entries' square of A.
*
=
*/
double Sum = 0;
for(int i = 0; i < n; i++)
for(int j = i + 1; j < n; j++)
Sum += A[i][j] * A[i][j];
return 2 * Sum;
}
Status JacobiMethod(int n, Matrix A, Vector EigenvalueVector, double ErrorController){
/*
*
= FUNCTION
* Name: JacobiMethod
* Description: Output the n eigenvalues via <EigenvalueVector>
*
=
*/
if(!CheckSymmetry(n, A)){
printf("The input matrix is not symmetry.\n");
return FAILURE;
}
int MaxEntry_i = 0; int MaxEntry_j = 0;
double MaxEntry = 0;
int LoopCounter = 0;
double s = 0; double t = 0;
double t1 = 0; double t2 = 0;
double c = 0; double d = 0;
double api = 0; double aqi = 0;
while(NonDiagSquareSum(n, A) > ErrorController){
MaxEntry = abs(A[0][1]); MaxEntry_i = 0; MaxEntry_j = 1;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++){
if(j == i) continue;
if(abs(A[i][j]) > MaxEntry){
MaxEntry_i = i;
MaxEntry_j = j;
MaxEntry = abs(A[i][j]);
}
}
s = (A[MaxEntry_j][MaxEntry_j] - A[MaxEntry_i][MaxEntry_i]) / (2 * A[MaxEntry_i][MaxEntry_j]);
t1 = -s - sqrt(s * s + 1); t2 = -t1 - 2 * s;
t = abs(t1) > abs(t2) ? t2 : t1;
if(s == 0) t = 1;
c = 1 / sqrt(1 + t * t); d = t * c;
for(int i = 0; i < n; i++){
if(i
MaxEntry_i i
MaxEntry_j)
continue;
api = A[i][MaxEntry_i]; aqi = A[i][MaxEntry_j];
A[i][MaxEntry_i] = c * api - d * aqi;
A[MaxEntry_i][i] = A[i][MaxEntry_i];
A[i][MaxEntry_j] = c * aqi + d * api;
A[MaxEntry_j][i] = A[i][MaxEntry_j];
}
A[MaxEntry_i][MaxEntry_i] -= t * A[MaxEntry_i][MaxEntry_j];
A[MaxEntry_j][MaxEntry_j] += t * A[MaxEntry_i][MaxEntry_j];
A[MaxEntry_i][MaxEntry_j] = 0;
A[MaxEntry_j][MaxEntry_i] = 0;
printf("Iteration #%d\n", ++LoopCounter);
printf("Non-Diagonal Entries' Square Sum = %lf.\n", NonDiagSquareSum(n, A));
PrintMatrix(n, A);
}
for(int i = 0; i < n; i++)
EigenvalueVector[i] = A[i][i];
printf("Eigenvalues:\n");
PrintVector(n, EigenvalueVector);
return SUCCESS;
}
int main(){
Matrix A = NULL;
int n = 0;
ReadFromInput(n, A, 1);
// GenerateRandomMatrix(n, A);
PrintMatrix(n, A);
Vector EigenvalueVector = new double[n];
JacobiMethod(n, A, EigenvalueVector, 0.000001);
return 0;
}
Result
Example 1
Raw Output:
$ ./JacobiMethod.o
Matrix A:
1.0000 2.0000 3.0000 4.0000
2.0000 5.0000 6.0000 7.0000
3.0000 6.0000 8.0000 9.0000
4.0000 7.0000 9.0000 10.0000
Iteration #1
Non-Diagonal Entries’ Square Sum = 228.000000.
1.0000 2.0000 -0.4323 4.9813
2.0000 5.0000 -0.1977 9.2174
-0.4323 -0.1977 -0.0554 0.0000
4.9813 9.2174 0.0000 18.0554
Iteration #2
Non-Diagonal Entries’ Square Sum = 58.078156.
1.0000 -0.5118 -0.4323 5.3433
-0.5118 0.2329 -0.1756 0.0000
-0.4323 -0.1756 -0.0554 -0.0908
5.3433 0.0000 -0.0908 22.8225
Iteration #3
Non-Diagonal Entries’ Square Sum = 0.975846.
-0.2381 -0.4986 -0.4006 0.0000
-0.4986 0.2329 -0.1756 -0.1155
-0.4006 -0.1756 -0.0554 -0.1861
0.0000 -0.1155 -0.1861 24.0606
Iteration #4
Non-Diagonal Entries’ Square Sum = 0.478622.
-0.5540 0.0000 -0.4324 -0.0618
0.0000 0.5488 0.0661 -0.0976
-0.4324 0.0661 -0.0554 -0.1861
-0.0618 -0.0976 -0.1861 24.0606
Iteration #5
Non-Diagonal Entries’ Square Sum = 0.104665.
-0.8038 0.0331 0.0000 -0.1466
0.0331 0.5488 0.0572 -0.0976
0.0000 0.0572 0.1944 -0.1302
-0.1466 -0.0976 -0.1302 24.0606
Iteration #6
Non-Diagonal Entries’ Square Sum = 0.061674.
-0.8047 0.0325 -0.0008 0.0000
0.0325 0.5488 0.0572 -0.0978
-0.0008 0.0572 0.1944 -0.1302
0.0000 -0.0978 -0.1302 24.0614
Iteration #7
Non-Diagonal Entries’ Square Sum = 0.027790.
-0.8047 0.0325 -0.0008 0.0000
0.0325 0.5488 0.0567 -0.0981
-0.0008 0.0567 0.1937 0.0000
0.0000 -0.0981 0.0000 24.0621
Iteration #8
Non-Diagonal Entries’ Square Sum = 0.008545.
-0.8047 0.0325 -0.0008 -0.0001
0.0325 0.5484 0.0567 0.0000
-0.0008 0.0567 0.1937 -0.0002
-0.0001 0.0000 -0.0002 24.0625
Iteration #9
Non-Diagonal Entries’ Square Sum = 0.002113.
-0.8047 0.0320 -0.0058 -0.0001
0.0320 0.5573 0.0000 -0.0000
-0.0058 0.0000 0.1849 -0.0002
-0.0001 -0.0000 -0.0002 24.0625
Iteration #10
Non-Diagonal Entries’ Square Sum = 0.000067.
-0.8055 0.0000 -0.0058 -0.0001
0.0000 0.5580 -0.0001 -0.0000
-0.0058 -0.0001 0.1849 -0.0002
-0.0001 -0.0000 -0.0002 24.0625
Iteration #11
Non-Diagonal Entries’ Square Sum = 0.000000.
-0.8055 -0.0000 0.0000 -0.0001
-0.0000 0.5580 -0.0001 -0.0000
0.0000 -0.0001 0.1849 -0.0002
-0.0001 -0.0000 -0.0002 24.0625
Eigenvalues:
-0.8055 0.5580 0.1849 24.0625
分析:
1. The sum of non-diagonal entries’ square shows a downward tendency。
2. Is the output correct?
(* Mathicscript: 4.0.0, Mathics 4.0.0 *)
In[1]:= A = {{1 - x,2,3,4},{2,5 - x,6,7},{3,6,8 - x,9},{4,7,9,10 - x}} Out[1]:= {{1 - x, 2, 3, 4}, {2, 5 - x, 6, 7}, {3, 6, 8 - x, 9}, {4, 7, 9, 10 - x}}
In[2]:= Solve[Det[A] == 0, x]
Out[2]:= {{x -> 6 + Sqrt[143 / 2 + 29 Sqrt[6]] + 5 Sqrt[6] / 2}, {x -> 6 - 5 Sqrt[6] / 2 - Sqrt[143 / 2 - 29 Sqrt[6]]}, {x -> 6 + Sqrt[143 / 2 - 29 Sqrt[6]] - 5 Sqrt[6] / 2}, {x -> 6 - Sqrt[143 / 2 + 29 Sqrt[6]] + 5 Sqrt[6] / 2}}
In[3]:= Solve[Det[A] == 0, x]//N
Out[3]:= {{x -> 24.0625}, {x -> -0.805485}, {x -> 0.558036}, {x -> 0.184914}}
So the program gives a correct output.
Lab 5 - Cubic Spline Interpolation
Description
Given function(or a point set), do a cubic spline interpolation. Require: at least 20 interpolation points, implement 2 boundary conditions and 3 interpolation method.
Code
Directory Tree
. ├── CubicSpline.md ├── Figure └── src ├── Arguments.txt ├── CubicSpline.py ├── FunctionSet.py ├── Lab5.cpp ├── Lab5.o └── __pycache__ └── FunctionSet.cpython-38.pyc
C code
/*
*
=
*
* Filename: Lab5.cpp
*
* Description:
*
* Version: 1.0
* Created: 05/11/2022 03:42:39 PM
* Revision: none
* Compiler: gcc
*
* Author: CuSO4_Deposit
*
*
=
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include <ctime>
using namespace std;
#define SUCCESS 0
#define FAILURE 1
#define INPUTPATH "./InputData.txt"
typedef int Status;
typedef double* Vector;
typedef double** Matrix;
typedef double Function;
Function f(double x){
double e = 2.718281828;
return (x + sin(2 * x)) / (1 + pow(e, -x));
}
Status PrintMatrix(int n, Matrix A){
/*
*
= FUNCTION
* Name: PrintMatrix
* Description: Print the Matrix A to the terminal. n is the Dimension of A.
*
=
*/
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
printf("%.4lf\t", A[i][j]);
}
printf("\n");
}
return SUCCESS;
}
Status PrintVector(int n, Vector v){
/*
*
= FUNCTION
* Name: PrintVector
* Description: Print the Vector v to the terminal(in row form). n is the Dimension of v.
*
=
*/
for(int i = 0; i < n; i++)
printf("%.4lf\t", v[i]);
printf("\n");
return SUCCESS;
}
Status ThomasSolve(int n, Matrix A, Vector x, Vector b){
/*
*
= FUNCTION
* Name: ThomasSolve
* Description: Solve Equation using Thomas Algorithm.
*
=
*/
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++){
if(j >= i - 1 && j <= i + 1 )
continue;
if(A[i][j] != 0){
printf("Matrix is invalid.\n A[%d][%d] = %lf.\n", i, j, A[i][j]);
return FAILURE;
}
}
Vector u = new double[n];
Vector v = new double[n];
Vector y = new double[n];
u[0] = A[0][0];
v[0] = A[0][1] / u[0];
y[0] = b[0] / u[0];
for(int k = 1; k < n - 1; k++){
u[k] = A[k][k] - A[k][k - 1] * v[k - 1];
v[k] = A[k][k + 1] / u[k];
y[k] = (b[k] - A[k][k - 1] * y[k - 1]) / u[k];
}
u[n - 1] = A[n - 1][n - 1] - A[n - 1][n - 2] * v[n - 2];
v[n - 1] = 0;
y[n - 1] = (b[n - 1] - A[n - 1][n - 2] * y[n - 2]) / u[n - 1];
x[n - 1] = y[n - 1];
for(int k = n - 2; k > -1; k--){
x[k] = y[k] - v[k] * x[k + 1];
}
return SUCCESS;
}
Status Sample(int n, double a, double b, Vector SamplePoints, int method){
/*
*
= FUNCTION
* Name: Sample
* Description: return a vector of SamplePoints.
*
=
*/
switch(method){
case 0:{
double h = (b - a) / n;
SamplePoints[0] = a;
for(int i = 1; i < n + 1; i++)
SamplePoints[i] = SamplePoints[i - 1] + h;
printf("SamplePoints:\n");
PrintVector(n + 1, SamplePoints);
break;
}
case 1:{
SamplePoints[0] = a;
SamplePoints[n] = b;
double randomNumber;
bool flag_moved;
for(int i = 1; i < n; i++){
randomNumber = a + (b - a) * (rand() / (RAND_MAX + 1.0));
flag_moved = 0;
for(int j = 0; j < i; j++){
if(SamplePoints[j] < randomNumber)
continue;
flag_moved = 1;
for(int k = i - 1; k >= j; k--){
SamplePoints[k + 1] = SamplePoints[k];
}
SamplePoints[j] = randomNumber;
break;
}
if(flag_moved == 0)
SamplePoints[i] = randomNumber;
}
break;
}
case 2:{
SamplePoints[0] = a;
SamplePoints[n] = b;
double Mid = (a + b) / 2;
if(n % 2) // n - 1 is odd
SamplePoints[n / 2] = Mid;
double randomNumber;
bool flag_moved;
for(int i = 1; i < n / 2.0; i++){
randomNumber = a + (Mid - a) * (rand() / (RAND_MAX + 1.0));
flag_moved = 0;
for(int j = 0; j < i; j++){
if(SamplePoints[j] < randomNumber)
continue;
flag_moved = 1;
for(int k = i - 1; k >= j; k--){
SamplePoints[k + 1] = SamplePoints[k];
}
SamplePoints[j] = randomNumber;
break;
}
if(flag_moved == 0)
SamplePoints[i] = randomNumber;
}
for(int i = n / 2 + 1; i < n; i++)
SamplePoints[i] = 2 * Mid - SamplePoints[n - i];
break;
}
default:
return FAILURE;
break;
}
return SUCCESS;
}
Status CubicSpline(Function f(double), double a, double b, int n, int Boundary, int SampleMethod){
/*
*
= FUNCTION
* Name: CubicSpline
* Description: Use Cubic Spline Method to interpolate function f.
* Parameter: 0, ..., n is the number of interpolation points.
* Condition = 0: Natrual Condition
*
=
*/
Matrix A = NULL;
ofstream ofs;
ofs.open("Arguments.txt", ios::out);
ofs << "[" << n << ", " << a << ", " << b << ", " << Boundary << ", " << SampleMethod << "]\n";
switch(Boundary){
case 0:{
A = new Vector[n - 1];
for(int i = 0; i < n - 1; i++){
A[i] = new double[n - 1];
}
for(int i = 0; i < n - 1; i++)
for(int j = 0; j < n - 1; j++)
A[i][j] = 0;
Vector SamplePoints = new double[n + 1];
Sample(n, a, b, SamplePoints, SampleMethod);
PrintVector(n + 1, SamplePoints);
Vector h = new double[n];
for(int i = 0; i < n; i++)
h[i] = SamplePoints[i + 1] - SamplePoints[i];
Vector d = new double[n - 1];
A[0][0] = 2;
A[0][1] = h[1] / (h[1] + h[0]);
d[0] = 6 * ((f(SamplePoints[2]) - f(SamplePoints[1])) / h[1] - (f(SamplePoints[1]) - f(SamplePoints[0])) / h[0]) / (h[1] + h[0]) - 0;
for(int i = 1; i < n - 2; i++){
A[i][i] = 2;
A[i][i + 1] = h[i + 1] / (h[i + 1] + h[i]);
A[i][i - 1] = 1 - A[i][i + 1];
d[i] = 6 * ((f(SamplePoints[i + 2]) - f(SamplePoints[i + 1])) / h[i + 1] - (f(SamplePoints[i + 1]) - f(SamplePoints[i + 0])) / h[i + 0]) / (h[i + 1] + h[i]);
}
A[n - 2][n - 2] = 2;
h[n - 1] = SamplePoints[n] - SamplePoints[n - 1];
A[n - 2][n - 3] = 1 - h[n - 1] / (h[n - 1] + h[n - 2]);
d[n - 2] = 6 * ((f(SamplePoints[n]) - f(SamplePoints[n - 1])) / h[n - 1] - (f(SamplePoints[n - 1]) - f(SamplePoints[n - 2])) / h[n - 2]) / (h[n - 1] + h[n - 2]);
Vector M = new double[n - 1];
ThomasSolve(n - 1, A, M, d);
printf("The Vector [x_0, ..., x_%d] is:\n[", n);
for(int i = 0; i < n; i++)
printf("%.4lf, ", SamplePoints[i]);
printf("%.4lf]\n", SamplePoints[n]);
printf("The Vector [h_0, ..., h_%d] is:\n[", n - 1);
for(int i = 0; i < n - 1; i++)
printf("%.4lf, ", h[i]);
printf("%.4lf]\n", h[n - 1]);
printf("The Vector [M_0, ..., M_%d] is:\n[%.4lf, ", n, 0.0);
for(int i = 0; i < n - 1; i++)
printf("%.4lf, ", M[i]);
printf("%.4lf]\n", 0.0);
ofs << "[";
for(int i = 0; i < n; i++)
ofs << SamplePoints[i] << ", ";
ofs << SamplePoints[n] << "]\n";
ofs << "[";
for(int i = 0; i < n - 1; i++)
ofs << h[i] << ", ";
ofs << h[n - 1] << "]\n";
ofs << "[0.0000, ";
for(int i = 0; i < n - 1; i++)
ofs << M[i] << ", ";
ofs << "0.0000]\n";
break;
}
case 1:{
double m0, mn;
printf("Please input f'(x_0), f'(x_n), seperated by space:\n");
cin >> m0 >> mn;
printf("\n");
A = new Vector[n + 1];
for(int i = 0; i < n + 1; i++){
A[i] = new double[n + 1];
}
for(int i = 0; i < n + 1; i++)
for(int j = 0; j < n + 1; j++)
A[i][j] = 0;
Vector SamplePoints = new double[n + 1];
Sample(n, a, b, SamplePoints, SampleMethod);
Vector h = new double[n];
for(int i = 0; i < n; i++)
h[i] = SamplePoints[i + 1] - SamplePoints[i];
Vector d = new double[n + 1];
A[0][0] = 2;
A[0][1] = 1;
d[0] = 6 * (((f(SamplePoints[1]) - f(SamplePoints[0])) / h[0]) - m0) / h[0];
for(int i = 1; i < n; i++){
A[i][i] = 2;
A[i][i + 1] = h[i] / (h[i] + h[i - 1]);
A[i][i - 1] = 1 - A[i][i + 1];
d[i] = 6 * ((f(SamplePoints[i + 1]) - f(SamplePoints[i])) / h[i] - (f(SamplePoints[i]) - f(SamplePoints[i - 1])) / h[i - 1]) / (h[i - 1] + h[i]);
}
A[n][n] = 2;
A[n][n - 1] = 1;
d[n] = 6 * (mn - (f(SamplePoints[n]) - f(SamplePoints[n - 1])) / h[n - 1]) / h[n - 1];
Vector M = new double[n + 1];
ThomasSolve(n + 1, A, M, d);
printf("The Vector [x_0, ..., x_%d] is:\n[", n);
for(int i = 0; i < n; i++)
printf("%.4lf, ", SamplePoints[i]);
printf("%.4lf]\n", SamplePoints[n]);
printf("The Vector [h_0, ..., h_%d] is:\n[", n - 1);
for(int i = 0; i < n - 1; i++)
printf("%.4lf, ", h[i]);
printf("%.4lf]\n", h[n - 1]);
printf("The Vector [M_0, ..., M_%d] is:\n[", n);
for(int i = 0; i < n; i++)
printf("%.4lf, ", M[i]);
printf("%.4lf]\n", M[n]);
ofs << "[";
for(int i = 0; i < n; i++)
ofs << SamplePoints[i] << ", ";
ofs << SamplePoints[n] << "]\n";
ofs << "[";
for(int i = 0; i < n - 1; i++)
ofs << h[i] << ", ";
ofs << h[n - 1] << "]\n";
ofs << "[";
for(int i = 0; i < n; i++)
ofs << M[i] << ", ";
ofs << M[n] << "]\n";
}
}
return SUCCESS;
}
int main(){
srand(time(0));
Matrix A = NULL;
Vector b = NULL;
CubicSpline(f, -2, 4, 25, 1, 2);
return 0;
}
python code
import numpy as np
import matplotlib.pyplot as plt
ArgumentsFile = open('Arguments.txt', 'r')
Arguments = ArgumentsFile.readlines()
n, a, b, Boundary, Sample = eval(Arguments[0])
x = np.array(eval(Arguments[1])).astype(float)
h = np.array(eval(Arguments[2])).astype(float)
M = np.array(eval(Arguments[3])).astype(float)
ArgumentsFile.close()
def truef(x):
return (x + np.sin(2 * x)) / (1 + (np.e) ** (-x))
y = truef(x)
FunctionFile = open('FunctionSet.py', 'w')
FunctionFile.write("def func(i, x):\n")
for i in range(25):
a0 = (-M[i + 1] * x[i] ** 3 + M[i] * x[i + 1] ** 3) / (6 * h[i]) + (-M[i] * x[i + 1] + M[i + 1] * x[i]) * h[i] / 6 + (x[i + 1] * y[i] - x[i] * y[i + 1]) / h[i]
a1 = (M[i + 1] * x[i] ** 2 - M[i] * x[i + 1] ** 2) / (2 * h[i]) + (M[i] - M[i + 1]) * h[i] / 6 + (y[i + 1] - y[i]) / h[i]
a2 = (M[i] * x[i + 1] - M[i + 1] * x[i]) / (2 * h[i])
a3 = (M[i + 1] - M[i]) / (6 * h[i])
FunctionFile.write(" if i == {}:\n".format(i))
#FunctionFile.write(" return", a0, "+ (", a1, ") * x + (", a2, ") * x ** 2 + (", a3, ") * x ** 3")
FunctionFile.write(" return " + str(a0) + " + (" + str(a1) + ") * x + (" + str(a2) + ") * x ** 2 + (" + str(a3) + ") * x ** 3\n")
FunctionFile.close()
from FunctionSet import func as f
plt.figure()
for i in range(n):
xi = np.linspace(x[i], x[i + 1], 15)
yi = f(i, xi)
plt.plot(xi, yi, color='blue')
plt.scatter(x, y, color='red', marker='x')
xtrue = np.linspace(a ,b)
plt.plot(xtrue, truef(xtrue), color='orange', alpha=0.7)
name = "Ex1Bdr" + str(Boundary) + "Sp" + str(Sample)
plt.title(name)
plt.savefig("../Figure/" + name + ".png")
plt.show()
In the python program, the expanded form of interpolation function is calculated by mathics/mathematica:
In[1]:= Collect[(Ma (b - x)^3 + Mb (x - a)^3) / (6 h) + ((b - x) ya + (x - a) yb) / h - (h / 6) ((b - x) Ma + (x - a) Mb), x]
Out[1]:= Ma b ^ 3 / (6 h) - Ma b h / 6 - Mb a ^ 3 / (6 h) + Mb a h / 6 - a yb / h + b ya / h + x (-Ma b ^ 2 / (2 h) + Ma h / 6 + Mb a ^ 2 / (2 h) - Mb h / 6 - ya / h + yb / h) + x ^ 2 (Ma b / (2 h) - Mb a / (2 h)) + x ^ 3 (-Ma / (6 h) + Mb / (6 h))
Result
$f(x) = \dfrac{x}{x ^ 2 + x + 1}$
$f(x) = \dfrac{x + \sin {2x}}{1 + e^{-x}}$
Lab 6 - FFT & IFFT
Code
/*
*
=
*
* Filename: FFT.cpp
*
* Description: Fast Fourier Transform Algorithm
*
* Version: 1.0
* Created: 05/29/2022 02:17:10 UTC
* Revision: none
* Compiler: gcc
*
* Author: CuSO4_Deposit
*
=
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include <ctime>
#include <complex>
#include <vector>
using namespace std;
#define SUCCESS 0
#define FAILURE 1
#define PI 3.1415926535
#define E 2.718281828
const complex<double>I(0, 1);
typedef int Status;
typedef vector<complex<double>> Vector;
typedef complex<double> Function;
Function F(double x){
return 0.7 * sin(4 * PI * x) + sin(10 * PI * x);
}
Status PrintVector(Vector v, int mode){
/*
*
= FUNCTION
* Name: PrintVector
* Description: Print the Vector v to the terminal(in row form). n is the Dimension of v.
*
=
*/
int n = v.size();
switch(mode){
case 0:
for(int i = 0; i < n; i++)
cout<< v[i] << " ";
break;
case 1:
for(int i = 0; i < n; i++)
cout<< v[i].real() << " ";
break;
case 2:
for(int i = 0; i < n; i++)
cout<< v[i].imag() << " ";
break;
default:
cout << "Invalid mode input." << endl;
}
printf("\n");
return SUCCESS;
}
Vector Sample(Function f(double), int Number){
/*
*
= FUNCTION
* Name: Sample
* Description: Sample Number points on interval[0, 1]
*
=
*/
if(Number & (Number - 1)){
cout << "Number must be the power of 2." << endl;
exit(1);
}
Vector fvector;
double stepsize = 1.0 / Number;
for(int i = 0; i < Number; i++){
fvector.push_back(f(i * stepsize));
}
return fvector;
}
Vector AddError(double size, Vector v){
/*
*
= FUNCTION
* Name: AddError
* Description: Add a error of [0, size) to v.
*
=
*/
int n = v.size();
cout << n;
Vector result(n);
for(int i = 0; i < n; i++)
result[i] = v[i] + size * (rand() / (RAND_MAX + 1.0));
return result;
}
Vector FFT(const Vector& f){
int n = f.size();
if(n == 1)
return f;
complex<double>wn;
wn = pow(E, - I * 2.0 * PI / (double)n);
complex<double>w(1, 0);
Vector f0, f1;
for(int i = 0; i < n / 2; i++){
f0.push_back(f[2 * i]);
f1.push_back(f[2 * i + 1]);
}
Vector g0, g1;
g0 = FFT(f0);
g1 = FFT(f1);
Vector g(n);
for(int k = 0; k < n / 2; k++){
g[k] = (g0[k] + w * g1[k]) / 2.0;
g[k + n / 2] = (g0[k] - w * g1[k]) / 2.0;
w = w * wn;
}
return g;
}
Vector IFFT(const Vector& f){
int n = f.size();
if(n == 1)
return f;
complex<double>wn;
wn = pow(E, I * 2.0 * PI / (double)n);
complex<double>w(1, 0);
Vector f0, f1;
for(int i = 0; i < n / 2; i++){
f0.push_back(f[2 * i]);
f1.push_back(f[2 * i + 1]);
}
Vector g0, g1;
g0 = IFFT(f0);
g1 = IFFT(f1);
Vector g(n);
for(int k = 0; k < n / 2; k++){
g[k] = (g0[k] + w * g1[k]);
g[k + n / 2] = (g0[k] - w * g1[k]);
w = w * wn;
}
return g;
}
Status PlotTime(Function F(double), int n){
/*
*
= FUNCTION
* Name: PlotTime
* Description: Output the code to plot F in python.
*
=
*/
ofstream ofs;
ofs.open("TimeParam.txt", ios::out);
ofs << "[";
for(int i = 0; i < n - 1; i++){
ofs << (double)i / n << ", ";
}
ofs << (double)(n - 1) / n << "]\n";
ofs << "[";
for(int i = 0; i < n - 1; i++){
ofs << F((double)i / n).real() << ", ";
}
ofs << F((double)(n - 1) / n).real() << "]\n";
return 0;
}
Status PlotFrequency(Vector g, int n){
/*
*
= FUNCTION
* Name: PlotFrequency
* Description: Visualize Fourier Transformation.
*
=
*/
ofstream ofs;
ofs.open("FrequencyParam.txt", ios::out);
ofs << "[";
for(int i = 0; i < n - 1; i++){
ofs << i << ", ";
}
ofs << n - 1 << "]\n";
ofs << "[";
for(int i = 0; i < n - 1; i++){
ofs << sqrt(g[i].real() * g[i].real() + g[i].imag() * g[i].imag()) << ", ";
}
ofs << sqrt(g[n - 1].real() * g[n - 1].real() + g[n - 1].imag() * g[n - 1].imag()) << "]\n";
return 0;
}
Status PlotTimeI(Vector g, int n, int mode){
/*
*
= FUNCTION
* Name: PlotFrequency
* Description: Visualize Fourier Transformation.
*
=
*/
ofstream ofs;
if(mode)
ofs.open("ITimeParam1.txt", ios::out);
else
ofs.open("ITimeParam0.txt", ios::out);
ofs << "[";
for(int i = 0; i < n - 1; i++){
ofs << i << ", ";
}
ofs << n - 1 << "]\n";
ofs << "[";
for(int i = 0; i < n - 1; i++){
ofs << g[i].real() << ", ";
}
ofs << g[n - 1].real() << "]\n";
return 0;
}
int main(){
srand(time(0));
Vector tempvector = Sample(F, 64);
Vector fvector = AddError(0.3, tempvector);
Vector gvector = FFT(fvector);
PrintVector(gvector, 1);
PrintVector(gvector, 2);
PlotTime(F, 64);
PlotFrequency(gvector, 64);
Vector igvector = IFFT(gvector);
PlotTimeI(igvector, 64, 0);
int n = gvector.size();
for(int i = 0; i < n; i++)
if(i > n / 8 && i < 3 * n / 8)
gvector[i] = (0, 0);
igvector = IFFT(gvector);
PlotTimeI(igvector, 64, 1);
return 0;
}
import numpy as np
import matplotlib.pyplot as plt
ArgumentsFile = open("./ITimeParam1.txt", 'r')
Arguments = ArgumentsFile.readlines()
x = np.array(eval(Arguments[0])).astype(float)
y = np.array(eval(Arguments[1])).astype(float)
plt.figure()
plt.plot(x, y)
name = "Ex2ITime1n7"
plt.title(name)
plt.savefig("../figure/" + name + ".png")
plt.show()
Lab7 - Romberg Integral
Code
/*
*
=
*
* Filename: Romberg.cpp
*
* Description: Implement Romberg Integral
*
* Version: 1.0
* Created: 06/14/2022 10:49:02 PM
* Revision: none
* Compiler: gcc
*
* Author: CuSO4_Deposit
*
*
=
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <math.h>
using namespace std;
#define SUCCESS 0
#define FAILURE 1
#define PI 3.1415926535
#define E 2.718281828
typedef int Status;
typedef double Function;
Function f(double x){
//return log(x);
return sqrt(2 - sin(x) * sin(x));
}
Status Romberg(Function f(double x), double a, double b, double& result, double AccControler, int MaxLoopNumber, int verbose){
/*
*
= FUNCTION
* Name: Romberg
* Description: return the Romberg integral of f on [a, b] through <result>,
* exit when loop <MaxLoopNumber> times or error < AccControler.
*
=
*/
double* RombergArray1 = new double[MaxLoopNumber + 1];
double* RombergArray2 = new double[MaxLoopNumber + 1];
double h = b - a;
RombergArray1[0] = (f(a) + f(b)) * h / 2;
if(verbose){
printf("%lf\n", RombergArray1[0]);
}
for(int k = 1; k < MaxLoopNumber; k++){
double sum = 0;
double hk = h / pow(2, k);
for(int i = 1; i < pow(2, k - 1) + 1; i++)
sum += f(a + (2 * i - 1) * hk);
RombergArray2[0] = (RombergArray1[0] + 2 * hk * sum) / 2;
for(int j = 1; j < k + 1; j++){
RombergArray2[j] = RombergArray2[j - 1] + (RombergArray2[j - 1] - RombergArray1[j - 1]) / (pow(4, j));
}
if(abs(RombergArray2[k] - RombergArray1[k - 1]) < AccControler){
result = RombergArray2[k];
return SUCCESS;
}
if(verbose){
for(int i = 0; i < k + 1; i++)
printf("%lf\t", RombergArray2[i]);
printf("\n");
}
for(int j = 0; j < k + 1; j++)
RombergArray1[j] = RombergArray2[j];
}
result = RombergArray2[MaxLoopNumber];
return SUCCESS;
}
int main(){
double result;
//Romberg(f, 1, 2, result, 0.000001, 20, 1);
Romberg(f, -PI / 6.0, 3.0 * PI / 4, result, 0.000001, 20, 1);
return 0;
}