Calculating eigenvalues of an infinite banded matrix using LAPACK - c++

I'm new to C++ and am trying to figure out how to use LAPACK to find the eigenvalues of an infinite banded matrix (anharmonic oscillator problem). I know that I'm calculating the matrix correctly as I've checked the values and they all match up. However, I'm not sure if I'm passing the values to the subroutine correctly or if I've got something mixed up as the eigenvalues that are being returned are not what I am expecting. I'm using the dsbtrd subroutine to compute this. Here's the manual for that: http://www.netlib.org/lapack/explore-html/d0/d62/dsbtrd_8f.html
Any ideas on where I might be going wrong?
#include <iostream>
#include <algorithm>
#include <string>
#include <math.h>
using namespace std;
//SUBROUTINE DSBTRD( VECT, UPLO, N, KD, AB, LDAB, D, E, Q, LDQ, WORK, INFO )
extern "C" {
void dsbtrd_(const char *vect, const char *uplo, int *n, int *kd, double *ab, int *ldab, double d[], double e[], double *q, int *ldq, double work[], int *info);
}
#define MAX 14
int main(){
// Values needed for dsbtrd
const char *vect = "V";
const char *uplo = "U";
int n;
int ldab = MAX;
int ldq = MAX;
int info;
double ab[MAX][ldab];
double d[MAX];
double e[MAX];
double q[MAX][ldq];
double work[MAX];
//other values needed
int i,j,delta;
double eps;
double a[MAX][MAX];
double g[MAX][MAX];
//Read in value of eps and n
cout <<"Enter epsilon: \n";
cin >> eps;
cout << "Epsilon = " << eps << "\n";
cout <<"Enter n: \n";
cin >> n;
cout << "n = " << n << "\n";
if(n >= MAX){
cerr << "n is great than max \n";
}
//Build matrix g
for(j = 0; j < n; j++){
for(i = 0; i < n; i++){
int m = min(i,j);
if(i == j){
g[i][j] = 1.5*(pow(m,2) + m +.5);
}else if( i == j + 2 || i == j - 2){
g[i][j] = (m + 1.5)*sqrt((m+1)*(m+2));
}else if(i == j + 4 || i == j -4){
g[i][j] = .25*sqrt((m+1)*(m+2)*(m+3)*(m+4));
}else{
g[i][j] = 0;
}
}
}
//Build the starting matrix a
//row i, column j
for(j = 0; j < n; j++){
for(i = 0; i < n; i++){
if(i == j){
delta = 1;
}else{
delta = 0;
}
a[i][j] = (i + .5)*delta + eps*g[i][j];
}
}
//Build the matrix ab
// ab(kd+1+i-j,j) = a(i,j) for max(1,j-kd)<=i<=j
int kd = n - 1;
for(j = 1; j <= n; j++){
for(i = max(1,j-kd); i <= j; i++){
ab[j-1][kd+i-j] = a[j-1][i-1];
}
}
//Solve for eigenvalues
dsbtrd_(vect, uplo, &n, &kd, &ab[0][0], &ldab, d, e, &q[0][0], &ldq, work, &info);
//Check for success
if(info == 0)
{
//Write answer
for(i = 0; i < n; i++){
cout << "Eigenvalue " << i << ": " << d[i] << "\n";
}
}
else
{
//Write error
cerr << "dsbtrd returned error " << info << "\n";
}
return info;
}

DSBTRD doesn't calculate eigenvalues. It reduces the matrix to tridiagonal form; you're pulling out the main diagonal of the resulting tridiagonal matrix and pretending that those are the eigenvalues, but they aren't.
You need to call DSTERF (or one of a few other routines) on the resulting tridiagonal form to get the eigenvalues.
For more details, consult the LAPACK User's Guide.

Related

How do I dereference multidimensional vector pointer?

