東北地方太平洋沖地震の地震波を音にしてみた

Posted on

地球物理をやる学科に居るので、地震も学んでいるのですが、ふと思いついたので地震計の観測した波形を音に見立ててWAVファイルにしてみました。

気象庁の強震波形(平成23年(2011年)東北地方太平洋沖地震)のページから、福島県郡山市朝日の、震度6のデータです。なんだか、雷みたいな音がしますね!

ソースコードはこちらです。PythonでCSV読んでWAVに書いているだけですが、一応使い方のサンプルとしては使えるのではないでしょうか。


凪のあすからの恋愛関係からページランクを求めてみました

Posted on

最近友人に薦められて、今日が最終回らしい「凪のあすから」を見ています。今6話なのですが、恋愛関係が大変複雑です。「深夜の昼ドラ? アニメ『凪のあすから』の人物相関図つくったよ」というページがあったので、引用しますと、こんな感じ。

うーん、グラフ理論って感じだ。そう思ってからピクシブの非公式カップリングのページを見てしまうと、もはや隣接行列か何かにしか見えなくなってきた…。

20130403隣接行列…グラフ理論…はっ!ページランク求めようページランク!

というわけで、今まで一回ぐらいやってみようと思っていた、ページランクの計算を実際にやってみました。こちらの「Google の秘密 – PageRank 徹底解説」を参考にしました。人間をページに見立てて、好意をリンクに見立てます。

ページランクとは結局何なのか

昔私が読んだ本だと、

  • 全てのページはページランク値PRを持っていて、
  • 他のリンクしているページそれぞれににPR/N(Nはページ内のリンク総数)を与えており、
  • ページランクの値PRはリンクされた他のページから貰ったページランク値の和に等しい

というのを読んだ気がします。つまり、貰ったページランク=あげたページランク=そのページのページランクという等式が成り立つということです。

元の論文にもそんな図が載っています。

20130403-2

Lawrence Page, Sergey Brin, Rajeev Motwani, Terry Winograd, ‘The PageRank Citation Ranking: Bringing Order to the Web’, 1998,
http://www-db.stanford.edu/~backrub/pageranksub.ps

これをグラフ理論と確率過程の話で表現すると、こうなります。

  • 各ページから他のページへ移動する確率の表を用意する(とりあえずすべてのリンクで等確率=1/リンク総数とする)
  • その表に従ってあるページから出発してリンクをたどり続ける
  • すると、どのページから出発しても、N回リンクをたどった時にあるページPに居る確率がN+1回目のそれと変わらなくなってくる(これを定常状態と呼びます)
  • その時の、N回目でそれぞれのページに居る確率がページランクです。

これがホントに元の話と一緒なのか?ということなのですが、

  • “もらうページランク”=(自分も含めた他のページにN−1回目に居る確率*それぞれの遷移確率)の和=N回目にそのページにいる確率
  • “あげるページランク”=(N回目にそのページにいる確率 * そのページから他のページへの遷移確率)の和=N回目にそのページにいる確率1

なので、もらうページランク=あげるページランクという関係は確かに成り立ちます。

求めてみる

ページ遷移確率表=行列

実際にもとめてみましょう。まずは、鍵となるページ遷移確率表を用意します。さっきの表を見ながら、ひーくんからまなかへ遷移する確率は1…みたいな感じで行列を作るとこうなります。一応、今回は友情は無視して恋愛関係だけ考えます。

M =
 ひーくん ちさき  まなか   要    さゆ   美海   つむぐ  あかり  至    みをり ←好き ↓好かれる
   0.00000   1.00000   0.00000   0.00000   0.00000   1.00000   0.10000   0.00000   0.00000   0.00000 ひーくん
   0.00000   0.00000   0.00000   1.00000   0.00000   0.00000   0.10000   0.00000   0.00000   0.00000 ちさき
   1.00000   0.00000   0.00000   0.00000   0.00000   0.00000   0.10000   0.00000   0.00000   0.00000 まなか
   0.00000   0.00000   0.00000   0.00000   1.00000   0.00000   0.10000   0.00000   0.00000   0.00000 要
   0.00000   0.00000   0.00000   0.00000   0.00000   0.00000   0.10000   0.00000   0.00000   0.00000 さゆ
   0.00000   0.00000   0.00000   0.00000   0.00000   0.00000   0.10000   0.00000   0.00000   0.00000 美海
   0.00000   0.00000   1.00000   0.00000   0.00000   0.00000   0.10000   0.00000   0.00000   0.00000 つむぐ
   0.00000   0.00000   0.00000   0.00000   0.00000   0.00000   0.10000   0.00000   0.50000   0.00000 あかり
   0.00000   0.00000   0.00000   0.00000   0.00000   0.00000   0.10000   1.00000   0.00000   1.00000 至
   0.00000   0.00000   0.00000   0.00000   0.00000   0.00000   0.10000   0.00000   0.50000   0.00000 みをり

普通、ページには複数のリンクがありますが、このアニメだと思い人が二人以上居るのは不倫と勘違いされて殴られた至だけです。

あと6話時点ではつむぐは誰も好きではないので、つむぐの行が全部0になるはずなのですが、そうしてしまうとページランクが求まりません2

これを元論文ではdangling pageと呼んでいます。元論文では「あんまり重要じゃないから削除して計算しています」と無視してしまっているのですが、つむぐくんを無視するのはかわいそう(?)なのと、仮につむぐくんを消してしまうと今度はまなかがdangling pageになって…となって最終的に大人組しか居なくなってしまうので、次に紹介するrandom surferモデルに習って、みんなを平等に好きなことにしました。

計算は掛け算するだけ

元の定義通り、「あるページからスタートしてリンクをたどり続けた時に、それぞれのページに居る確率が一定になってくる」まで遷移させ続けます。

たとえば、ひーくんからはじめましょう。はじめはひーくんに居ると仮定しているので、ひーくんに居る確率は1で、他みんな確率0とします。

1回リンクをたどると、グラフを見るとひーくんはまなかが好きなので、まなかの確率が1になるはず。

