Rubyのキーワード begin・rescue・else・ensure・end

英語の授業でmoodle言うCMSを使っている。主にReadingの練習用です。
“many many many many write!”なんて言ってますけど読むことも大切ですねって。
読み物が置いてあって読むわけですが、まぁいままで読んでたのはまぁまぁ簡単だったのよね。
読んでそれについてのQUIZに答えると。まぁ大体70%ぐらいは正解しますね。ほとんど正解なんてときもある。
宿題で今学期の目標分進めておきましょうとか書いてあったので家からやってたんですが、
その読み物を読み終わったら”TOEFL”と書いてあって、TOEFLの何だろうと思ったらTOEFLの問題文だった。
そしてQUIZはTOEFLの問題。やったが難しい。1回目の正解率40%でこのQUIZの合格ラインの60%越えないわ。
その問題だが、この文章にはなんて言う題名が合いますか?とか、ここから類推できるのはどれですかとか。
これ国語のテストみたいですね。事実英語圏の人が受けても4択なのに中ぐらいの点数しか取れないんだと。
ちなみにTOEFLは大学の留学のための英語力をチェックするための試験です。


そこでensureとかなんとか書いてあって調べたら「確実にする」とかいう意味だった。
なんかで見た言葉だなと思ったらRubyの例外処理用のキーワードですわ。
普通例外処理用のキーワードというと try~catch~finallyですよね。
C#の場合このように書きます。

try{
System.IO.StreamReader sr=new System.IO.StreamReader("foobar.txt");
try{
data=sr.ReadToEnd();
}finally{
sr.Close();
}
}catch(System.Exception e){
System.Console.WriteLine("Catch! {0}",e);
}

tryしてcatchでその例外をキャッチすると。
ここではSystem.Exceptionでキャッチしてるが、System.IO.IOExceptionとかでキャッチするとそれ以外は無視する。
catchは何個も連ねて書いていいのでこのときはこうという風に条件分岐ができる。
finallyは必ずストリームを閉じるとかそういうことを忘れないようにという使います。
ただしC#の場合はusing構文を使うのが普通ですが。

  using(System.IO.StreamReader sr=new System.IO.StreamReader("foobar.txt")){
data=sr.ReadToEnd();
}

IDisposableを実装したオブジェクトなら自動的に破棄できると。
usingを使う癖を付けておきましょうとよく言われます。


しかしRubyは違う。

begin
fh=File.open('foobar.txt')
begin
fh.each do |line|
print line
end
ensure
fh.close
end
rescue => e
p e
end

Rubyではbegin~rescue~else~ensure~endという構文を使います。
まつもとさん曰く、試してして失敗をキャッチするというよりかはなんかあったときレスキューに行くというほうがいいよね。
とどこかに書いてあったような気がするんだがなぁ……
まぁいいや、とりあえずキーワードが違うんです。
beginから始まることについて、例外がraise(throwではない)されればrescueに行き、何もなければelseに行く。
そしてどちらにせよ最後はensureに行くという構造をしている。
rescueでは rescure => eと例外について受け取る変数を指定したり、 rescue Errno::ENOENT のように例外を限ることもできる。
上の例ではelseは使っていない。
もっとも上の例について言えば、入れ子になってる begin~ensure~endは、

  File.open do |fh|
fh.each{ |line| print line }
end

のようにFile.openをブロック付きメソッド呼び出しすればいいんですけどね。


このRubyのそれの言葉の意味を考えると、
rescue : 例外来たら駆けつけるよ
else : 例外なく終えてしまったなら……
ensure : ここにあることは確実に実行されます
という風な意味でしょう。ここにあるelseってのはしっくりきませんけどね。
rescueで楽しいことはretryっていうのがあるんですね。これしたらbeginからやり直すことができる。
自転車がパンクしたってrescueに応急修理すればretryすればいいじゃない。
そして家に着いたらensureで確実に点検しましょうよ。なかなか自然だと思います。
いいキーワードだと思います。
が……問題は\try~catch~finallyというキーワードがあまりに有名なので混乱せんかということだ。
あとthrowがraiseだったり。厄介なのはthrowに別の意味あったりする。
同じようなことはPerlにも言えますけどね。Cで言うところのbreak,continueがlast,nextだったり。
Rubyでもnextは使われていますね。
まぁ慣れてしまえばそっちのほうがいいのかもしれんが、慣れるまでは大変そうです。

最小二乗法で近似させる工作

今日は最小二乗法の話。ちょっとおもしろい話を聞いたもんでね。
こんな字を書いたら普通は「さいしょうにじょうほう」と読むと思うのですが、
人によってはこの字のまま「さいしょうじじょうほう」と読むから困る。字と読みがあってない。
二乗と自乗は意味が一緒だから結構ごちゃごちゃにして使われていますね。
なので最小二乗法を最小自乗法と書く人もいる。そして「さいしょうじじょうほう」と読む。
僕は自乗よりかは二乗と書くことが多いけど、口ではもしかしたら自乗と読んでるかも知れん。