I'm stuck trying to get the value of what A[i][j] is pointing to. double a = A[i][j];. How do I correctly do it? Could someone please explain?
// g++ jacobi.cpp -O0 -o jacobi && ./jacobi
#include <iostream>
#include <iomanip>
#include <vector>
#include <climits>
using namespace std;
void print_matrix(vector<vector<double>>& m) {
for (int i = 0; i < m.size(); i++) {
for (int j = 0; j < m[0].size(); j++) {
cout << setw(5) << fixed << setprecision(2) << m[i][j] << " ";
}
cout << endl;
}
cout << "==================================" << endl;
}
// calculate average temperature based on average of adjacent cells
double avg_temp_at(vector<vector<double>>& matrix, int i, int j) {
return (
matrix[i][j] +
(j-1 >= 0 ? matrix[i][j-1] : 0) +
(i-1 >= 0 ? matrix[i-1][j] : 0) +
(j+1 < matrix[0].size() ? matrix[i][j+1] : 0) +
(i+1 < matrix.size() ? matrix[i+1][j] : 0)
) / 5;
}
// sequential Jacobi algorithm
vector<vector<double>> jacobi_relaxation(vector<vector<double>>& matrix, int& threshold) {
vector<vector<double>> B (matrix.size(), vector<double>(matrix[0].size(), 0));
vector<vector<double>>* A = &matrix;
double max_delta = INT_MAX;
while (max_delta > threshold) {
max_delta = 0;
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix[0].size(); j++) {
B[i][j] = avg_temp_at(*A, i, j);
double a = A[i][j];
double delta = abs(B[i][j] - a);
max_delta = max(max_delta, delta);
}
}
print_matrix(B);
A = &B;
}
return *A;
}
int main() {
int threshold = 1;
int n = 6;
vector<vector<double>> matrix (n, vector<double>(n, 0));
matrix[1][2] = 100;
matrix[2][2] = 100;
matrix[3][2] = 100;
print_matrix(matrix);
vector<vector<double>> x = jacobi_relaxation(matrix, threshold);
}
I tried your code and it gave me error on this line:
double a = A[i][j];
Change that line into this:
double a = (*A)[i][j];
and it will work.
Explanation:
It's basically the same trick as in line B[i][j] = avg_temp_at(*A, i, j);. A is a pointer, which is pointing to a vector. To accessing to pointers "real data" you must use the *.
Here you can find more info about pointers.
Hope it helps.

C++ Laplace expansion

I'm writing a program to find the determinant of a matrix n x n, using Laplace expansion.
Briefly, the program creates a two-dimensional array based on a user request. The users choose the size of the two-dimensional array and fills it in themselves. Next comes the computation of the matrix using Laplace.
The problem is that I can't use the resulting array values in the determinant function. I'm completely new to C ++, so any help would be welcome. The code shown below. Thanks
#include<iostream>
#include<iomanip>
#include<math.h>
using namespace std;
void fin(int**, int, int);
void fout(int**, int, int);
int main() {
int **board, n;
double alpha, beta;
cout << "Enter the number of rows and columns: ";
cin >> n;
cout << endl;
board = new int* [n];
for(int row = 0; row < n; row++)
board[row] = new int[n];
fin(board,n,n);
cout << endl;
fout(board,n,n);
cout << endl;
cout << "Determinant of the matrix is " << determinant(board, n);
cout << endl;
return 0;
}
void fin(int **p, int R, int C)
{
for(int row = 0; row < R; row++)
{
cout << "Enter " << C + 1 << " numbers for row number " << R + 1 << ": ";
for(int col = 0; col < C; col++)
cin >> p[row][col];
cout << endl;
}
}
void fout(int **p, int R, int C)
{
for(int row = 0; row < R; row++)
{
for(int col = 0; col < C; col++)
cout << setw(5) << p[row][col];
cout << endl;
}
}
int determinant( int **result, int n) {
int det = 0;
int submatrix[10][10];
if (n == 2)
return ((result[0][0] * result[1][1]) - (result[1][0] * result[0][1]));
else {
for (int x = 0; x < n; x++) {
int subi = 0;
for (int i = 1; i < n; i++) {
int subj = 0;
for (int j = 0; j < n; j++) {
if (j == x)
continue;
submatrix[subi][subj] = result[i][j];
subj++;
}
subi++;
}
det = det + (pow(-1, x) * result[0][x] * determinant( submatrix, n - 1 ));
}
}
return det;
}

Newton Interpolation in C++

