UPDATE:这是解决方案,我在每一行添加了一个标量,以使下溢,溢出得到控制。感谢所有帮助人员。
我一直在研究c ++中的LU分解,希望有一天会分解并解决一个大的稀疏矩阵。我找到了一些代码并对其进行了修改以供我自己使用,但它不适用于大型矩阵。它适用于尺寸为5×5的矩阵。我需要它适用于尺寸为100乘100或更大的矩阵。我在mat-lab中检查了我的解决方案,我的代码给出了完全错误的结果。我觉得问题来自于我的代码中的划分,如果是这样,任何关于如何解决这个问题的建议将非常感激,任何帮助将不胜感激。
这是我的代码。
更新:
#include <algorithm>
// **
* END ***
/*
* LUDecomp.cpp
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <fstream>
#include <string.h>
#include <iomanip>
#include "LUDecomp.h"
using namespace std;
LUDecomp::LUDecomp()
{
}
void LUDecomp::h_pivot_decomp(int MAT1, double a[], int p[], int q[])
{
int i = 0, j = 0, k = 0;
int n = MAT1;
int pi = 0, pj = 0, tmp = 0;
double max = 0.0;
double ftmp = 0.0;
//Stores the scaling of each row or column.
double* vv = new double[MAT1 + 5];
//Loop over rows toget the implicit scaling information.
max = 0.0;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if ((ftmp = fabs(a(i,j))) > max)
{
max=ftmp;
}
}
//No nonzero largest element.
if (max == 0.0)
{
throw("Singular matrix in LUdcmp");
}
//Save the scaling.
vv[i]=1.0/max;
}
// The k element determines which pivot element you are in thereby
// determining the submatrix starting at the upper left corner of the matrix.
for (k = 0; k < n; k++)
{
// pi: stores row needing to be swapped.
// pj: stores column needing to be swapped.
// max: makes a zero element in the matrix into a very tiny number.
pi = -1, pj = -1, max = TINY;
//find pivot in submatrix a(k:n,k:n) by finding the absolute value of the biggest element.
for (i = k; i < n; i++)
{
for (j = k; j < n; j++)
{
//j = k;
ftmp = vv[i] * fabs(a(i,j));
// Decides if current max is bigger than current element.
if (ftmp>max)
{
max = ftmp;
// Index of row being swapped.
pi=i;
// Index of column being swapped.
pj=j;
}
}
}
{
// Stores the permutation of row swaps.
tmp = p[k];
p[k] = p[pi];
p[pi] = tmp;
}
//Swaps the scalling factor if needed.
if (k != pi)
{
vv[pi] = vv[k];
cout << "Scaling factor: " << vv[pi] << endl;
}
// Swaps the indicated rows to move the max pivot
// element of the submatrix k into place.
for (j = 0; j < n; j++)
{
// The k and pi index stays the same so the row
// number stays the same, the j changes to iterate threw the row.
ftmp = a(k,j);
a(k,j)=a(pi,j);
a(pi,j)=ftmp;
//cout << a(k,j) << " , " << a(pi,j) << endl;
}
{
// Stores the permutation of column swaps.
tmp = q[k];
q[k] = q[pj];
q[pj] = tmp;
//cout << q[k] << " , " << q[pj] << endl;
}
// Swaps the indicated columns to move the max pivot
// element of the submatrix k into place.
for (i = 0; i < n; i++)
{
// The k and pj index stays the same so the column
// number stays the same, the i changes to iterate threw the column.
ftmp = a(i,k);
a(i,k)=a(i,pj);
a(i,pj)=ftmp;
//cout << a(i,k) << " , " << a(i,pj) << endl;
}
// END PIVOT
cout << fixed << showpoint;
cout << setprecision(20);
// Check pivot size and decompose
if ((fabs(a(k,k))>TINY))
{
for (i=k+1;i<n;i++)
{
// Column normalisation, Does first element under pivot k row i.
ftmp=a(i,k)/=a(k,k);
cout << "k,k " <<a(k,k) << " , " << endl;
// Does the rest of row i.
for (j=k+1;j<n;j++)
{
//a(ik)*a(kj) subtracted from lower right submatrix elements
a(i,j)-=(ftmp*a(k,j));
//cout <<"i,j "<< a(i,j) << endl;
}
}
}
}
//END DECOMPOSE
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
cout << a(i,j)<<" ";
}
cout << endl;
}
}
void LUDecomp::h_solve(int MAT1, double a[], double x[], int p[], int q[])
{
// Forward substitution; see Golub, Van Loan 96
// And see http://www.cs.rutgers.edu/~richter/cs510/completePivoting.pdf
int i = 0, ii = 0, j = 0;
double ftmp = 0.0;
double* xtmp = new double[MAT1 + 5];
cout << fixed << showpoint;
cout << setprecision(4);
// Swap rows
// Put be vector back like it should be by using the permutations from the row swapping.
for (i = 0; i < MAT1; i++)
{
xtmp[i] = x[p[i]]; //value that should be here
//cout << xtmp[i] << endl;
}
// Ly=b
for (i = 0; i < MAT1; i++)
{
ftmp = xtmp[i];
if (ii != 0)
for (j = ii - 1; j < i; j++)
ftmp -= a(i,j)*xtmp[j];
else if (ftmp!=0.0)
ii=i+1;
xtmp[i] = ftmp;
//cout << xtmp[i] << endl;
}
// Backward substitution
// Partially taken from Sourcebook on Parallel Computing p577
// Solves Ux=y
cout << "xtmp " << xtmp[MAT1 - 1] << " a " << a(MAT1-1,MAT1-1)<< endl;
xtmp[MAT1 - 1] /= a(MAT1-1,MAT1-1);
//cout << xtmp[MAT1 - 1] << endl;
for (i = MAT1 - 2; i >= 0; i--)
{
ftmp = xtmp[i];
//cout << "ftmp " << ftmp << endl;
for (j = i + 1; j < MAT1; j++)
{
ftmp -= a(i,j)*xtmp[j];
//cout << "ftmp in "<<ftmp << endl;
}
xtmp[i] = (ftmp) / a(i,i);
}
// Last bit
// Swap columns
// Takes the final answer and puts it back into its proper order by
// using the permutations from the column swapping.
for (i = 0; i < MAT1; i++)
{
x[q[i]] = xtmp[i];
}
delete xtmp;
}
// Method to get output from the LU Decomposition.
void LUDecomp::output(unsigned int MAT1, double a[], double b[])
{
// Pivot array's for the permutation vectors.
int* p_pivot = new int[MAT1 + 5];
int* q_pivot = new int[MAT1 + 5];
// Sets the elements in the permutation vectors up to receive permutations.
// p_pivot is for row permutations and is initialized to {0,1,...,r};
// q_pivot is for column permutations and is initialized to {0,1,...,r};
for (unsigned int i = 0; i < MAT1; i++)
{
p_pivot[i] = i;
q_pivot[i] = i;
}
// Call to decomposition method passing (size,matrix to be decomposed, not used, not used).
h_pivot_decomp(MAT1, a, p_pivot, q_pivot);
// Call to solve passing (size, matrix in LU form, b vector, not used, not used).
h_solve(MAT1, a, b, p_pivot, q_pivot);
// Have solution.
// Used for file output.
ofstream outFile;
// Allow for appenending to a file already created.
outFile.open("outSolMatrix.txt");
// Sets the precision of the output to the file.
outFile << fixed << showpoint;
outFile << setprecision(4);
// Output results to file answer is {0,1,...,n}.
for (unsigned int i = 0; i < MAT1; i++)
{
outFile << i << " " << b[i] << endl;
}
outFile << "End" << endl;
delete p_pivot;
delete q_pivot;
outFile.close();
}
如果您需要查看,h文件就在这里。
#ifndef LUDECOMP_H_
#define LUDECOMP_H_
class LUDecomp {
public:
#define a(i,j) a[(i)*MAT1+(j)]
const static double TINY = 1e-20;
LUDecomp();
void h_pivot_decomp(int MAT1, float *a, int *p, int *q);
void h_solve(int MAT1, float *a, float *x, int *p, int *q);
void output(unsigned int MAT1, float *a, float *b);
private:
};
#endif /* LUDECOMP_H_ */
再次感谢,如果您需要查看其他任何内容,请与我们联系。
答案 0 :(得分:2)
尝试将float
替换为double
。浮点数不是很好的复杂计算类型,因为它非常小(只有4个字节),所以不精确(只有7-8位)。所以最好使用double(8字节,15-16位)。但是如果你需要更精确的计算,你必须使用另一个数据结构来表示值(比如在Matlab,Maple和其他系统中)。请参阅Arbitrary-precision arithmetic。