何のことかというと誤差の二乗の総和が最小になるように近似曲線を引きましょうという話です。
その方法は線形近似、y=ax+bの形で近似することならなんとか手計算でも出来るが、
それ以外の近似ともなると超めんどくさい。
けどできないわけじゃないらしい。
その方法はWikipedia:最小二乗法#正規方程式による解法を見ればよい。
なんか意味分からんこと書いてあるけど、読み解くとこういうことだ。
(x1,y1),(x2,y2)…(xn,yn)
というデータをy=a0+a1x1….+amxmの形に近似するとき、
これを行列を使って処理するんですね。というわけでその行列やらを画像で書いてみた。
最小二乗法の式
これは何のことかというとGという各項の関数、1,x,x2に各データのxを代入したものをデータごとに行にして並べた行列と、
各項の係数をまとめた行列a、各データのyをまとめた行列yを使って考えると言うこと。
そしたらGaが各データのyをaの係数を並べたものを使って近似したyが並ぶ行列になると。
これとyとの差を取って、その各項の二乗の総和が最小になるようにaを決めればいいと。
そのためにはGTGa=GTyとなればよいことが数学的にわかっていると。
この導出はできるはずなんだが気が遠くなりそうなので無視。
ちなみにGTは転置行列のこと。行と列を入れ替えた行列ね。
これを変形するとa=(GTG)-1GTyとなると。
すなわちGTGを計算してこれの逆行列を求めたらあとは行列のかけ算ばっかりで求まると。


それで何を多項式で近似したのかというと近鉄の運賃。
そのためにプログラムを作った。
Perlで作りましたと言いたいところだが、Rubyでやってみた。
データを取ってきて、OOoで編集して、中間距離と運賃の表を用意した。

1.5	150
5 200
(以下続く)

タブ区切りで並べただけですね。中間距離なんて言い出したのは確かJRがそうだったよなと思ったから。
これをdata.txtとして置いてこんなプログラムを用意した。

class Array
def matrix_mul(other)
raise if self[0].length!=other.length
self.map{|a| other[0].each_index.map{|j| a.each_index.inject(0){|s,k| s+a[k]*other[k][j] } } }
end
def gauss(*y)
raise if self[0].length!=self.length
raise if self.length!=y[0].length
a=self.map{|p| p.clone }
a.each_index do |i|
p=a[i][i]
a.each_index{|j| a[i][j]/=p }
y.each_index{|j| y[j][i]/=p }
(i+1...a.length).each do |j|
q=a[j][i]
a.each_index{|k| a[j][k]-=q*a[i][k] }
y.each_index{|k| y[k][j]-=q*y[k][i] }
end
end
(a.length-1).downto(0) do |i|
0.upto(i-1).each do |j|
p=a[j][i]
i.upto(a.length-1){|k|a[j][k]-=p*a[i][k]}
y.each_index{|k| y[k][j]-=p*y[k][i] }
end
end
return y
end
end
data=[]
File.open('data.txt','r') do |fh|
data=fh.map{|l| x,y=*(l.split(/\s/)); [x.to_f,y.to_f] }
end
dim=2
g=data.map{|xy|(0..dim).map{|n| xy[0]**n }}
gtg=g.transpose.matrix_mul(g)
gtginvt=gtg.gauss( *(gtg.each_index.map{|i| gtg.each_index.map{|j|i==j ? 1.0 : 0.0} }) )
at=[data.map{|xy| xy[1] }].matrix_mul(g).matrix_mul(gtginvt)
at[0].each_with_index do |a,i|
print "#{a}*x^#{i}+"
end
puts;

まずは行列の操作についてメソッドをいろいろ用意した。
ここでは行列を行ごとに配列にしたものをまとめたものとした。[[1,2],[3,4]]のように表すわけね。
転置はArray#transposeでできるのでわざわざ作らなかったが、実は1行で足りる。

self[0].each_index.map{|j| self.each_index.map{|i| self[i][j] } }

