スパース行列の作成
スパース行列の作成
MATLAB® はスパース行列を自動的に作成しません。そのため、行列内でゼロ要素の占める割合が十分大きいかどうかを判断し、スパース行列にするかどうかを決めてください。
行列の "密度" は、非ゼロの要素数を行列要素の総数で除算した結果を示します。行列 M
に対しては、次のようになります。
nnz(M) / prod(size(M));
nnz(M) / numel(M);
非常に密度の低い行列ほど、スパース形式を使用することで良い結果を得られる可能性が高くなります。
非スパース行列からスパース行列への変換
非スパース行列をスパース ストレージに変換するには、関数 sparse
に引数を 1 つ指定します。
以下に例を示します。
A = [ 0 0 0 5 0 2 0 0 1 3 0 0 0 0 4 0]; S = sparse(A)
S = (3,1) 1 (2,2) 2 (3,2) 3 (4,3) 4 (1,4) 5
表示される出力に、S
の非ゼロ要素とその行と列のインデックスが一覧表示されます。要素は内部データ構造を反映して、列ごとに並べ替えられます。
行列の次元があまり大きくない場合は、関数 full
を使ってスパース行列を非スパースのストレージに変換できます。たとえば、A = full(S)
は例の変換を反転させます。
非スパース行列のスパース ストレージへの変換は、スパース行列作成方法としてはそれほど使用されません。行列の次元の大きさが非スパース ストレージが可能である程度の場合は、スパース ストレージへ変換してもあまり容量の節約にはなりません。
スパース行列を直接作成
関数 sparse
に引数を 5 つ与えると、非ゼロ要素のリストからスパース行列を作成できます。
S = sparse(i,j,s,m,n)
i
と j
は、それぞれ行列の非ゼロ要素の行インデックスと列インデックスを表すベクトルです。s
は、対応する (i,j)
ペアによってインデックスが指定される非ゼロ値のベクトルです。m
は結果の行列の行の次元で、n
は列の次元です。
前の行列の例 S
は、次のように直接入力できます。
S = sparse([3 2 3 4 1],[1 2 2 3 4],[1 2 3 4 5],4,4)
S = (3,1) 1 (2,2) 2 (3,2) 3 (4,3) 4 (1,4) 5
sparse
コマンドには、さまざまな使用方法があります。上の例は、行列の非ゼロ要素の最大数を length(s)
に設定する方法です。必要に応じて、要素の最大数よりも大きな値を 6 番目の引数に設定すると、必要なストレージ量を再度割り当てなくても非ゼロ要素を追加できます。
2 次微分演算子の行列表現はスパース行列の良い例です。これは対角に -2、上対角と下対角に 1 をもつ三重対角行列です。作成方法は多数ありますが、ここでは 1 つの例を示します。
n = 5; D = sparse(1:n,1:n,-2*ones(1,n),n,n); E = sparse(2:n,1:n-1,ones(1,n-1),n,n); S = E+D+E'
S = (1,1) -2 (2,1) 1 (1,2) 1 (2,2) -2 (3,2) 1 (2,3) 1 (3,3) -2 (4,3) 1 (3,4) 1 (4,4) -2 (5,4) 1 (4,5) 1 (5,5) -2
F = full(S)
は、対応する非スパース行列を表示します。
F = full(S)
F = -2 1 0 0 0 1 -2 1 0 0 0 1 -2 1 0 0 0 1 -2 1 0 0 0 1 -2
行列の対角要素からスパース行列を作成
行列の対角要素をベースにスパース行列を作成する方法は一般的な方法であり、関数 spdiags
を使用して行います。構文は、次のようになります。
S = spdiags(B,d,m,n)
対角要素が p
である m 行 n 列の出力行列 S
は、以下のように作成されます。
B
はmin(m,n)
行 p 列のサイズの行列です。S
の対角要素がB
の列に入力されます。d
は長さp
のベクトルで、その整数要素はS
の対角要素を設定します。
つまり、B
の j
列の要素は d
の j
要素によって設定された対角になります。
メモ
B
の列が対角要素の置き換わる部分より長い場合、上側の対角には B
の列の下部要素が、下側の対角には B
の列の上部要素が入ります。
たとえば行列 B
とベクトル d
を考えます。
B = [ 41 11 0 52 22 0 63 33 13 74 44 24 ]; d = [-3 0 2];
この行列を使って、7 行 4 列のスパース行列 A
を作成します。
A = spdiags(B,d,7,4)
A = (1,1) 11 (4,1) 41 (2,2) 22 (5,2) 52 (1,3) 13 (3,3) 33 (6,3) 63 (2,4) 24 (4,4) 44 (7,4) 74
これに対応する非スパース行列 A
は次のようになります。
full(A)
ans = 11 0 13 0 0 22 0 24 0 0 33 0 41 0 0 44 0 52 0 0 0 0 63 0 0 0 0 74
spdiags
はスパース行列から対角要素を取り出すことも、または既存の対角要素を新しい値で置き換えることもできます。詳細については、「help
spdiags
」と入力してください。
スパース行列のインポート
MATLAB 以外のツールで計算したスパース行列もインポートできます。関数 spconvert
とコマンド load
を使用して、インデックスと非ゼロ要素のリストを含むテキスト ファイルをインポートします。たとえば 3 列のテキスト ファイル T.dat
(1 列目が行のインデックス リスト、2 列目が列のインデックス リスト、3 列目が非ゼロ値リストからなるファイル) を考えます。次のステートメントは T.dat
を MATLAB に読み込み、スパース行列 S
に変換します。
load T.dat
S = spconvert(T)
save
コマンドおよび load
コマンドは、MAT ファイルにバイナリ データとして保存されたスパース行列の処理もできます。