これを我々が先ほど作った行列を使って計算しようとするなら、先ほどの行列Mに、ひーくんを1としたベクトルPを掛ければよいです。

octaveでやるとこんな感じです。

octave:95> M=[ 0 1 0 0 0 1 1/10 0 0 0 ; 0 0 0 1 0 0 1/10 0 0 0; 1 0 0 0 0 0 1/10 0 0 0; 0 0 0 0 1 0 1/10 0 0 0 ; 0 0 0 0 0 0 1/10 0 0 0 ; 0 0 0 0 0 0 1/10 0 0 0; 0 0 1 0 0 0 1/10 0 0 0 ; 0 0 0 0 0 0 1/10 0 1/2 0; 0 0 0 0 0 0 1/10 1 0 1; 0 0 0 0 0 0 1/10 0 1/2 0 ]
(略)
octave:96> P = [1; 0; 0; 0; 0; 0; 0; 0; 0; 0] ←ひーくんに居る確率を1としたベクトル
octave:97> M*P
ans =

   0
   0
   1
   0
   0
   0
   0
   0
   0
   0

というわけで、まなかは三番目の要素で、それが1となったので、見事正しい結果を得られています。これを沢山続けてみましょう。10000回ぐらい掛けると変わらなくなってきます。

octave:98> (M^10000)*P
ans =

   0.00000
   0.00000
   0.00000
   0.00000
   0.00000
   0.00000
   0.00000
   0.22222
   0.55556
   0.22222

…あれぇ?最後の3人、つまり大人組以外ゼロ?なんか間違ったかなぁ?

ランダム・サーファー・モデル

こうなってしまった原因は、大人組から子供組へ繋がっていないことです。つむぐくんは全員が好きだと仮定したので、子供組から大人組へはつむぐくんから遷移することが出来るのですが、その後は大人組の間でぐるぐるぐるぐる巡り続けることになります。ひーくんからはじめても長い目で見ればいつかは大人組に入ってしまい、そこで定常状態となるので、子供組の確率がすべて0になってしまったのです。グラフ理論の言葉でいうと、グラフを辿ると元の位置に必ず戻ってこれる大人組のような部分を再帰類と呼び、そうではなく元に戻れない子供組のような部分を非再帰と呼ぶそうですが、あまりこれ自信をもって解説できないので、しません…。

元の論文ではこれをRank sinkと読んでいて、そのためにランダム・サーファー・モデルというのを考慮しています。これはどういうモデルかというと、「時々はまったくリンクされていない別のページに飛ぶ」と考慮しているモデルです。具体的には、新しい遷移確率行列を次のように定義します。

octave:99> M2=(M*1/1.15)+((1/10)*0.15/1.15)

これは、まず今までの確率を少し下げた上で、あるページから他のページへ僅かな確率で飛ぶようにした、ということです。凪のあすからの言葉を使えば、ひょっとするとひーくんは他の女の子(や男の子)にも興味を持つかもしれないよねというモデルです。

この修正したモデルでは、あるページから他のページへ少ない確率ながら必ずジャンプできるので、Rank sinkのような問題は起こりません。

早速、計算してみましょう。

octave:100> (M2^10000)*P
   0.095976 ひーくん
   0.060684 ちさき
   0.106569 まなか
   0.043208 かなめ
   0.023111 さゆ
   0.023111 美海
   0.115780 つむぐ
   0.135981 あかり
   0.259599 至
   0.135981 みをり

やはり両思いは強いのですね!(?) 子供組を見ると、やはり特に重要そうなキャラクターであるひーくん、まなか、つむぐの三人のページランクが高いので、おおよそページランクの妥当性を示せたと言っていいんでしょうか!?とりあえず、この三人に注目して今後は視聴を続けたいと思います!

蛇足:固有値・固有ベクトルを使って求める

なんか10000回も行列を掛け算するのは…という感じしますか?元の論文だとその方法で計算してると書いてあるのですが、これは行列の固有値・固有ベクトルを使っても求めることが出来ます。

固有値・固有ベクトルをおさらいしておくと、

  • ある行列Mに対する、
  • 固有値μ・固有ベクトルVは、
  • 次のような関係を満たすものです
  • MV = μV

ここで、固有値μ=1なら、MV=Vとなって、N回目とN+1回目でのそれぞれのページに居る確率が全く同じという事になり、ちょうど私達が求めたかったベクトルと一致しますね!

octaveで求めるとこんな感じになります。

octave:142> eig(M2)
ans =
   1.00000 + 0.00000i ←求めたい、固有値1の固有ベクトルは1番目だと分かる
   0.78950 + 0.00000i
   0.19713 + 0.55213i
   0.19713 - 0.55213i
  -0.86957 + 0.00000i
  -0.59237 + 0.00000i
  -0.25222 + 0.45314i
  -0.25222 - 0.45314i
   0.00000 + 0.00000i
   0.00000 + 0.00000i

octave:143> [V, D] = eig(M2); ←固有値と固有ベクトルを再度格納
octave:144> V(:,1) ←固有ベクトル1番目を取得する
ans =
   0.252078
   0.159383
   0.279899
   0.113484
   0.060701
   0.060701
   0.304091
   0.357146
   0.681825
   0.357146
↑固有ベクトルは整数倍しても固有ベクトルで、octaveはベクトルの大きさを1に正規化するので、さっきの結果と合わない
octave:146> V(:,1) ./ sum(V(:,1)) ←ベクトルの要素の合計が1となるようにすると…
ans =
   0.095976
   0.060684
   0.106569
   0.043208
   0.023111
   0.023111
   0.115780
   0.135981
   0.259599
   0.135981
↑先ほどの結果と一致する!

こんな感じで計算できます。固有値ってこんなのにも使えるんですね〜。ちなみに、この行列の固有値のうち、絶対値が一番大きいものはかならず1になることがペロン=フロベニウスの定理から言えるらしいのですが、よくわからないので解説できません…。

感想

凪のあすからは線形代数と確率過程とグラフ理論を学べる神アニメ

