ソリューション・エクスプローラー構成
lu.h #ifndef LU_H #define LU_H #include "vector.h" #include "matrix.h" /** * @brief LU分解(A=LU) * @param[out] L 下三角行列 * @param[out] U 三角行列:対角成分は全て1 * @param[in] A LU分解対象行列 * @return 行列式 */ double lu_decomp(matrix* L, matrix* U, const matrix* A); /** * @brief LU分解を用いて連立方程式を解く * @param[out] x 解ベクトル * @param[in] L 三角行列 * @param[in] U 上三角行列:対角成分は全て1 * @param[in] b 右辺ベクトル */ void lu_solve(vector* x, const matrix* L, const matrix* U, const vector* b); #endif /* LU_H */ |
lu.c
#include "lu.h"
double lu_decomp(matrix* L, matrix* U, const matrix* A) {
int i, j, k;
int n = A->size1;
double det;
/* AをLにコピー */
matrix_copy(L, A);
det = 1.0;
for (i = 0; i < n; ++i) {
det *= L->val[i][i];
/* Lの計算 */
/* l_{j,i} = 0, (j=0,...,i-1) */
for (j = 0; j < i; ++j) {
L->val[j][i] = 0.0;
}
/* Uの計算 */
/* u_{i,j} = 0, (j=0,...,i-1) */
for (j = 0; j < i; ++j) {
U->val[i][j] = 0.0;
}
/* u_{i,i} = 1 */
U->val[i][i] = 1.0;
/* u_{i,j} = a_{i,j}/l_{i,i}, (j=i+1,...,n-1) */
for (j = i + 1; j < n; ++j) {
U->val[i][j] = L->val[i][j] / L->val[i][i];
}
/* Aの再計算 */
/* A-lu^T */
for (j = i + 1; j < n; ++j) {
for (k = i + 1; k < n; ++k) {
L->val[j][k] -= L->val[j][i] * U->val[i][k];
}
}
}
return det;
}
void lu_solve(vector* x, const matrix* L, const matrix* U, const vector* b) {
/* ここを実装せよ */
}
|
lu_test.c
#include <stdlib.h>
#include "vector.h"
#include "matrix.h"
#include "lu.h"
/**
* / 8 16 24 32 \
* A = | 2 7 12 17 |
* | 6 17 32 59 |
* \ 7 22 46 105 /
*
* / 160 \
* b = | 70 |
* | 198 |
* \ 291 /
* @param[out] A 係数行列
* @param[out] b 右辺ベクトル
*/
void set_equation1(matrix* A, vector* b) {
/* 行列サイズ指定 */
int N = 4;
/* 領域確保 */
matrix_new(N, N, A);
vector_new(N, b);
/* 係数行列要素指定 */
A->val[0][0] = 8;
A->val[0][1] = 16;
A->val[0][2] = 24;
A->val[0][3] = 32;
A->val[1][0] = 2;
A->val[1][1] = 7;
A->val[1][2] = 12;
A->val[1][3] = 17;
A->val[2][0] = 6;
A->val[2][1] = 17;
A->val[2][2] = 32;
A->val[2][3] = 59;
A->val[3][0] = 7;
A->val[3][1] = 22;
A->val[3][2] = 46;
A->val[3][3] = 105;
/* 右辺ベクトル要素指定 */
b->val[0] = 160;
b->val[1] = 70;
b->val[2] = 198;
b->val[3] = 291;
}
/**
* / 3 2 1 \
* A = | 2 4 3 |
* \ 1 3 5 /
*
* / 6 \
* b = | 10 |
* \ 12.5 /
* @param[out] A 係数行列
* @param[out] b 右辺ベクトル
*/
void set_equation2(matrix* A, vector* b) {
/* 行列サイズ指定 */
int N = 3;
/* 領域確保 */
matrix_new(N, N, A);
vector_new(N, b);
/* 係数行列要素指定 */
A->val[0][0] = 3;
A->val[0][1] = 2;
A->val[0][2] = 1;
A->val[1][0] = 2;
A->val[1][1] = 4;
A->val[1][2] = 3;
A->val[2][0] = 1;
A->val[2][1] = 3;
A->val[2][2] = 5;
/* 右辺ベクトル要素指定 */
b->val[0] = 6;
b->val[1] = 10;
b->val[2] = 12.5;
}
/**
* / 1 2 2 \
* A = | 3 6 2 |
* \ 1 1 1 /
*
* / 1 \
* b = | 7 |
* \ 5 /
* @param[out] A 係数行列
* @param[out] b 右辺ベクトル
*/
void set_equation3(matrix* A, vector* b) {
/* 行列サイズ指定 */
int N = 3;
/* 領域確保 */
matrix_new(N, N, A);
vector_new(N, b);
/* 係数行列要素指定 */
A->val[0][0] = 1;
A->val[0][1] = 2;
A->val[0][2] = 2;
A->val[1][0] = 3;
A->val[1][1] = 6;
A->val[1][2] = 2;
A->val[2][0] = 1;
A->val[2][1] = 1;
A->val[2][2] = 1;
/* 右辺ベクトル要素指定 */
b->val[0] = 1;
b->val[1] = 7;
b->val[2] = 5;
}
int main(void) {
int N; /* 行列サイズ */
double det; /* 行列式 */
matrix A; /* 係数行列 */
vector b; /* 右辺ベクトル */
matrix L; /* L */
matrix U; /* U */
vector x; /* 解ベクトル */
char sw[2]; /* 方程式切替スイッチ */
printf("input 1,2,3 ? ");
fgets(sw, sizeof (sw), stdin);
switch (atoi(sw)) {
case 1:
set_equation1(&A, &b);
break;
case 2:
set_equation2(&A, &b);
break;
case 3:
set_equation3(&A, &b);
break;
default:
return EXIT_FAILURE;
}
/* 行列サイズ指定 */
N = A.size1;
/* 領域確保 */
matrix_new(N, N, &L);
matrix_new(N, N, &U);
vector_new(N, &x);
/* 係数行列表示 */
printf("A =\n");
matrix_print(&A, "%f");
/* 右辺ベクトル表示 */
printf("b = ");
vector_print(&b, "%f");
/* LU分解 */
det = lu_decomp(&L, &U, &A);
/* LとUを表示 */
printf("L =\n");
matrix_print(&L, "%f");
printf("U =\n");
matrix_print(&U, "%f");
/* 行列式表示 */
printf("det = %3.0f\n", det);
/* LU分解を用いて連立方程式を解く */
lu_solve(&x, &L, &U, &b);
/* 解ベクトル表示 */
printf("x = ");
vector_print(&x, "%f");
/* 領域解放 */
matrix_delete(&A);
matrix_delete(&L);
matrix_delete(&U);
vector_delete(&b);
vector_delete(&x);
return EXIT_SUCCESS;
}
|
|
出力例
input 1,2,3 ? 1 A = [8.000000, 16.000000, 24.000000, 32.000000 2.000000, 7.000000, 12.000000, 17.000000 6.000000, 17.000000, 32.000000, 59.000000 7.000000, 22.000000, 46.000000, 105.000000] b = [160.000000, 70.000000, 198.000000, 291.000000] L = [8.000000, 0.000000, 0.000000, 0.000000 2.000000, 3.000000, 0.000000, 0.000000 6.000000, 5.000000, 4.000000, 0.000000 7.000000, 8.000000, 9.000000, 8.000000] U = [1.000000, 2.000000, 3.000000, 4.000000 0.000000, 1.000000, 2.000000, 3.000000 0.000000, 0.000000, 1.000000, 5.000000 0.000000, 0.000000, 0.000000, 1.000000] det = 768 x = [4.000000, 3.000000, 2.000000, 1.000000]