けいじゅ@いしつかです. In [ruby-dev:27730] the message: "[ruby-dev:27730] Re: Matrix class is broken without mathn", on Nov/18 02:02(JST) Shin-ichiro HARA writes: >原です。 >ちょっと間が空いてしまいました。すいません。Integer成分の >determinantの話の続きです。 いえ, こちらこそ. まず, 原さんの意見に賛成するのですが, いくつか誤解があるようなので, そちらから: >私が誤解しているのか、どうも石塚さんの話がぴんとこないのです >が、、、私は、現行ではRationalをrequireするだけでなく、更に >各成分をRational化してdetに放り込まなくてはならないのが問題 >だと思うのです。 話をはしょり過ぎましたかね. detの定義の中でrational.rbをrequireし, かつquoで計算するようにしよう というのが, 私の主張でした. quoで計算することになりますので, 成分をRational化をする必要はなく, quo が出てきた時点でRational化されます. >>det計算中Rationalをrequireする場合, >>すべてがIntegerの場合, 結果は必ずInitegerになり, >>行列中1要素でもFloatが入っている場合, 結果は必ずFloatになり, >>Rationalになることはありません. > >今回問題になっているのは、整数行列の行列式はどうあつかうべき >か、ですよね? です. ここで言いたかったのは, 成分にFloatが混じっていてもちゃんと動作 するよといいたかったのでした. >>ですので, (内部の計算がどうなっているかは別として), それぞれの >>クラスに応じた自然な結果が出ることが必ず保証できます. > >細かい話ですが、整数行列の成分をRational(x, 1)で全て有理数 >化してdetを計算させると、結果はRationalですよね。mathn.rbを >導入するとIntegerですけど。 そうなりますね. 整数行列のdet結果はRational(x,1)になります. # 上で述べてあるように, Rational化は特に必要ないです. >>あと, パフォーマンスのことを気にするなら, 最初っから要素は >>Floatにすべきだと思います. > >私がquoを使った方がいいと思うのは、整数行列のdetを計算したと >きとんでもない値が出るのを防げるからという理由で、ただその一 >点に尽きます。 >それに対して石塚さんはrational.rbをrequireして各成分、 >Rational()でラップしてくれ、と主張しているわけですよね。 >私はそれは面倒すぎるのではないかと、そして今後も忘れて >意図しない結果に悩む人が大勢出るのではないかと思います。 上で述べたように私の案でもそういう問題は解決しています. >それならちょっとかっこ悪くても「quoでFloat」でいいのでは >ないでしょうか。 >現行をquo式にしたメリットデメリットまとめると、 > >-------------------------------------------------------------- >成分 | 現行 | quo式 >-------------------+--------------------+--------------------- >全てInteger | NG | 戻値:Float > | | 誤差が気になることも >-------------------+--------------------+--------------------- >全てInteger | NG | 戻値:Rational >rationa.rb導入のみ | | 遅い >-------------------+--------------------+--------------------- >全てRational | 戻値:Rational | 戻値:Rational > | 遅さは気にならない | 遅さは気にならない >-------------------+--------------------+--------------------- >全てFloat | 戻値:Float | 戻値:Float > | 誤差は気にならない | 誤差は気にならない >-------------------+--------------------+--------------------- いちおう, Rational+quoだと: -------------------------------------------------------------- 成分 | 現行 | Rational+quo式 -------------------+--------------------+--------------------- 全てInteger | NG | 戻値: Integer(にできる) | | 遅い -------------------+--------------------+--------------------- 全てInteger | NG | 戻値: Integer(にできる) rationa.rb導入のみ | | 遅い -------------------+--------------------+--------------------- 全てRational | 戻値:Rational | 戻値:Rational | 遅さは気にならない | 遅さは気にならない -------------------+--------------------+--------------------- 全てFloat | 戻値:Float | 戻値:Float | 誤差は気にならない | 誤差は気にならない -------------------+--------------------+--------------------- という感じです. ですので, quo式よりもRational+quo式の方が安全よりになっ ていると考えたわけです. ただ, Rational+quo式 は, detを計算すると勝手にrational.rbをrequireして しまうので, det前と後でquoを用いているメソッド(inv等)の振る舞いが変わっ てしまうことに気が付きましたので, やはりまずいかなぁ. と思っていたとこ ろでした(^^;; >更にもう一つ提案なんですが、整数行列のdetの計算には、互除法 >を使ったそこそこ速いのがあります: > def determinant_e (中略) > end >これは、整数行列をRatinal()してから、現行detを計算するより >かなり速いです。次は15次行列の整数成分の行列式を5回計算させ >たのにかかった時間です。 > >determinant : 4.278sec. >determinant_e : 0.329sec. おー. すばらしい. >------------------------------------------------------------ >成分 | quo式 | determinant_e >-------------------+----------------------+----------------- >全てInteger | 戻値:Float | 戻値:Integer > | 誤差が気になることも | やや遅い >-------------------+----------------------+----------------- >全てInteger | 戻値:Rational | 戻値:Integer >rationa.rb導入のみ | 遅い | やや遅い >-------------------+----------------------+----------------- >全てRational | 戻値:Rational | 戻値:Rational > | 気にならない遅さ | 気にならない遅さ >-------------------+----------------------+----------------- >全てFloat | 戻値:Float | NG > | 気にならない誤差 | >-------------------+----------------------+----------------- > >そこで提案なんですが、Matrix のdetはquo式にし、と同時に >determinant_e(det_iという名前もいいですが)も定義しておいて、 ちなみに, determinant_e の eは何の省略形です? > 【整数行列を扱う場合の注意】 > 整数行列の行列式を計算させるときは、Matrix#det_iを使いましょ > う。Matrix#detは、rational.rbをrequireしていない状態でFloat、 > requireしている状態でRationalを返します。 > >と、マニュアルに記述するのです。 > >どうでしょう? >ちなみに、determinant_eは[ruby-math:625]のコードをシンプルに >したものです。他にも幾つかバリエーションを試してみたのですが、 >結局[ruby-math:625]のコードが速いのでこちらの方がいいかもし >れません。 オリジナルdetと形がすごく似ているので, det_625 の方がよいかなぁ... って感じです. 結論としては, 原(新)案に賛成です. ただ, 行列の要素にはいろいろなものが入る可能性があるので, det_eがちゃ んと動作する条件を明確にした方がよいかと思います. __ ---------------------------------------------------->> 石塚 圭樹 <<--- ---------------------------------->> e-mail: keiju / ishitsuka.com <<---