スポンサーサイト
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
【--/--/-- --:-- 】
| スポンサー広告 | コメント(-) | トラックバック(-) |
Ruby との悪戦苦闘で明けた新年

年明けには Ruby プログラミングをやった.去年の夏に「プログラミング教育用なんかにもいいかも」と書いたことのある ruby だけど,いま教えているオペレーションズ・リサーチの授業でじっさい ruby プログラミングをやることにした.プログラミングの経験がないという受講生が「プログラミングをやってみるいい機会」と意欲を見せたため,「じゃあ,すぐにマスターできる言語で行こう」と,急遽予定に組み入れた.

といってもボクもほとんど知らない言語だ (というか,プログラミング自体の経験も浅い) .まずはこちらの文献集にあった,まつもとの「rubyユーザガイド」 (ちょっと古い; また,初心者である自分にはあまり分かりやすくなかった) と Chris Pine の「プログラミング入門: Rubyを使って」(大部分は初心者でも読めるだろうけど,9章の後半と10章はむずかしそう) をざっと読んだ.プログラミングをはじめてからは,その文献集の「入門編」の「サイト」にある情報や,「オブジェクト指向スクリプト言語 Ruby リファレンスマニュアル」その他を参照した.

プログラミングに出した課題はこんなタイプの問題だ: 「カップ 0, 1, 2 はそれぞれ 10, 7, 3 の容量を持つ.最初は容量10のカップに水が満杯の状態 [10, 0, 0] である.カップ i から j への水の移し替えを繰り返して,目標である [5, 5, 0]を実現したい.」この例にかんするかぎりは,9段階の移し替えで目標が達成できることが,すべての場合を網羅的に調べることで手作業で確認できる. (上述の科目で少し学ぶ) グラフ理論を知っていれば,この種の問題をプログラムで扱えるように表現するのは簡単だろう.アルゴリズムを考えることもたやすい.

それでもはじめての言語というのはいろいろと戸惑うものだ.ありがちなミスのパタンは,マニュアルと悪戦苦闘したり試行錯誤を繰り返すうちにだいたい分かって来た.で,できあがった最初のプログラムは,9段階の移し替えを実行するだけで 5 時間もかかり,10 段階以上は結果を出せなかった.そんなバカな! 「オブジェクト指向でプログラムを書いたのが悪かったんだろうか?」「再帰で関数を定義したのが悪かったんだろうか?」などと疑った.Mac OS X にはじめからインストールしてあった ruby がたまたま当たりが悪いバージョンなのかもしれないと思って,最新安定版 1.8.6 に入れ替えたり,クリスマスにリリースされたばかりの「高速」不安定版 1.9.0 を (一年近く触れていなかった) Windows PC にインストールしたりもした.だがそれらの対処法はいずれも見当違いだった.

ところでMac OS X に ruby 1.8.6 をインストールするのには,MacPorts を使った.これはボクにとっては前進だ.Unix ふうというだけでいままで毛嫌いしてたけど,やってみたらたいしたことはなかった.最初の導入は多少面倒だけど,こいつをいったんインストールしておけば,ほとんどの unix 向けソフトがコマンド 1 行でインストールできるようになる.そういうソフトとしては,pTeX, Octave, Maxima などがある.可能性が一発で広がるわけだ.こちらのサイトも参考になるだろう.MacPorts を使えるようになったのは,失敗から生まれた収穫といえるだろう.

では,なにがプログラムをそんなに遅くしていたのか? どうやら関数の相互参照であるようだ.たとえば history(t) という関数を定義するのに history(t-1) と obtained(t-1) を参照する一方で,obtained(t-1) を定義するのに obtained(t-2) と history(t-1) を参照するようになっていた.数学的には問題はなさそうだが,おそらくプログラム的には問題になるんだろうな.history(t) の定義のなかに使われていた関数 obtained(t-1) を単なるローカル変数に置き換えた.するとそれまで5時間かかってもできなかった計算が,1秒程度でできるようになった! やれやれ.

「関数を変数に置き換えた」とあっさり書いている.「そんなに簡単にできるならはじめから変数で書けばいい」と思うだろう.実際そのとおりなんだろうけど,これは慣れあるいは経験の問題かもしれない.[以下,インデント部分に修正を加えた.追記参照.] たとえば 1 から 10 の整数 i を合計するプログラムでは s = s + i などと書いて,右辺の値の左辺の変数への代入を表すけど,数学ではふつうそうはやらない.添字をつけて si = si-1 + i とするか,関数にして s(i) = s(i-1) + i とやりたくなるわけだ.添字をつけて何段階目の更新かというのをはっきりさせるわけだ.そういう癖にしたがって書いたプログラムが (メモリを浪費せず,かつ素早く) 自然に動いてくれたほうが都合いいと思ってるアマチュアプログラマはけっこういるかもしれない.

