ホームページTOPへ戻る
--------------------------------------------------------------------- MaTX Mailing-list FAQ ver0.4 2003/02/08 by onishimu --------------------------------------------------------------------- Q01. この FAQ はいったいなんですか?
Q02. A = X \ Y の演算で singular といわれます。どうしてでしょう。
Q03. matc で *.mm のファイルをコンパイルすると
sh: cpp: command not found といわれるのですが、これは何でしょう?
Q04. CoMatrix として宣言した行列に、一度でも null matrix [] を代入してしまう
と、その先の処理では、もともとの行列を CoMatrixとしては扱ってくれません。
Q05. MaTX での null Matrix って何ですか?
Q06. Matlab で作られたデータファイルを MaTX で読みたいのですが。
Q07. はじめから用意されている大域変数って何ですか?
Q08. 計算誤差が気になります。非常に大きな数の計算はよくないのでしょうか?
そもそも EPS って何ですか?
Q09. 規則性はあるけれども非常に疎な行列をうまく記述したいです。
Q10. 行列を append していくループの実行時間が遅いように思えます。
Q11. 行列のランク(階数)を計算しようとすると手計算と違った値になります。
Q12. Matlab と MaTX どちらの数値演算能力が高いのですか?
Q13. Floating point exception というエラーが出ました。
Q14. プログラムミスで 3.0E+310 のような値が誤って代入されたことがあります。
値の限界はどのように決められているのでしょう。
Q15. logspace をするときに
logspace(Array), Confliction of the argument class
と言われて作れません。
Q16. ファイルが存在するかしないかをチェックしたいです。
Q17. 外部コマンド実行の system の返り値はどのようになっていますか?
Q18. 処理系によって pipe が使えない場合(Windows版など)、どうすれば
その分岐ができますか?
Q19. 転置や逆などの記号が見づらいので陽に書きたいのです。
Q20. MaTX を立ち上げて what としたとき、User Function に何も表示され
ません。
Q21. ツールボックスを作りたいのですが、何か注意することはありますか?
Q22. ftp server にあるマニュアルの印刷方法を教えてください。
Q23. test.mm から matc した作ったファイルが動かないのですが。
Q24. UNIX では MaTX はシェアードライブラリを使うそうですが、static link
は可能ですか。
Q25. 0,1,2,3,4,...100 という 101 個の配列はどうやったら作れますか?
Q26. MaTX の配列と C 言語の配列とでやりとりをしたいのです。何かよい例題
はありませんか?
Q27. 行列成分を read で代入したいのですが、うまくいきません。
Q28. むだ時間を含むシステムをシミュレーションするには?
Q29. UNIX での作業環境から Windows への移行にためらっています。MaTX する
ための Windows 上の便利なツールはありませんか?
Q30. Win95 MaTX ではどのくらいの大きさの行列まで取り扱えるのでしょう。
Q31. fopen で用いるファイルディスクリプタの型は何でしょう?
Q32. プログラムをインタプリタとコンパイラで動かした場合、結果が異なりま
した。どんなことが考えられますか?
Q33. ファイルのインクルードが複雑になっていてうまくコンパイルできません。
Q34. fread, fwrite の使い方がよくわかりません。
Q35. RtMaTX はどのくらいの負荷に耐えられるのですか?
Q36. m2mm という m-file->mm-file トランスレータがあるそうですが、どこ
にありますか?
Q37. 数値微分はできますか?
Q38. gnuplot の multiplot を使ってプロットできますか?
Q39. Windows では大文字と小文字を区別しないので、UNIX で使っていたファイ
ルが使えず困っています。
Q40. インクルードしたら、syntax error が出るんですが。
Q41. MaTX コードのそれぞれの行の実行に必要な時間が知りたいです。
Q42. matc するファイルには必ず main 関数が必要ですか?
Q43. インタプリタで main 関数の引数をシミュレートするには?
Q44. Windows95 で MaTX の install directory が深い場合、コマンドラインが
が長すぎることで問題が出ています。
Q45. 連続系対象、離散系制御器のシミュレーションで演算時間遅れはどう書く
のでしょうか?
Q46. シミュレーション結果のデータファイルが巨大です。
Q47. バイナリファイルの read の挙動がおかしいです。
Q48. 時分割でシミュレーションしたいです。
Q49. シミュレーションの際、simulink の scope のような機能はありませんか?
Q50. OdeAuto の Auto ってなにを自動化してくれているのですか?
Q51. RKF45 って何ですか?
Q52. 3次以上の多次元配列が使いたいです。
Q53. Ode の積分刻みってどうやって決めるのですか?
Q54. a = [[1 2 3][4 5 6][7 8 9]] の逆行列がおかしいのですが。
Q55. 計算結果の行列に存在する非常に小さい成分を全部 0 にしたいのです。
Q56. Meadow を使っています。.emacs の MaTX modeの設定を教えてください。
Q57. Meadow を使っています。色をつけたいんです。
Q58. なんかフォントの色が灰色で見にくいのですが。
Q59. ある条件をみたした時に Ode を止めたいのですが。
Q60. Matlab のように便利な toolbox は公開されていませんか?
Q61. なんかMaTX for Borland-C の計算結果がおかしいです。
Q62. Windows NT/2000/XP で MaTX を使用すると,画面が乱れます。
Q63. 複素行列の擬似逆行列がおかしいです。
Q64. mm ファイルが実行されません。それに、なんのメッセージも出ません。
Q65. ソケット通信がうまいくいきません。
Q66.
Q67.
Q68.
----------------------------------------------------------------------- Q01.この FAQ はいったいなんですか?
-----------------------------------------------------------------------
A01. (Qリストへ戻る) この FAQ は 1995 年 5 月ごろからの MaTX mailng-list に出た質問を*軽く* onishimu がまとめたものです。もう少し数が増えたら質問の分野別振り分けも 行っていきたいと考えています。 この内容は mailing-list での質問、回答をまとめたものが基礎となってい ますが、onishimu が書き換えたところも多いため、 MaTX の作者がその内容 を保証するものではありません。onishimu もこの FAQ の内容から生じた心的 肉体的時間的物質的損害などを補償しません。 ----------------------------------------------------------------------- Q02. A = X \ Y の演算で singular といわれます。どうしてでしょう。
-----------------------------------------------------------------------
A02. (Qリストへ戻る) A = X \ Y の演算について説明します。 (1) X が正方の場合: X*A = Y をピボット付ガウス消去法で解きます。実際は ガウスの消去法とアルゴリズム的に等価なピボット付LU分解を用いていま す。効率よく計算するために(十分に安定であるといわれている)完全ピボ ット選択(行と列の両方を入れ換える)ではなく部分ピボット選択(行だけ を入れ換える)を行なっています。 (2) X が非正方の場合: X*A = Y の最小二乗解を求めます。具体的にはピボ ット付QR分解を行なって擬似逆行列を計算しています。 X が正方の場合はピボット付ガウスの消去法が用いられます。X の正則性は {L,U,P} = lu(X) によって得られる上三角行列 U の対角成分の絶対値で判定 しています。もし、計算した結果の対角成分の最小値が、 EPS = 2.0^-54 = 5.5511151e-17 より小さい場合、非正則(singular)と判定されます。 また、行列 X が正方でかつ「対称」の場合、対称行列の逆行列はコレスキー 分解によって X = R'* R のように上三角行列の積に分解できます。そして A = R\(R'\Y) によって解を計算できます。一般に方程式の係数行列が対称行列の場合,LU 分解を使うよりコレスキー分解を使う方が精度良いようです。 Matlab で計算できて、MaTX で計算できないというケースがおこる場合があり ますが、これは、Matlab は A = X \ Y の計算をする前に,行列 X が対称行列 であるか調べて,対称行列ならコレスキー分解を使っているからです。 MaTX でも、対称行列の場合には陽に R = chol(X); // X = R'*R A = R\(R'\Y); のようにすると,A を計算できます。 ただ、いちいち対称行列のチェックをしていることが適切かどうかは目的によ ると考えられます。 ----------------------------------------------------------------------- Q03. matc で *.mm のファイルをコンパイルすると
sh: cpp: command not found といわれるのですが、これは何でしょう?
-----------------------------------------------------------------------
A03.(Qリストへ戻る) MaTXのプリプロセッサ機能は,内部でCプリプロセッサ(cpp)を呼ぶことで 実現されています。解決方法は,PATHの通っているディレクトリへcppから リンクを張ることです。linuxの場合,cppは/lib/cppにあります。 Windows 版で、インストール直後の環境をいじってしまうと、この cpp の設定 で MaTX が動かなくなることがあります。 環境変数 MATXCPP に用いる cpp を設定することができます。 なお、Windows Visual-C, Borland-C 版を使う場合に、Visual-C や、Borland-C のプリプロセッサを使うか、MaTX の プリプロセッサ(実は DJGPP の cpp) を 使うかは、MATXCPP 環境変数で制御できます。 ----------------------------------------------------------------------- Q4. matc compiler の動作についての質問です。
CoMatrix として宣言した行列に、一度でも null matrix [] を代入してしまう
と、その先の処理では、もともとの行列を CoMatrixとしては扱ってくれません。
例えば
CoMatrix C ;
Complex tmp ;
read C ;
if (condition A) {
C = [] ;
}
tmp = C(1,1) ;
とすると、compiler は 「tmp と C(1,1) では型があわないよ」というエラー
メッセージを返して来ますが、C = [] ではお咎めなしです。
これを回避するには C = CoMatrix([]) とすればいいのですが、だとすると、
C = [] をしようとした時にエラーメッセージが出て欲しい気がするのですが。
-----------------------------------------------------------------------
A04. (Qリストへ戻る) MaTXを使っている方で「CoMatrix宣言」を知っている人はあまり多くないと思 います。というのは,すべての行列の宣言は「Matrix宣言」を使えば良いから です。では,なぜ CoMatrix, PoMatrix, RaMatrix のような宣言があるのでし ょうか? 次の2つのプログラムを使って理由を説明します。 ------------------------------------------------------------ Program-1 | Program-2 ------------------------------------------------------------ afo.mm | afo2.mm | Func void afo() | Func void afo2() { | { Matrix a; | Matrix a; void foo(); | void foo2(); | a = [1 2]; | a = [(1,2), (3,4)]; foo(a); | foo2(a); } | } | ------------------------------------------------------------ foo.mm | foo2.mm | Func void foo(a) | Func void foo2(a) Matrix a; | CoMatrix a; { | { print a(1,1); | print a(1,1); } | } | ------------------------------------------------------------ Program-1は afo()で a に実行列を代入していますが,Program-2は afo2()で a に複素行列を代入しています。そして,a を引数として foo() と foo2() をそれぞれ呼び出しています。注意して欲しいのは,foo() では引数が Matrix 宣言されているのに,foo2() では CoMatrix 宣言されていることです。 もし,このCoMatrix宣言が無ければ,コンパイラは a(1,1) が複素数で あることを知ることができないのです。(インタプリタなら分かります) なぜなら,行列 a の実体(大きさ,型)は実行時にならないと決まらない からです。 行列だけの演算(和差積商など)しかないなら,行列の大きさや型による演算の 違いはクラスライブラリが引き受けてくれるので,CoMatrixのような宣言は必要 ありません。 したがって,次の注意が必要になります。 o 関数を定義するとき,あらかじめ引数の型が詳しく分かっているなら, その宣言をする。関数自身の型(戻り値)も同じ。 o 条件分岐によって行列の型が変わる場合,型変換関数を使って型を 指定する。 ----------------------------------------------------------------------- Q05. MaTX での null Matrix って何ですか?
-----------------------------------------------------------------------
A05.(Qリストへ戻る) null Matrix には real null matrix complex null matrix polynomial null matrix rational null matrix の4種類があり,`` [] '' は real null matrix を意味します。 現在の MaTX には,real null matrix の記述法しかありませんから, 他の null matrix を入力するには,CoMatrix() や PoMatrix() など の型変換関数を用いることになります。 ----------------------------------------------------------------------- Q06. Matlab で作られたデータファイルを MaTX で読みたいのですが。
-----------------------------------------------------------------------
A06.(Qリストへ戻る) (方法1) Matlab で最初から MaTX データ形式でファイルに書き出す。 (方法2) Matlab でアスキー形式の save を >> save afo.mat A -ascii; で行った場合には、たとえば、 A = [ 1 2 3 ; 4 5 6]; は 普通は >> save afo.mat A -ascii; で、afo.mat に 1.0000000e+000 2.0000000e+000 3.0000000e+000 4.0000000e+000 5.0000000e+000 6.0000000e+000 と save されます。 ここで、MaTX では text 形式は転置する必要があるので、一度転置してから save します。すると >> A2 = A'; >> save afo.mat A2 -ascii; で 1.0000000e+000 2.0000000e+000 3.0000000e+000 4.0000000e+000 5.0000000e+000 6.0000000e+000 という afo.mat が出来上がります。MaTX では、最初の行にその行列の行数、 列数を記述する必要があります。2行3列というヘッダ # 2 3 を最初の行に挿入して # 2 3 1.0000000e+000 2.0000000e+000 3.0000000e+000 4.0000000e+000 5.0000000e+000 6.0000000e+000 とすれば MaTX で MaTX (1) read A << "afo.mat" で読み込めます。 MaTX ver 5.2.28 以降から、# 2 3 のヘッダがなくても MaTX で読みこむ ことができるようになりました。ただし、読みこみ速度が非常に劣るので スピード重視ならばヘッダをつけることが推奨されます。 (方法3) バイナリ形式のセーブを行った場合、Matlab は ver4.x と ver5.x でデータの形式が違うため、現在のところ ver5.x のデータを読むツールは 用意されていません。Matlab ver5.x で >> save afo.mat A -V4 とすれば、ver4.x 形式でセーブされます。この場合、MaTX の matlab_read や matlab_write 関数が適用できます。 詳しくは MaTX/inputs/matrix/matlabio.mm を参照してください。 ただし、Windows 版ではバイナリファイルのリードには注意が必要です。 ver 5.0.12 以上の version を用いる必要があります。 ----------------------------------------------------------------------- Q07. はじめから用意されている大域変数って何ですか?
-----------------------------------------------------------------------
A07.(Qリストへ戻る) MaTX を起動して、 MaTX (1) who としたときに現れる PI, PID, EPS, Inf, NaN, ans という変数です。whos コマンドで中身が表示されます。 Name Class Size(Value) PI Re_Number 3.14159 PID Integer 5971 EPS Re_Number 2.22045e-16 Inf Re_Number Inf NaN Re_Number NaN ans Re_Number 0 です。ans は最も最近の計算結果が代入されています。 ----------------------------------------------------------------------- Q08. 計算誤差が気になります。非常に大きな数の計算はよくないのでしょうか?
そもそも EPS って何ですか?
-----------------------------------------------------------------------
A08.(Qリストへ戻る) 以下の例題を見てみます。以下の MaTX コード Func void main() { Real L0, L1; Real a, b, k; L0 = 848.0; L1 = 848.0+128.0; k = 32537.7883; a = (L1-L0)*k; b = (L1*k-L0*k); printf("%e\n", a-b); } の結果は(matx, matc 両方とも) -1.862645e-09 となります。 Func void main() { Real L0, L1; Real a, b, k; L0 = 848.0; L1 = (848.0+128.0); k = 32537.7883; a = (L1-L0)*k; b = 128*k; printf("%e\n", a-b); } の結果は 0.0 になります。これはどうして起こるのでしょうか? また、 # 1 1 3.25377883E+4 というファイル(afo.mat)を読み込むと、 MaTX (1) read a << "afo.mat" MaTX (2) a === [a] : ( 1, 1) === ( 1) ( 1) 3.25377883E+04 MaTX (3) printf("%1.30e\n",a(1,1)) 3.253778830000000016298145055771e+04 という結果になります。この下のほうの数字はどこから出てきたのでしょう? このような問題の発生した現象の主な原因は、浮動小数点数の加減算にともなう 「桁そろえ誤差」です。桁そろえ誤差は、コンピュータが加算器または減算器 が一定の桁数しか扱えないために生じるもので、「積み残し誤差」または 「情報落ち誤差」と呼ばれます。 加減算の積み残し誤差について次のことが知られています。 実数 x のコンピュータ内部での値を FL(x) とすると、 |FL(x + y) - (x + y)| <= max{|x|, |y|, |x + y|} * eps |FL(x - y) - (x - y)| <= max{|x|, |y|, |x - y|} * eps という関係が成り立ちます。この式を使って問題のプログラムの誤差 を調べます。問題の箇所は b = (L1 * k) - (L0 * k); です。 x := L1 * k = 31756881 y := L0 * k = 27592044 eps = 2.220446E-16 (double の場合) |FL(x - y) - (x - y)| <= max{|x|, |y|, |x - y|} * eps = 31756881 * eps = 7.051442E-9 となり、実際に発生した誤差「-1.862645e-09」を十分説明できます。 結局,大きな値どうしの減算が問題の原因と結論できます。 では、どうすれば大きな値の減算を含む計算を精度良くできるか、 考えます。まずは,C 言語で記述された以下のプログラムを見て下さい。 void main() { double L0, L1, a, b, k; long double L0_l, L1_l, a_l, b_l, k_l; L0 = 848.0; L1 = 848.0 + 128.0; k = 32537.7883; a = (L1 - L0) * k; b = (L1 * k) - (L0 * k); printf("a - b = %e\n", a - b); L0_l = 848.0; L1_l = 848.0 + 128.0; k_l = 32537.7883; a_l = (L1_l - L0_l) * k_l; b_l = (L1_l * k_l) - (L0_l * k_l); printf("a_l - b_l = %e\n", a_l - b_l); } double の代りに long double を使うのが手っ取り早い方法です。しかし、 これでは計算がかなり遅くなったり、使用するメモリが倍増します。そこで、 以下のような工夫をします。すなわち、大きな数の減算をする部分のみを (long double)にキャストするのです。これが数値計算の常套手段です。 残念ながら,現在は MaTXは(long double)をサポートしていません。 もちろん、matc -mm で C 言語に変換した後,問題の箇所を (long double) でキャストする方法はあります。 以上より、先の例題における MaTX (3) printf("%1.30e\n",a(1,1)) 3.253778830000000016298145055771e+04 この下のほうの数字は FL(3.25377883E4) = 3.253778830000000016298145055771e+04 なのだと考えられます。 一般に 10^(-16)程度以下の値は信頼できないというように言われますが、 これは、double を使う計算の計算機イプシロンは,eps = 2.220446E-16 だからです。 ちなみに,計算機イプシロン eps とは,その計算機で 1 + eps == 1 を満たさない最小の正の数です。ほとんどの計算機では, 以下のプログラムで得られます。 Func void get_machine_eps() { Real eps; eps = 1; while (1 + eps/2 != 1) { eps = eps/2; } print eps; } また,ANSI 標準 C では,float.h で定義されています。 ----------------------------------------------------------------------- Q09.規則性はあるけれども非常に疎な行列をうまく記述したいです。
-----------------------------------------------------------------------
A09.(Qリストへ戻る) shiftLeft, shiftRight, shiftUp, shiftDown や、 rotateLeft, rotateRight, rotateUp, rotateDown を使うと簡単です。 たとえば、 |-2 1 0 ... 0| | 1 -2 1 0 ... 0| | 0 1 -2 1 0 ... 0| | . 0 1 -2 1 0 ... 0| | . . 0 1 -2 1 0 ... 0| | . . . . . . ... 0| | . . . . . . 1 0| | . . . . 0 1 -2 1| | . . . . . . 0 1 -2| のような 100x100の対称行列は、 I100 = I(100); A = -2*I100 + shiftLeft(I100) + shiftRight(I100); で記述できます。 ----------------------------------------------------------------------- Q10. 行列を append していくループの実行時間が遅いように思えます。
-----------------------------------------------------------------------
A10.(Qリストへ戻る) これはその通りです。 a = []; for (i = 1; i <= 100; i++) { a = [a, rand(2)]; } のように行列自身の大きさが append されて大きくなる場合、メモリの確保 を行う必要があるため著しく速度が落ちます。このような場合は最初から 大きな行列を確保しておいてから、ピース行列による記述をしたほうが賢明 です。 a = Z(2,200); ai = Z(2,2); for (i = 1; i <= 100; i++) { a(1, i, ai) = rand(2); } ----------------------------------------------------------------------- Q11. 行列のランク(階数)を計算しようとすると手計算と違った値になります。
-----------------------------------------------------------------------
A11.(Qリストへ戻る) rank の計算にも計算精度の問題が常に生じます。どの値から 0 だとみなすか によって rank の判定が変わってしまうからです。そこで、rank の判定の際 には、その判定基準を陽に書くことができます。 MaTX で help rank とすると、 Integer rank(Matrix M1): rank of a matrix Integer rank(Matrix M1, Real tol): rank of a matrix Default: tol = frobnorm(M1)*EPS となります。つまり、デフォルトでは 行列のフロベニウスノルムに EPS を 乗じた値より以下は 0 とみなして rank 判定を行っているわけです。 微妙な rank 判定を行う必要がある場合には、この値を操作すればよいわけ です。 ----------------------------------------------------------------------- Q12. Matlab と MaTX どちらの数値演算能力が高いのですか?
-----------------------------------------------------------------------
A12.(Qリストへ戻る) "数値演算能力"という表現は非常に曖昧ですが、onishimu の主観も入った両者 の比較を考えてみます。 まず大きな違いは MaTX にはインタプリタとコンパイラの2つが用意されている ということです。設計や解析など速度を必要としない計算に対してはインタプリ タで十分ですし、いちいちコンパイルする必要がないのはデバッグ効率が非常に 高くなると思います。 大規模なシミュレーションなどを行う場合にはインタプリタなんて使って時間を ロスするわけにはいきません。コンパイルして、さらにできた実行ファイルを バッチ処理などすることができるため、非常に能率的にシミュレーションできる でしょう。 Matlab は完全にデファクトスタンダードになりつつありますので、最新のアル ゴリズムがすぐに toolbox として商品化されますのでその点は非常に有利です。 また、売りものですから、保守契約に入ればサポートの面でも安心できるでしょ う(toolbox の代金や保守契約金を払う余裕があればの話ですが)。 Matlab は売りものなのでマニュアルが MaTX よりしっかりしています。使って いるアルゴリズムの説明も書いてあるので,信頼できるように思われています。 しかし,少し問題があります。良く読んでみると分かるのですが,すべての アルゴリズムが説明(公開)されているわけではないのです。 LINPACK や EISPACK のアルゴリズムを改良(修正)して使っていると書かれて いるところもありますしたがって,ユーザは Matlab をブラックボックスと して使わざるをえないのです。クリティカルな計算をする人にとってはアルゴ リズムの公開が重要になると思います。 ここに記したことは一部の比較です。MaTX と Matlab のどちらが良いかは 本当に目的に依ると思います。 ----------------------------------------------------------------------- Q13. Floating point exception というエラーが出ました。
-----------------------------------------------------------------------
A13.(Qリストへ戻る) 算術関数(sin, cos, tan, sqrt など)に渡される引数の値が不適切なとき、 "Floating point exeption (浮動(少数)点例外)"が発生します。例えば、 平方根関数sqrt()に負の値が渡されると発生します。ただし,使用してい るOSに依っては発生しない(例外をトラップできない)こともあります。 ----------------------------------------------------------------------- Q14. プログラムミスで 3.0E+310 のような値が誤って代入されたことがあります。
値の限界はどのように決められているのでしょう。
-----------------------------------------------------------------------
A14.(Qリストへ戻る) 値の限界はいろいろな条件に依存するので,厳密に定義するのは難しいのです が,UNIX 系 OS の場合には /usr/include/values.h で定義されている MAXDOUBLE, MINDOUBLE が (MaTX の Real 変数,C の double 変数)の限界の参考になると思います。 この値は処理系によって微妙に違います。この理由は以下のように考えられ ます。floating point で実数を表現するフォーマットはIEEE 754規格で定義 されていますが,マイクロプロセッサの設計者や C 言語の実装者がこの規格 を厳密に遵守しているとは限りません。また,浮動少数点算術の分野における C 規格では,浮動少数点の各種仮引数を表現するのに十分な用語を定義する ことに努力が払われていますが,正しい答えを得ることについては,ほとんど 説明的なものしかありません。 double変数の最大値に限って説明すると,最大値(オーバーフローかもしれ ない)が発生すると,あるマシンでは結果の量が大きすぎて表現できないか もしれないし,別のマシンではなんらかの表現をするかもしれない。結果と して生じるオーバーフローは,トラップ(割り込み)を発生させるかもしれな いし,特殊なコード値(MAXDOUBLEかもしれない)を生成したり,あるいは, 有効な値との区別が難しいゴミの値を生成する場合もありえます。 ----------------------------------------------------------------------- Q15. logspace をするときに
logspace(Array), Confliction of the argument class
と言われて作れません。
Duplicate undefining for '(0 x 0)' in MatUndef().
と言われて作れないこともあります。
-----------------------------------------------------------------------
A15.(Qリストへ戻る) これは logspace の第一、第二引数が実数でないときに言われるエラーです。 MaTX (1) w = logspace(-2, 2, 300); だとエラーが出ますが、 MaTX (2) w = logspace(-2.0, 2.0, 300); とすれば問題ありません。logspace は第一、第二引数は Real 型でなければ ならないからです。 ----------------------------------------------------------------------- Q16. ファイルが存在するかしないかをチェックしたいです。
-----------------------------------------------------------------------
A16.(Qリストへ戻る) access("path", mode)でアクセス権を調べられます。 mode を省略すると,読み込みに関するアクセス権を調べられます。 アクセス権がある場合,0が返されます。 ----------------------------------------------------------------------- Q17. 外部コマンド実行の system の返り値はどのようになっていますか?
-----------------------------------------------------------------------
A17.(Qリストへ戻る) 外部コマンドの実行が成功すると 0 が返されます。 ----------------------------------------------------------------------- Q18. 処理系によって pipe が使えない場合(Windows版など)、どうすれば
その分岐ができますか?
-----------------------------------------------------------------------
A18.(Qリストへ戻る) #ifdef HAVE_PIPE pipe("...."); #endif によって分岐できます。 ----------------------------------------------------------------------- Q19. 転置や逆などの記号が見づらいので陽に書きたいのです。
-----------------------------------------------------------------------
A19.(Qリストへ戻る) 転置 : A' : trans(A) 共役転置 : A# : conjtrans(A) 逆 : A~ : inv(A) 累乗 : A^B : pow(A, B) という関数が使用できます。 ----------------------------------------------------------------------- Q20. MaTX を立ち上げて what としたとき、User Function に何も表示され
ません。
-----------------------------------------------------------------------
A20.(Qリストへ戻る) これは MaTX 環境変数の設定のミスによることが多いです。 MaTX がインストールされている directory を設定する必要があります。 ----------------------------------------------------------------------- Q21. ツールボックスを作りたいのですが、何か注意することはありますか?
-----------------------------------------------------------------------
A21.(Qリストへ戻る) o 大域変数を使わない。 o 統一された関数名を付ける。 o インタプリタでしか使えない機能を使わない。 o 1つのファイルに関連する関数を入れる。 o MMファイルの先頭に関数の説明を書く。 (helpコマンドは,MMファイルの最初のコメントを表示します。) などがあります。 ----------------------------------------------------------------------- Q22. ftp server にあるマニュアルの印刷方法を教えてください。
-----------------------------------------------------------------------
A22.(Qリストへ戻る) 日本語版: (matx-jp.ps.gz: 片面印刷用) (book-jp-1.ps.gz: 両面印刷用: 奇数ページ) (book-jp-2.ps.gz: 両面印刷用: 偶数ページ) (book-jp-two.ps.gz: 両面印刷用: 2冊同時印刷) 英語版: (matx-eg.ps.gz: 片面印刷用) (book-eg-1.ps.gz: 両面印刷用: 奇数ページ) (book-eg-2.ps.gz: 両面印刷用: 偶数ページ) (book-eg-two.ps.gz: 両面印刷用: 2冊同時印刷) マニュアルの製作手順は次のようになります。 1冊だけマニュアルを製作する場合,手順(d)が少し面倒です。 (1) 日本語のマニュアルが2冊同時に必要な場合 (a) book-jp-two.ps を印刷する (b) 印刷された用紙全部をそのまま裏返してプリンタにセットする (c) book-jp-two.ps をもう一度印刷する (d) 用紙を半分に切ると,2冊の日本語マニュアルができる (2) 日本語のマニュアルが1冊だけ必要な場合 (a) book-jp-1.ps を印刷する (b) 印刷された用紙全部をそのまま裏返してプリンタにセットする (c) book-jp-2.ps を印刷する (d) 適当にソートする (e) 用紙を半分に切ると,1冊の日本語マニュアルができる (3) 英語のマニュアルの製作も同様です。 ----------------------------------------------------------------------- Q23. test.mm から matc した作ったファイルが動かないのですが。
-----------------------------------------------------------------------
A23.(Qリストへ戻る) UNIX には test というコマンドがあります。 % which test で表示される test の位置を確認してください。陽にカレントディレクトリの ファイルを実行したい場合には % ./test としてください。 ----------------------------------------------------------------------- Q24. UNIX では MaTX はシェアードライブラリを使うそうですが、static link
は可能ですか。
-----------------------------------------------------------------------
A24.(Qリストへ戻る) % matc -static mmmark.mm とすると static link されます。ファイルサイズは大きくなりますが、実行 スピードは若干速くなります。 ----------------------------------------------------------------------- Q25. 0,1,2,3,4,...100 という配列はどうやったら作れますか?
-----------------------------------------------------------------------
A25.(Qリストへ戻る) 101 個になりますので、 MaTX (1) A = linspace(0.0, 100.0, 101); で作れます。ただし、これは Real を成分として持つ配列になります。 MaTX (1) A = [ 0:1:100 ] でも同じ結果を得ます。これは等差配列の記述方法です。 ----------------------------------------------------------------------- Q26. MaTX の配列と C 言語の配列とでやりとりをしたいのです。何かよい例題
はありませんか?
-----------------------------------------------------------------------
A26.(Qリストへ戻る) 以下の例が参考になるでしょう。matc -mm などで mm-file を C 言語に変換し てそれを眺めると理解が深まるでしょう。 // // read_write_samp.mm // // このプログラムは unsigned char 型の成分をもつ行列の // ファイル入出力を行うC言語の関数をテストします。 // // matcc read_write_samp.mm read_write.c // ./read_write_samp // Matrix read_unsigned_char_matrix(); Integer write_unsigned_char_matrix(); Func void main() { Integer rows, cols; String file1, file2; Matrix a, b; read a, file1; if (write_unsigned_char_matrix(file1, a) != 0) { error("Can't save %s", file1); } read file2, rows, cols; b = read_unsigned_char_matrix(file1, rows, cols); if (Rows(b) == 0) { error("Can't read %s", file2); } print a-b; } --------o--------o--------o---- /* * read_write.c * * int MatGetRows(mat) mat の行数 * Matrix mat; * * int MatGetCols(mat) mat の列数 * Matrix mat; * * Matrix MatDef(name, m, n) m x n の name という名前の * char *name; 実行列を作る。 * int m, n; * * Matrix MatSetValue(mat, i, j, dd) mat の i 行 j 列に dd を代入する。 * Matrix mat; * int i, j; * double dd; * * double MatGetValue(mat, i, j) mat の i 行 j 列 成分を返す。 * Matrix mat; * int i, j; */ #include#include #include #include Matrix read_unsigned_char_matrix(filename, rows, cols) char *filename; int rows, cols; { int i, j, k; Matrix a; unsigned int size; unsigned char *dd; FILE *fp; size = rows * cols; dd = (unsigned char *)malloc(size * sizeof(unsigned char)); if (dd == 0) { fprintf(stderr, "Out of memory, while reading %s.\n", filename); return MatDef("", 0, 0); } if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "Can't open %s.\n", filename); return MatDef("", 0, 0); } if (fread((char *)dd, sizeof(unsigned char), size, fp) != size) { free((char *)dd); fclose(fp); fprintf(stderr, "Data is broken in %s.\n", filename); return MatDef("", 0, 0); } a = MatDef("", rows, cols); for (i = 0; i < rows; i++) { k = i*cols; for (j = 0; j < cols; j++) { MatSetValue(a, i+1, j+1, (double)*(dd + k + j)); } } fclose(fp); return a; } int write_unsigned_char_matrix(filename, a) char *filename; Matrix a; { int i, j, k; int rows, cols; unsigned int size; unsigned char *dd; FILE *fp; rows = MatGetRows(a); cols = MatGetCols(a); size = rows * cols; dd = (unsigned char *)malloc(size * sizeof(unsigned char)); if (dd == 0) { fprintf(stderr, "Out of memory, while reading %s.\n", filename); return -1; } if ((fp = fopen(filename, "w")) == NULL) { fprintf(stderr, "Can't open %s.\n", filename); return -1; } for (i = 0; i < rows; i++) { k = i*cols; for (j = 0; j < cols; j++) { *(dd + k + j) = (unsigned char)MatGetValue(a, i+1, j+1); } } if (fwrite((char *)dd, sizeof(unsigned char), size, fp) != size) { free((char *)dd); fclose(fp); fprintf(stderr, "Error, while writing to %s.\n", filename); return -1; } fclose(fp); return 0; } ----------------------------------------------------------------------- Q27. 行列成分を read で代入したいのですが、うまくいきません。
-----------------------------------------------------------------------
A27.(Qリストへ戻る) 行列の成分を入力するには,次のような方法があります。 [例1] Func void main() { Matrix mat; mat = ONE(1,1); read mat; // 直接行列を編集 print mat; } [例2] Func void main() { Real d; Matrix mat; mat = ONE(1,1); read d; // 別の変数に入力 mat(1,1) = d; // 行列に代入 print mat; } ----------------------------------------------------------------------- Q28. むだ時間を含むシステムをシミュレーションするには?
-----------------------------------------------------------------------
A28.(Qリストへ戻る) シミュレーションの際に過去の時刻のデータを用いたい場合には OdeXY() を 使います。例題を示します。この例題は,むだ時間のあるシステムのシミュレ ーションではありませんが,参考になると思います。 OdeXY を Ode45HybridAuto などと使う場合には、dtmax と同時に dtsav を (delay より)小さくする必要があることに注意が必要です。 // // dx(t) // ---- = A x(t) + B u(t) // dt // // u(t) = f x(t) // Matrix A,B; void diff_eqs(), link_eqs(); Func void main() { Matrix x0; Array TC,XC,UC; A = [[0,1,0] [0,0,1] [0,0,0]]; B = [0,0,1]'; x0 = [1,0,0]'; {TC, XC, UC} = Ode45HybridAuto(0.0, 5.0, 0.5, x0, diff_eqs, link_eqs); print [[TC][XC][UC]] >> "foobar"; } Func void diff_eqs(DX, t, X, UY) Real t; Matrix X, DX, UY; { Matrix xp, up, dxp; xp = X; up = UY(1,*); dxp = A * xp + B * up; DX = [dxp]; } Func void link_eqs(UY, t, X) Real t; Matrix UY, X; { Matrix xp,up; Matrix xp2, up2; xp = X; up = [-1,-2,-3] * xp; {xp2, up2} = OdeXY(t-0.1); // OdeXY()に時間を渡すと,その時刻の // 状態 X と入出力 U Yがリストで返る。 if (Rows(xp2) == 0) { // ただし,時刻が0以下のときは,0 x 0 xp2 = Z(xp); // の X と UY を返します。 up2 = Z(up); } UY = [[up][xp][xp2][up2]]; } ----------------------------------------------------------------------- Q29. UNIX での作業環境から Windows への移行にためらっています。MaTX する
ための Windows 上の便利なツールはありませんか?
-----------------------------------------------------------------------
A29.(Qリストへ戻る) この種の情報は賞味期間が短いので、ここのページに比較的簡易にまとめています。
-----------------------------------------------------------------------
Q30. Win95 MaTX ではどのくらいの大きさの行列まで取り扱えるのでしょう。
-----------------------------------------------------------------------
A30.(Qリストへ戻る) 最大で1000*1000位の行列計算を行いたいような場合、扱える行列の大きさは, 使用するコンピュータのメモリの容量(仮想記憶があればハードディスク容量) によって決まります。 例:A,B,Cとも1000次の行列の場合に C=A*B; といった計算を行いたい。 MaTXの内部では実数を倍精度(double型)で扱うので,行列のデータを保存する だけで A = 1000*1000*8 バイト + B = 1000*1000*8 バイト + C = 1000*1000*8 バイト = 24 Mb のメモリが必要です。インタプリタ(matx)で実行するには,この2倍のメモリ が必要になります。 DJGPP では DOS prompt で go32-v2 を実行して, DPMI memory available: 8000 Kb DPMI swap space available: 40000 Kb のように表示された場合,8000+40000=48000Kb のメモリが使用可能なはずです。 swap はハードディスクの残量によって決まるようです。 最近のパソコンはメモリも多いし、CPUもすごく早いので 500x500程度の行列 演算ならば問題ないですが、それより大きくなると大変です。このあたりの比較 は似たようなソフトで行っています。ご参考まで。
-----------------------------------------------------------------------
Q31. fopen で用いるファイルディスクリプタの型は何でしょう?
-----------------------------------------------------------------------
A31.(Qリストへ戻る) MaTX では Integer を用います。 ----------------------------------------------------------------------- Q32. プログラムをインタプリタとコンパイラで動かした場合、結果が異なりま
した。どんなことが考えられますか?
-----------------------------------------------------------------------
A32.(Qリストへ戻る) 関数呼出しにおいてインタプリタは引数をチェックできますが,プロトタイプ 宣言がないのでコンパイラは引数をチェックできません。 将来的にはプロトタイプ宣言を実現するつもりですが,現バージョンでとれる 方策は,プログラムをインタプリタとコンパイラの両処理系で実行すること です。 ----------------------------------------------------------------------- Q33. ファイルのインクルードが複雑になっていてうまくコンパイルできません。
-----------------------------------------------------------------------
A33.(Qリストへ戻る) 次のような場合どうすればよいのでしょうか? ・A, B, C, D という4つのファイルがある。 ・Dには afo() という関数がある ・B と C は、afo() という関数が必要で、共に D というファイルをインクル ードしている。 ・A は B と C をインクルードしている。 ・A を matc でコンパイルする。 この操作を行うと、D の afo() という関数が Redefinition しようとしたと言 われて、うまくコンパイルができません。 解決例としては o B と C は D をインクルードせず,afo() の宣言だけをする。 o A は B と C をインクルードしない。 o A, B, C, D を matcc でコンパイルする。 (例: matcc A.mm B.mm C.mm D.mm) ----------------------------------------------------------------------- Q34. fread, fwrite の使い方がよくわかりません。
-----------------------------------------------------------------------
A34.(Qリストへ戻る) 関数 fread(fd, size, type) は指定したファイルからバイナリデータを読み 込み,それを成分とする行ベクトルを返します。読み込みに失敗すると,0 x 0 の行列を返します。fd は fopen() が返すファイルディスクリプタ, sizeは 読み込むデータ数, type は読み込むデータの型です。 type には,C 言語の データの型を指定しまう。以下の表に指定できる型を示します。ただし,符合 あり(signed )の型を指定できないことがあります。 ============================================================ バイナリデータの型 ============================================================ "char" 文字 (8 bits) "signed char" 符合あり文字 (8 bits) "unsigned char" 符合なし文字 (8 bits) "short" 整数 (16 bits) "signed short" 符合あり整数 (16 bits) "unsigned short" 符合なし整数 (16 bits) "int" 整数 (16,32,64 bits) "signed int" 符合あり整数 (16,32,64 bits) "unsigned int" 符合なし整数 (16,32,64 bits) "long" 整数 (32 bits) "signed long" 符合あり整数 (32 bits) "unsigned long" 符合なし整数 (32 bits) "float" 単精度浮動小数点数 (32 bits) "double" 倍精度浮動小数点数 (32 bits) ============================================================ 関数 fwrite(fd, mat, type) は行列 mat の成分を指定したファイルに指定し たデータ型のバイナリで書き込みます。データは行の順に書き込まれます。fd は fopen() が返すファイルディスクリプタ, mat は書き込む行列, type は書 き込むデータの型です。 type には,C 言語のデータの型を指定します。 行列の成分を int 型のバイナリでファイルに保存し,そのデータを別の行列 に読み込む例を以下に示します。 // 行列 A を int 型のバイナリデータとして保存する A = [1 2 3 4 5]; fd = fopen("data", "w"); fwrite(fd, A, "int"); fclose(fd); // 5 個の int 型のバイナリデータを行列 B に読み込む fd = fopen("data", "r"); B = fread(fd, 5, "int"); fclose(fd); ----------------------------------------------------------------------- Q35. RtMaTX はどのくらいの負荷に耐えられるのですか?
-----------------------------------------------------------------------
A35.(Qリストへ戻る) 過去の一例を示します。 (1) 環境 PC: Gateway2000 G6-266(Pentium-II 266MHz) Memroy 48M OS: Windows95 IO: Contec製D/A変換ボード(DA|12-8C(PC))を搭載 I/Oアドレス等の予約をマニュアルで行う driver: ドライバは説明書と添付のサンプルプログラムを参考にして, 指定した電圧を出力する関数をmmファイル上に記述. RtMaTX: DOS(DJGPP) version 4.320をreadme.djrに従ってインストール. 実験者: MaTXのプログラミング経験はあるが,RtMaTXを扱うのは初めて. (2) 方法 ・一定時間毎に正弦波の電圧をD/Aに出力させる簡単なmmファイルを作成し, コンパイル後 DOS窓(フルスクリーンではありませんでした)で実行する. D/Aの出力波形をオシロスコープで観察. (3) 結果 a)サンプリングタイムが1msec以上の場合は,サンプリングタイム毎に ホールドされた正弦波がオシロスコープで観察された. 予定した回数だけ繰り返して,正常に終了した. b)サンプリングタイムが1msec未満の場合には,出力波形がおかしくなった. サンプリングタイムが1msecとして動作しているように思われた. 予定した回数だけ繰り返して,正常に終了した. ちなみに RtMaTX では DOS上では 0.1 msec 単位でサンプリング時間を指定できるようになっている。 c)実行中に軽い負荷(ウインドウの位置をずらすなど)をかけても, 影響は見られなかった. d)実行中に重い負荷(netscape communicatorを立ち上げる)をかけると プログラムは極端に遅くなり,ほとんど実行を停止した.波形は一定値になった. 負荷を除くと(立ち上がったnetscape communicatorをアイコン化する), 何事もなかったかのように動きだし,正常な波形を出力して終了した. (マシンがハングアップする事を予想していた) e)安定性について, ・上記実行中に,マシンがハングアップする事は無かった. ・mmファイルが正しければ,必ず正常に終了した.(Ctrl-cも必ず受け付けた ) ・定義していないメモリアクセス(行列の存在しない要素をアクセスする)を 行うと,プログラムは警告を発して,凍ってしまう.この場合は, ウインドウ(DOS窓)を強制終了することによって,一応プログラムを終了で きた. (4) 結論 a)Multi task OS のはずの Windows95でもRtMaTXは安定して動作した. b)サンプリングタイムを1msec以下に設定すると,正しく割り込みが行われない. c)w(3-d) などから察するに,RtMaTXのリアルタイム性は失われているが, 他に負荷をかけなければ,それなりに正確なリアルタイムプログラム として動作する. 実用化には,他のプログラムによる負荷をかけないようにする工夫が必要. ----------------------------------------------------------------------- Q36. m2mm という m-file->mm-file トランスレータがあるそうですが、どこ
にありますか?
-----------------------------------------------------------------------
A36.(Qリストへ戻る) その昔は公開されていましたが、残念ながら現在は公開されておりません。 幸運にも公開された時代に取得している場合、 m2mm を使用するには perl-4.x が必要なので注意が必要です。 m2mm は 2 回実行する必要があります。1回目に変数情報などがまとめられ、 2回目で変数情報が決定されます。変数の型がない Matlab を MaTX に変換する には、変数の型を決定する必要があるためです。 逆に MaTX から Matlab への変換についてはそれほど困難ではないでしょう。 ・変数宣言を取り除く。 ・行列代入式を [[ ]] から [ ; ] に変換する。 ・関数の形態を {} から function ...とする。 ・if for を書き換える。 だけです。 Basic な計算のみならば、どちらも文法はほとんど変わりません。 ----------------------------------------------------------------------- Q37. 数値微分はできますか?
-----------------------------------------------------------------------
A37.(Qリストへ戻る) bilin()という関数を使えばできます。この機能をチェックするプログラム が以下の例題です。 Func void test_bilin() { Polynomial s; Real T; Rational G, Ga; Array w,g,p,ga,pa,gat,pat,gaf,paf,gab,pab; Matrix A,B,C,D,At,Bt,Ct,Dt; Matrix Af,Bf,Cf,Df,Ab,Bb,Cb,Db; s = $; T = 50.0; w = logspace(-3.0, 0.0); G = Rational(T*s); Ga = T*s/(1 + T*s); // 微分要素 Ts {g,p} = Bode_tf(G,w); g = 20*log10(g); mgplot_semilogx(1, w, g, {sprintf("%gs", T)}); // 近似微分要素 T*s/(1 + T*s) {A,B,C,D} = tfm2ss([Ga]); {ga,pa} = bode(A,B,C,D,1,w); ga = 20*log10(ga); mgreplot_semilogx(1, w, ga, {sprintf("%gs/(1 + %gs)", T, T)}); // タスティン台形近似 {At,Bt,Ct,Dt} = bilin(A,B,C,D,1,"Tustin",[T]); {gat,pat} = dbode(At,Bt,Ct,Dt,T,1,w); gat = 20*log10(gat); mgreplot_semilogx(1, w, gat, {"Tusin"}); // 前進差分近似 {Af,Bf,Cf,Df} = bilin(A,B,C,D,1,"FwdRec",[T]); {gaf,paf} = dbode(Af,Bf,Cf,Df,T,1,w); gaf = 20*log10(gaf); mgreplot_semilogx(1, w, gaf, {"FwdRec"}); // 後退差分近似 {Ab,Bb,Cb,Db} = bilin(A,B,C,D,1,"BwdRec",[T]); {gab,pab} = dbode(Ab,Bb,Cb,Db,T,1,w); gab = 20*log10(gab); mgreplot_semilogx(1, w, gab, {"BwdRec"}); } ----------------------------------------------------------------------- Q38. gnuplot の multiplot を使ってプロットできますか?
-----------------------------------------------------------------------
A38.(Qリストへ戻る) 以下、マニュアルからの抜粋です。 mgplot_subplot(win,m,n,p) は,ウィンドウ win を m 行n 列の長方形に面に 分割し,p 番目の面をカレント面にする。これ以後, mgplot() 関連の全ての 操作はこの面に対して行われる。面はウィンドウの一番上の行の左から右に, 上から下の行に向かって数える。 mgplot_subplot(win,m,n,p) は,指定した 位置にすでに面が存在していれば,その面をカレント面にする。 mgplot(win,1,1) または mgplot(win,1,1,1) はウィンドウに存在している全 ての面を消去し,ウィンドウ全体を1個の面にする。 1個ウィンドウを4分割し,4個の異なるグラフをプロットする例を以下に示す。 w = linspace(-PI,PI); s = sin(w); c = cos(w); mgplot_subplot(1,2,2,1); mgplot(1,w,s); mgplot_subplot(1,2,2,2); mgplot(1,w,c); mgplot_subplot(1,2,2,3); mgplot(1,w,2*s); mgplot_subplot(1,2,2,4); mgplot(1,w,2*c); この例では,左上に sin(x),右上に cos(x),左下に sin(2x),右下に cos(2x) が表示される。 ----------------------------------------------------------------------- Q39. Windows では大文字と小文字を区別しないので、UNIX で使っていたファイ
ルが使えず困っています。
-----------------------------------------------------------------------
A49.(Qリストへ戻る) MaTX は,変数や関数の名前の大文字と小文字を区別しますが,Windows 95/NT はファイル名の大文字と小文字を区別しないので,MaTX もファイル名について は大文字と小文字を区別できません。 ただし,require 修飾子を用いれば,ある程度回避できます。 例えば,afo(), AFO(), Afo() という関数があり,これらを区別してファイル から読み込み,実行するには,3 個の関数をAFO.MM という 1 個のファイルに 保存し,呼び出す側でこれらの関数を require 修飾子付きで宣言すれば良い のです。 // AFO.MM Func void af() { } Func void AFO() { } Func void Afo() { } // 呼び出し側 void afo() require "AFO.MM"; void AFO() require "AFO.MM"; void Afo() require "AFO.MM"; Func void bar() { afo(); AFO(); Afo(); } ----------------------------------------------------------------------- Q40. インクルードしたら、syntax error が出るんですが。
-----------------------------------------------------------------------
A40.(Qリストへ戻る) #include "afo.mm" でインクルードした場合、afo.mm が Func void afo(){ }ここ1 ここ2 ここ2 まで return code が入っていれば問題ないが、ここ1 でファイルが 終了している場合 "./afo.mm", at or near line 2, "}# 2 "main.mm" 2", syntax error とその行でエラーが発生します。これは仕様です。C言語でも同様の現象が 起きます。 ----------------------------------------------------------------------- Q41. MaTX コードのそれぞれの行の実行に必要な時間が知りたいです。
-----------------------------------------------------------------------
A41.(Qリストへ戻る) settimer() と gettimer() という関数があります。これを使えば, settimer(); qr(rand(100,20)); print gettimer(); で QR 分解にかかったプロセスの実行時間(CPUを占有した時間)を計測できます。 ----------------------------------------------------------------------- Q42. matc するファイルには必ず main 関数が必要ですか?
-----------------------------------------------------------------------
A42.(Qリストへ戻る) 必要です。ただし、matc したあとにできる実行ファイルの名前は第一引数の mmファイル名です。 ----------------------------------------------------------------------- Q43. インタプリタで main 関数の引数をシミュレートするには?
-----------------------------------------------------------------------
A43.(Qリストへ戻る) // afo.mm Func void main(argc, argv) Integer argc; List argv; { Integer i; Real s; s = 0.0; for (i = 2; i <= argc; i++) { print argv(i,String), "\n"; s = s + Real(argv(i,String)); } print s; } のようなファイルの場合 % matc afo.mm % ./afo 1.0 2.0 を実行すると, 1.0 2.0 s = 3.00000000E+00 の結果を得ます。同様のことをインタプリタで行うには, % matx afo.mm -e 'main(3,{"afo","1.0","2.0"})' とします。 ----------------------------------------------------------------------- Q44. Windows95 で MaTX の install directory が深い場合、コマンドラインが
が長すぎることで問題が出ています。
-----------------------------------------------------------------------
A44.(Qリストへ戻る) Win95 の DOS 窓を使うとき, config.sys に SHELL=C:\COMMAND.COM /P /U:255 /L:768 /E:2048 に書くと,コマンドラインに多くの文字を書けるようになると思います。 ちなみに /E:nnnnn --- 環境変数領域の初期サイズをバイト数(160〜32768)で で指定する。デフォルトは256。 /L:nnnn --- パラメータ /P 指定時に内部バッファサイズをバイト 数(128〜1024)で指定する。デフォルトは256。 /U:nnn --- パラメータ /p 指定時に入力バッファサイズをバイト 数(128〜255)で指定する。デフォルトは128。 /P --- 新しいコマンドインタプリタを常駐させる。EXITによ る終了は不可となる。 です。ついでに autoexec.bat に DOSKEY /LINE:255 と書いておくと,ヒストリのバッファサイズも 255 になります。 ----------------------------------------------------------------------- Q45. 連続系対象、離散系制御器のシミュレーションで演算時間遅れはどう書く
のでしょうか?
-----------------------------------------------------------------------
A45.(Qリストへ戻る) 一番簡単な方法は大域変数を用いることでしょう。たいていの場合一サンプル 遅れで表すことになりますので、 ある SISO な連続系 A,B,C プラントに対して一サンプル遅れで SISOな離散 系 Ac,Bc,Cc,Dc の制御器を適用する例を示します。この例では、制御器の 出力 yc の一つ前の値を pre_yc とし、これを link_eqs の UY に代入する ことで一サンプル遅れを記述しています。 Matrix A, B, C, D; Matrix Ac, Bc, Cc, Dc, Xc; Matrix pre_yc; Func void main() { Real end_time, sampling_time, dtsav, h; Matrix x0, TC, XC, UC: Matix diff_eqs(), link_eqs(); h = 1.0e-3; dtsav = 1.0e-2; sampling_time = 0.01; end_time = 10.0; x0 = Z(Rows(A), 1); Xc = Z(Rows(Ac), 1); pre_yc = Z(Rows(Cc),1); {TC, XC, UC} = OdeHybrid(0.0, end_time, x0, sampling_time, diff_eqs, link_eqs, h, dtsav); print [[TC][XC][UC]] >> "result.mat"; } Func void diff_eqs(DX, t, X, UY) Real t; Matrix X, DX, UY; { Matrix x, u; x = X(1:Rows(A), 1); u = UY(1,1); DX = A * x + B * u; } Func void link_eqs(UY, t, X) Real t; Matrix UY, X; { Matrix x, yc, uc; x = X(1:Rows(A), 1); uc = C * x; yc = Cc * Xc + Dc * uc; Xc = Ac * Xc + Bc * uc; UY = pre_yc; pre_yc = yc; } 上位の制御器と下位の制御器があって、それぞれ演算時間遅れがあるという ケースはよくあることです。たとえば下位のサーボループが早いサンプリング 時間で回っており、その上位の制御系はサーボループへの目標値を決定している 場合などはこのケースにあてはまります。このような、数種類の演算時間遅れが あるシステムを取り扱いたい人は、その演算時間遅れの最大公約数な値を疑似 サンプル時間として OdeHybrid を使い、link_eqs の中で計算を行うか行わ ないかを選ぶという方法もあります。 たとえば 0.02 サンプリング時間のシステムに対して、制御器がK1,K2の 2 種類あり、それぞれ 0.002, 0.004 の演算時間遅れがあるとします。この 場合、OdeHybrid のサンプリング時間を最大公約数の 0.002 とします。 よって link_eqs の UY は 10回に 1回の割合だけ更新されなければなりません。 しかし演算時間遅れがありますので、10回 link_eqs が呼ばれた中で 1回計算は 行うが、その計算の出力は K1 は 1回おいてから出力し、K2 は 2回おいてから 出力すればよいことになります。つまり、 | | 本当のサンプル | | | | | | | | | | | | | | | | | | Ode で計算するサンプル -------------------------------------> time 0 1 2 3 4 5 6 7 8 9 0 で プラント出力を計算する。 0 の情報を用いて K1, K2 の制御器の出力を計算する。 1 の時に K1 の出力を UY に代入する。 2 の時に K2 の出力を UY に代入する。 ということになります。 しかし、この場合サンプリング時間が最大公約数に限られる、OdeHybrid の サンプリング時間が短くなりすぎる、といった欠点が考えられます。 でもやっぱり任意な演算時間遅れがほしいという人は OdeXY を用いることに なります。OdeXY はシミュレーションの状態ベクトル、入出力ベクトルの 任意の時間を引き出す関数ですから、たとえば、一サンプル遅れは Func void link_eqs(UY, t, X) Real t; Matrix UY, X; { Matrix pre_X, pre_UY, pre_x, uc; x = X(1:Rows(A), 1); {pre_X, pre_UY} = OdeXY(t-sampling_time); if (Rows(pre_X) == 0) { pre_X = Z(pre_X); pre_UY = Z(pre_UY); } pre_x = pre_X(1:Rows(A), 1); uc = C * pre_x; yc = Cc * Xc + Dc * uc; Xc = Ac * Xc + Bc * uc; UY = yc; } とします。link_eqs が呼ばれた時に出力される UY はそのひとつ前の サンプル時間の情報 pre_x を用いて計算された uc をもとにしていますので 一サンプル遅れが実現できることになります。 ただし、制御器の状態の初期値が 0 でない場合には最初の t=0 での制御器 出力が出てしまいますので、注意が必要です。 これを発展させて任意の演算時間遅れを実現します。tdelay だけ演算時間が あるとします。 プラント(i) (i) (i+1) |<--sampling_time-->| | | | | -------------------------------------> time |==== tdealy |==== | | | | (A) | | |<--constant-------->| (j) (j+1) 制御器(j) 今まではプラント時間を中心に考えてきました。しかし、link_eqs は サンプリング時間で 1度しか呼ばれないので、プラント時間を中心に考える ことはできません。プラント時間を中心に考えた場合には、サンプルの間に link_eqs の出力を変化させなければなりませんが、OdeHybrid では、それが できないからです。 しかし、実際には別にプラント時間(i)にこだわる必要はありません。 制御器を中心に時間の推移を考えればよいのです。つまり、OdeHybrid が 考えるサンプルを制御器側(j)に考えます。すると、単に {pre_X, pre_UY} = OdeXY(t-tdelay); とするだけでよいことになります。OdeHybrid は j の時間間隔で呼ばれます。 よって、 Func void link_eqs(UY, t, X) Real t; Matrix UY, X; { Matrix pre_X, pre_UY, pre_x, uc; x = X(1:Rows(A), 1); とした時に取り出される x は (i)時刻のものではなく、(j)時刻のものです。 ここに注意が必要です。 しかし、この場合最初のサンプルの出力はどうなってしまうのでしょう? プラント(i) (i=0) (i=1) |<--sampling_time-->| | | | | -------------------------------------> time |==== tdealy |==== | | | | (A) | | |<--constant-------->| (j=0) (j=1) 制御器(j) 普通はプラント時刻を中心に考えますので、t=i=0 ですから、t=tdelay までは 制御器の出力は 0 のはずです。制御器側時刻(j)で考えた場合、 j=0 の前の、 t=i=0 oから t=tdelay までの時間は存在しないことになってしまいます。 ひとつの方法は OdeHybrid に渡す状態の初期値 x0 を操作することです。 シミュレーションは制御器時間で行われますので、x0 は j=0 の時の t=tdely の時の値にする必要があります。つまり、 前もって制御器出力は 0 として、t=i=0 におけるプラントの初期状態から t=tdelay までのシミュレーションを行い、t=tdelay の場合のプラント状態 (つまり、制御器時間における x0 の値)を決定しておきます。そして、その値 を x0 として演算時間遅れのシミュレーションを行えばよいわけです。 この場合も、制御器の状態初期値が 0 ならば問題ありませんが、状態初期値 が 0 以外の場合には t=j=0 で制御器の出力を 0 にする必要があります。 ----------------------------------------------------------------------- Q46. シミュレーション結果のデータファイルが巨大です。
-----------------------------------------------------------------------
A46.(Qリストへ戻る) この Ode は {T, X, U} = Ode(t0, t1, x0, diff_eqs, ..., link_eqs, h, dtsav); Array T, X, U; Real t0, t1, h(= 4.0E-2), dtsav(= max(h, 1.0E-3)); Matrix x0; Matrix diff_eqs(), link_eqs(); というもので、dtsav という変数がデータをセーブする間隔を表します。 極端に長い時間をシミュレーションする際にはここの値を調整してデータ ファイルの巨大化を防ぐことができます。 ----------------------------------------------------------------------- Q47. バイナリファイルの read の挙動がおかしいです。
-----------------------------------------------------------------------
A47.(Qリストへ戻る) Windows ではバイナリファイルの open を行う際には明示的に b オプションを つける必要があります。そうでないと OS が勝手に改行コードなどの変換を行 うからです。MaTX 5.0.12 より fopen の際に b オプションをつけることが できるようになりました。この version 以降を用いると回避できます。 なお、UNIX においてはこのような現象は発生しませんので、問題なく open して read できるはずです。 ----------------------------------------------------------------------- Q48. 時分割でシミュレーションしたいです。
-----------------------------------------------------------------------
A48.(Qリストへ戻る) 極端に時間の長い 1000 秒間などのシミュレーションの場合には、100 秒ごと に時間を save したいという要求があるかと思います。MaTX で Ode 関数を 用いた場合にはその Ode 関数の途中でデータを save することはできません。 そこで、Ode を複数回呼び出すことになります。Ode は状態の初期値を指定でき ますので、一度目に呼び出された Ode で得られた最終状態を次に用いればよい ことになります。つまり、 FileNameBase = "result"; DATAALL = Z(10, 1000); for (i = 1; i < 10; i++) { if (i == 1) { x0 = Z(3, 1); // 最初は状態の初期値は 0 } else { x0 = XC(1:3, Cols(XC)); // 2回目以降は前回の最後の状態 } {TC, XC, UC} = OdeHybrid(100.0*(i-1), 100.0*i, sampling_time, x0, diff_eqs, link_eqs, h, dtsav); // 100*(i-1)秒から 100*i 秒までをシミュレーション DATA = [[ TC ][ XC ][ UC ]]; DATAALL(1, i, DATA) = DATA; // データをアペンド FileName = FileNameBase + int2str(i); // それまでの結果を save するファイル名を決める。 print DATAALL >> FileName; } のようになります。 ----------------------------------------------------------------------- Q49. シミュレーションの際、simulink の scope のような機能はありませんか?
-----------------------------------------------------------------------
A49.(Qリストへ戻る) UNIX では pipe を用いてデータを MaTX からほかのツールに飛ばすことができる でしょう。Windows においては、残念ながら現在のところ、そのような機能は備 わっておりません。どうしてもシミュレーション途中の変数をグラフィカルで見 たいという場合には、時分割シミュレーションの形式にしてデータファイルを 少しずつ作っていくか、link_eqs 関数などから C 言語を用いて何らかのツールに データを飛ばすしか方法はありません。 データを飛ばす場合には、連続時間のシミュレーションの場合には、diff_eqs が 積分刻みをいったりきたりして呼ばれてしまうので、飛ばすタイミングに注意が 必要です。 一番容易な方法は、socket 通信を用いた処理関数を C 言語で記述し、それらを リンクして MaTX から外に飛ばすことでしょう。 ----------------------------------------------------------------------- Q50. OdeAuto の Auto ってなにを自動化してくれているのですか?
-----------------------------------------------------------------------
A50. (Qリストへ戻る) 積分を行う際の時間刻み幅 h を自動的に調節してくれています。アルゴリズム は以下のようになっています。 x を h 進める前に次の 2 つの計算をします。 1. x を h/2 だけ 2 回進めたときの値を ya、x をh だけ 1回進めた時の 値を yb とします。 (ya - yb)/ya <= epsilon の判定を行い、この条件が満たされるまで h を 1/2 ずつ小さくして いきます。 2. x を h だけ 2 回進めたときの値を yc、x を 2h だけ 1 回進めた時の 値を yd とします。 (yc - yd)/yc <= epsilon の判定をし、この条件が満たされるまで h を 2 倍ずつ大きくします。 つまり、この計算では h を決めるために、積分 1step の間に最低 3 回の 計算が必要になります。 ----------------------------------------------------------------------- Q51. RKF45 って何ですか?
-----------------------------------------------------------------------
A51. (Qリストへ戻る) 数値積分では、一般に 4次のルンゲクッタ法が用いられますが、当然 5次の ルンゲクッタ法も存在します。 その 5 次のルンゲクッタ法の計算を行う場合に、非常に巧みな演算で同時に 4 次の計算も行えるという方法を Fehlberg という人が考えました。この人の 頭文字をとって RKF45 アルゴリズムと呼んでいます。 Ode45Auto という関数は RKF45 アルゴリズムを用いて同時に計算された 4 次と 5次の二つのルンゲクッタ法の誤差から積分刻みを自動調整しています。 Ode45Auto は積分 1 step あたり最低 2 回の計算ですみます。OdeAuto は 最低 3 回の計算で必要ですので、速度的には 45Auto が早いといえます。 ----------------------------------------------------------------------- Q52. 3次以上の多次元配列が使いたいです。
-----------------------------------------------------------------------
A52. (Qリストへ戻る) MaTX には Array と Matrix しか配列に関する型は存在しません。従って、 C 言語のように double A[3][5][3]; のようには直接記述できません。しかし、考えてみれば 3 次元配列といって も 2 次元配列の配列でありますから、ピース行列を用いた記述と本質的には 等価になります。つまり、 EI = Z(5,3); A = Z(1, 3, EI); とすれば、5行3列の 2次元配列が 1行ブロック3列ブロック分確保されますから double A[3][5][3] と本質的には同じです。 従って 4次元配列まではこの考え方と同様に記述できます。 たとえば、C 言語における A[2][3][5][3] の中での [0][1][0][2]成分への 読みについては result = A[0][1][0][2]; としますが、MaTX では result = [A(1, 2, EI)](1,3); と書けば同様です。また、書き込みについては A[0][1][0][2] = 1.0; と同様なことは EJ = Z(5,3); EJ(1,3) = 1.0; A(1, 2, EI) = EJ; と記述できます。 ----------------------------------------------------------------------- Q53. Ode の積分刻みってどうやって決めるのですか?
-----------------------------------------------------------------------
A53. (Qリストへ戻る) この質問は MaTX に限らず、自作ソフトも含めたいかなるシミュレーションの 場合にも遭遇する問題です。刻みを大きくすれば当然シミュレーションに要 する時間も短くなります。 "十分に小さい"刻みがよいという表現が使われるのは、シミュレーション対象 の特性に強く依存するからです。 信頼性のあるシミュレーション結果は、刻み幅を自動調節する OdeAuto か Ode45Auto を用いて誤差を陽に指定することで得られます。 しかし、自動調節によってシミュレーションに要する時間が増大する場合も あります。非常に固有振動数が高いシミュレーション対象の場合には、激しく 状態が変化しますから、刻み幅自動調節によって刻み幅がどんどん短くなって しまい、シミュレーションに要する時間が激増します。 十分に小さいシミュレーション結果をまず出しておいてから、"同じような" 結果を出すような刻み幅まで大きくしていって、シミュレーションに要する 時間を短縮化することはよくあることです。 ----------------------------------------------------------------------- Q54. a = [[1 2 3][4 5 6][7 8 9]] の逆行列がおかしいのですが。
-----------------------------------------------------------------------
A54. (Qリストへ戻る) 不思議なことに?、例題によく使えそうなこの行列は実はかなり条件数の悪い 行列です。(というか 1 行目から2行目を引いて、2行目から3行目を引いてという 普通の処理で明らかなのですが) MaTX(1) a = [[ 1 2 3][4 5 6][7 8 9]]; MaTX(2) inv(a) の結果は非常に大きな値でしょう。また、 MaTX(3) a*a~ はきっと単位行列になりません。 MaTX(3) cond(a) で行列の条件数を調べられますが、この行列は cond(a) = 1.9626899e+17 と いうものであり、逆行列を求めようとすべき行列ではありません。 つまり、ランクが 2 という行列なわけで、理論的には逆行列は存在しない のに強引に計算しようとすると、こういうことになるわけです。 このような特殊な行列に限らず、どんな計算をするときにも行列の条件数には 注意を払うべきです。 ----------------------------------------------------------------------- Q55. 計算結果の行列に存在する非常に小さい成分を全部 0 にしたいのです。
-----------------------------------------------------------------------
A55. (Qリストへ戻る) たとえば以下のような場合が考えられます。 MaTX(1) A = [[1 2][3 4]]; MaTX(2) B = A * A~ === [ans] : ( 2, 2) === ( 1) ( 2) ( 1) 1.00000000E+00 0.00000000E+00 ( 2) 8.88178420E-16 1.00000000E+00 このゴミのような小さな値が気になるのであれば、round2z という関数を用い ます。この関数は tolerance より小さい値を 0 に丸めます。 MaTX(3) B = round2z(A * A~, 1e-13); とすれば === [ans] : ( 2, 2) === ( 1) ( 2) ( 1) 1.00000000E+00 0.00000000E+00 ( 2) 0.00000000E+00 1.00000000E+00 となるでしょう。 ----------------------------------------------------------------------- Q56. Meadow を使っています。.emacs の MaTX modeの設定を教えてください。
-----------------------------------------------------------------------
A56. (Qリストへ戻る) Windows な環境で MaTX をやるには Meadow はすばらしい環境です。 .emacs に記述する例として以下のようなものがあります。 ------ここから------- (defun my-matx-mode-hook-func () (setq c-file-style "my-matx")) ; (defconst my-matx-style '( ;; This offset is based on "KIYOTA-San" style. (c-basic-offset . 4) ;; 基本のオフセット (c-comment-only-line-offset . 0) ;; コメントのみの行のオフセット (c-offsets-alist ;; + : c-basic-offset x 1 ;; - : x -1 ;; ++: x 2 ;; --: x -2 ;; * : / 2 ;; / : / -2 を表す (integer) ;; オフセットとは、基本的に直前の空白でない行の先頭の非空白類文字 ;; からのずれを表す。 . ((string . c-lineup-dont-change) (c . c-lineup-C-comments) ;; コメント内でのオフセット (defun-open . 0) ;; 関数を始めるときの { の位置 (defun-close . 0) ;; 関数を終わるときの } の位置 (defun-block-intro . +) ;;関数が始まった { の次のオフセット (class-open . 0) (class-close . 0) (inline-open . +) (inline-close . 0) (func-decl-cont . +) (knr-argdecl-intro . +) ;; 関数の引数宣言の部分のオフセット (knr-argdecl . 0) (topmost-intro . 0) (topmost-intro-cont . 0) (member-init-intro . +) (member-init-cont . 0) (inher-intro . +) (inher-cont . c-lineup-multi-inher) (block-open . 0) ;; 関数内での { のオフセット (block-close . 0) (brace-list-open . 0) (brace-list-close . 0) (brace-list-intro . +) (brace-list-entry . 0) (brace-entry-open . 0) (statement . 0) (statement-cont . +) ;; 構文が続くときのオフセット (statement-block-intro . +) ;; 関数内の { の次の行のオフセット (statement-case-intro . +) ;; case ?: の次の行のオフセット (statement-case-open . 0) (substatement . +) (substatement-open . 0) (case-label . 0) ;; case ?: のオフセット (access-label . -) (label . 0) ;; label のオフセット MaTX では使わない (do-while-closure . 0) ;; do-while 文の while から始まる行のオフセット (else-clause . 0) ;; if 文の else から始まる行のオフセット (catch-clause . 0) (comment-intro . c-lineup-comment) (arglist-intro . c-lineup-arglist-intro-after-paren) (arglist-cont . 0) (arglist-cont-nonempty . matx-lineup-arglist) ;; )と]のオフセット (arglist-close . matx-lineup-arglist) ;;完全にブロックが閉じる)と]のオフセット (stream-op . c-lineup-streamop) (inclass . +) (cpp-macro . -1000) (cpp-macro-cont . c-lineup-dont-change) (friend . 0) (objc-method-intro . -1000) (objc-method-args-cont . c-lineup-ObjC-method-args) (objc-method-call-cont . c-lineup-ObjC-method-call) (extern-lang-open . 0) (extern-lang-close . 0) (inextern-lang . +) (namespace-open . 0) (namespace-close . 0) (innamespace . +) (template-args-cont . +) (inlambda . c-lineup-inexpr-block) (lambda-intro-cont . +) (inexpr-statement . 0) (inexpr-class . +))))) (c-add-style "my-matx" my-matx-style) (add-hook 'matx-mode-hook 'my-matx-mode-hook-func) ; (defun Usuda-emacs-header-change () (interactive) (save-excursion (condition-case nil (progn ;バージョン変更 (goto-char (point-min)) (search-forward-regexp "\\(;;[ \t]*Version[ \t]*:[ \t]*\\)\\([^\n]*\\)") (let ((DATA (match-data))(STR (match-string 2))(NEW)) (string-match "\\([0-9]+\\.[0-9]+\\.\\)\\([0-9]+\\)" STR) (setq NEW (concat (match-string 1 STR)(number-to-string (1+ (string-to-number (match-string 2 STR)))))) (set-match-data DATA) (replace-match (concat (match-string 1)NEW)) ) ;モディファイ時間 (goto-char (point-min)) (search-forward-regexp "\\(;;[ \t]*Last-Modify[ \t]*:[ \t]*\\)\\([^\n]*\\)") (replace-match (concat (match-string 1)(current-time-string)) t) )(error)) )) ------ここまで------- ----------------------------------------------------------------------- Q57. Meadow を使っています。色をつけたいんです。
-----------------------------------------------------------------------
A57. (Qリストへ戻る) font-lock を使う設定をします。.emacs には以下のように記述できます。 ------ここから------ ;; ;; font-lock-mode の設定 ;; ; font-lock-mode を常時利用する (global-font-lock-mode t) ; 表示の高速化のために fast-lock-mode を利用する (setq font-lock-support-mode 'fast-lock-mode) ; キャッシュファイルの格納先を指定する (let* ((file-dir "~/.emacs-flc")) (if (file-exists-p file-dir) ; ~/.emacs-flc の存在をチェック ; 存在するならば、キャッシュファイルの格納先に指定 (setq fast-lock-cache-directories (list file-dir)))) ------ここまで------ また、色を変えたい場合は .emacs に以下のように記述すれば希望の色を つけられます。 ------ここから------ (make-face 'comment-face) (set-face-foreground 'comment-face "moccasin") (setq font-lock-comment-face 'comment-face) ; (make-face 'string-face) (set-face-foreground 'string-face "orange") (setq font-lock-string-face 'string-face) ; (make-face 'keyword-face) (set-face-foreground 'keyword-face "cyan") (setq font-lock-keyword-face 'keyword-face) ; (make-face 'builtin-face) (set-face-foreground 'builtin-face "Plum1") (setq font-lock-builtin-face 'builtin-face) ; (make-face 'function-name-face) (set-face-foreground 'function-name-face "White") (setq font-lock-function-name-face 'function-name-face) ; (make-face 'variable-name-face) (set-face-foreground 'variable-name-face "White") (setq font-lock-variable-name-face 'variable-name-face) ; (make-face 'type-face) (set-face-foreground 'type-face "yellow") (setq font-lock-type-face 'type-face) ; (make-face 'constant-face) (set-face-foreground 'constant-face "green") (setq font-lock-constant-face 'constant-face) ; (make-face 'warning-face) (set-face-foreground 'warning-face "Pink") (setq font-lock-warning-face 'warnig-face) ; (make-face 'reference-face) (set-face-foreground 'reference-face "Pink") (setq font-lock-reference-face 'reference-face) ------ここまで------ ----------------------------------------------------------------------- Q58. なんかフォントの色が灰色で見にくいのですが。
-----------------------------------------------------------------------
A58. (Qリストへ戻る) Windows では terminal はかなり限られてしまいます。Windows 95/98 では DOS 窓を使わざるを得ません。しかも DOS 窓のフォントの色はなんか灰色で 見にくいですね。DOS窓の色は Windows NT では自由に設定できます。 しかし、Windows 95/98 ではできません。DOSWIN10.LZH というソフトがこれを 解消してくれます。 ----------------------------------------------------------------------- Q59. ある条件をみたした時に Ode を止めたいのですが。
-----------------------------------------------------------------------
A59. (Qリストへ戻る) OdeStop という関数を用います。 たとえば、状態ベクトル X の (1,1) 成分が 0.2 より小さくなった時にシミュ レーションを止めたい場合は、diff_eqs や link_eqs の中に if (X(1,1) < 0.2) { OdeStop(); } と記述すればよいです。Odeは、この OdeStop が呼ばれるまでに計算された 結果を返しますので、そこまでのシミュレーション結果が無駄になることは ありません。 不安定なシステムなどで、シミュレーションが発散してしまうときには、状態 を、ある程度大きな値でこのようにトラップすれば、発散してしまったシミュ レーションに時間を費やすことがないでしょう。 ----------------------------------------------------------------------- Q60. Matlab のように便利な toolbox は公開されていませんか?
-----------------------------------------------------------------------
A60. (Qリストへ戻る) m-file だけで記述される Malab の toolbox は、その気になれば、その ほとんどを MaTX へ変換できるでしょう。しかし、Matlab toolbox は売り物 ですから、単に変換したものをそのまま公開することはできないでしょう。 かといって、 m-file で実現されているアルゴリズムは、そのほとんどが、 特許となっているようなものではなく、論文として立派に公知なものに記述 されているわけですから、それを各自が mm-file 化することは問題ないと 思われます。 論文を理解するには、よく読んで数式を追って証明を理解するのはもちろん ですが、実際に論文で提案されている方法をシミュレーションしてみて初め て実感できるものではないでしょうか。 ----------------------------------------------------------------------- Q61. なんか MaTX for Borland-C の計算結果がおかしいです。
-----------------------------------------------------------------------
A61. (Qリストへ戻る) 残念ながら、Borland-C を用いた MaTX では倍精度の計算ができていません。 なぜか、どこかで単精度に変換されてしまい、固有値の算出などに耐え得る ものになっておりません。Borland-C 版の MaTX を使うときには計算精度に ついて十分注意をはらう必要があります。 しかし、この問題は MaTX-BC ver.5.3.8 以降では修正されています。 ただ、5.3.8 で MaTX-VC にバグが混入しましたので、ver.5.3.12 以降を 使えば計算結果に問題はないはずです。 ----------------------------------------------------------------------- Q62. Windows NT/2000/XP で MaTX を使用すると,画面が乱れます。
-----------------------------------------------------------------------
A62. (Qリストへ戻る) Windows NT/2000/XP のWindowsディレクトリの system32 にある CONFIG.NT の 中に ansi.sys ドライバーの設定を追加してください。例えば device=%SystemRoot%\system32\ansi.sys あるいは, devicehigh=%SystemRoot%\system32\ansi.sys として下さい。 ----------------------------------------------------------------------- Q63. 複素行列の擬似逆行列がおかしいです。
-----------------------------------------------------------------------
A63. (Qリストへ戻る) MaTX ver5.2.5-5.3.3 では複素行列の特異値分解にバグが混入しています。 擬似逆行列の計算には特異値を用いますから、このバグが混入した MaTX で 複素行列の擬似逆行列を計算できません。 しかし、その MaTX でも例えば以下のような関数で擬似逆行列は計算可能です。 Func CoMatrix pseudoinv2(a) CoMatrix a; { Integer i, ranka; Matrix D1, D, Dinv; CoMatrix V, U, Ainv, F; D1 = Re(Matrix(vec2diag(sqrt(Array(eigval(a#*a)))))); ranka = rank(a); D = Z(Rows(a), Cols(a)); for (i = 1; i <= ranka; i++) { D(i, i) = D1(i, i); } V = eigvec(a#*a); U = eigvec(a*a#); F = a * V; for (i = 1; i <= ranka; i++) { U(:, i) = [Matrix(sqrt(Array(eigval(a#*a))))](i, 1)~* F(:, i); } ranka = rank(a); Dinv = Z(Cols(a), Rows(a)); for (i = 1; i <= ranka; i++) { Dinv(i, i) = D(i, i)~; } Ainv = V * Dinv * U#; return Ainv; } なんか for loop が多くてかっこ悪いですね。それにゼロ特異値の判定に rank を使うのは問題がありそうです。実はこんな風に改良できます。 Func CoMatrix pseudoinv2(a) CoMatrix a; { Integer ranka; Real tol; Matrix sval, Dinv; CoMatrix V, U, Ainv; sval = sqrt(Array(Re(eigval(a#*a)))); // 半正定エルミート行列の特異値 tol = norm(a, "fro") * EPS; // 許容誤差 ranka = Integer(sum(sval .> tol)); // tol より大きい特異値の数 U = eigvec(a*a#); V = eigvec(a#*a); U(:, 1:ranka) = [a * V](:, 1:ranka)*vec2diag(sval(1:ranka).~); Dinv = Z(Cols(a),Rows(a)); Dinv(1:ranka,1:ranka) = vec2diag(sval(1:ranka).~); Ainv = V * Dinv * U#; return Ainv; } このようにvec2diag や diag2vec を用いることで、 for loop をなくす ことができます。for loop はインタプリタにおいて実行速度の低下を招く ので、できるだけ使わないようにしましょう。(可読性を損なわない程度に) [a * V](:, 1:ranka)*vec2diag(sval(1:ranka).~); という表現はとても便利です。計算途中をテンポラリの変数に入れることなく、 成分を参照することが可能です。例えば、 C = A * B; val = C(3,1); というような無駄な変数 C を定義することなく、 val = [A * B](3,1); と記述できます。 ----------------------------------------------------------------------- Q64. mm ファイルが実行されません。それに、なんのメッセージも出ません。
-----------------------------------------------------------------------
A64. (Qリストへ戻る) これは、おそらくその mm ファイルの先頭で #include "*****.mm" として、なんらかのファイルを include しているはずです。そのファイルが 存在しない場合には default では MaTX は何もメッセージを出してくれず、 何も実行してくれません。 このような場合は多くは matx -v というメッセージ表示モードにすると問題が解決できる場合があります。 ----------------------------------------------------------------------- Q65. ソケット通信がうまいくいきません。
-----------------------------------------------------------------------
A65. (Qリストへ戻る) ver5.3.x でのWindows版ではソケット通信がうまくいかないケースが多々報告 されています。ver5.3.12 以降では修正されています。 ----------------------------------------------------------------------- Q66.
-----------------------------------------------------------------------
A66. (Qリストへ戻る) ----------------------------------------------------------------------- Q67.
-----------------------------------------------------------------------
A67. (Qリストへ戻る) ----------------------------------------------------------------------- Q68.
-----------------------------------------------------------------------
A68. (Qリストへ戻る)