systemvue是一款專用的雷達,通信仿真軟件,其底層的封裝的模塊庫是用c++寫的。
聽博士哥哥說該軟件目前處於推廣階段,由於目前模塊庫匱乏,所以比較蛋疼,就在這蛋疼的時候,我導師接到了這塊燙手的山芋,然後更蛋疼的是,把這個寫庫的任務分給了我。。。。於是乎我又重拾C++大法,被迫暫停大數據比賽(我的穿衣搭配啊),全力轉到寫庫上面來。最近接到博士哥哥的一個任務,讓我寫一個矩陣求逆的模塊,給systemvue用。不管怎麼樣,寫起來再說。
#include <iostream>
.......
然後怎麼辦。。。
腦子裏面搜索着矩陣求逆的算法,想到以前本科老師講過有個克萊默算法,求矩陣的逆的,先求矩陣的行列式,然後按照公式套一下,這是第一種方法。然後想到了算法導論上面貌似有矩陣運算的討論,打開一開果然有。第28章都是關於矩陣運算的,有求解線性方程的問題,有矩陣求逆的問題,也有對稱正定矩陣和最小二乘逼近 。
上面講的大致算法是通過將矩陣求逆運算轉換成線性方程求解問題,比如求A矩陣的逆,AX=E,E爲單位陣,X(i)爲X的第i列,e(i)爲E的第i列,有A*X(i) = e(i)。X爲A的逆矩陣,寫到這些相信大家明白了,A的逆矩陣X即爲n個方程的解組成的,換句話說這n個解是X矩陣的列向量。至於怎麼求解線性方程組,算法導論提供了一種LUP分解的方法。
LUP分解:找三個n*n矩陣L,U和P,滿足PA=LU,P爲置換矩陣,講A = P(逆)LU,在求解Ax=b時,兩邊同乘以P,即得LUx=Pb,L爲下三角矩陣,U爲上三角矩陣,x可以通過簡單的循環過程求出。該算法的關鍵點在於找到LUP這三個矩陣。具體的矩陣求解過程在這裏就不詳細說明了,有興趣的同學可以在算法導論上仔細研讀。
下面貼下我的C++代碼。由於好久沒有寫過C++代碼了,所以寫的並不是很好,數組定義應該用vector容器,不應該定長,而且就算定長也不應該用魔數來寫,起碼定義const int 常量。這裏各位不要學不負責任的我,壞壞的說一句,要是輸入模塊的矩陣維數超過100的話,我的程序就要出錯了。。。。
類聲明:
#include <iostream>
#include <cstdio>
class Matrix{
public:
Matrix();
~Matrix();
int get_size() const;
void inverse();
void show() const;
void initialize();
void lupDecomposition(int (*p)[100], double (*left)[100], double (*up)[100]);
private:
double data[100][100];
int rowsize, colsize;
double* lupSolve(double (*left)[100], double (*up)[100], int *position, double *b);
};
類函數定義:
#include "Matrix.h"
Matrix::Matrix()
{
rowsize = 3;
colsize = 3;
for (int i = 0; i < rowsize; i++)
for (int j = 0; j < colsize; j++) {
data[i][j] = (i + j ) * j + 1;
}
}
Matrix::~Matrix()
{
}
void Matrix::initialize()
{
using namespace std;
int myrowsize = 0, mycolsize = 0;
cout << "input the size of Matrix (row, col) : " << endl;
cin >> myrowsize >> mycolsize;
rowsize = myrowsize;
colsize = mycolsize;
cout << "input the value of Matrix !" << endl;
for (int i = 0; i < myrowsize; i++)
for (int j = 0; j < mycolsize; j++) {
cin >> data[i][j];
}
}
void Matrix::show() const
{
printf("the rowsize is %d, the colsize is %d\n", rowsize, colsize);
for (int i = 0; i < rowsize; i++) {
for (int j = 0; j < colsize; j++)
printf("%f ", data[i][j]);
printf("\n");
}
}
int Matrix::get_size() const
{
return colsize;
}
void Matrix::lupDecomposition(int (*p)[100], double (*left)[100], double (*up)[100])
{
int n = get_size();
int position[100] = {0};
//初始化position數組
for (int i = 0; i < n; i++) {
position[i] = i;
}
//定義矩陣a, 並且賦值
double a[100][100] = {0};
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
a[i][j] = data[i][j];
for (int k = 0; k < n; k++) {
double max_row_data = -100000;
int max_row = k;
for (int i = k; i < n; i++) {
if (abs(a[i][k]) > max_row_data) {
max_row_data = abs(a[i][k]);
max_row = i;
}
}
if (max_row_data == 0) {
printf("this Matrix is singular!");
return;
}
int tmp = 0;
tmp = position[k];
position[k] = position[max_row];
position[max_row] = tmp;
for (int i = 0; i < n; i++) {
double tmp = 0;
tmp = a[k][i];
a[k][i] = a[max_row][i];
a[max_row][i] = tmp;
}
for (int i = k+1; i < n; i++) {
a[i][k] /= a[k][k];
for (int j = k+1; j < n; j++)
a[i][j] -= a[i][k]*a[k][j];
}
}
//給矩陣P賦值
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
if (j == position[i])
p[i][j] = 1;
else
p[i][j] = 0;
}
//給矩陣left賦值
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
if (i == j)
left[i][j] = 1;
else if (i > j)
left[i][j] = a[i][j];
else
left[i][j] = 0;
}
//給矩陣up賦值
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
if (i <= j)
up[i][j] = a[i][j];
else
up[i][j] = 0;
}
}
double* Matrix::lupSolve(double (*left)[100], double (*up)[100], int *position, double *b)
{
int n = get_size();
double x[100] = {0};
double y[100] = {0};
for (int i = 0; i < n; i++) {
double partSum = 0;
for (int j = 0; j <= i-1; j++)
partSum += left[i][j]*y[j];
y[i] = b[position[i]] - partSum;
}
for (int i = n-1; i >= 0; i--) {
double partSum = 0;
for (int j = i+1; j <= n-1; j++)
partSum += up[i][j] * x[j];
x[i] = (y[i] - partSum) / up[i][i];
}
return x;
}
void Matrix::inverse()
{
double left[100][100] = {{1, 0, 0}, {0.2, 1, 0}, {0.6, 0.5, 1}};
double up[100][100] = {{5, 6, 3}, {0, 0.8, -0.6}, {0, 0, 2.5}};
int position[100] = {2, 0, 1};
int p[100][100] = {0};
/*double *x;
x = lupSolve(left, up, position, b);
for (int i = 0; i < 3; i++)
printf("%f ", x[i]);*/
lupDecomposition(p, left, up);
//得到position,和得到單位矩陣額e[n][n]
int n = get_size();
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (p[i][j] == 1)
position[i] = j;
double e[100][100] = {0};
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (i == j)
e[i][j] = 1;
else
e[i][j] = 0;
//構造逆矩陣
double result[100][100] = {0};
for (int i = 0; i < n; i++) {
double *x = NULL;
x = lupSolve(left, up, position, e[i]);
for (int j = 0; j < n; j++)
result[j][i] = x[j];
}
//打印result數組
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
printf("%f ", result[i][j]);
printf("\n");
}
return;
}