ところで数の合計といえば,はじめに s = 0 と設定して(1..10).each do |i| とやるのがただしいが,ボクがはじめのころ書いたプログラムには (1..10).each do |i| と書いたあとに s = 0 とする類いの初歩的なミスがあった.(これだと合計は 55 ではなく 10 になってしまう.) さすがに合計を求めるだけのプログラムではそういうミスはしないだろうけど,ループとか条件が何重かにネストする,より複雑なプログラムだと,意外とおかしてしまうミスかもしれない.

それにしても「おまじない」の類いをほとんど記述せずにプログラムが書けるのは気持ちいい.できたプログラムは普通に書くアルゴリズムよりもむしろ簡単かも.たとえば (?) 上記の水移し問題 (油移し問題) のインスタンスである abura にたいする結果を表示する---より具体的にはその履歴 history(t) を t = 0 から t = 12 まで表示する---には,以下のように書けばいい:

(0..12).each do |t|
p abura.history(t)
end

追記 (1/10/2008). あまりにも単純すぎてポイントが伝わらなかった例を差し替えた.以下は修正前の記述.「プログラムでは x = x + 1 と書いて,右辺の値の左辺の変数への代入を表すけど,数学ではふつうそうはやらない.わざわざ添字をつけて xt = xt-1 + 1 とするか,関数にして x(t) = x(t-1) + 1 とやりたくなるわけだ.(この例は簡単すぎるので説得力ないけど,もっとむずかしくなると添字をつけて何段階目の更新かというのをはっきりさせた方が分かりやすくなる例は少なくないはずだ.)」

スポンサーサイト
【2008/01/08 20:44 】
| プログラミング | コメント(2) | トラックバック(1) |
年末は家具の入れ替えとか順序数とか

年末が遠い過去に思える.

年末はなにをしたっけ.ニトリで L 型デスクを買って部屋に入れた.ネットショッピングで買ったレース調遮音カーテンと書棚4つを部屋に導入し,古い机と書棚は「物置」に移動した.部屋は書斎ぽくなった.でも箱詰めして押し入れに入れてあった本 (といっても箱はふたがしてないものが大部分だったので,すぐ見れるようにはなっていた) を書棚に移したらすぐいっぱいになった.本というのは場所を取るものだ.

その前は竹内外史『集合とはなにか』と篠田らの『集合・位相演習』(サイエンス社)の集合論の後半 (6-10章) をざっと読んで,今年書く予定のペーパーに必要な知識というか直観を仕入れた.「直観を仕入れる」って言い方はヘンってのはおいとこう.無限上昇列があるからといって無限下降列がとれるわけでないことは,たとえば自然数の全体 ω を考えれば分かるだろう.一般読者としては,「一般の順序集合で,ある要素の前に無限上昇列があるからといって,その要素から始まる無限下降列が存在するとはいえない」ことを知っておけば十分だろう.たとえば,どんな (たとえ非可算でも) 《順序数》をとっても,無限下降列は作れない.順序数ってのは自然数の概念を拡張した集合で,たとえば ω・2 = ω + ω = {0, 1, 2, 3, ..., ω, ω +1, ω+2, ω+3, ...} のように ω のコピーをふたつ用意して,最初のコピーの次に2番目のコピーを並べたものは順序数だ (2 のコピーをω回ならべた 2・ωとはべつ).ω +1 以前に無限個要素があるけど,ω +1 から始まる無限下降列は作れない.ほかにも ω・ω = ω2 のように ω, ω・2, ω・3, ω・4, ... のリミットに来る順序数もある.ω3, ω4, ... のリミットである ωω もある (ノーテーションは同じだけど,ωω は ω から ω への関数の集合とはべつもの).ωωω もある.これらの操作によって,バカでかい無限の「数」が作れると思うかもしれないが,それらはせいぜい加算個の要素しか持たない「小さな」順序数だ.だからより大きな順序数を作る操作も必要で,たとえば実数の濃度に対応する最初の順序数というのを考えることができる.順序数はいくらでも大きくできるが,その部分列で減少するものを作れば必ず有限個で終わるのだ.

休み前には今年教える可能性の高い MBA プログラム向けの「経済分析」にむけて,伊藤元重の『ビジネスエコノミクス』 なんかも読んでみた.すぐ読めてすぐ忘れるたぐいのものだけど,副読本には悪くないかも.流通業界の話とかするには抽象的プレーヤーを持ち出すよりも,イオンとかセブンイレブンとかプレーヤーが具体的なほうが一般人には受けるんだろうな.

つづく

【2008/01/08 19:55 】
| | コメント(1) | トラックバック(0) |
| ホーム |
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。