行列のかけ算はmatrix_mulメソッドとして用意した。
配列aで表される行列と配列bで表される行列の積は、a.matrix_mul(b)で求まると。
かけ算の実際の操作は1行で書いた。Rubyはこういうの得意ですね。
injectをつかうことで掛けたやつの総和を簡単に求められるので1行で作りやすいですね。
ガウスの掃き出し法を行うことで連立方程式を解くメソッドとしてgaussメソッドを用意した。
[[1.0,2.0],[3.0,4.0]].gauss([5.0,7.0])とすると、1x+2y=6;3x+4y=7の解として、[[-3.0,4.0]]が得られる。
実際は右辺をいろいろ変えたのを一回で求められるようにして、答えをまとめて配列で出すようにしている。
というのも逆行列の求め方の1つに連立方程式を解く方法があるわけです。
右辺を(1,0,0,…,0)としたもの、(0,1,0…0)としたもの……(0,0,0….,1)としたものの答えを縦に並べたものを左から並べたら逆行列なんですね。
これを手計算でやっている例は掃き出し法を使った逆行列の計算 (C/C++プログラミング)あたりを見てください。
実はこの作業は右辺を変えた連立方程式を一気に解いていることに等しいわけです。
掃き出し法を忠実に実装しただけなので詳しいことはさっきのページを見てください。
完成したそれで [[1.0,2.0],[3.0,4.0]].gauss([1,0],[0,1]) とすると [[-2.0, 1.5], [1.0, -0.5]] と出てくるので、
求める逆行列は-2.0,1.5、1.0,-0.5という列が並ぶ行列ですね。
ただその行列はさっきのルールでは[[-2.0,1.0],[1.5,-0.5]]となる行列なので最後に転置してやらんといかん。


これらを使ってさっきの計算をするわけだ。
dimに何次方程式で近似するかを入れる。それに応じてGの用意をする。
データを読み込んで、それから行列Gを表す配列gを作る。うまいことmapで作れてしまう。
Gを転置したものとGの積をgtgとして求めて、
これの逆行列をさっきのgaussを使って求めるが、最後に転置しないでgtginvtとしておく。
最後に初めに書いた関係を使ってaを求めるわけだが、
yaは縦一列に数字が並んだ行列だ。これをさっきのルールで表すと[[1],[2],[3]]などなってめんどくさい。
なので手間
を省くためこれを転置した[[1,2,3]]などを使いたい。
画像の最後に書いた式はそれをしたいがために変形した式。
(ABC)T=CTBTATの関係があるのでそれを使っている。
というわけでyを転置したものを[data.map{|xy| xy[1] }]で作り出してからaを転置したものを求めてatとする。
最後にこのatの結果を式で表示させる。上品な表示はできないけど。


結果だが、まず1次で近似すると、175.86+11.50L[円]となる。
グラフに書くと傾きが一定ではないので結構ずれているのが見て取れる。
2次で近似すると、138.93+12.56L-0.004538L2となる。これで結構近づく。
それ以上に増やしたらさらに近づくが、まぁこれぐらいでいいでしょう。
十数円の誤差はあるが、運賃もきれいに決まっているわけではないだろう。
他の会社との兼ね合いで10円ぐらいでもいじってるかもしれん。だから何箇所かは誤差が出る。
しかし近鉄に乗るだけで140円ぐらい徴収される計算なのか。距離が短いとやっぱり損だ。


この関係を使って少し遊んでみた。
難波から宇治山田も明星も運賃は同じ1750円だが、実際は距離は130.7km,139.2kmと違う。
もし近鉄の運賃が1円単位で決まるなら一体何円になるのだろうか。
この近似式から類推してみる。するとそれぞれ1703円,1799円と100円ほど違う。
運賃を数式で書いておけば、これを10円単位に調整したら実際に距離によりふさわしい運賃が取れる。
最近は自動化が進んでいるのでそれでも問題なさそうです。
回数券使ってる人にはちょっとつらいかもしれないけど。


もう1つ、近鉄の長距離の運賃は安いと評判だが、もっと長距離ならどうなるか考えてみた。
とはいえ、これは近鉄の運賃のデータがある区間だけしかあてにならんが。
2次ならそんなに悪くないんだが、5次だと範囲外に出て少し言ったら運賃が下がり始めた。
そんなこと実際にはあるわけないんだが。
まぁしかし二次ならそこまではひどくなかったし、二次関数で運賃を与えることはありそうなので試してみた。
大阪から東京までJRでは556.4kmで、JRでは運賃8510円ですね。
ここでこの近似式から近鉄の運賃ならなんぼか類推してみる。と、5722円とやたら安い。
実際こんな数字になるかはわからないが、250km乗って2790円だから、多分6200円よりは安いだろう。
だからそんなに大それた数字じゃないように見える。
というかJRは近鉄ほど大胆に安くならないので長距離では高めですね。
もっとも距離だけで決まるのかはよくわかりませんが。


今回は多項式でやったが、別にxの代わりにexを使えば指数関数に近似できる。
logexと1を使えば対数関数に近似できる、
sin(ωt),cos(ωt),sin(2ωt),cos(2ωt),…を使えばなんか周期関数に近似できるかも。
基本はこれを使えばいいですね。
しかし行列の計算はアルゴリズムさえ出来てしまえばコンピュータですぐできるね。
手では絶対やりたくないが。