ていうか実は前期のアニメで一番好きだったのは「いなり、こんこん、恋いろは」で、京都と出雲にまで行ってきたのですが、それを書く日は来るのだろうか…!?

  1. 他のページへの遷移確率の和は1です。リンク総数*(1/リンク総数)=1。 []
  2. つむぐから他のページに遷移できないので、確率がそこで皆0になってしまう []

紙ジェクションマッピングしてみた

Posted on

あけましておめでとうございます!今年もよろしくおねがいします。去年はあまりいろいろ出来なかったので、今年は少しずつでも、何かできればなと思っています。せっかく転学部までしたので物理をちゃんと身につけたい1ですし、大学再受験も本腰いれてやってきたいです。

さて、新年早速何かアウトプットしよう、ということで、去年作って放置していた「紙ジェクションマッピング」というネタを投稿します。

紙ジェクションマッピングしてみた

プロジェクションマッピングってご存知でしょうか。

20140102_07
東京駅が動き出す!? この冬見られる話題のプロジェクションマッピングまとめ

こういう感じで立体物に映像を投影するアートで、最近いろいろなところで行われているようです。

これっぽい事がしたいのですが、うちにはプロジェクタのような高いものはありません。ので、代わりに1枚50円で印刷できるコンビニのプリンタで何か似たようなことが出来ないかと模索した結果、こんな感じになりました。


仕組みは非常に単純で、ある角度から眺めると立体的に見えるように紙に印刷してあります。

20140102_01作り方ですが、まずこのマーカー画像をセブンネットプリントで印刷して(宣伝)、

20140102_03こんな感じで撮影します。このとき、カメラのファインダから眺めた時に台形が真四角に見えるようにするのがポイントです。

20140102_02この状態で撮った画像がこちら

20140102_04これを作ったソフトで変形させて適当にホワイトバランスを調整。

20140102_05これを紙に印刷して、マーカー画像を印刷した紙の代わりにこの紙をおきます。

20140102_01この状態で動画を撮ったのが、先ほどのニコ動の動画です。

20140102_06実態としては、台形に変形させただけの簡単画像加工をしただけということになりますw

今後の課題

今回は一番簡単な平面でしたが、もっといろいろなものに紙ジェクションしたいですね。たとえば、ティッシュの箱に貼り付けて、ある角度から見ると立体的に見える…とか。今位置合わせが非常にしんどいのですが、ARマーカーでなんとかできるといいんじゃないかなーとかも考えてます。3D力が問われる!!

ただ、結局プリンタの実力があまり高くないせいで、紙に写した方がそんなにリアルに見えないので限界かなという気がしています。っていうかそれがお蔵入りしてた原因です…(◞‸◟ )

  1. 物理とか数学って何やるにしても役に立つと思います []

飼い猫を殺したくて獣医師になろうとした話

Posted on

昨日は一人でディズニーランドに行って客の観察をしていました。という訳で、昨日書くはずだった「つらぽよアドベントカレンダー」を今日書きます。すいません。身の上話です。獣医学科行ったのに物理系に転学部して再度医学部(人間)を目指す話です。

皆が皆ペットが好きなわけじゃない

私が育った家では猫を飼っていたのですが、私は猫が大嫌いでした。

部屋はすぐ毛だらけになってパソコンのファンを破壊してくれます。

糞尿をところ構わずする1ので掃除に気が滅入るのはもちろん、糞をした先がお気入りの本の上で再度絶望。

トイレの置いてあるケージが食事する場所のすぐ隣にある(そこぐらいしか場所が無かった)ので、ずっと糞の匂いが充満する中で家族と楽しいお食事タイム。

去勢もしていない2ので頻繁に発情してしまい、そのときは金切り声に毎日毎日耐えないといけません。メス猫なのですが、私に擦り寄ってくるのも、私の雄性を自覚させるので嫌でした。

家族みたいに「にゃんこーww」とか言う人なら良いのでしょうが、私はそうではありません。私に会った人は私の頭皮が炎症を起こしてるのを知ってると思いますが、あれも猫を飼い始めて一ヶ月後くらいに始まりました。「尋常性乾癬」といって原因不明の皮膚病なのですが、私は原因はどうも猫なんじゃないかと、どうしたって考えます。猫を飼うまでは全く問題なかったので。

そんな嫌なことがあっても猫が好きな人は「そんなの猫なんだから仕方ないじゃん」「たかが猫で」という感じなので、友人知人ならともかく、家族、しかも私一人となると我慢するしかありません。

どんどんどんどん猫、いや、ペット全般に対する嫌悪感が醸成されていきました。13年くらいですかね、人生の半分以上です。

保健所で獣医師になったら猫を駆除できる

そのストレスが最大になってたのが去年の7月ごろで、ちょうど未踏がはじまって自宅でずっと開発していた時期でした。慣れない自宅での開発の上、さらに猫でのトラブルが続いていい感じに気が滅入る毎日。発散できないストレスは他の形で発散するしかないというのが教科書にも載ってる真理で、人生がそのいけにえになりました。

去年の7月は進学振り分け3の時期でもありました。実はさらにその前の年にも進学振り分けをしていて、その時には天文学科に内定してたのですが、必修単位の問題で進級できず内定取り消しになってしまい、仕方なしに二度目の進学振り分けでした。前の年は天文だったので、再度天文か、あるいは近い分野である地球惑星物理を選ぶつもりでした。受験した時も、物理と地学で入ったので…。

が、その時本当に猫の事で頭が一杯で、獣医学科に行って保健所で猫を駆除する仕事につくことで代償的に「飼い猫を殺そう」と思ってしまいました。実際、進学振り分けのフォームに獣医学科と書いたら大分精神的に落ち着いたのを覚えています。ずいぶんいい進路にその時は見えたのです。今猫に苦しまされてても6年経ったら保健所で思いっきり猫を駆除できるんだ、と。大分精神的には楽になりながら開発できました。それは、事実です。

というわけで、私は今度は獣医学科に行くことになりました。

