• 検索結果がありません。

H:\Projects2013\MatrixLibrary\MatrixLibrary\MatrixLibrary.cs /* ************************ * * * 行列関係のライブラリ * * * ************************ * * 行列の要素 A.V

N/A
N/A
Protected

Academic year: 2021

シェア "H:\Projects2013\MatrixLibrary\MatrixLibrary\MatrixLibrary.cs /* ************************ * * * 行列関係のライブラリ * * * ************************ * * 行列の要素 A.V"

Copied!
7
0
0

読み込み中.... (全文を見る)

全文

(1)

/* ************************ * * * 行列関係のライブラリ * * * ************************ * * ・行列の要素 A.Value[m, n] * ・n次単位行列(static) Matrix.Identity(n) * ・m×n型零行列(static) Matrix.Zero(m, n) * ・行列式(static) Matrix.Determinant(A) * ・逆行列 A.Inverse() * ・m行n列目を除いた小行列 A.SubMatrix(m, n) ただし、行、列の開始は0 * ・転置行列 A.Transpose() * * 以下は演算子のオーバーロード * ・型が同じで同じ要素を持つ行列の比較 == * ・型が同じで同じ要素を持つ行列の比較  != * ・行列の足し算 A + B * ・行列の引き算 A - B * ・行列の掛け算 A * B * ・スカラー倍 2 * A * ・スカラー倍 A * 2 * * クラス作成の方法

* ・行列の型を指定し、後から値を代入 var A = new Matrix(2, 3);

* A.Value = new decimal[2, 3] { { 1, 2, 3 }, { 4, 5, 6 } };

* ・値を代入しながら行列を作成 var A = new Matrix(new decimal[3, 3] { { 1, 0, 1 }, { 0, 1, 0 }, { 0, 0, 1 } }); * * 2014.2.17完成 * */ using System; using System.Text; namespace MatrixLibrary {

public class Matrix {

public decimal[,] Value;

private int rowLength, columnLength;

public Matrix(int m, int n) // 行列の型だけを指定するconstructor {

// m <= 0またはn <= 0の場合はエラーを返す if (m <= 0 || n <= 0)

(2)

rowLength = m; columnLength = n;

Value = new decimal[m, n]; // m×n型行列 }

public Matrix(decimal[,] elementValue) // 値を代入しながら行列を生成するconstructor {

rowLength = elementValue.GetLength(0); columnLength = elementValue.GetLength(1); Value = new decimal[rowLength, columnLength]; for (var r = 0; r < rowLength; r++)

for (var c = 0; c < columnLength; c++) Value[r, c] = elementValue[r, c]; }

// Override ToString()

public override string ToString() {

var val = new StringBuilder(); val.Clear();

for (var r = 0; r < rowLength; r++) {

for (var c = 0; c < columnLength; c++)

val.Append(Value[r, c].ToString() + " "); val.Append("\n"); } return val.ToString(); } // identity matrix

public static Matrix Identity(int n) // n次の単位行列を返す {

// n <=0 の場合はエラーを返す if (n <= 0)

throw new ArgumentException("単位行列の生成:作成される行列は行数、列数ともに正の整数でなくてはなりません"); var I = new Matrix(n, n);

for (var r = 0; r < n; r++) for (var c = 0; c < n; c++) I.Value[r, c] = 0; for (var r = 0; r < n; r++) I.Value[r, r] = 1; return I; } // zero matrix

(3)

{

// m <= 0またはn <= 0の場合はエラーを返す if (m <= 0 || n <= 0)

throw new ArgumentException("零行列の生成:作成される行列は行数、列数ともに正の整数でなくてはなりません"); var Z = new Matrix(m, n);

for (var r = 0; r < m; r++) for (var c = 0; c < n; c++) Z.Value[r, c] = 0; return Z; } // determinant

public static decimal Determinant(Matrix X) // 行列を第1列について展開し、行列式の値を求める {

// 正方行列でないとエラーを返す if (X.rowLength != X.columnLength)