C# 4.0の残念なタプル

僕はTwitterをやってるのだが、その中でC#のLINQ大好きな人がいるわけだ。
その人がC# 4.0についていろいろ書いているのだが、
どうもタプルが導入されるそうです。


タプルとはなにかというのをちょっと考えてみる。
Rubyで整数・整数・文字列の組み合わせを表すなら単に配列を使えばいいねというのは誰もが考えること。

x=[123,1,'カール']
puts "#{x[2]} #{x[0]*x[1]}円"

配列とかハッシュとかというのは便利なものです。
しかしこれと同じことをC#でやろうとすると厄介。
だって配列は同じ型しか入れられないから。
intとintとstringの入る配列はobject[]だが、そうすると型の情報が消えてしまう。
Rubyの場合は型は動的に判定するから配列になんでもかんでも投げ込んでいいが、
なかなかそうもいかない。


まぁそのためにいちいちクラスを作ればいいんだがそれもめんどくさい。
というわけでタプルという道具があるわけだ。
Tuple<(Of <(T1, T2, T3>)>) Class
ジェネリックを使っていますね。最近はおなじみになってきたよね。
ここでTupleを使えばさっきの条件を満たすものが作れる。
このTupleは作ったら内容は変えられないようです。
とりあえずこれを使えばこんな風にさっきのことはかける。

System.Tuple x=new System.Tuple(123,1,"カール");
System.Console.WriteLine("{0} {1}",x.Item1*x.Item2,x.Item3);

なるほどね。


とはいうもののその人はあんまりおもしろくないとも言っていた。
というのも多重代入とかできないしと。
多重代入というのはPerlやRubyではおなじみですね。(参考記事 : 座標のように代入する変数の入れ替え)
タプルといえばこれでしょと。
Rubyでもさっきのxについてこんなことはできます。

price,pieces,name = *x
*y = price,pieces,name
x,y=y,x

まぁ*yに代入する相当のことはタプルを作ることなのでできますけどね。
まぁ確かにこう言う仕組みが欲しいなぁという気持ちはありますよね。


とはいえ、この辺は言語の仕様を変えないと。
そのためにはタプルのリテラルがいりますよって。
そういうのがないとようやらんでって。そこまではC# 4.0ではできないようです。
しかし多重代入ってありがたい機能なんですけどね。
なんでかというのはさっきの参考記事でも見てください。

はんだづけする工作タイム

今日は体験入学の手伝いで学校に行っていた。明日もですね。
工作を見ていたのですが、いやー作りたくなってきますね。
それなら作れよというかもしれんがあれマイコンいるから。
結局マイコンのおかげでなんとかなっているような面はありますからね。
ある意味では楽しくない回路ですよね。
しかしこれをトランジスタとかTTLとかタイマーで作ったらえらい大変なんだろうなとは思った。
作れないことはない……のかな?


まぁそんなことも思いながらやっているわけですが、はんだ付けして工作するわけですわ。
これの面倒を見るのが手伝いの学生の仕事。
こんな風に工作しましょうとかいう話をしていくわけだ。
結構極性間違える人いるんですよ。
あれですね。部品は表につけるけど、足は裏に出てくるというあたりが。
まぁこういうのは考えながら作るに限ると思いますよ。
こっちがグランドだから……と考えて。まぁプリント基板なんで向きさえ間違えなければうまくいくかな。


となると、あとははんだ付けですが、これもなかなか難しい。
僕はまだ工作する機会があったのでわりとうまいことできますけど。
というわけでうまい付け方を見せるわけだ。
何がポイントかというと、はんだを離した後数秒はんだごてを離さないこと。
これですね。これが短いとうまくいかない。まぁ長すぎるのも本当はよろしくないが電気は通るのでよいとしよう。
あとははんだごては尖っているけど、だからといって先だけ当てればいいのかというとこれではうまくいかない。
面で当てるようにしないとうまく温まらない。この2つがうまくいく秘訣かなと思う。
という風に言うのだが、慣れないとこれがうまくいかない。
うまくなじまなかったり、はんだが基板にくっついてしまったり。
まぁその一方ですぐにうまくなってしまう人もいるしいろいろ。


そういえば今日はそんな話は出なかったけど、普段の実験って地味ですよね。
モータ回すよといったら派手な実験に見えますが、実際は計器を並べてこれを読み取ることばかり。
モータ回っているんですけど、どんな調子かというのは回転数以外は電流だったり電圧だったり電力だったり。
まぁそういうものを測定することで分かると。
今回の工作は初めにも書いた通りマイコン使ってるあたりがチートですわ。
だからかなり派手なことも出来ますね。
まぁしかし実際炊飯器とかマイコン様々ですよね。そういう世界を見ていたんですね。
と体験入学の工作に思ったことを書いてみた。