I had to write Newton Interpolation in C++, but I have some problems...
In addition I had to use function which returns array and I couldn't use two-dimensional arrays.
It's my code:
#include <iostream>
using namespace std;
void interpol(double *, double *, int, int);
double *countDivide(double *y, double *x, int n);
int main()
{
int n;
cout << "Give ammount of nodes: " << endl;
cin >> n;
double arg;
double *x = new double[n];
double *y = new double[n];
for(int i = 0; i < n; i++)
{
cout << "x[" << i << "] = ";
cin >> x[i];
cout << "y[" << i << "] = ";
cin >> y[i];
}
cout << "Give arg: ";
cin >> arg;
double* b = countDivide(y, x, n);
interpol(b, x, n, arg);
return 0;
}
double *countDivide(double *y, double *x, int n)
{
int i, j;
double z;
for (i = 0; i < n; j++)
{
z = y[0];
for (j = 0 ; j > n - i; j++)
{
y[j] = (y[j] - y[j - 1]) / (x[i + j] - x[j]);
}
y[n - i] = z;
}
return y;
}
void interpol(double *p, double *x, int n, int arg)
{
double w;
double sum = 0;
int j, i;
for (i = n - 1; i >= 0; i--)
{
w = 1;
for (j = 0; j < i; j++)
w*= (arg - x[j]);
w *= p[j];
sum += w;
}
cout << sum << endl;
}
But program is stopping after
cin >> arg
What's wrong? I don't know what is wrong with that code, because I spent much time on it...
Thanks for your help.
This loop doesnt look right
for (i = 0; i < n; j++)

Least squares polynomial fitting works only with even number of coordinates

