私は 100 x 100 の三重対角行列を作成しようとしています。2 が対角線を下っており、-1 が 2 を囲んでいます。3 つの対角線に 1 のみを含む三重対角行列を作成し、行列の加算を実行して必要なものを取得できますが、3 つの対角線を必要に応じてカスタマイズする方法があるかどうかを知りたいです。maplehelp には、有用なものは何もリストされていません。
4 に答える
LinearAlgebraパッケージのMatrix関数は、その位置に応じて行列の各エントリに値を割り当てることができる関数であるパラメータ(init)を使用して呼び出すことができます。
これはうまくいくでしょう:
f := (i, j) -> if i = j then 2 elif abs(i - j) = 1 then -1 else 0; end if;
Matrix(100, f);
LinearAlgebra [BandMatrix]も機能します(そして、特にstorage = band [1]を使用する場合は、はるかに高速になります)。おそらく、shape=symmetricも使用する必要があります。
初期化関数を含む答えは、f
正方形の nxn 行列に対して O(n^2) の作業を行います。理想的には、このタスクは O(n) である必要があります。これは、入力するエントリが 3*n 未満であるためです。
また、特別な (バンドなどの) ストレージやインデックス関数を持たない結果の Matrix が必要だとします (後で任意の部分に書き込むことができるようにするため)。また、バンド構造体 Matrix を別の汎用 Matrix() 呼び出しでラップして、使用される一時メモリが 2 倍になり、収集可能なガベージが生成されることで、このような問題を回避したくないとします。
これを行うには 2 つの方法があります (O(n^2) 方式で各エントリに f を適用するか、別の do ループを使用しないでください)。1 つ目は、一時として 3 つのバンドを作成することです (これは収集されるガベージですが、少なくとも n^2 サイズではありません)。
M:=Matrix(100,[[-1$99],[2$100],[-1$99]],scan=band[1,1]);
この 2 番目の方法では、M をウォークし、3 つのスカラー値だけを入力するルーチンを使用します (したがって、3 つのバンド リストを明示的に必要としません)。
M:=行列(100):
ArrayTools:-Fill(100,2,M,0,100+1);
ArrayTools:-Fill(99,-1,M,1,100+1);
ArrayTools:-Fill(99,-1,M,100,100+1);
ArrayTools:-Fill はコンパイル済みの外部ルーチンであるため、解釈された Maple 言語の (適切な) メソッドよりも原則的には高速であることに注意してください。'float[8]' などのハードウェア データ型を持つ Matrix M では特に高速です。
ちなみに、上記のアロー手続きが「無効なアロー手続きです」というエラーで失敗したのは、2D Math モードで入力したことが原因である可能性が高いです。Maple 13 の 2D Math パーサーは、if...then...end 構文を矢印演算子の本体として認識しません。代替手段 (他の誰かが答えたように f を proc として書くことを除く) は、1D Maple 記法モードで f (未編集) を入力するか、 f を編集して の演算子形式を使用することですif
。おそらく、here の演算子形式では、elif を処理するif
ためにネストされた が必要です。if
例えば、
f := (i,j) -> `if`(i=j,2,`if`(abs(i-j)=1,-1,0));
Matrix(100,f);
jmbr が提案するソリューションは、動作するように適応させることができます。
f := proc(i, j) i = j の場合 2 elif abs(i - j) = 1 の場合 -1 そうでなければ 0 終了する場合 プロセスを終了します。 マトリックス (100, f);
また、後でバンドマトリックスの性質を破壊する必要があるとのコメントを理解しています。これにより、BandMatrix を使用できなくなります。そうですか。これに対する最も簡単な解決策は、BandMatrix 呼び出しを通常の Matrix 呼び出しでラップすることです。これにより、必要に応じて変更できる Matrix が得られます。
Matrix(LinearAlgebra:-BandMatrix([1,2,1], 1, 100));