オーディオプレイヤーを調べてみる

今日、朝にD-Snapに音楽を転送しようと思った。
そしたら容量不足だと出てきた。
SD2枚体制でやってきたがもうこれも終わりなのかも知れない。
D-Snapはうまくいかなかったらしい。


というと、D-Snapがかなり悪い機械に見えますが決してそんなことはありません。
多くはSD-Audioの規格が原因だったわけですから。999曲までしか入らないとか。
あとはSDHC使うと電池の持ちが極端に悪くなるとか。この2つが悪かった点です。
一方いい点はいくつかありました。
まず電池の持ちがすごくいい。60時間は持つ。これはすばらしい。
あとSDをセキュア対応でないアダプタに刺して、簡単に転送する方法もあるということ。(参考記事 : D-SnapでTake away!)
この2つの点では非常によい。
特に1つ目の特徴はなかなか満たせるものではない。
そういう良かった点悪かった点を見て、ちょっと考えてみた。


まず、フラッシュメモリ内蔵ですが、どうもこれはどうにもならない気がする。
SD-Audioの拡張を行わなかったPanasonicが悪いのだが、どうも本体とメモリの分離はうまくいかなかったらしい。
本当に残念。それが改良されるならよかったが実際にはPanasonicは撤退してしまった。
なのでどうにもならん。
となると慎重に容量を考えなくてはならない。
今のところ音楽は5GBある。あれ?2GB2枚じゃはいらないじゃないのと言うかもしれない。
これはmp3への変換の時にビットレートを落としていたから。まぁ持ち出すには大きいかと思って。
そういう調整をすることはあるかもしれないが一応これが目安。
ここから考えて8GBあれば結構大丈夫そう。ぜいたくを言うなら16GBあれば完璧かな。
ということを考えてプレイヤーを探してみた。
とはいってもアップルのiPodとSONYのWalkmanぐらいしかないんですけどね。
まぁあとはCreativeのZENとかJVCのalneoとかあるのかな。


このうち興味を引かれたのはZENですね。
というのもZEN X-Fiというやつはなかなかにすごい。
まず、簡単な転送方法がありますね。それはSDカードを使う方法。
なかなか便利そうです。こういう方法があるのは少ないですから。
あと端子もUSB-MiniBなので端子も困らなくていいですね。マスストレージモードにすればべんりそう。
電池は残念ながら36時間しか持たないらしい。まぁそんなもんですか。
友人が使っているのだがなかなかよろしいと言っていた。
なかなか興味がそそられる機能が多いね。
WMAにも対応している、というか基本みたいだし。これはありがたいね。
ただしちょっと大きい。D-Snapよりほんの少し大きいぐらい。ビデオ再生機能付いてたりするので。


Walkmanですが、これは型によって違うのでなんとも。
型ごとにいろいろ違うらしい。
iPodは僕の考えに合うのはそのうちiPod nanoですが、これが案外高い。
実はZEN X-Fiは公式ストアで8GBで13800円、16GBで18800円なんですが、
価格.comでのiPod nanoの8GBの底値が15190円だというあたりからして結構高いことがわかります。
電池の持ちもとてもいいわけでもないし、僕としてはあんまり楽しくない。
人によると思いますけどね。


まぁちょっと考えてみようと思います。
なんせ買い換えなんてためらうほどにD-Snapようできてるから。
けど残念な点も目立つのもまたD-Snapなので考えてみようと思う。

……だと思うよ…じゃなくて

今日の話題は……について。
これリーダー言います。これを表記するときは…(U+2026)を2つ連ねて書くのが普通。
あれ? 2つ使うの? という話ですね。


僕も最近まで気にしてなかったんですけど実はこうらしいです。
原稿用紙では2マスつかうところから来ています。そして点の数は6つ。
昔のいわゆる半角カナの時代はこれに合わせて・(U+FF65、とUnicodeで書くのもどうかしてるが)を6つ並べていたと。
それを引き継いだものが‥(U+2025)なんですね。
これをつかう場合なんと3つ並べて使うと。なにがなんでも点6つなんですね。
というわけで原稿用紙に合わせるならば点6つになるようにするべきらしいです。
最近はそれにあわせて3点リーダーを2つ並べるようにしている。


同様のことは―でも言えますね。
――と並べる必要があるらしい。これも原稿用紙で2マス使ってたから。
余談だが、このダッシュという記号。JISコードとUnicodeのマッピングがうまくいっていないらしい。
JIS規格ではU+2014を使うべきらしいのだが、Shift_JISについてはU+2015であるとか言うからわけがわからない。
どうも複雑な事情があるようです。まぁしかし多分U+2014を使うのがいいのだと思います。
と言っている上のそれがU+2014かは自信はない。