throw new ArgumentException("行列式:正方行列でない行列では行列式を計算できません"); return determinantSub(X);

}

private static decimal determinantSub(Matrix X) {

var tmpMat = new Matrix(X.rowLength, X.columnLength); for (var r = 0; r < X.rowLength; r++)

for (var c = 0; c < X.columnLength; c++) tmpMat.Value[r, c] = X.Value[r, c];

if (tmpMat.rowLength == 1) // 1×1行列ならその値をそのまま返す return tmpMat.Value[0, 0];

else if (tmpMat.rowLength == 2) // 2×2行列になったら行列式の値を返す

return tmpMat.Value[0, 0] * tmpMat.Value[1, 1] - tmpMat.Value[0, 1] * tmpMat.Value[1, 0]; else if (tmpMat.rowLength == 3) // 3×3行列になったら行列式の値を返す

{

decimal det = 0;

det += tmpMat.Value[0, 0] * tmpMat.Value[1, 1] * tmpMat.Value[2, 2]; det += tmpMat.Value[0, 1] * tmpMat.Value[1, 2] * tmpMat.Value[2, 0]; det += tmpMat.Value[0, 2] * tmpMat.Value[1, 0] * tmpMat.Value[2, 1]; det -= tmpMat.Value[0, 2] * tmpMat.Value[1, 1] * tmpMat.Value[2, 0]; det -= tmpMat.Value[0, 1] * tmpMat.Value[1, 0] * tmpMat.Value[2, 2]; det -= tmpMat.Value[0, 0] * tmpMat.Value[1, 2] * tmpMat.Value[2, 1]; return det;

}

else // 第1列について展開 {

decimal det = 0;

(4)

if (tmpMat.Value[r, 0] != 0)

det += tmpMat.Value[r, 0] * determinantSub(tmpMat.SubMatrix(r, 0)) * (r % 2 == 0 ? 1 : (-1)); return det;

} }

// inverse

public Matrix Inverse() {

// 正方行列でないとエラーを返す if (rowLength != columnLength)

throw new ArgumentException("逆行列:正方行列でない行列では逆行列を計算できません"); if (Determinant(this) == 0)

throw new ArgumentException("逆行列:行列式の値が0の行列は逆行列を計算できません"); var result = new Matrix(rowLength, columnLength);

if (rowLength == 1)

result.Value[0, 0] = 1 / Value[0, 0]; else if (rowLength == 2)

{

decimal det = Determinant(this);

result.Value[0, 0] = Value[1, 1] / det; result.Value[0, 1] = -Value[0, 1] / det; result.Value[1, 0] = -Value[1, 0] / det; result.Value[1, 1] = Value[0, 0] / det; }

else {

decimal det = Determinant(this); for (var r = 0; r < rowLength; r++)

for (var c = 0; c < columnLength; c++)

result.Value[r, c] = cofactor(r, c) / det; }

return result; }

private decimal cofactor(int r, int c) // 余因子行列の行列式を返す {

return Determinant(SubMatrix(c, r) * ((c + r) % 2 == 0 ? 1 : (-1))); }

// row行目とcol列目を除いた小行列 ただし、最初の行は0行目、最初の列は0列目 public Matrix SubMatrix(int row, int col)

(5)

// rowが行列の行数を上回ったり、colが行列の列数を上回るとエラーを返す if (row >= rowLength || col >= columnLength)

throw new ArgumentException("小行列の作成:除くべき行、列番号がもとの行列の行数または列数を上回っています"); // row<0またはcol<0の場合はエラーを返す

if (row < 0 || col < 0)

throw new ArgumentException("小行列の作成:除くべき行、列番号は0以上である必要があります"); var result = new Matrix(rowLength - 1, columnLength - 1);

var rr = 0;

for (var r = 0; r < rowLength; r++) {

if (r != row) {

var cc = 0;

for (var c = 0; c < columnLength; c++) if (c != col) result.Value[rr, cc++] = Value[r, c]; rr++; } } return result; } // Transpose