生物はおもしろい、が、そんな人生でいいのか

獣医学科の講義には一応全部出たのですが、想像よりはおもしろかった。生物の身体の仕組みとか全然知りませんでしたし。実習も、解剖とか生体をいじるタイプなら結構楽しく、自分がおもってたよりは自分は手先が器用なんだという事もわかりました。生物は初心者だったのですが、それでも単位は一つ落とすだけで済みました。

しかし、卒業後の進路にはどれも魅力を感じられません。元々は保健所で猫を駆除しようかと思ってましたが、人生を盛大に棒に振るような進路でそれはどうなんだろうと冷静にもなってきました。っていうか、そもそも保健所は猫は駆除しません。捨てられたペットなら処理しますが、それも最近はできるだけしないように引き止めるらしいです4。製薬会社だと動物実験で薬の効果を確かめるような仕事があったりするのですが、毎日動物を扱うのかとと思うと…。いわゆる「町の獣医さん」も動物をずっと触ってると考えると気が狂いそうです。動物嫌いには辛い進路が多い。動物を活かす仕事よりは殺す仕事のほうが多いので、動物好きでも辛そうですが…。

そして医学部再受験へ…

そういうわけで、獣医学科から、当初行く予定だったうちの片方である地球惑星物理学科に転学部しました。本当は天文学科が一番良かったのですが、天文学科に行きたい人が多くて、競争が激しくて転学部させて貰えませんでした。。。すでに一留している上で転学部のペナルティでもう一年留年になるので、二留になりました。浪人もしてるので、ついに三年遅れになってしまいました。

この騒動でただでさえ悪かった家族関係も最悪になった(もともと私が我慢してたのだから、露呈しただけとも言える)事もあり、鬱病になってしまいました。獣医学科に居た時に一番おもしろかった話は脳に効く薬の話5だったのですが、期せずして自分の身体で実験することに…。実際飲んでみると、想像以上に精神状態が変わるので、結構驚けます。人間の脳はこんなにも簡単に操作できてしまうのか、と。

物理系は出ても就活がただでさえつらぽよな上3年遅れとなり、このままこのコースを行くのもつらぽよな気がしています。就活するならSEとかプログラマ、あるいはいっそ就活なんかせずにフリーランスや起業ですが、そもそも私はプログラミングを生涯の仕事にしたら幸せにはなれないタイプの人間な気がする(またその話はいたしましょう)ので、卒業したら医学部に入り直そうと今では考えています。ちなみに、獣医学科でも卒業後に人間の医学部に入り直す人は珍しくありません。

医学は確かに興味深く学べたので、動物の医学にしたのは失敗でしたが、人間なら進路も私にも魅力的な進路が多いので、なれると思ってます。医師という仕事は、他の業種みたいに「需要を作りだ」したりせずに、病気の治療や健康維持という確実にある需要に確実に答える仕事である、というのが一番魅力に感じている点です。

私の作っているソフトウェアも、実はそうなのです。さきゅばすを作ったのは、ネットが無くてニコ動を見られない友達が家や学校でもコメント付きの動画が見られるようにですし、ど〜なっつも、時間が戻れるようなプログラミング言語が無いとコンテンツを作るのが明らかにしんどいからです。単純な技術的興味から書くことももちろんたくさんありますが、基本的には困ったことを解決するためにプログラムを書いています。

もし仮に受かったらなのですが、ある程度人生経験は積んだつもりですし、以前から興味もあったので、精神科の医師になりたいです。メンタルヘルスの重要性は鬱病になったこともあってよくわかりました。。。他には産業医も良いですね。

まあでも、受かるかどうかはわからないよね。駄目だった時用に情報系大学院の準備などもしておくつもりです。

蛇足:動物が嫌いな人はペットをどう思っているか

この際なのでちょっと書いてみます。

私は動物が嫌いで、実習でラットやマウスを殺すことにも特に良心の呵責とかを感じない人間ですが、それでもペットという営みは嫌いです。生命をおもちゃにして人形ごっこしてるように思います。人間があの「かわいい姿(人口的な作り物っぽさと獣の嫌な部分の足し算の、どこが可愛いのか全然分からないけど)」を生み出すために無理して交配(端的に言えば近親相姦)した結果出てきた遺伝病で苦しむペットが多いのも、命を弄んでるように思います。その自覚が無いまま、「かわいいかわいい」で飼うのには私は嫌悪感を感じます。

ちなみに最近上野動物園に行ったら、小動物が軒並み常同行動(同じ場所に居続けるストレスによって同じ行動を只管しつづけるようになること)してたので、動物園という存在もどうなのかなぁと思うようになりました。

  1. いつもではない、が、二週間に一度だって嫌だ []
  2. 交尾させて儲けたかったそうだが、その時点で無知丸出しですな []
  3. 東大は入ってから学科が決まるのですが、その制度をこう呼びます []
  4. 野山に放たれて余計面倒な問題になるだけじゃないかなぁ []
  5. 動物でも問題行動を起こしてると処方されることがある []

クリスマスはNoiz2saをAndroidで!

Posted on

おひさしぶりです。21日のニコニコ学会βは良かったですね。特に良かったのは研究100連発で、本職の人のすごさを見ると、私も何かつくりたいな〜って気分になります。私はボランティア(登壇者へのカンペ出し)として参加しました。凄い人を間近に見れるという特典付き(?)の嬉しいけど責任重大なお仕事です。イベント運営って大変ですね…。あと野糞の人は本気でマッドだ(褒め言葉)。

Noiz2saをAndroidに移植してみた!

Noiz2saはABA Gamesさんの開発した、アブストラクトな感じのシューティングゲームです。私はこのゲームがSTGに入り始めたきっかけだけあって、大好きです。

去年はWebに移植したNoiz2saを公開しましたが、今年はAndroidに移植したものを公開します。

クリスマス、そして年末年始といえばシューティングゲーム!ぜひお楽しみ下さい。敵の弾を避けて撃つ、指一本で遊べるシンプルなゲームです。