しかしコンピュータで作られた文書を見ると…単独で使われていることも多い。
ダッシュも―のみで使われていることも多い。
別に大きな問題があるわけでもないですけどね。意味はわかるし。
けど印刷物でこれはどうなんだろうか。一応は原稿用紙の使い方に合わせておくべきかなと。
ただ、全く悪いとも言えないわけですね。
というのも同様のものはヨーロッパでもあるわけですわ。
それは…と書くわけだ。1文字でU+2026を使うことも、ってこれは…じゃないか。
日本語では真ん中にありますが、ヨーロッパの言葉だと下にもってくるのかな。
これに合わせて使うならば…または…単独で使うこともあるかもしれない。
まぁしかし純粋な日本語の文章ならどうなのかなとは思うけど。


まぁなにやらお堅いことを言ってきましたけど大切なのはなにかというと、
原稿用紙に書くときミスしちゃだめですねってことです。
まぁこういう事実を知っておくかどうかで変わってくることもあるでしょう。
さすがに毎度毎度……と打つのは手間だし間違いやすいしいいことばかりじゃないんだが、
ここぞというときに間違ったら残念。それなら普段からやる方がいいかもしれません。

足し続けるたたみこみ、かけるたたみこみ

今日はちょっとおもしろいページを見つけた。
初心者向け 畳み込み(たたみこみ)解説 (東北工業大学 情報通信工学科 中川研究室)
至って真面目なページですね。
しかしその内容は結構へんてこな内容。


ラプラス変換の公式集に、こういうのが載ってるんですよね
f(t)*g(t)=∫0tf(t-τ)g(τ)dτ → F(s)G(s)
なんかすごい簡単な公式ですよね。けどこれが取り上げられることなくてね。
まぁそんなもんかと思ってたけど何かわからないものというのには興味がそそられるものです。
しかしこの式見せられてもなんやねんというのはあるわな。
そう思っていままで気にしてなかったのだが、偶然こんなおもしろいページをみつけてしまった。
ということで読んでみた。


この話では、f(t)が時刻tに起きた事件でのショックの度合を表した関数、
g(t)がt=0のときショック度1のショックな事件があったときの時刻tのときのショックの度合。
このf(t)*g(t)というのが何を表すのかというと、tのときの総合的なショックの度合になる。
ということが書かれているわけですね。
t=1のときに3、t=2のときに1、t=5のときに5のショックな出来事が起きたときのt=10のときのショックの度合は、
3×g(10-1)+1×g(10-2)+5×g(10-5)
となりますねという話です。そういうことをやる話らしい。


しかしf(t)という関数はどんなものなんだろうか。
さっきの例で使ったf(t)は3δ(t-1)+1δ(t-2)+5δ(t-5)って関数なんじゃないかな。
δ(t)ってのはデルタ関数といってt=0のときだけ値を持って、その値は∞だと。
けどむやみやたらに∞なんじゃなくて、全部積分すると1になるという不思議な関数。
そんなものがあるんですね。不思議な感じですが。
それでさっきの式に当てはめるとうまいこといく。
なるほどね。
ということはg(t)という関数は、なにかにδ(t)という入力を与えたときの反応なわけだ。
人間にδ(t)というショックをあたえたときのショックの度合とか、
回路にδ(t)という電圧を与えたときの流れる電流とか、そういうことなんですね。


ラプラス変換でLC直列回路の過渡現象を解くときにこんな計算をする。
I(s)=V(s)/(Ls+R)
これはV(s)のラプラス変換する前のv(t)ってやつと、1/(Ls+R)のラプラス変換する前の(1/L)e-(R/L)tのたたみこみのラプラス変換がI(s)だということか。
ということは(1/L)e-(R/L)tという関数はδ(t)という電圧を加えたときの流れる電流なのか。
いやー、不思議なもんです。しかしδ(t)なんて電圧ありえるのか知りませんけど。
それはいいんだが、v(t)ってのはさっきのショックみたいにデルタ関数のかたまりではない。
今日はこれが正弦波交流だと。さてどうする。
というわけだが、これはτの近所を非常に短い時間dτに区切って、
この区間を積分すると多分v(τ)dτになるでしょう。
積分すると同じだけになる非常に短い時間だけ値を持つデルタ関数を用意してやって、
それを投げ込んだときの反応……というのを延々と足し合わせていっているんだろうね。


そう考えると普段やってた計算も恐ろしいものだよね。
デルタ関数に対する反応をひたすら足し続けるということをかけ算1つでやってたんだから。
いやー、ラプラス変換とは恐ろしいやつですね。
まぁそれを気にせずできるのもいいところなんでしょう。
こんな計算、手ではやりたくないわ。

cosのものぐさラプラス変換