public Matrix Transpose() {

var result = new Matrix(columnLength, rowLength); for (var r = 0; r < rowLength; r++)

for (var c = 0; c < columnLength; c++) result.Value[c, r] = Value[r, c]; return result;

}

// Overloading '==' operator

public static Boolean operator ==(Matrix A, Matrix B) // 行列の型が同じですべての要素の値がそれぞれ等しい時にtrue {

if (A.rowLength != B.rowLength) return false; if (A.columnLength != B.columnLength) return false; for (var r = 0; r < A.rowLength; r++)

for (var c = 0; c < A.columnLength; c++)

if (A.Value[r, c] != B.Value[r, c]) return false; return true;

(6)

// Overloading '!=' operator

public static Boolean operator !=(Matrix A, Matrix B) // 行列の型が異なったり、要素の値が1つでも異なるとfalse {

if (A.rowLength != B.rowLength) return true; if (A.columnLength != B.columnLength) return true; for (var r = 0; r < A.rowLength; r++)

for (var c = 0; c < A.columnLength; c++)

if (A.Value[r, c] != B.Value[r, c]) return true; return false;

}

// Overloading '+' operator

public static Matrix operator +(Matrix A, Matrix B) {

// AとBの型が異なるとエラーを返す

if (A.rowLength != B.rowLength || A.columnLength != B.columnLength)

throw new ArgumentException("行列の和:左の行列と右の行列の型が一致しません"); var result = new Matrix(A.rowLength, A.columnLength);

for (var r = 0; r < A.rowLength; r++)

for (var c = 0; c < A.columnLength; c++)

result.Value[r, c] = A.Value[r, c] + B.Value[r, c]; return result;

}

// Overloading '-' operator

public static Matrix operator -(Matrix A, Matrix B) {

// AとBの型が異なるとエラーを返す

if (A.rowLength != B.rowLength || A.columnLength != B.columnLength)

throw new ArgumentException("行列の差:左の行列と右の行列の型が一致しません"); var result = new Matrix(A.rowLength, A.columnLength);

for (var r = 0; r < A.rowLength; r++)

for (var c = 0; c < A.columnLength; c++)

result.Value[r, c] = A.Value[r, c] - B.Value[r, c]; return result;

}

// Overloading '*' operator

public static Matrix operator *(Matrix A, Matrix B) // 行列どうしの積 {

// Aの列数とBの行数が一致しないときにエラーを返す if (A.columnLength != B.rowLength)

(7)

var result = new Matrix(A.rowLength, B.columnLength); for (var r = 0; r < A.rowLength; r++)

for (var c = 0; c < B.columnLength; c++) {

result.Value[r, c] = 0;

for (var i = 0; i < A.columnLength; i++)

result.Value[r, c] += A.Value[r, i] * B.Value[i, c]; }

return result; }

// Overloading '*' operator

public static Matrix operator *(decimal d, Matrix A) // 行列のスカラー倍(スカラーは左から) {

var result = new Matrix(A.rowLength, A.columnLength); for (var r = 0; r < A.rowLength; r++)

for (var c = 0; c < A.columnLength; c++) result.Value[r, c] = d * A.Value[r, c]; return result;

}

// Overloading '*' operator

public static Matrix operator *(Matrix A, decimal d) // 行列のスカラー倍(スカラーは右から) {

var result = new Matrix(A.rowLength, A.columnLength); for (var r = 0; r < A.rowLength; r++)

for (var c = 0; c < A.columnLength; c++) result.Value[r, c] = d * A.Value[r, c]; return result;

} } }

参照

関連したドキュメント

[r]

[r]

I Samuel Fiorini, Serge Massar, Sebastian Pokutta, Hans Raj Tiwary, Ronald de Wolf: Exponential Lower Bounds for Polytopes in Combinatorial Optimization. Gerards: Compact systems for

と発話行為(バロール)の関係が,社会構造(システム)とその実践(行

処理対象水に海水由来の塩分が含まれており,腐食