USBのゲームパッドをつなぐと、PC版と同様な操作で遊ぶことも可能です。

ダウンロードはこちらから

バッドノウハウFAQ

移植時のバッドノウハウを書きます

Q.リソースのファイルの拡張子がamrとかなのはなぜですか

このように置かないと、リソースが圧縮される時に圧縮されてしまい、AssetManagerからランダムリードすることが出来なくなってしまうからです。

あっコーナー分けた割に一個しか思い浮かばなかった…質問は随時受け付けています。


HDDを壊さないためにACアダプタにシール貼った

Posted on

区別のつかないACアダプタ

ACアダプタ、好きですか。私はだいきらい!です(何

ハードウェアごとに別々のACアダプタが必要で、使いたいのはハードウェアなのに大きなACアダプタばかりが部屋を占拠していってしまいますし、何より種類が無数にあるACアダプタの区別が全然付きません。

パナソニックやソニーのような大企業(?)の作っているデバイスでは、ACアダプタを見れば何のハードウェア用なのかすぐに分かるのです。たぶん、このACアダプタならPSPの充電用でしょう、とかね。

しかし、独自のラベルを付けたりせず、ACアダプタのメーカが製造したものをそのまま同封している場合、本当に区別がつかなくなります。このACアダプタは何用のACアダプタでしょう。電圧と電流は分かるのですが…。

20130710_1

こたえ:HDDケース。

…わからないですよね!

ACアダプタ間違えてHDDが壊れた

単純に区別がつかないだけなら、仮にどのデバイスがどのACアダプタか区別が付かなくなっても、トライ&エラーで動くまで試せばよいのですが、それをやると壊れてしまうことがあります…。

今回、HDDのケースに、誤って正しい12vのアダプタではなく、間違った24vのACアダプタを接続してしまったところ、HDDケースは無事だったのですが、HDD本体が壊れてしまいました。

ううう…。保護回路とかは流石に無いんだろうなぁ…。

原始的解決法:シール

一回失敗したら、それはもう仕方がないので「次がない」ように対策しましょう。やはりココは原始的にシール…で…。

メモックロールテープというのがたまたま手元にあったので、これを使いました。テプラとか普通のセロハンテープとかとは違って、べとつかずに綺麗に剥がせるので精神衛生によい気がします、が、もしかするとすぐ取れちゃうかも…(この辺は要検討)

20130710_220130710_3

なんか他にいい方法あったら教えてね!!


二条項BSDとのデュアルライセンス。さきゅばす2.0b4を公開しました

Posted on

久しぶりの更新です。。。。

久しぶりにさきゅばすのアップデートを行いました。またマイナー更新ですけど…。

2.0b4のダウンロードはこちらから!

リリースノート

デュアルライセンスになりました

今回のver 2.0b4のソースから、

  • GPL v3 or later
  • 2-clause BSD License

のデュアルライセンスになりました。派生物のライセンスはこのどちらか一方か、両方(デュアルライセンスのまま)を選ぶことができます。また、改造されたffmpegに関しては、勝手にBSDにすることはできないので、従来どおりGPL v3のままとなります。

また、GPL v3のライブラリがリンクされているので、配布バイナリも従来どおりGPL v3のままです。

ライブラリの更新とバグの修正を行いました

その他の更新はこんな感じです。

  • 2chのスレで見つかってたいくつかのバグを修正しました。
  • x264とかffmpeg本体のライブラリの更新を行いました。
  • ビルドシステムがcmakeからwafになりました。pythonで書きやすい。
    • このためにwafにバグ修正パッチまで投げました…(1.7.10でaccepted)
  • 未踏ソフトウェア事業で開発していたもののうち、基礎的な部分をライブラリ「しなもん」として切り出し、そちらを利用することにしました。
  • 上記の影響でlibxml2への依存が消えています。icuにも陽には依存しなくなりました(しなもんを通して陰に依存はしています)。

追記

2ちゃんで報告されてた「【第10回MMD杯本選】騒がしいゆーじょー【超遅刻カオス】 」の音ズレ問題ですが、たぶんacodecがaac(ffmpegの内蔵aacエンコーダ)が問題を引き起こしてるのではないかと思います1。外部ライブラリであるlibvo_aacencにすると解決するようです。

今までは変換レシピでaacを使うものがいくつかありましたが、今回のバージョンからlibvo_aacencだけにしました。

  1. スレに書こうかと思ったらまた規制掛かっててファッ!? []

2012年度未踏事業でスーパークリエイター認定されました

Posted on

1月まで独立行政法人 情報処理推進機構(IPA)未踏IT人材発掘・育成事業の支援で「プログラミング言語ど~なっつ」と、それを用いた「ファミコンを題材にした電子教材のような何か」を作っておりましたが、本事業でスーパークリエータに認定されました。わーいわーい(謎

5/29にはスーパークリエータ認定授与式があり、そこで再度プレゼンテーションを行います。でも平日だよ!

今後の展開なのですが、とりあえず時間操作ができるプログラミング言語、ど~なっつの改善をしたいな~と思っておりまして、

とかやりたいです。特に最後ですが、これが出来ればニワン語の/seekとかにも対応できるし、現状抽象構文木をそのまま評価している「ねこまた」をど~なっつVMへのトランスレータにすることが出来れば、リアルタイム再生も夢でないくらいには高速化できる…かも??

本業(学生)の方があるので支援期間中ほどの速度は出せませんが、ぼちぼち書けていければな~と思います。進学する学科、間違えちゃったかなあ…。


エラー処理の地学史、もしくはあなたがMaybeモナドを使うべき理由。

Posted on

(以下、カノッサの屈辱(テレビ番組)のノリでお願いします)

コンピュータの理論を確立したチューリング。彼は、無限のテープの長さを持ち、単なる計算を行うだけのチューリングマシンを夢想した。

しかし、我々の生きる現実世界におけるコンピュータでのプログラムに於いては、計算の失敗=エラーが発生するのは避ける事ができない宿命である。ネットワーク接続失敗、ファイルが見つからない、メモリが確保出来なかった…等々。すべてのエラーを書き出すには、それこそ無限の長さの紙が必要であろう。プログラム進化の歴史は例外との戦いであると言っても過言ではない。今回の講義では、プログラミング言語の様々な進化のうちの「エラー処理」に着目し、その長い戦いの歴史を概観する。

まずは、いにしえの先エクセプション紀におけるエラー処理を見てみよう。

先エクセプション紀:エラーコード-1の時代

エクセプション(exception)と呼ばれる隕石が衝突する以前の時代は先エクセプション紀と呼ばれている。この時代での例外処理の特徴は、エラーコードという概念の存在である。数学の関数を模したプログラム言語の「関数」とよばれる生物は、値を一つだけ戻すことができる。当時地球を支配していたAPI関数たちはこの「戻り値」を用いてエラーが発生した旨を伝えることで、上位のプログラマにその処理を託した。

//int loadNumberFromFile(const char* url);
// ファイルを読んで、そこに書かれた数字を返す。失敗した場合は-1を返す。
// ex) number.txtに"12"と書かれていれば、12を返す。
int status = loadNumberFromFile("number.txt");

これがこの時代における典型的な「失敗する可能性のある関数」の姿である。戻り値として計算が失敗した場合に特別な値を返すことでその旨を表現し、多くの場合、-1などマイナスの値が好んで使われた。これを「エラーコード」と呼ぶ。

しかし、上記の例を見れば分かる通り、正常な結果と失敗した結果を同じint型の変数一つで表してしまうことで、いくつか問題が発生した。例えば、上記のプログラムでは、もしもファイル中に「-1」と書かれていた場合、このAPI関数は「正常な結果として」-1を返してしまうかもしれない。プログラマにはそれを区別する事ができない。必ず非負の数値が書かれていることを要請し、マイナスの場合はすべてエラーとすれば問題は解決するが、APIに要求とされる機能によってはそれは許されないかもしれない。そのような場合、このように苦肉の策として追加のポインタを使うケースがあった。

// ファイルを読んで、そこに書かれた数字を返す。
// 失敗したか否かの情報がstatus内に格納され、失敗したら-1が格納される。
// int loadNumberFromFile(const char* url, int* status);
int status = 0;
int result = loadNumberFromFile("number.txt", &status);
if(status == -1)....

このポインタを用いて間接的に値を返す手法によって、プログラマに結果の値を一つしか伝えることができない、という関数の問題を回避することができた。しかし、この方法には明らかに欠陥がある。「処理が失敗したか否か」も、「成功した場合のその結果」もどちらも「関数から返ってくる値」のはずであるが、この方法ではその対称性が崩れてしまっており、あたかもstatusは入力値のようにも見えてしまっている。また、どちらをポインタとして渡して格納させるかはライブラリごと、関数ごとに違い、勘違いして双方を入れ替えてしまう悲劇も発生していた。また、Javaなどのように「参照型」を渡すことができない言語においては、この方法を(直接は)使うことができない。

Windowsの一部のAPIやOpenGLなどでは、別の関数を呼びエラーの発生を確認するという方式も考えだされた。

// int loadNumberFromFile(const char* url);
int result = loadNumberFromFile("number.txt", &status);
int status = getError();
if(status == -1) ....

この方法では、失敗する可能性のあるAPI関数の呼び出しの直後に特定の関数を呼ぶことでエラーの発生を確認した。当然、エラーを確認するまえに別のAPI関数を呼び出してしまうと、エラーを正しく処理することができない。

// int loadNumberFromFile(const char* url);
int result = loadNumberFromFile("number.txt", &status);
int result2 = anotherFunction(); /* !ここでもエラーが発生するかもしれない ! */
// loadNumberFromFileのエラーをもはや反映しない
int status = getError(); 
if(status == -1) ....

保守や機能拡張時などにおいては、その事をすっかり忘れてしまい、明後日なエラーメッセージを前に途方に暮れるという事態も珍しいことではなかった。

また、別の関数をわざわざ呼ばなければならない点はやはり手間が大きく、この方式では輪をかけてエラーが無視されることとなった。

エラーコード-1の亜種として、nullを返すAPIが棲息する地域もあった。Java大陸や、C++海溝の一部などに見られる化石などから明らかになっている。このような関数呼び出しの場合、一見エラーを返さないような計算に見える:

String data = client.readDataFromNet();

dataがnullであれば失敗である事を示し、そうでない場合は成功した結果を表すという方式である。

この方式も、エラーコードと同様、正しい結果としてnullが返ってくる可能性がある場合にうまく対処できない。さらに「null」というただひとつの値しか返すことができないため、結局失敗した理由を他の方法を用いてAPI使用者に伝えなければならないという問題があった。多くのAPIでは実装工数がないの魔法の一声で、その方法は提供しないこともあった。

エラーコードの体系や伝え方(nullを返す・関数を呼ぶ・エラーコードを使う・ポインタを渡す)は当然、APIの創造主や、APIごとにまちまちであり、APIを消費するプログラマはそれらを個別に理解し、正しく対処することが求められた。そしてもちろん、そこには言語処理系のサポートは一切ない。

結果、そのエラー判定コードが正しいことをコンパイラで事前に判定することができないため、プログラマのその日の体調や気分によってはバグが発生することとなった。

エクセプション隕石の衝突

地球上でエラーコードを持つ多様な生物が棲息していたある日、ついに事件は起こった。エクセプション隕石の衝突がそれである。エクセプション隕石は地球上の多種多様な生物に深刻なダメージを与えたが、特に構造化の三要素へのダメージは深刻であった。

当時のプログラミング言語の構文細胞において、順次・反復・分岐の三生物が共生し、細胞小器官となる進化が発生していた。この三つの器官をまとめて「構造化の三要素」と呼ぶ。

/* 順次(上から下に実行) */
int a=10;
int b=a*10;

/* 反復(繰り返し) */
int sum = 0;
for(int i=0;i<100;++i){
    sum += i;
}

/* 分岐 */
if( isOdd(x) ){
    printf("odd number!\n");
}

しかし、一部の言語はそれよりも原始的なgotoと呼ばれる器官を退化させることなく持ち続け、APIを消費する一部の生物種は、例外の処理に好んでgotoを用いた。

if( maybeFail() == ERROR_FAIL ){
    goto fail1;
}
...
fail1:
    /* 失敗時の処理 */

エクセプション隕石は、この原始的なgotoと構造化の三要素との悪魔融合合体進化を発生させた。なぜこのような奇妙な進化が起こったのかは、未だに議論のあるところである。この合体進化した新たな器官は、隕石の名前にちなんで「エクセプション」と呼ばれた。

try {
    int result = maybeFail();
    int result2 = maybeFail2();
    ....
} catch (Error const& e) {
    /* 例外時の処理 */
}

エクセプションは構造化の三要素のような姿を持ちつつ、goto文のような文脈を跳躍する特性も有する。APIを消費する上位のプログラマは、エラーの発生があたかも無いかのように処理を記述しつつ、最後にエラーに纏めて対処する事となった。

構造化の三要素とエラーコードを用いたAPI消費の多くのケースでは、ひとつでもエラーが発生した場合、次の処理を行うことは通常不可能であったため、多くのプログラムではエラーが発生したら、すぐにgoto文で失敗時の処理に移るということが見られた。

if( maybeFail() == ERROR ){
    goro error;
}
if( maybeFail2() == ERROR ){
    goro error;
}
if( maybeFail3() == ERROR ){
    goro error;
}
error:
return -1;

エクセプションでは、これらをcatch節 という仕組みを使うことで共通化した。すなわち、エラーが発生したら移行の処理は全てスキップし、catch節の中でそのエラーに纏めて対処するということである。

try {
    int result = maybeFail();
    int result2 = maybeFail2();
    int result3 = maybeFail3();
   ....
} catch (Error const& e) {
    /* 例外時の処理 */
}

エクセプションを持つ言語は地球上で広く繁栄することとなった。エクセプション器官を持つプログラミング言語は、オブジェクト指向と呼ばれる骨格も同時に持つことが多く、オブジェクト指向とエクセプションには関係があると考えられているが、先述の議論から構造化プログラミングとの関係の方が深いという異論も存在する。

しかし、このエクセプションは悪魔融合合体であるがゆえに、黒魔術的弱点を有する。

多くのプログラムでは、構造化の三要素が守られる事を暗黙の前提としてソフトウェアが構築されていくが、エクセプションの仕組みではエラーが発生するとそれがgoto由来の文脈跳躍生によってほぼ無化されてしまう。

またエクセプションの仕組みは処理の流れを変えることに依存しているため、処理の流れが複数存在するスレッド環境などではさらに技巧を用いることが必要とされ、多くの場合それはうまく動作することは無かった。

これらの事に端を発した多臓器不全で亡くなる生物は少なくなく、「More Effective C++」などの当時を研究する古医学書では1章をこのエクセプション由来の疾患に割かれている。

さらに、「で、結局纏めて対処しろって言われてもどうすれば良いんだ…」との声も根強く、catch節には何も書かれない事態も珍しい物では無くなった。これを「例外潰し」と呼ぶ。

エラーコードの復権:地殻内空洞での”数学”との遭逢、そしてMaybe種とEither種

エクセプション隕石はエラーコード種を概ね絶滅させたが、地下3000mではほそぼそと生きながらえる事となった。地下3000mには酸素がほぼ存在しないため、好気性生物であったエラーコード種には進化が求められた。そのための遺伝子を提供したのが、地殻内空洞に棲息する「数学」と呼ばれる、一連の生物群である。

この生物種がエラーコード種に提供したのは、「モナド」と呼ばれる強力な遺伝子である。この特徴を詳しく見てみよう。

エラーコード種に起こった問題である「同じ型で成功と失敗を表されるので、正しい結果の”-1″と失敗を表す”-1″の区別がつかない」という欠点を、値の上位に成功か失敗かを表す仕組み1である「Maybe」や「Either」を加えることで表現。さらに、nullの持つ「失敗としてただひとつの値しか返すことができない」という問題も、失敗時の型にその情報を付加できるようにすることで解決することとなった。

-- Leftが失敗、Rightが成功
data Either a b = Left a | Right b
--引数に応じて処理、失敗するかもしれない
maybeFaile :: ArgType -> Either String Result
-- ----------------
case maybeFail arg of
    Left a -> ... --aにはエラーの理由が
    Right b -> ... --bには成功した結果が

思わぬ副作用として、エラーを無視することが出来なくなった。戻り値のMaybe/Eitherから結果を取り出すには、必ずエラーか否かをチェックする必要がある2

これは今までのプログラミング言語種でも可能であった。Cなら構造体と共用体で、C++ならクラスの仕組みを用いることで実現できる。しかし、それだけではエラーコードかどうかをチェックする今までの方法とあまり変わらず、煩雑なエラーチェックが必要になる。

すなわち、MaybeやEitherの導入だけでは、次のような非常に煩雑な記述が必要になってしまう、ということである。

--maybeFailとmaybeFail2とmaybeFail3を使った処理
--この三つの関数は、どれも失敗するかもしれないのでEitherを返す。
func = case maybeFail arg of
	Left err -> return (Left "error on maybeFail")
	Right ok -> case (maybeFail2 ok arg2) of
		Left err2 -> return (Left "error on maybeFail2")
		Right ok2 -> case (maybeFail3 ok2 arg3) of
			Left err3 -> return (Left "error on maybeFail3")
			Right ok3 -> return (Right ok3)

この状況に力を与えたのが、かの有名な「モナド」遺伝子である。

モナド遺伝子のbindの力とMaybeやEitherが共生することで、上のような煩雑なエラー処理は次のように至極単純化された。

func = do
    ok <- maybeFail arg
    ok2 <- maybeFail2 ok arg2
    ok3 <- maybeFail3 ok2 arg3
    return (Just ok3)

表層を見ると、エラー処理が全て消え去ってしまっている。エクセプションではエラーを処理するために存在するcatch節が、完全に消滅している。しかし、エラーを「潰した」りはされない。もし、この関数を実行した際にmaybeFail2でエラーが発生した場合、その下位関数のエラー値がそのまま返され、続くmaybeFail3はスキップされる。

-- 途中でエラーが発生すれば、その結果が返される。潰れされない。
func -- -> Left "error occur on maybeFail2"
-- 最後まで成功すれば、最後にreturnした値が返される
func -- -> Right result

エクセプションにあった、構造化の三要素が無化されてしまう事によって生じうる問題はここでもまだ残っているが、MaybeやEitherは制御構造ではなく、単なる値であるため、エクセプションに比べて柔軟である。例えば、エクセプションを用いたプログラミング言語種では「何度か実行し、成功を試行する」といった仕組みを作るのは一般的に面倒であるが、Maybeを使えばこのように簡単である。

-- 渡された関数を何度か実行し、一度でも成功すればその結果を、
-- n回実行しても失敗するならNothingを返す
tryFunc :: Int -> ( Int -> Maybe Result ) -> Maybe Result
tryFunc n thunk =
    if n <= 0 then Nothing
    else
        case (thunk n) of
            Nothing -> tryFunc (n-1) thunk
            Just x -> Just x

この関数を用いてラップすることで、既存のMaybeを返す関数も簡単に「N回試行」させることができるようになる。

func = do
    ok1 <- maybeFail
    -- maybeFail2だけは10回だけ試行する。一回でも成功すればよい。
    ok2 <- tryFunc 10 maybeFail2
    ....
    return (ok3)

このように、「失敗するかもしれない」処理の内側と外側の行き来が非常に簡単になったことで、エクセプションの問題も対処しやすくなっている。

まとめ

  • エラーコードでは…
    • 正しい結果の-1と、エラーコードの-1を区別するのが困難
    • エラーコードのチェックが面倒くさい
    • 大体エラーコードのチェックなんてしなくなってくる
  • JavaやC++の例外機構では…
    • 例外が発生すると以降の処理が全部スキップされてしまうことに起因するバグ
    • 例外は潰されるもの
  • MaybeやEitherでは…
    • エラーを無視できない
    • 下位で発生したエラーをそのまま上位に渡すのが簡単
    • エラーが発生する処理とその周囲との行き来が簡単

私が現在理解したところによるMaybe/Either/Optionalの利点はこんな感じです。あと文中のHaskellがIOがどこでも起こせるかのような書き方ですが、IOと組み合わせると論点がぼやけそうなんです、ごめんなさい。ツッコミ、お待ちしています

ちなみに

JavaでもC++でも、匿名クラスやlambda式を多用することでMaybe/Eitherモナドは使うことができます。C++だとこんな感じで実装できます。Javaでもバイトで書いたことがあるのですが、バイトで書いたので手元にコードはありません(ぉ

 

  1. 多くの場合、型によって提供された []
  2. Just x <- maybeFailは邪悪なので無視 []

More Effective C++ ー 読むならC++を何万行も書く前に読みましょう。

Posted on

有名な「Effective C++」の続編の本です。未踏の期間が終わったこともあり、読む時間を作ることができました。

この本は英語版で、一応日本語版もあるのですが、訳の評判はあまり良くありません。英語版の方も非常に読みやすい英語で、JavaDocレベルの英語が読めればなんとかなると思います。気のきいたジョークに使われる日常単語がいまいち分からなくて全部調べてたので、いまいち笑えませんでしたが…(ーー;

 Effective C++に比べて枝葉の話が多い

続編ということもあり、前編であるEffective C++では言語の根本的な部分のと比較して、Moreの方では細かい話が多いです。

前著の方では、例えば

  • コピーコンストラクタやデストラクタ、operator =を定義しないと勝手にコンパイラが定義してしまいますよ
  • 値渡しよりconst参照渡しを考えた方がいいですよ
  • newしたものはdelete、new [] したものはdelete[]、と対応させないといけません。
  • private継承や多重継承は注意深く使ったほうがいいですよ

といった内容が多く、他言語を使っていたプログラマがC++の世界を理解するには丁度良かったと思うのですが、今回のMoreの方では、

  • 関数の引数で暗黙的な変換が起こるのは値渡しかconst参照渡しの時だけで、しかも変換は一度しか起きません
  • 参照カウントなスマートポインタ
  • デストラクタは例外が起こってもちゃんと実行されるのでリソースリークを避けるのに使えます。
  • 多重継承・virtual継承する時のオブジェクトのデータフォーマットはこうなっている(事が多い)ですよ

といった内容です。最後の項目はvtableやvptrの実態がよくわかったので参考になったのですが、その他の項目は今ではインターネット上のC++に関する文章や、STLをある程度使っていると「そらそうよ…」「せやな…」と思ってしまう内容が多く、Effective C++を読んだ時に感じた、あの驚きをもう感じることはできませんでした。Effective C++を読んで少しC++を書き始めた時期に読めばもっと参考になったのでしょうが、数万行書いた後となると…。

改訂が繰り返されているEffective C++と違い、Moreは95年から一度も改訂されていません。STLは出たばかりの時期だったようです。

本を読むよりソースを読んで書いてWebのリソース読むのが好きな人は、まあ読まなくても…。

この本の中で特に一番大きく扱われているのは、参照カウント・スマートポインタです。sharedされている値そのものが参照カウント数を管理する、boostでいうところのintrusive_ptr相当のものをじっくり実装したあと、階層を一個上げてshared_ptr相当のものを実装します。が、相当のものがある事からも分かる通り、どちらも既に有名なもので、いまいち読んでも驚きがありません。しかもweak_ptrを扱っていませんし、参照カウントで問題になる「自分へのshared_ptrを基本的に持てない」という問題も扱っていません。

もしも読むなら、Effective C++を読んでちょっとC++を書いたらすぐに読むことをお勧めします!