最適化セミナーのご案内

5.8 行列クラスMatrix

 一般の行列はMatrixというクラスで表現されます.対称行列と同様に,一般行列自体の定義と,一般行列の構造の定義は別々に行う必要があります.例えば,次のような$2\times 3$の行列を定義したいとします.

\[X = \left( \begin{array}{ccc} x+y & 0 & 1 \\ -1 & 2 & z \end{array} \right)\]

 この場合,以下のように記述します.

Set S="1 2";
Set T="1 2 3";
Element i(set=S),j(set=T);
Matrix X((i,j));
Variable x,y,z;
X["1,1"] = x + y;
X["1,2"] = 0;
X["1,3"] = 1;
X["2,1"] = -1;
X["2,2"] = 2;
X["2,3"] = z;

 iは行列の行の添字,jは行列の列の添字です.Matrix X((i,j))に表れる二重括弧を省略してMatrix X(i,j)と記述することはできません.

 行列クラスを用いて,正方行列を定義することも可能です.ただし,対称行列とは異なり,上下三角部分いずれか一方に関して定義しても対称化されませんので,非対称な行列を定義することができます.

 複数の行列を一括して定義することもできます.例えば,次の例では一般行列$X_{1}, \ldots, X_{10}$を一括して定義しています.

Set S="1 2";
Set T="1 2 3";
Element i(set=S),j(set=T);
Set N="1 .. 10";
Element n(set=N);
Matrix X(index=n,(i,j));

 行列自体の添字nにはindex=を付ける必要があります.個別の行列内部の添字(i,j)にはindex=を付与してはいけません.

 ここでは添字付けられた行列を行列族とよぶことにします.行列族の各々は行列ですが,行列族から行列を参照するには,丸括弧().at()関数を使います.

Matrix X(index=n,(i,j));
Matrix Z((i,j));
Z = X(1) + X(2);
Z = X.at(1) + X.at(2);
// Z = X[1] + X[2]; 違法

 さらに行列の成分を参照する場合には,丸括弧や.at()の後に続けて角括弧[]を使って参照します.対称行列の場合と同様に,行列族の添字と行列の成分の添字を連結して角括弧[]だけで参照することもできます.

Matrix X(index=n,(i,j));
Matrix Z((i,j));
Z["1,1"] = X(1)["1,1"] + X(2)["1,1"];
Z["1,1"] = X.at(1)["1,1"] + X.at(2)["1,1"];
Z["1,1"] = X["1,1,1"] + X["2,1,1"];

 上の三つの代入文はどれも同じ意味に解釈されます.

 

 行列クラスには行列演算が定義されています.二つの行列の型が整合すれば加算,減算,乗算を行うことができます.行列同士の加減乗にはそれぞれ,+, -, *演算子が対応します.また,行列やベクトルやそれらの演算で表現された制約式も定義することができます.通常の制約式と同様に,等式制約には==を使い,不等式制約には,>=<=を使います.行列クラスは添字を2つ内包したExpressionクラスとみることができます.添字を2つ持ったExpressionを用いて行列の加減乗に相当する演算を定義すれば,行列クラスを使わなくても行列演算は可能ですが,行列クラスを使えば記述が容易に済みます.

Set S="1 2 3";
Set T="1 2 3";
Element i(set=S),j(set=T);
Matrix X((i,j)), Y((i,j)), Z((i,j));
Z = X + Y;         // 行列の足し算
Z = X - Y;         // 行列の引き算
Z = X * Y;         // 行列の掛け算
Z = 2 * X;         // 行列の定数倍
Z = X / 2.0;       // 行列の全成分を2.0で割る

 行列の足し算や引き算では行列のサイズは変わりませんが,掛け算ではサイズが変わることがあります.行列の掛け算の結果を行列に代入する際には行列の宣言時に与えた行列のサイズに注意します.

 

 行列クラスには,加減乗の他に行列固有の演算が関数として用意されています.行列のトレース(対角和)にはtr()関数,行列の転置にはtrans()関数,行列同士の内積にはinprod()関数が対応します.関数の戻り値はそれぞれ,Expression, Matrix, Expressionになります.

 

 次は,これらの関数の使用例です.行列の演算では添字を陽に書かないことに注意します.

Set S="1 2 3";
Set T="1 2 3";
Element i(set=S),j(set=T);
Matrix X((i,j)), Y((i,j)), Z((i,j));
Expression e,d;
e = tr(X);         // 行列のトレース
Z = trans(X);      // 行列の転置
d = inprod(X, Y);  // 行列の内積

 行列クラスには次のような操作関数が用意されています.

  • .nrow()  行数をintで返す
  • .ncol()  列数をintで返す
  • .row(const Element& i)  i行目をVectorで取得する
  • .col(const Element& j)  j列目をVectorで取得する
  • .subRect(const Set&, const Set&)  行列の一部分をMatrixで取得する
  • .val.print()  現在の値を表示する
  • .printDim()  行列のサイズを表示する

 また,零行列や単位行列を表現したい場合には,Matrixクラスのサブクラスである,ZeroMatrixクラスやUnitMatrixを使います.ZeroMatrixクラスとUnitMatrixクラスはMatrixクラスとは違い,値を設定することなく零行列や単位行列として使うことができます.また,オブジェクトを宣言することなくzeros(const Set& S, const Set& T)unit(const Set& S, const Set& T)といった関数で零行列や単位行列を表すこともできます.

Set S="1 2 3";
Element i(set=S), j(set=S);
Matrix X((i,j));
ZeroMatrix O(i);   // 零行列
UnitMatrix I(i);   // 単位行列
X - I >= 0;        // 半正定値の意味

 $n\times n$の正方行列>= 0という記述をすると,行列のすべての成分が零以上であるという意味ではなく,行列の半正定値制約という意味に解釈されます.このとき,行列の対称性はチェックされませんので,かならず,対称になるように値を設定しておく必要があります.($n\times n$の正方行列<= 0という記述をすると,$-1$倍した行列の半正定値制約という意味に解釈されます.)

 $n\times 1$の行列>= 0という記述をすると,行列のすべての成分が零以上であるという意味に解釈されます.この場合,右辺に0以外の値を持ってくることはできません.($n\times 1$の行列<= 0という記述をすると,行列のすべての成分が零以下であるという意味に解釈されます.)

 

 Matrixには外部ファイルから値を設定することができます.SIMPLEデータ形式でデータを与えることができ,添字なしのMatrixであれば,添字を2つ持ったSIMPLEのデータ形式で与え,添字付けられたMatrixであれば,行列族の添字の次元に2を加えた次元のSIMPLEのデータ形式で与えます.


 

 

上に戻る