I've written a programme which calculates the equation of a parabola by giving a number of coordinates but it only works with an even number of coordinates. If I enter an uneven number it will display some nonsense bs.
Here is the code (I couldn't copy the code here because of some formatting problems):
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
int main()
{
int i, j, k, n, N;
n = 2;
cout << "Number of data pairs:" << endl;
cin >> N;
double * x = new double[N];
double * y = new double[N];
cout << endl << "Enter the x-axis values:" << endl;
for (i = 0; i<N; i++)
cin >> x[i];
cout << endl << "Enter the y-axis values:" << endl;
for (i = 0; i<N; i++)
cin >> y[i];
double X[5];
for (i = 0; i<2 * n + 1; i++)
{
X[i] = 0;
for (j = 0; j<N; j++)
X[i] = X[i] + pow(x[j], i);
}
double B[3][4], a[3]; //B is the Normal matrix(augmented) that will store the equations, 'a' is for value of the final coefficients
for (i = 0; i <= n; i++)
for (j = 0; j <= n; j++)
B[i][j] = X[i + j];
double Y[3];
for (i = 0; i<n + 1; i++)
{
Y[i] = 0;
for (j = 0; j<N; j++)
Y[i] = Y[i] + pow(x[j], i)*y[j];
}
for (i = 0; i <= n; i++)
B[i][n + 1] = Y[i];
n = n + 1;
for (i = 0; i < n; i++)
{
for (k = i + 1; k < n; k++)
if (B[i][i] < B[k][i])
for (j = 0; j <= n; j++)
{
double temp = B[i][j];
B[i][j] = B[k][j];
B[k][j] = temp;
}
}
for (i = 0; i<n - 1; i++) //loop to perform the gauss elimination
for (k = i + 1; k<n; k++)
{
double t = B[k][i] / B[i][i];
for (j = 0; j <= n; j++)
B[k][j] = B[k][j] - t*B[i][j]; //make the elements below the pivot elements equal to zero or elimnate the variables
}
for (i = n - 1; i >= 0; i--) //back-substitution
{
a[i] = B[i][n];
for (j = 0; j < n; j++)
if (j != i)
a[i] = a[i] - B[i][j] * a[j];
a[i] = a[i] / B[i][i];
}
cout << endl << "The equation is the following:" << endl;;
cout << a[2] << "x^2 + " << a[1] << "x + " << a[0];
cout << endl;
delete[]x;
delete[]y;
system("pause");
return 0;
}
The outputs I got from 3 and 4 coordinates:
3 coordinates:
Number of data points:
3
Enter the x-axis values:
1
2
3
Enter the y-axis values
1
4
9
The equation is the following:
1.02762e+47x^2 + -4.316e+47x + 3.90495e+47
4 coordinates:
Number of data points:
4
Enter the x-axis values:
1
2
3
4
Enter the y-axis values
1
4
9
16
The equation is the following:
1x^2 + -0x + 0
Any ideas or tips?
Thanks in advance
The comments already posted note that some of the indexing is out of bounds (exceeds the size of the matrix). I would prefer to input the x,y data as one pair of values per line, an x value and a y value, which is an easy change to make (cin >> x[i] >> y[i]), but the examples below use the sequence from the original question.
Example code for conventional method for quadratic equation fit:
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
int main()
{
int i, j, k, N;
cout << "Number of data pairs:" << endl;
cin >> N;
double * x = new double[N];
double * y = new double[N];
cout << endl << "Enter the x-axis values:" << endl;
for (i = 0; i<N; i++)
cin >> x[i];
cout << endl << "Enter the y-axis values:" << endl;
for (i = 0; i<N; i++)
cin >> y[i];
double B[3][4] = {0.0}; // generate augmented matrix
for(k = 0; k < 3; k++){
for (i = 0; i < N; i++) {
for (j = 0; j < 3; j++) {
B[k][j] += pow(x[i], j + k);}
B[k][3] += y[i]*pow(x[i], k);}}
for(k = 0; k < 3; k++){ // invert matrix
double q = B[k][k]; // divide row by B[k][k]
for(i = 0; i < 4; i++){
B[k][i] /= q;}
for(j = 0; j < 3; j++){ // zero out column B[][k]
if(j == k)
continue;
double m = B[j][k];
for(i = 0; i < 4; i++){
B[j][i] -= m*B[k][i];}}}
cout << endl << "The equation is the following:" << endl;;
cout << B[2][3] << " x^2 + " << B[1][3] << " x + " << B[0][3];
cout << endl;
delete[]x;
delete[]y;
system("pause");
return 0;
}
Example conventional code for generic degree equation:
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
int main()
{
int d, i, j, k, n;
cout << "Degree of equation:" << endl;
cin >> d;
double **A = new double *[d+1];
for (k = 0; k < d+1; k++) {
A[k] = new double[d+2];
for (i = 0; i < d+2; i++) {
A[k][i] = 0.0;}}
cout << "Number of data pairs:" << endl;
cin >> n;
double * x = new double[n];
double * y = new double[n];
cout << endl << "Enter the x-axis values:" << endl;
for (i = 0; i < n; i++)
cin >> x[i];
cout << endl << "Enter the y-axis values:" << endl;
for (i = 0; i < n; i++)
cin >> y[i];
for(k = 0; k < d+1; k++){
for (i = 0; i < n; i++) {
for (j = 0; j < d+1; j++) {
A[k][j] += pow(x[i], j + k);}
A[k][d+1] += y[i]*pow(x[i], k);}}
for(k = 0; k < d+1; k++){ // invert matrix
double q = A[k][k]; // divide A[k][] by A[k][k]
// if q == 0, would need to swap rows
for(i = 0; i < d+2; i++){
A[k][i] /= q;}
for(j = 0; j < d+1; j++){ // zero out column A[][k]
if(j == k)
continue;
double m = A[j][k];
for(i = 0; i < d+2; i++){
A[j][i] -= m*A[k][i];}}}
cout << endl << "The equation is the following:" << endl;
for(k = d; k >= 2; k--)
cout << A[k][d+1] << " x^" << k << " + ";
cout << A[1][d+1] << " x" << " + " << A[0][d+1] << endl;
for (k = 0; k < d+1; k++)
delete[] A[k];
delete[]A;
delete[]y;
delete[]x;
system("pause");
return 0;
}
Sample test input:
3
4
1
2
3
4
10
49
142
313
I normally use an alternative algorithm that avoids having to invert a matrix, which is better for higher order polynomials, but unneeded for a quadratic equation.
If interested in the alternative algorithm, here is a link to a pdf file that describes the algorithm and includes pseudo code. I have old working code, but it needs to be converted (it uses cgets() which is rarely supported anymore).
http://rcgldr.net/misc/opls.pdf
Example code. It's really old and originally ran on an Atari ST. I converted it to work with Visual Studio. The reason for all of the statics was to reduce the number of symbols that the linker would have to deal with.
/*------------------------------------------------------*/
/* fit4.c polynomial fit program */
/* originally written in 1990, minimal updates */
/*------------------------------------------------------*/
/* disable Visual Studio warnings for old functions */
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
/* mmax = max # coefficients */
/* nmax = max # points */
/* bfrsz = bfr size */
/* linsz = size of line bfr */
#define mmax 11
#define nmax 300
#define bfrsz 0x2000
#define linsz 64
static void polyf();
static void gcoef();
static void gvar();
static void calc();
static void calcx();
static void rdata();
static void gdata();
static int gtlin();
static char gtchr();
static int conrs();
static char cbfr[64]; /* console response bfr */
static char line[linsz];
static int lineno;
static char sbfr[bfrsz]; /* file params */
static FILE *sfp;
static char *sptr, *send;
static int gteof;
static int wf;
static int m, n; /* input values */
static double x[nmax];
static double y[nmax];
static double w[nmax];
static double b[mmax]; /* generated values */
static double A[mmax];
static double B[mmax];
static double L[mmax];
static double W[mmax];
static double p2[nmax];
static double p1[nmax];
static double p0[nmax];
static double c[mmax]; /* coefficients for y(x) */
static double z[nmax]; /* calculated y[] */
static double xi, zi, vr;
static double D0, D1; /* constants */
static double *pp2; /* pointers to logical p2, p1, p0 */
static double *pp1;
static double *pp0;
static double *ppx;
static double *px, *pf, *pw; /* for gdata */
main()
{
int i;
name0:
printf("\nEnter name of data file: "); /* get file name */
if(!conrs())
return(0);
sfp = fopen(&cbfr[2], "rb"); /* open file */
if(sfp == (FILE *)0){
printf("\nfile not found");
goto name0;}
wf = 0; /* ask for weighting */
printf("\nUsing weights (Y/N)? ");
if(!conrs())
return(0);
if('Y' == (cbfr[2]&0x5f))
wf = 1;
deg0:
printf("\nEnter degree of equation (1-n): "); /* get # terms */
if(!conrs())
return(0);
sscanf(&cbfr[2], "%d", &m);
if(m >= mmax)
goto deg0;
sptr = send = (char *)0;
gteof = 0;
lineno = 0;
gdata(); /* get data */
printf("\n%5d points found ", n);
polyf(); /* generate b[], A[], B[] */
gcoef(); /* generate coefficients */
gvar(); /* generate variance */
for(i = 0; i <= m; i++){
printf("\n%3d b%12.4le A%12.4le B%12.4le",
i, b[i], A[i], B[i]);
printf(" L%12.4le W%12.4le", L[i], W[i]);}
printf("\nvariance = %12.4le\n", vr);
for(i = m; i; i--)
printf("%12.4le X**%1d + ", c[i], i);
printf("%12.4le\n", c[0]);
for(i = 0; i < n; i++){ /* calculate results */
xi = x[i];
calc();
z[i] = zi;}
for(i = 0; i < n; i += 1) /* display results */
printf("\n%14.6le %14.6le %14.6le %14.6le",
x[i], y[i], z[i], y[i]-z[i]);
printf("\n");
return(0);
}
/*------------------------------------------------------*/
/* polyf poly fit */
/* in: x[], y[], w[], n, m */
/* out: b[], A[], B[], L[], W[] */
/*------------------------------------------------------*/
static void polyf()
{
int i, j;
D0 = (double)0.; /* init */
D1 = (double)1.;
pp2 = p2;
pp1 = p1;
pp0 = p0;
j = 0;
A[j] = D0; /* calc A, p[j], p[j-1], L, W */
L[j] = D0; /* note A[0] not used */
W[j] = D0;
for(i = 0; i < n; i++){
pp0[i] = D1;
pp1[i] = D0;
L[j] += w[i];
W[j] += w[i]*y[i];}
B[0] = D0;
b[j] = W[j]/L[j];
for(j = 1; j <= m; j++){
ppx = pp2; /* save old p[j], p[j-1] */
pp2 = pp1;
pp1 = pp0;
pp0 = ppx;
A[j] = D0; /* calc A */
for(i = 0; i < n; i++){
A[j] += w[i]*x[i]*pp1[i]*pp1[i]/L[j-1];}
L[j] = D0; /* calc p[j], L, W */
W[j] = D0;
for(i = 0; i < n; i++){
pp0[i] = (x[i]-A[j])*pp1[i]-B[j-1]*pp2[i];
L[j] += w[i]*pp0[i]*pp0[i];
W[j] += w[i]*y[i]*pp0[i];}
B[j] = L[j]/L[j-1]; /* calc B[], b[] */
b[j] = W[j]/L[j];}
}
/*------------------------------------------------------*/
/* gcoef generate coefficients */
/* in: b[], A[], B[] */
/* out: c[] */
/* uses: p0[], p1[], p2[] */
/*------------------------------------------------------*/
static void gcoef()
{
int i, j;
for(i = 0; i <= m; i++){ /* init */
c[i] = p2[i] = p1[i] = p0[i] = 0.;}
p0[0] = D1;
c[0] += b[0]*p0[0];
for(j = 1; j <= m; j++){ /* generate coefs */
p2[0] = p1[0];
p1[0] = p0[0];
p0[0] = -A[j]*p1[0]-B[j-1]*p2[0];
c[0] += b[j]*p0[0];
for(i = 1; i <= j; i++){
p2[i] = p1[i];
p1[i] = p0[i];
p0[i] = p1[i-1]-A[j]*p1[i]-B[j-1]*p2[i];
c[i] += b[j]*p0[i];}}
}
/*------------------------------------------------------*/
/* gvar generate variance */
/*------------------------------------------------------*/
static void gvar()
{
int i;
double tt;
vr = 0.;
for(i = 0; i < n; i++){
xi = x[i];
calc();
tt = y[i]-zi;
vr += tt*tt;}
vr /= n-m-1;
}
/*------------------------------------------------------*/
/* calc calc zi, given xi */
/* in: c[] */
/*------------------------------------------------------*/
static void calc ()
{
int i;
zi = c[m];
for(i = m-1; i >= 0; i--)
zi = zi*xi + c[i];
}
/*------------------------------------------------------*/
/* calcx calc zi, given xi */
/* in: b[], A[], B[] */
/*------------------------------------------------------*/
static void calcx()
{
int i;
double q2, q1, q0;
if(m == 0){
zi = b[0];
return;}
if(m == 1){
zi = b[0]+(xi-A[1])*b[1];
return;}
q1 = b[m];
q0 = b[m-1]+(xi-A[m])*q1;
for(i = m-2; i >= 0; i--){
q2 = q1;
q1 = q0;
q0 = b[i]+(xi-A[i+1])*q1-B[i+1]*q2;}
zi = q0;
}
/*------------------------------------------------------*/
/* gdata get data */
/*------------------------------------------------------*/
static void gdata()
{
px = &x[0];
pf = &y[0];
pw = &w[0];
while(1){
gtlin(); /* get a line */
if(gteof)
break;
if(lineno == nmax){
printf("\ntoo many points\n");
break;}
if(wf){ /* stuff values */
sscanf(line, "%le%le%le", px, pf, pw);}
else{
sscanf(line, "%le%le", px, pf);
*pw = 1.0;}
px++; /* bump ptrs */
pf++;
pw++;}
fclose(sfp); /* close file */
n = lineno; /* set # points */
}
/*------------------------------------------------------*/
/* gtlin get a line of data */
/*------------------------------------------------------*/
static int gtlin()
{
char chr;
int col;
col = 0;
while(1){
chr = gtchr();
switch(chr){
case 0x0a: /* line feed */
lineno++;
return(col);
case 0x1a:
return(col);
default:
line[col] = chr;
col++;
if(col >= linsz){
printf("line # %d too long\n%s",lineno, line);
return(col);}}}
}
/*------------------------------------------------------*/
/* gtchr get a char */
/*------------------------------------------------------*/
static char gtchr()
{
int cnt;
if(gteof) /* check for eof */
return(0x1a);
if(sptr == send){
if(!(cnt = (int) fread(sbfr, 1, bfrsz, sfp))){
fclose(sfp);
gteof = 1;
return(0x1a);}
sptr = sbfr;
send = sbfr+cnt;}
return(*sptr++);
}
/*------------------------------------------------------*/
/* conrs get string from console */
/*------------------------------------------------------*/
static int conrs()
{
int i;
memset(cbfr, 0, sizeof(cbfr)); /* get a line */
cbfr[0] = sizeof(cbfr)-2;
fgets(cbfr+2, sizeof(cbfr)-2, stdin);
cbfr[1] = (char)(strlen(&cbfr[2])-1);
i = cbfr[1];
cbfr[2+i] = 0;
return(i);
}
Example data file. I named it fitdat.txt:
1 1
2 4
3 9
Compile and run the program. Enter the name of the data file, then N when prompted for using weights, and then 2 for the degree of the equation to be generated. (If using weights, the first column would be the weighting factor, a weight of 2 would be the same has two instances of the same data point, but weights can be values like 1.5).
Here you are reading an uninitialized value a[j]:
for (i = n - 1; i >= 0; i--) //back-substitution
{
a[i] = B[i][n];
for (j = 0; j < n; j++)
if (j != i)
a[i] = a[i] - B[i][j] * a[j];
a[i] = a[i] / B[i][i];
}

Reading matrix from txt file to do Gaussian Elimination (C++)

So I'm trying to read a matrix A from a text file, which it does correctly. A vector B is entered by the user. Then I want to perform Gaussian Elimination (Ax = b) to get the solution vector x. The values I get for x are -1.#IND and I have no idea why...I'm guessing something is going wrong in SystemSolution?
#include <iostream>
#include <vector>
#include <iomanip>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
//this program does gaussian elimination for a matrix Ax=b
vector<double> SystemSolution(vector<vector<double>> A, vector<double> b)
{
//Determine and test size of a matrix
int n = A.size();
for (int i = 0; i < n; i++)
if (n != A[i].size())
throw "Error! Number of rows and columns of matrix must be equal!";
vector<double> x(b.size());
//x is the vector of solutions
for (int i = 0; i < n - 1; i++)
{
for (int j = i + 1; j < n; j++)
{
//Finding pivot
double pivot = A[i][i];
int index = i;
for (int k = i + 1; k < n; k++)
{
if (pivot > abs(A[k][i]))
{
index = k;
pivot = A[k][i];
}
}
//Row exchange
for (int k = 0; k < n; k++)
{
double tmp = A[i][k];
A[i][k] = A[index][k];
A[index][k] = tmp;
}
//Elimination
double coefficient = -(A[j][i] / A[i][i]);
for (int k = i; k < n; k++)
{
A[j][k] += coefficient*A[i][k];
}
b[j] += coefficient*b[i];
}
}
//Back-substitution
x[n - 1] = b[n - 1] / A[n - 1][n - 1];
for (int i = n - 2; i >= 0; i--)
{
double sum = 0;
for (int j = i; j < n; j++)
{
sum += x[j] * A[i][j];
}
x[i] = (b[i] - sum) / A[i][i];
}
return x;
}
void PrintVector(const vector<double> &b)
{
for (int i = 0; i < b.size(); i++)
cout << setiosflags(ios::showpoint | ios::fixed | ios::right)
<< setprecision(4)
<< setw(8) << b[i] << endl;
}
void PrintMatrix(const vector<vector<double> > &A)
{
for (int i = 0; i < A.size(); i++)
{
for (int j = 0; j < A[i].size(); j++)
cout << setiosflags(ios::showpoint | ios::fixed | ios::right)
<< setprecision(4)
<< setw(8) << A[i][j];
cout << endl;
}
}
int main()
{
int n;
cout << "Please enter the number of rows/columns:";
cin >> n;
ifstream matrixFile;
matrixFile.open("matrix.txt");
if (matrixFile.is_open()){
//matrix A values
vector<vector<double>> A(n, vector<double>(n));
vector<double> b(n);
string line;
int col = 0;
int row = 0;
while (getline(matrixFile, line)){
istringstream stream(line);
int x;
col = 0; //reset
while (stream >> x){
A[row][col] = x;
col++;
}
row++;
}
cout << "Please enter vector b:"<<endl;
//vector b values
for (int i = 0; i < row; i++)
{
cout << "b[" << i + 1 << "]= ";
cin >> b[i];
}
vector<double> x = SystemSolution(A, b);
cout << "- SOLUTIONS -" << endl;
cout << "Matrix:" << endl;
PrintMatrix(A);
cout << "\nVector x:" << endl;
PrintVector(x);
}
else{
cout << "File failed to open!";
}
matrixFile.close();
return 0;
}
There could be some divisions by zero in your code:
double coefficient = -(A[j][i] / A[i][i]);
/* .. */
x[n - 1] = b[n - 1] / A[n - 1][n - 1];
/* .. */
x[i] = (b[i] - sum) / A[i][i];
Check out Gauss-elimination here:
Square Matrix Inversion in C
Review and debug yours.