Search this site
Embedded Files
Skip to main content
Skip to navigation
Cybernetics Laboratory
Home
Activities
Method
Theses
Themes
Cybernetics Laboratory
Home
Activities
Method
Theses
Themes
More
Home
Activities
Method
Theses
Themes
Guide of matrix1.c
Continued from the Guide for Basic Library matrix0.c
>
Back
>
matrix1.c
14. mat_t *mat_copy(mat_t *org, mat_t *mat)
機能
行列 org を行列 mat に複製します。 mat を初期化(mat_init)したあとでなければ使用できません。
使用例
次のプログラムは行列 A を行列 B に複製します。
#include "matrix1.c"
int main(void) {
mat_t A, B;
mat_init(&A); mat_set(&A, "1,2;3,4"); mat_print(&A); printf("\n");
mat_init(&B); mat_copy(&A, &B); mat_print(&B);
mat_free(&A); mat_free(&B);
return 0;
}
実行すると
(1, 1): 1.000000 (1, 2): 2.000000
(2, 1): 3.000000 (2, 2): 4.000000
(1, 1): 1.000000 (1, 2): 2.000000
(2, 1): 3.000000 (2, 2): 4.000000
が表示されます。 最初の行列は元の行列 A,二番目の行列は複製された行列 B です。
15. mat_t *mat_trans(mat_t *org, mat_t *mat)
機能
行列 org の転置を行列 mat に設定します。 mat を初期化(mat_init)したあとでなければ使用できません。
使用例
次のプログラムは行列 A の転置行列 B を求めます。
#include "matrix1.c"
int main(void) {
mat_t A, B;
mat_init(&A); mat_set(&A, "1,2,3;4,5,6"); mat_print(&A); printf("\n");
mat_init(&B); mat_trans(&A, &B); mat_print(&B);
mat_free(&A); mat_free(&B);
return 0;
}
実行すると
(1, 1): 1.000000 (1, 2): 2.000000 (1, 3): 3.000000
(2, 1): 4.000000 (2, 2): 5.000000 (2, 3): 6.000000
(1, 1): 1.000000 (1, 2): 4.000000
(2, 1): 2.000000 (2, 2): 5.000000
(3, 1): 3.000000 (3, 2): 6.000000
が表示されます。 行と列とが入れかわったことがわかります。
16. mat_t *mat_sprod(mat_t *org, double coef, mat_t *mat)
機能
行列 org のスカラー coef 倍を算出し,行列 mat に設定します。 mat を初期化(mat_init)したあとでなければ使用できません。
使用例
次のプログラムは,行列 A の 1.5 倍の行列 B を求めます。
#include "matrix1.c"
int main(void) {
mat_t A, B;
mat_init(&A); mat_set(&A, "1,2,3;4,5,6"); mat_print(&A); printf("\n");
mat_init(&B); mat_sprod(&A, 1.5, &B); mat_print(&B);
mat_free(&A); mat_free(&B);
return 0;
}
実行すると
(1, 1): 1.000000 (1, 2): 2.000000 (1, 3): 3.000000
(2, 1): 4.000000 (2, 2): 5.000000 (2, 3): 6.000000
(1, 1): 1.500000 (1, 2): 3.000000 (1, 3): 4.500000
(2, 1): 6.000000 (2, 2): 7.500000 (2, 3): 9.000000
が表示されます。 最初の行列における各要素が,二番目の行列では 1.5 倍になっています。
17. mat_t *mat_add(mat_t *frst, mat_t *scnd, mat_t *mat)
機能
行列 frst と行列 scnd の和を算出し,行列 mat に設定します。 mat を初期化(mat_init)したあとでなければ使用できません。
エラー
与えられた二つの行列の大きさが整合しないとき,*** DIM MISMATCH *** と表示して停止します。
使用例
次項 mat_sub の使用例参照。
18. mat_t *mat_sub(mat_t *frst, mat_t *scnd, mat_t *mat)
機能
行列 frst と行列 scnd の差を算出し,行列 mat に設定します。 mat を初期化(mat_init)したあとでなければ使用できません。
エラー
与えられた二つの行列の大きさが整合しないとき,*** DIM MISMATCH *** と表示して停止します。
使用例
次のプログラムは行列 A と行列 B を設定したのち,まず和行列 C を求め,次に C から B を引いた差行列 D を求めます。
#include "matrix1.c"
int main(void) {
mat_t A, B, C, D;
mat_init(&A); mat_init(&B); mat_init(&C); mat_init(&D);
printf("A =\n"); mat_set(&A, "1,2;3,4"); mat_print(&A);
printf("\nB =\n"); mat_set(&B, "5,6;7,8"); mat_print(&B);
printf("\nC = A + B =\n"); mat_add(&A, &B, &C); mat_print(&C);
printf("\nD = C - B =\n"); mat_sub(&C, &B, &D); mat_print(&D);
mat_free(&A); mat_free(&B); mat_free(&C); mat_free(&D);
return 0;
}
実行すると
A =
(1, 1): 1.000000 (1, 2): 2.000000
(2, 1): 3.000000 (2, 2): 4.000000
B =
(1, 1): 5.000000 (1, 2): 6.000000
(2, 1): 7.000000 (2, 2): 8.000000
C = A + B =
(1, 1): 6.000000 (1, 2): 8.000000
(2, 1): 10.000000 (2, 2): 12.000000
D = C - B =
(1, 1): 1.000000 (1, 2): 2.000000
(2, 1): 3.000000 (2, 2): 4.000000
が表示されます。 行列 D は,元の行列 A に間違いなく一致しています。
19. mat_t *mat_mul(mat_t *frst, mat_t *scnd, mat_t *mat)
機能
行列 frst と行列 scnd の積を算出し,行列 mat に設定します。 mat を初期化(mat_init)したあとでなければ使用できません。
エラー
与えられた二つの行列の大きさ(frst の列数と scnd の行数)が整合しないとき,*** DIM MISMATCH *** と表示して停止します。
使用例
次のプログラムは,2×3 行列 A と 3×2 行列 B を設定したのち積 C = AB を求めます。
#include "matrix1.c"
int main(void) {
mat_t A, B, C;
mat_init(&A); mat_init(&B); mat_init(&C);
printf("A =\n"); mat_set(&A, "1,2,3;4,5,-6"); mat_print(&A);
printf("\nB =\n"); mat_set(&B, "1,-2;3,-4;5,-6"); mat_print(&B);
printf("\nC = AB =\n"); mat_mul(&A, &B, &C); mat_print(&C);
mat_free(&A); mat_free(&B); mat_free(&C);
return 0;
}
実行すると
A =
(1, 1): 1.000000 (1, 2): 2.000000 (1, 3): 3.000000
(2, 1): 4.000000 (2, 2): 5.000000 (2, 3): -6.000000
B =
(1, 1): 1.000000 (1, 2): -2.000000
(2, 1): 3.000000 (2, 2): -4.000000
(3, 1): 5.000000 (3, 2): -6.000000
C = AB =
(1, 1): 22.000000 (1, 2): -28.000000
(2, 1): -11.000000 (2, 2): 8.000000
が表示されます。 積は 2×2 行列になりました。
20. mat_t *mat_minor(mat_t *org, int row, int col, mat_t *mat)
機能
2 行以上かつ 2 列以上の行列 org から第 row 行と第 col 列とを除去することによって得られる縮小行列を,行列 mat に設定します。 与えられた行列が 1 行か 1 列の場合,動作は保証されません。 mat を初期化(mat_init)したあとでなければ使用できません。
使用例
次のプログラムは,行列 A から第 2 行と第 3 列とを除去した縮小行列 B を求めます。
#include "matrix1.c"
int main(void) {
mat_t A, B;
mat_print(mat_set(mat_init(&A), "11,12,13,14;21,22,23,24;31,32,33,34"));
printf("\n");
mat_print(mat_minor(&A, 2, 3, mat_init(&B)));
mat_free(&A); mat_free(&B);
return 0;
}
実行すると
(1, 1): 11.000000 (1, 2): 12.000000 (1, 3): 13.000000 (1, 4): 14.000000
(2, 1): 21.000000 (2, 2): 22.000000 (2, 3): 23.000000 (2, 4): 24.000000
(3, 1): 31.000000 (3, 2): 32.000000 (3, 3): 33.000000 (3, 4): 34.000000
(1, 1): 11.000000 (1, 2): 12.000000 (1, 3): 14.000000
(2, 1): 31.000000 (2, 2): 32.000000 (2, 3): 34.000000
が表示されます。 3×4 行列が 2×3 行列に縮小されました。
21. double mat_det(mat_t *mat)
機能
1 次以上の正方行列 mat の行列式の値を出力します。 mat を初期化(mat_init)したあとでなければ使用できません。
補足
mat_det は詳しくは,2 次以上の正方行列 A = (aij) の行列式の計算を,det(A) = a1j⊿1j + a2j⊿2j + … + anj⊿nj(⊿ij は (i, j) 余因子)という事実を利用して再帰的に 1 次低い正方行列の行列式の計算に帰着させます。 最終的に帰着される 1 次正方行列 A = (a11) の行列式は,自明 det(A) = a11 です。
エラー
mat が正方行列ではないとき,*** NOT SQUARE *** と表示して停止します。
使用例
次のプログラムは,2 次正方行列 A の行列式と 3 次正方行列 B の行列式を求めます。
#include "matrix1.c"
int main(void) {
mat_t A, B;
mat_init(&A); mat_init(&B);
printf("A =\n"); mat_set(&A, "1,2;3,4"); mat_print(&A);
printf("\nB =\n"); mat_set(&B, "1,2,3;4,5,6;7,8,9"); mat_print(&B);
printf("\n");
printf("det(A) = %f\n", mat_det(&A));
printf("det(B) = %f\n", mat_det(&B));
mat_free(&A); mat_free(&B);
return 0;
}
実行すると
A =
(1, 1): 1.000000 (1, 2): 2.000000
(2, 1): 3.000000 (2, 2): 4.000000
B =
(1, 1): 1.000000 (1, 2): 2.000000 (1, 3): 3.000000
(2, 1): 4.000000 (2, 2): 5.000000 (2, 3): 6.000000
(3, 1): 7.000000 (3, 2): 8.000000 (3, 3): 9.000000
det(A) = -2.000000
det(B) = 0.000000
が表示されます。 行列 B の行列式は零となり,B は非正則(特異)であること,したがって逆行列 B-1 は存在しないことがわかります。
22. double mat_adjelem(mat_t *mat, int row, int col)
機能
2 次以上の正方行列 mat における (row, col) 余因子の値を出力します。 mat を初期化(mat_init)したあとでなければ使用できません。
使用例
次のプログラムは 3 次正方行列 A の (1, 2) 余因子を求めます。
#include "matrix1.c"
int main(void) {
mat_t A;
mat_print(mat_set(mat_init(&A), "1,2,3;4,5,6;7,8,9"));
printf("\n%f\n", mat_adjelem(&A, 1, 2));
mat_free(&A);
return 0;
}
実行すると
(1, 1): 1.000000 (1, 2): 2.000000 (1, 3): 3.000000
(2, 1): 4.000000 (2, 2): 5.000000 (2, 3): 6.000000
(3, 1): 7.000000 (3, 2): 8.000000 (3, 3): 9.000000
6.000000
が表示されます。 実際,(1, 2) 余因子は (4 * 9 - 6 * 7) * (-1)1+2 = 6 です。
23. mat_t *mat_adj(mat_t *org, mat_t *mat)
機能
2 次以上の正方行列 org の余因子行列(org の (j,i) 余因子を (i,j) 要素とする行列)を算出し,行列 mat に設定します。 mat を初期化(mat_init)したあとでなければ使用できません。
使用例
次のプログラムは 3 次正方行列 A の余因子行列 B を求めます。
#include "matrix1.c"
int main(void) {
mat_t A, B;
mat_init(&A); mat_init(&B);
printf("A =\n"); mat_set(&A, "2,3,3;1,2,2;6,3,6"); mat_print(&A);
printf("\nadj(A) =\n"); mat_adj(&A, &B); mat_print(&B);
mat_free(&A); mat_free(&B);
return 0;
}
実行すると
A =
(1, 1): 2.000000 (1, 2): 3.000000 (1, 3): 3.000000
(2, 1): 1.000000 (2, 2): 2.000000 (2, 3): 2.000000
(3, 1): 6.000000 (3, 2): 3.000000 (3, 3): 6.000000
adj(A) =
(1, 1): 6.000000 (1, 2): -9.000000 (1, 3): 0.000000
(2, 1): 6.000000 (2, 2): -6.000000 (2, 3): -1.000000
(3, 1): -9.000000 (3, 2): 12.000000 (3, 3): 1.000000
が表示されます。
24. double mat_inv(mat_t *org, mat_t *mat)
機能
1 次以上の正方行列 org の逆行列を算出し行列 mat に設定すると共に,行列式の値を出力します。 ただし,行列式が零のときは逆行列が存在せず mat は不定となります。 mat を初期化(mat_init)したあとでなければ使用できません。
補足1
行列式 org の絶対値が NEAR_ZERO(0.000005)未満のとき,行列式は零であると判断します。
使用例1
次のプログラムは 3 次正方行列 A の逆行列 B = A-1 を算出したのち,積 C = BA = A-1A が単位行列になることを確かめます。
#include "matrix1.c"
int main(void) {
double det;
mat_t A, B, C, D;
mat_init(&A); mat_init(&B); mat_init(&C); mat_init(&D);
printf("A =\n"); mat_set(&A, "2,3,3;1,2,2;6,3,6"); mat_print(&A);
if((det = mat_inv(&A, &B)) == 0) { printf("\n*** SINGULAR ***"); exit(1); }
printf("\ndet(A) = %f\n\nB = inv(A) =\n", det); mat_print(&B);
printf("\nC = BA =\n"); mat_mul(&A, &B, &C); mat_print(&C);
printf("\nD = Neat C =\n"); mat_attrac(&C, &D); mat_print(&D);
mat_free(&A); mat_free(&B); mat_free(&C); mat_free(&D);
return 0;
}
実行すると
A =
(1, 1): 2.000000 (1, 2): 3.000000 (1, 3): 3.000000
(2, 1): 1.000000 (2, 2): 2.000000 (2, 3): 2.000000
(3, 1): 6.000000 (3, 2): 3.000000 (3, 3): 6.000000
det(A) = 3.000000
B = inv(A) =
(1, 1): 2.000000 (1, 2): -3.000000 (1, 3): 0.000000
(2, 1): 2.000000 (2, 2): -2.000000 (2, 3): -0.333333
(3, 1): -3.000000 (3, 2): 4.000000 (3, 3): 0.333333
C = BA =
(1, 1): 1.000000 (1, 2): 0.000000 (1, 3): -0.000000
(2, 1): 0.000000 (2, 2): 1.000000 (2, 3): 0.000000
(3, 1): 0.000000 (3, 2): 0.000000 (3, 3): 1.000000
D = Neat C =
(1, 1): 1.000000 (1, 2): 0.000000 (1, 3): 0.000000
(2, 1): 0.000000 (2, 2): 1.000000 (2, 3): 0.000000
(3, 1): 0.000000 (3, 2): 0.000000 (3, 3): 1.000000
が表示されます。 変数の桁数は有限なので,積 C の各要素は必ずしも厳密な 0 や 1 になるとは限りません。 この障害を軽減するため C に mat_attrac を適用した結果が行列 D です。 確かに単位行列となっていることがわかります。
使用例2
別の行列 A を設定します。 使用例1 のプログラムとは,A の要素だけが異なります。
#include "matrix1.c"
int main(void) {
double det;
mat_t A, B, C, D;
mat_init(&A); mat_init(&B); mat_init(&C); mat_init(&D);
printf("A =\n"); mat_set(&A, "1,2,3;4,5,6;7,8,9"); mat_print(&A);
if((det = mat_inv(&A, &B)) == 0) { printf("\n*** SINGULAR ***"); exit(1); }
printf("\ndet(A) = %f\n\nB = inv(A) =\n", det); mat_print(&B);
printf("\nC = BA =\n"); mat_mul(&A, &B, &C); mat_print(&C);
printf("\nD = Neat C =\n"); mat_attrac(&C, &D); mat_print(&D);
mat_free(&A); mat_free(&B); mat_free(&C); mat_free(&D);
return 0;
}
実行すると
A =
(1, 1): 1.000000 (1, 2): 2.000000 (1, 3): 3.000000
(2, 1): 4.000000 (2, 2): 5.000000 (2, 3): 6.000000
(3, 1): 7.000000 (3, 2): 8.000000 (3, 3): 9.000000
*** SINGULAR ***
が表示されます。 この行列 A の行列式は零だからです(mat_det の使用例参照)。
補足2
mat_inv は,余因子行列を行列式で割ったもの(行列式の逆数にてスカラー倍したもの)が逆行列に等しいという事実を利用して逆行列を求めます。 計算の精度が良好な反面,計算複雑度が高いので,行列がある程度大きいとメモリスワップが頻繁に生じるなど,処理時間が極端に長くなる現象が現れます。
25. double mat_eq(mat_t *coef, mat_t *cons, mat_t *mat)
機能
係数行列を coef,定数行列を cons とする行列方程式を解き,解を行列 mat に設定すると共に,coef の行列式の値を出力します。 ただし,行列式が零のときは不能解であり mat の内容は不定となります。 mat を初期化(mat_init)したあとでなければ使用できません。
補足1
定数行列は 1 列でなければなりません。 また,係数行列の列数と定数行列の行数とは一致しなければなりません。
補足2
行列 coef の行列式の絶対値が NEAR_ZERO(0.000005)未満のとき,行列式を零と判断しています。
使用例
連立方程式
2 * x1 + 3 * x2 + 3 * x3 = 17
1 * x1 + 2 * x2 + 2 * x3 = 11
6 * x1 + 3 * x2 + 6 * x3 = 30
を解くため,次のプログラムは係数行列 A と定数行列 C を設定して行列方程式 AX = C の解 X = A-1C を求めます。
#include "matrix1.c"
int main(void) {
mat_t A, C, X;
mat_init(&A); mat_init(&C); mat_init(&X);
printf("A =\n"); mat_set(&A, "2,3,3;1,2,2;6,3,6"); mat_print(&A);
printf("\nC =\n"); mat_set(&C, "17;11;30"); mat_print(&C);
printf("\nX =\n"); mat_eq(&A, &C, &X); mat_print(&X);
mat_free(&A); mat_free(&C); mat_free(&X);
return 0;
}
実行すると
A =
(1, 1): 2.000000 (1, 2): 3.000000 (1, 3): 3.000000
(2, 1): 1.000000 (2, 2): 2.000000 (2, 3): 2.000000
(3, 1): 6.000000 (3, 2): 3.000000 (3, 3): 6.000000
C =
(1, 1): 17.000000
(2, 1): 11.000000
(3, 1): 30.000000
X =
(1, 1): 1.000000
(2, 1): 2.000000
(3, 1): 3.000000
が表示されます。 連立方程式の解は x1 = 1,x2 = 2,x3 = 3 であることがわかります。
26. int mat_govrow(mat_t *mat, int col, double *govcoef)
機能
行列 mat において,第 col 列の第 col 行以降の要素にのみ注目し,最も支配的な,すなわち,絶対値が最大の要素を govcoef に代入すると共に,その要素が第何行にあるかを出力します。
補足
mat の列数は行数以上でなければなりません。
エラー
col が 1 以上かつ行数以下でないとき,*** OUT OF DIM *** と表示して停止します。
使用例
次のプログラムは,まず 4×4 行列を設定して印刷したのち,col を 1 から 4 まで変化させつつ,第 col 列における支配的な要素と行を印刷します。
#include "matrix1.c"
int main(void) {
int i = 1;
double govcoef;
mat_t A;
mat_print(mat_set(mat_init(&A), "1,-4,30,200;4,-1,40,300;2,-2,20,400;3,-3,10,100"));
for(; i <= 4; i++) printf("\ncol = %d: govrow = %d", i, mat_govrow(&A, i, &govcoef));
mat_free(&A);
return 0;
}
実行すると
(1, 1): 1.000000 (1, 2): -4.000000 (1, 3): 30.000000 (1, 4): 200.000000
(2, 1): 4.000000 (2, 2): -1.000000 (2, 3): 40.000000 (2, 4): 300.000000
(3, 1): 2.000000 (3, 2): -2.000000 (3, 3): 20.000000 (3, 4): 400.000000
(4, 1): 3.000000 (4, 2): -3.000000 (4, 3): 10.000000 (4, 4): 100.000000
col = 1: govrow = 2
col = 2: govrow = 4
col = 3: govrow = 3
col = 4: govrow = 4
が表示されます。 実際,第 col = 1 列の第 col = 1 行以降の要素 1,4,2,3 にのみ注目すると,最も支配的な要素は 4 であり,その要素は第 govrow = 2 行にあります。 また,第 col = 2 列の第 col = 2 行以降の要素 -1,-2,-3 にのみ注目すると,最も支配的な要素は -3 であり,その要素は第 govrow = 4 行にあります。
>
Back
>
For Learning
>
Home
Google Sites
Report abuse
Google Sites
Report abuse