Power関数の働き・役割
Power関数は、正方行列を指定した整数の指数で累乗(数を繰り返し掛ける処理)するための関数です。
この関数を使用すると、行列を繰り返し乗算したり、逆行列(後程説明します)を計算した上で累乗を求めることができます。たとえば、元の行列を正の整数で累乗すると行列のべき乗が計算され、負の整数で累乗すると行列の逆数(逆行列)を使ったべき乗が計算されます。
行列の累乗や逆行列は、線形代数や物理シミュレーション、経済モデルの計算で広く使用されます。
正方行列とは
正方行列とは、行数と列数が同じであるような行列を指します。たとえば、2行2列や3行3列の行列が正方行列に該当します。具体的には以下のような形です。
2行2列の正方行列:
[[a, b],
[c, d]]
3行3列の正方行列:
[[a, b, c],
[d, e, f],
[g, h, i]]
正方行列は、行列の累乗や逆行列の計算を行う際に重要な性質を持っています。
逆行列とは
逆行列とは、ある行列に対して掛け算を行ったとき、単位行列(後程説明します)になる行列のことを指します。具体的には、行列Aに対して逆行列を A^{-1} とすると、以下が成り立ちます。
A × A^{-1} = 単位行列
これを具体例で確認します。
元の行列 とその逆行列A^{-1}
行列Aを次のように設定します。
A = [[4, 7],
[2, 6]]
行列式の計算 行列式 det(A) は次の公式で計算します。
det(A) = (a * d) - (b * c)
det(A) = (4 * 6) - (7 * 2)
= 24 - 14
= 10
逆行列の計算
次に、逆行列の公式を適用します。
A^{-1} = (1 / det(A)) * [[d, -b],
[-c, a]]
各値を代入すると、
A^{-1} = (1 / 10) * [[6, -7],
[-2, 4]]
= [[0.6, -0.7],
[-0.2, 0.4]]
逆行列の検証 A×A^{-1}= I を計算して確認します。
A = [[4, 7],
[2, 6]]
A^{-1} = [[0.6, -0.7],
[-0.2, 0.4]]
A × A^{-1} = [[(4*0.6 + 7*-0.2), (4*-0.7 + 7*0.4)],
[(2*0.6 + 6*-0.2), (2*-0.7 + 6*0.4)]]
= [[2.4 - 1.4, -2.8 + 2.8],
[1.2 - 1.2, -1.4 + 2.4]]
= [[1, 0],
[0, 1]]
結果として単位行列が得られました。
単位行列 I = [[1, 0],
[0, 1]]
このように、逆行列 A−1A^{-1} を掛けることで元の行列A は単位行列に変換されます。
単位行列とは
単位行列とは、すべての対角成分が1で、それ以外の成分が0である正方行列のことを指します。この行列は、行列の掛け算において中立的な役割を果たし、他の行列を変化させません。たとえば、行列A に対して単位行列 Iを掛けると次のようになります。
A × I = A
具体例として、2行2列の単位行列は次のようになります。
[[1, 0],
[0, 1]]
単位行列は、指数が0のときの結果として返され、行列計算の基礎的な存在です。
Power関数の引数について
matrix matrix::Power(
const int power // 乗
);
Power関数は、正方行列を累乗するために使用され、以下の引数を取ります。
第1引数: power
正の値を指定すると、元の行列がその指数回だけ掛け合わされます。たとえば、指数が3であれば行列を3回掛け算します。
負の値を指定すると、元の行列の逆行列を計算し、その逆行列が指定した回数だけ掛け合わされます。たとえば、指数が-2であれば逆行列を2回掛け算します。
指数が0の場合は、行列に依存せずに単位行列を返します。単位行列はすべての行列の掛け算で中立的な役割を果たすため、この挙動は行列計算の基本ルールを反映しています。
この引数は、累乗操作の挙動を制御するための重要なパラメータです。
Power関数の戻り値について
Power関数の戻り値は、累乗計算の結果として得られる正方行列です。この戻り値は、指定された指数と元の行列に基づいて次のように変化します。
戻り値の型
戻り値の内容
指数が正の値の場合
元の行列を指定された指数回掛け算した結果の行列が返されます。たとえば、指数が3の場合、元の行列を3回掛け合わせた結果が戻ります。
A^3 = A × A × A
指数が負の値の場合
元の行列の逆行列を計算し、その逆行列を指定された回数だけ掛け算した結果の行列が返されます。たとえば、指数が-2の場合、次のように計算されます。
A^(-2) = (A^(-1)) × (A^(-1))
このとき、元の行列が正則である必要があります。正則でない場合、逆行列が計算できずエラーになります。
※正則とは
指数が0の場合
単位行列が返されます。この単位行列は元の行列のサイズに合わせたものになります。単位行列は、行列計算において中立的な役割を果たします。
A^0 = I (単位行列)
戻り値の例
たとえば、次の行列A を考えます。
A = [[2, 1],
[1, 1]]
この行列に対してPower関数を適用した場合、以下の結果が得られます。
指数が3の場合
A.Power(3) = [[13, 8],
[8, 5]]
行列を3回掛け算します。これは A × A × A を計算することと同じです。
- 最初に A × A を計算します。各成分は次のように計算します。
- 1行1列目: (2 * 2) + (1 * 1) = 4 + 1 = 51行2列目: (2 * 1) + (1 * 1) = 2 + 1 =
- 32行1列目: (1 * 2) + (1 * 1) = 2 + 1 = 32行2列目: (1 * 1) + (1 * 1) = 1 + 1 = 2
[3, 2]] - 次に、この結果をさらに A と掛け算します。各成分は次のように計算します。
- 1行1列目: (5 * 2) + (3 * 1) = 10 + 3 = 131行2列目: (5 * 1) + (3 * 1) = 5 + 3 = 82行1列目: (3 * 2) + (2 * 1) = 6 + 2 = 82行2列目: (3 * 1) + (2 * 1) = 3 + 2 = 5
[8, 5]]
指数が負の値の場合
元の行列の逆行列を計算し、その逆行列を指定された回数だけ掛け算した結果の行列が返されます。たとえば、指数が-の場合、結果は次のようになります。
A.Power(-1) = [[1, -1],
[-1, 2]]
A⁻¹ = (1 / det(A)) × [[d, -b],
[-c, a]]
- 行列式 det(A) を計算します。det(A) = (2 * 1) – (1 * 1) = 2 – 1 = 1
- 逆行列を求めます。
- 1行1列目: 1 / 1 * 1 = 11行2列目: 1 / 1 * (-1) = -12行1列目: 1 / 1 * (-1) = -12行2列目: 1 / 1 * 2 = 2
A.Power(-1) = [[1, -1],
[-1, 2]]
指数が0の場合
A.Power(0) = [[1, 0], [0, 1]] (単位行列)
このように、Power関数は元の行列を累乗計算した結果を戻り値として返します。
Power関数を使ったサンプルコード
void OnStart()
{
// 行列を累乗する例を示すスクリプト
// 正方行列を定義します
// ここでは、2行2列の行列 i を作成しています。
// この行列は次のような形を持ちます:
// [[0, 1],
// [-1, 0]]
matrix i = {{0, 1},
{-1, 0}};
// 定義した行列 i をエキスパートログに出力します
// これにより、現在の行列の形を確認できます。
Print("元の行列 i:\n", i);
// 行列 i を3乗した結果を出力します
// 3乗とは、行列 i を3回掛け算することを意味します。
// 具体的には、次の計算が行われます:
// i × i × i
// 結果として、新しい行列が得られます。
Print("行列 i の3乗 (i.Power(3)):\n", i.Power(3));
// 行列 i を0乗した結果を出力します
// 0乗の場合、どの行列であっても単位行列が返されます。
// 単位行列とは、対角成分がすべて1で、それ以外が0の行列です。
// 例えば、次の形になります:
// [[1, 0],
// [0, 1]]
Print("行列 i の0乗 (i.Power(0)):\n", i.Power(0));
// 行列 i の -3 乗を計算して結果を出力します
// 負の乗数では、行列の逆行列を使って計算が行われます。
// 例えば、-3乗の場合は次の計算が行われます:
// i^(-3) = (i^(-1)) × (i^(-1)) × (i^(-1))
// このとき、行列 i が正則である(逆行列が存在する)必要があります。
Print("行列 i の -3乗 (i.Power(-3)):\n", i.Power(-3));
/*
以下は出力例です:
元の行列 i:
[[0, 1]
[-1, 0]]
行列 i の3乗 (i.Power(3)):
[[0, -1]
[1, 0]]
行列 i の0乗 (i.Power(0)):
[[1, 0]
[0, 1]]
行列 i の -3乗 (i.Power(-3)):
[[0, -1]
[1, 0]]
*/
}
サンプルコードの解説
以下は、Power関数を使って行列の累乗を計算し、その結果をエキスパートログに出力するスクリプトの解説です。
イベントハンドラー OnStart関数
このコードでは、スクリプトの開始時にOnStart関数が呼び出されます。OnStart関数は、スクリプトのエントリーポイントとして動作し、以下の手順を自動的に実行します。
行列の定義
最初に、行列i が定義されています。この行列は次の形を持っています。
i = [[0, 1],
[-1, 0]]
行列i は 2 行 2 列の正方行列です。この行列は定義した時点で、エキスパートログに出力されます。Print関数を使用して、行列の内容を確認できます。
行列の 3 乗計算
次に、行列i を 3 乗する操作が行われます。3乗は、行列i を 3 回掛け算することを意味します。具体的には次のような計算です。
i × i × i
この計算では行列の掛け算を繰り返します。計算過程は以下の通りです。
- i と i を掛け算します。 まず、行列の掛け算のルールに従って 1 回目の掛け算を行います。行列i を自分自身と掛けると次の結果が得られます。 計算式:
- 1 行 1 列目: (0*0) + (1*-1) = 0 – 1 = -11 行 2 列目: (0*1) + (1*0) = 0 + 0 = 02 行 1 列目: (-1*0) + (0*-1) = 0 + 0 = 02 行 2 列目: (-1*1) + (0*0) = -1 + 0 = -1
[[-1, 0], [ 0, -1]]
- 1 回目の結果と i をさらに掛け算します。 再び行列の掛け算を適用して次のように計算します。 計算式:
- 1 行 1 列目: (-1*0) + (0*-1) = 0 + 0 = 01 行 2 列目: (-1*1) + (0*0) = -1 + 0 = -12 行 1 列目: (0*0) + (-1*-1) = 0 + 1 = 12 行 2 列目: (0*1) + (-1*0) = 0 + 0 = 0
[[0, -1], [1, 0]]
この結果がエキスパートログに出力されます。
行列の 0 乗計算
次に、行列i の 0 乗が計算されます。指数が 0 の場合、結果は元の行列に関係なく単位行列となります。単位行列とは、次の形を持つ行列のことです。
[[1, 0],
[0, 1]]
単位行列は掛け算において中立的な役割を果たし、他の行列に影響を与えません。この結果もエキスパートログに出力されます。
行列の -3 乗計算
最後に、行列i の -3 乗が計算されます。負の指数の場合、元の行列の逆行列を計算し、その逆行列を繰り返し掛け算します。
まず、行列i の逆行列を求めます。 逆行列は次の形になります。
[[ 0, -1], [ 1, 0]]
次に、逆行列を 3 回掛け算します。 この計算は 3 乗の場合と同様に行われます。結果として、以下の行列が得られます。
[[0, -1], [1, 0]]
この結果もエキスパートログに出力されます。
結果の出力
すべての計算結果が Print 関数を使用してエキスパートログに出力されます。出力例は次の通りです。
元の行列 i:
[[0, 1],
[-1, 0]]
行列 i の3乗 (i.Power(3)):
[[0, -1],
[1, 0]]
行列 i の0乗 (i.Power(0)):
[[1, 0],
[0, 1]]
行列 i の -3乗 (i.Power(-3)):
[[0, -1],
[1, 0]]
補足:Power関数を使わずに行列の累乗計算をおこなう場合のサンプルコード
// 行列を累乗するカスタム関数
// この関数は、入力された行列 a を指定された指数 power で累乗し、結果を行列 c に格納します。
// 累乗計算には、行列の掛け算や逆行列の計算を使用します。
bool MatrixPower(matrix& c, const matrix& a, const int power)
{
//--- 行列 a が正方行列かどうかをチェックします。
// 正方行列とは、行数と列数が等しい行列のことです。
// 行数と列数が異なる場合、累乗は定義されないため、false を返します。
if(a.Rows() != a.Cols())
return(false);
//--- 入力行列 a の行数と列数を取得します。
// 行列の結果も同じサイズである必要があるため、これを記録します。
ulong rows = a.Rows(); // 行数
ulong cols = a.Cols(); // 列数
//--- 結果を格納する行列 result を初期化します。
// サイズは元の行列 a と同じになります。
matrix result(rows, cols);
//--- 指数が 0 の場合
// すべての行列に対して 0 乗の結果は単位行列になります。
// 単位行列は、すべての対角成分が 1、それ以外が 0 の特殊な正方行列です。
if(power == 0)
result.Identity(); // result に単位行列をセットします
else
{
//--- 指数が負の値の場合
// 負の指数は、元の行列の逆行列を累乗計算に使用します。
if(power < 0)
{
// 元の行列 a の逆行列を計算します。
// 逆行列が存在しない場合(行列が特異行列の場合)は計算に失敗します。
matrix inverted = a.Inv(); // a の逆行列
result = inverted; // 結果行列 result を逆行列で初期化
//--- 負の指数の絶対値分だけ掛け算を繰り返します。
// 例: power = -3 の場合、inverted × inverted × inverted を計算します。
for(int i = -1; i > power; i--) // i を -1 から power までデクリメント
result = result.MatMul(inverted); // result と inverted を掛け算
}
else
{
//--- 指数が正の値の場合
// 元の行列を正の指数分だけ掛け算します。
result = a; // 結果行列 result を元の行列 a で初期化
// 例: power = 3 の場合、a × a × a を計算します。
for(int i = 1; i < power; i++) // i を 1 から power までインクリメント
result = result.MatMul(a); // result と a を掛け算
}
}
//--- 計算結果を出力パラメータ c に格納します。
// result に計算結果が格納されているので、それを c にコピーします。
c = result;
//--- 計算が成功したことを示す true を返します。
return(true);
}
コードの解説
上記コードは、Power関数を使わずに行列の累乗計算をおこなうためのカスタム関数を定義しています。
この関数では、指定された行列を入力し、正の指数や負の指数、あるいはゼロの指数で累乗計算を行います。結果は出力引数に格納されます。
関数の概要
関数名は MatrixPower です。この関数は、入力行列と累乗の指数を受け取り、計算結果を出力変数に格納します。戻り値は計算が成功したかどうかを示す真偽値です。
戻り値
仮引数
- 第一引数の c
出力用の行列です。累乗の結果がこの行列に格納されます。関数の呼び出し元で利用できます。 - 第二引数の a
累乗を計算する元となる入力行列です。この行列は正方行列である必要があります。 - 第三引数の power
累乗の指数を指定します。この値により計算結果が変わります。正の値では行列を繰り返し掛け算し、負の値では逆行列を使用します。ゼロの場合は単位行列が返されます。
正方行列のチェック
最初に、行列が正方行列であるかをチェックしています。正方行列とは、行数と列数が等しい行列のことです。これを確認するために、Rowsメソッドと Colsメソッドを使って行数と列数を取得し、それを比較します。もし正方行列でなければ、累乗は計算できないため、関数は偽を返して終了します。
入力行列のサイズ取得
行列のサイズ(行数と列数)を Rows メソッドと Cols メソッドを使って取得します。このサイズは、結果となる行列を作成するために使用されます。結果行列result は、元の行列と同じサイズで初期化されます。
ゼロ乗の場合
累乗の指数がゼロの場合、数学のルールに従い単位行列が結果になります。単位行列とは、対角成分がすべて1で、それ以外の成分がすべて0の正方行列です。この操作では Identity関数を使用して、result 行列を単位行列に設定します。
負の指数の場合
累乗の指数が負の値の場合、まず行列の逆行列を計算する必要があります。逆行列は Inv メソッドを使って計算されます。その後、逆行列を累乗の絶対値分だけ掛け算します。たとえば、指数がマイナス3であれば、次のように計算します。
inverted * inverted * inverted
掛け算は MatMul メソッドを使用して行われ、計算結果が result に順次格納されます。
正の指数の場合
累乗の指数が正の値の場合、元の行列を累乗回数分だけ繰り返し掛け算します。たとえば、指数が3の場合、次のように計算します。
a * a * a
ここで a は元の行列です。この掛け算も MatMul メソッドを使って行い、計算結果が result に格納されます。
計算結果の格納
累乗の計算が完了すると、result に格納された結果を出力引数である c に代入します。これにより、関数の呼び出し元で計算結果を利用できるようになります。
戻り値
関数は、計算が成功した場合に真を返します。計算に失敗した場合、偽を返します。たとえば、正方行列でない場合や逆行列が存在しない場合には偽が返されます。
計算の流れ
例として、行列a が次の形を持つとします。
a = [[2, 1], [1, 1]]
指数が3の場合、計算の流れは次のようになります。
- a と a を掛け算します。
- 1行1列目: (2*2) + (1*1) = 4 + 1 = 5
- 1行2列目: (2*1) + (1*1) = 2 + 1 = 3
- 2行1列目: (1*2) + (1*1) = 2 + 1 = 3
- 2行2列目: (1*1) + (1*1) = 1 + 1 = 2 結果: [[5, 3], [3, 2]]
- 上の結果と a を掛け算します。
- 1行1列目: (5*2) + (3*1) = 10 + 3 = 13
- 1行2列目: (5*1) + (3*1) = 5 + 3 = 8
- 2行1列目: (3*2) + (2*1) = 6 + 2 = 8
- 2行2列目: (3*1) + (2*1) = 3 + 2 = 5
結果: [[13, 8], [8, 5]]
計算が完了し、c に結果が格納されます。
この関数は、正の指数、ゼロ、負の指数をサポートしており、幅広い累乗計算に対応できます。結果の正確性を保つために、正方行列や逆行列の存在条件を適切にチェックしています。