ソリューション・エクスプローラー構成
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]