宿題で定義に基づいてラプラス変換しろとかいう宿題が出るわけだ。
そこでcos(ωt)をしろとか言われるわけだ。
答えはs/(s22)だ、これは逆変換の時にも使うし。
だけどどっちがsinだったけ、と迷ってしまうこともある。
だから定義に基づいては言い過ぎだけどラプラス変換を計算でして確かめることがある。


定義に基づいてラプラス変換しろと言われると、こういう計算をしなければならない。
0cos(ωt)e-stdt
しかしこの計算は実はハード。なので賢い人はここでeの力を借りる。
というかオイラーの公式ですね。(参考記事 : 三角関数の公式を思い出すオイラー)
cos(ωt)=(ejωt+e-jωt)/2 と置き換えるんですね。
そしたら指数法則を使ってまとめればわりと簡単になる。
そして整理してやると最終的にはさっきの式が出てくる。
僕はよく忘れたときにはcosをそれでさっきのように書き換えて、
それぞれをラプラス変換した(1/(s-jω)+1/(s+jω))/2を整理してs/(s22)を作って確かめていた。


一見ズルいように見える方法ですが、これでもかなり真面目な方です。
友人がこういう計算をしていたわけです。
L{cos(ωt)}=L{Re(ejωt)}=Re[ L{ejωt}
L{ }ってのはラプラス演算子っていうラプラス変換する演算子です。
ようは、cos(ωt)のラプラス変換はejωtのラプラス変換の実部ですよと言っているわけ。
ほんまかいなと思うところだが、確かに1/(s-jω)=(s+jω)/(s22)だからね。
まぁsが実数なのかというのは疑問ですが、確かにそう考えれば出てくる。
この方法、実は教科書にも載ってるぐらいなのでまぁ正しいのでしょう。
しかしこれでいいのかな。


というのもラプラス変換のsというのは実は複素数なんですよね。
まぁ複素数がからまないものなら実数の世界のものは大概実数に帰ってくるでしょうというのは分かるんだ。
例えばcos(α+β)もsin(α+β)もα・βがともに実数なら実数でしょうと。
その変形でオイラーの公式を使ってもまぁ問題ないでしょうと。
実際cos(α+β)=Re{ej(α+β)}と計算しても同じ結果が出てきますからね。


けど、ラプラス変換もそうなのかっていうのは僕にはようわからん。
まぁしかし確かめ算には使えそうだ。正しいと言うことは見て知っているんだから。
しかしこれをレポートに書いてしまったのは良かったのだろうか。
あまり気にしないことにしよう。

これじゃ減衰振動、これじゃ過制動、これこそ臨界制動

やっと長い長い回路の宿題が終わった。
よく夏休みのとき数学とか理科とかで小冊子が渡されてこれを全部やってこいというのがあった。
あれは結構量が少ないのでわりとすぐに終わって楽だったね。
今回はB4の紙1枚でそれ2冊以上の苦労をした気がする。
あれですね。解答を別紙に書かせるというのはいいアイデアですよね。
あの紙1枚で9枚ものレポート用紙を消費してしまったのは終わってからわかったことだ。


そのとき1つ大きなミスをしてしまった。そのせいで無駄に1枚消費したわけだが。
それはRLC直列回路の過渡現象の解析ですね。
Rは抵抗、Lはコイル、Cはコンデンサ、まぁオールスターですね。
というのも定数係数2階線形微分方程式というやつの一般解は3つのパターンに分かれる。
1つは解がA1eαt+A2eβtの形になるもの。
あんまりおもしろくない。
1つは解が(A1+A2t)eαtの形になるもの。
ちょっと変な答えですよね。
もう1つは解が(A1cos ωt+A2sin ωt)eλtの形になるもの。
なんと三角関数が出てきた。これはなかなか楽しい。
過渡現象の解析をするとこういうものが出てくるわけです。
これがRLCのパラメータによって決まるわけですよ。
それで僕は最後に挙げた三角関数のだけ書いて、それ以外書かなかったと。
けど実際はパラメータの決め方によってはそれ以外にもなることがあると。
なのでこの3つを全部網羅したものを作る必要があったと。


ところでこの3つって式ではあれだが、実際はどうなんだというのはなかなかわからない。
というわけでRLC直列回路を作ってシミュレーションしてみた。
コンデンサを10[V]まで充電してこれにコイルと抵抗をつないで放電する実験ね。
まぁ抵抗も多少コイル分を持つといわれているからね。
それにしては極端すぎる実験だが、まぁそういうときもあるだろう。
C=1[nF]、L=1[mH]は固定でRだけ変えてシミュレーション。
過渡解析結果
V1はRを小さめの0.5[kΩ]にしたとき。
Lの割に小さすぎるRにしたらこういう風に振動してしまう。これがsin,cosが解になるやつ。
V2はRを2[kΩ]にしたとき。
実はこれ以上小さくすると振動してしまうが、ここならなんとか振動しなくて済む。
実はこれが2番目に書いた(A1+A2t)eαtの形の解になるやつ。
V3はRをさらに大きくして4[kΩ]にしたとき。
抵抗が小さい方が流れる電流は減るから放電は遅くなる。
これらは運動の言葉を使って、減衰振動・臨界制動・過制動ということがあるらしい。回路でも。
運動でこれは何なのかというと、バネに重りをつるしたとき、
空気抵抗が小さいときはバネは振動しつづける、けど減衰してついには適当に伸びて止まる。これ減衰振動。
空気抵抗が大きいときはゆっくり落ちて止まる。これが過制動。
その中間、ちょうど振動しないで落ちただけで止まる。これが臨界制動ですね。


ついつい振動するのがたのしくて減衰振動だけ書いてしまった。
LCと見れば発振する、という嘘というか、ちょっと用心しろよという話を聞いていたからね。
LCあってもRによって発振するかどうかとか、発振するにしても周波数が変わってくる。
まぁちゃんと計算によって調べろということですね。
具体的に数値が書いてあれば決められたんですけど、記号だけではね。
まぁさすがにRが負の数になるとかそんなことはないんですけど。
というわけで1枚追加して3通りに分けて答えを書いて完成と。

再利用がはかどるC# 4.0の共変性・反変性

今日は日食だったのでそのことを書けばよさそうなもんだが、
これについては別の所に書いたのでもう書かない。
まぁ曇りだったけど少しは見えたかな。なかなかよかったね。


ちょっと前に教えてもらったんだが、C#の配列はなかなか変である。
というのもこういうことができてしまう。

string[] strs=new string[] { "a","b" };
object[] objs=strs;
objs[1]=System.Text.Encoding.UTF8;

string[]をobject[]にキャストできると。しかも暗黙的に。
問題ではないと思う人もあるかもしれんが、strsとobjsは同じものを指しているというのが問題。
string型配列として作られたところにそれ以外の型のオブジェクトを入れることはできない。
というわけで代入するときにSystem.ArrayTypeMismatchExceptionが出る。
なのでこのキャストは明らかに不正なんですが、コンパイルは通ってしまう。
まぁこんな不気味な変換はやったことなかったから知らなかったわ。


同じようなことはSystem.Collections.Generic.Listなんかにはできません。
そりゃ一般に通用する技じゃないですからね。
これがC# 4.0から変わるらしいです。
その前に今まででもできていたことを書いておく。

static string ToString(object obj) {
return obj.ToString();
}
static void Main(string[] args) {
Func fo2s=ToString;
Func fs2o=ToString;
}

object型を引数にとりstring型を返すメソッドがあったと。
このメソッドはFuncデリゲートを使って表すことができると。
けどこのメソッドはobject型という範囲を狭めてstring型に限定して、返すstring型はobject型でもあると拡大解釈して、
string型を引数に取り、object型を返すメソッドであるとしてFuncデリゲートでも表せる。
不思議な性質ですよね。けど理屈には合ってる。
引数の型の範囲を狭める方を反変性、返り値の型を拡大解釈する方を共変性と言うそうだ。
まぁ詳しいことはデリゲート#covariance と contravariance (++C++)を見て欲しい。


このことによれば入口はどれだけ狭めても構わない、出口はいくら広げても構わないと。
これをC# 4.0からはジェネリックにも拡大しましょうということです。
残念ながらSystem.Collections.Generic.Listのメソッド・プロパティは入口にも出口にもTを使っている。
例えばインデクサ(mylist[idx]の形式でアクセス出来るプロパティ)では入口であるセッターも出口であるゲッターもT型。
残念ながらそれは叶わない。
けど出て行く一方のSystem.Collections.Generic.IEnumerableとかは共変性が認められると。
すなわちIEnumerableはIEnumerableでもあると。
逆に反変性はジェネリックデリゲートで使うことが多いかな。
System.Comparisonとか、これはT型の2つの引数を取って大小をintで返すものですね。


これができるようになると何がうれしいか。
IEnumerableの方はIFooインターフェースを実装したクラスの型の何がくるかわからなくても、
IEnumerableだけ受け付けるようにすればOKと。
今までだとこういう場合ってSystem.Collections.IEnumerableを要求するしかなかったと思うんだよね。
だけどそうすると型の点では不安だからね。型がわかるのはありがたい。
ComparisonはAクラスを継承したBクラスの比較にAクラス用のやつが使えるとか。
まぁ再利用がはかどると。
どっちかというと後者のほうはありがたかったりして。
もうC# 4.0も近づいてきているのでちょっと期待している。