2010年10月22日金曜日

Maxwellの面積計

面積計の歴史をウェブで探すといろいろ見つかる. それを読むと, 円錐(cone)がどうのこうのと書いてあったりする. 面積計の基本知識として, このブログでは円錐の機能を説明しよう.



この図は, Johannes Oppikoferの面積計といわれるものである. Maxwellのと違い, 台枠は固定されていて, 手前にある針を前後に動かすと, その支持腕が伸び縮みし, また腕を左右に動かすと, 支持腕とその右にごちゃごちゃ見える機構が一緒に左右に動く.

ごちゃごちゃの機構の中央に横倒しになった円錐が見える. 円錐は, 機構が左右に動くと, その幅に従った角度だけ水平の軸の周りに回転する. また円錐の上方に, 立っている文字盤があり, その下に小さい円板があって, 円錐に接している. この円板から上は, 支持棒の前後の動きと連動しており, 針が奥に行くほど円板は円錐の頂点に近いところで円錐に接するようになる.

つまり, 針が左右に dx 動くとき, 円板, つまり文字盤の回転する量 dφ は, 針の奥からの距離 y に dx を掛けたものに比例するわけである.



というわけで, 面積計になるのだが, 針を前後に動かす時, 円板が円錐面を横車を押すように動くのが, Maxwellたちの気に入らなかったようである. たしかに, Maxwellの半球と全球の機構はそうなっていない.

また, 円錐の母線が奥の方では低くなるので, 円板や文字盤の高さを変えることも考えなければならない.

Oppikoferの面積計は, 1827年に考案され, 1836年にパリで制作, 販売されたそうだ.

2010年10月18日月曜日

マッチ棒の立方体

すいぶん前のことだが, 数学セミナーにSystem-5というコラムがあった. 東大の高橋秀俊先生, 森口繁一先生, 学習院大学, のちに東大情報科学科の米田信夫先生, 立教大学の島内剛一先生と私が, 持ち回りでなにか書いていた.

今回のブログは, 私が以前そこに書いたものだ.

オランダ Delft大学のvan der Poel先生が大宮の拙宅に来られた時, おみやげといって, 下の写真のようなマッチ棒で出来た箱を下さった. van der Poel先生によると, デンマークのPeter Naur先生(Backus Naur FormのNaurさん)の問題 「接着剤を使わずマッチ棒だけで立方体を作れ」を考えた結果作ったものだそうだ.

van der Poel先生に頂いたものは, 遠の昔にどこかへいってしまった. この写真のは, 私がこの週末に作ったものである.



マッチ棒を90本も使っているから, ちらちらするが, 三面図を書いてみると, このようになる. 第3角法になっていて, 右下が正面図, 左が側面図, 上が平面図である. マッチの軸に色が着いていて, 薬の部分が白くなっている.




原理的には, 下の図のように, 3対のカードを組合わせ, 対同士を輪ゴムで止めると立体が出来るのと同様である.



実際に作ってみると, この写真のようになる.



ただ, 輪ゴムは, 接着剤ではないが, 違反であって, 輪ゴムの代りにマッチ棒を使えばいいのである. (上の図の左下.) この図ではマッチ棒は抜けてしまいそうだ. しかし, 別の面の力で絞められると, 抜けなくなるのである.

というわけで, 下の図のように, 1,2,3,...,21の順で, マッチ棒を組み立てると, この立方体が完成する. この図では, 薬の方に色がついている. 20と21では, 上に薬が来る時に色がついている.





この図と三面図の正面図の対応は, こうだ. 1は正面図の底の緑の横向きのマッチ. 2は下から2段目の青の奥向きのマッチ. 3から17は, 赤の横向き, 奥向きのマッチ, 18は上から2段目の青の奥向きのマッチ. 19は蓋の緑の横向きのマッチ. 20と21は平面図の奥向きのマッチである.

しかし, 実際やってみると, 賽の河原よろしく, 出来上がる前に崩れてしまう. まぁ, 完成するには, よく考え, ちょっとしたノウハウを利用する必要がある. それは ひ み つ.

2010年10月15日金曜日

Maxwellの面積計

Maxwellといえば電磁気学で習う4つの式や悪魔(demon)を思い出す. 昔の学者はなんでも屋で, そのMaxwellは面積計も, しかも2種類も, 発明したことを最近知った.

Internetで探すと, The Scientific Letters and Papers of James Clerk Maxwellにあるこういう図


や, RutherfordJournalにあるこういう図



が見つかる.

今回は, この面積計の説明である.

下の図を見て欲しい.


これは面積計を上から見たところである. 水平に置かれた回転軸ABがあり, 右方に車輪Hがある. 左方には, 半球KCBがあり, Bが極に対応する. 手前の方, VXに沿って動くMと, 半球の中心Sを通る鉛直軸を結ぶ, 伸縮する棒MSがある. MSから直角に出た枠SDがあり, EFを回転軸とする全球ECB'Fが半球にCで接している. MがOの位置にあると, SDはASと重なり, 全球の赤道DB'が半球の極Bに接し, MがOから左へ行くにつれ, 全球はSを中心に上にあがるが, 球面同士は滑らないものとする. 従って, ∠OSMをθとすると, ∠BSC, ∠B'DCもθである.

面積を計測する時は, 面積計を平行に手前に引いたり, 遠方に押したりしながら, Mが図形の周囲を辿るようにする. RutherfordJournalの図の破線や, 台車の右下の車輪から推察出来る通りである. 面積計の押し引きに応じ, 車輪Hが紙との摩擦で回転し, 同軸の半球も回転し, それに接する全球も回転する.

OMの距離をy, OSの距離をh, 車輪Hの半径をR, 半球, 全球の半径をr とし, 面積計をdxだけ奥に押した時の全球の回転角dψを計算してみる. xの正方向は, Hと半球の向こうへの回転, 全球の手前への回転とする. Hの回転角(radian)は dφ=dx/R. するとC点で半球の緯線が鉛直方向に動く距離は, rsinθdφ. 全球のCでの緯線の半径はr cosθ. 全球の緯線も鉛直方向に同じ長さ動くから, 従って回転角dψ=r sinθdφ/r cosθ=dφtan θ. ところで, tanθ=y/h. ∴dψ=dφy/h=(dx y)/hR.

この面積計で円の面積を計ってみる. R=1, h=2, 円の半径=1とする.



最初, Mを計測対象の赤線の円の真下に置く. この時の半球と全球の中央の経線を赤で示す. 以後の図で,この経線の移動が分かる.



円周の1/4のところまでMが移動した. 面積計も奥へ移動し, 車輪Hが回転し, 半球の目印の経線も1radianだけ回った. ここまででスキャンした面積をオレンジ色で示す. それに相当した角度だけ, 全球も回転した.



Mは円の真上まで来た. 面積計はさらに奥まで移動した. 半球も全球も回転を続ける. 半球の回転角は2 radian. 半球の下側に入ったので, 破線で示す.



円周の右を辿って下がり, 3/4来たところ. 車輪も半球も先ほどとは逆に回転し, 面積を記録している全球も逆回転した.



Mは円周を一周した. 半球の経線は元に戻り, 全球の経線は, 面積πの半分を円周に一致して示す.

Maxwellはこの面積計を作成したわけではない. 実際に作るのは難しそうである.

2010年9月29日水曜日

学者猿コンサル

前回のブログ(コンサル)は, 検討も設計も多少杜撰であった. 改めて考えた描き方はこうだ.

これは2変数関数の値を表示するいわば計算図表みたいなものである. 計算図表には, 変数の変域があるわけで, 今回はそれをxminと, xmaxとする. また2つの変数をx0と, x1とする. つまりxmin≤x0, x1≤xmaxである.



xminとxmaxの基線の上に, x0とx1の点A, Bをとり, それを脚とする長さlの二等辺三角形CABを描く. ACをCで左に135度曲げてDの方向へ長さm(=l/√2)だけ伸ばしDとする. BCをCで右に135度曲げてFの方向へ長さmだけ伸ばしFとする. CD, CFを2辺とする菱形CDEFを作ると, Eが関数の値の場所になり, その座標は(x0+x1)/2, (x1-x0)/2となる.



x座標は誰にでもすぐ分かるが, y座標がかくもきれいな形なのは不思議である. これからは幾何学だが, まず二等辺三角形CABの底角はどちらもαなので, 頂角∠ACB180-2αである. ACの長さはl, ∠ACDは45度, CDはl/(√2)なので, DACは直角二等辺三角形である. DEの線はDから下向きに45-αなので, 菱形で上半分の角度も同じゆえ, ∠CDEは2α-90. 従って, ∠ADEは180-2αとなり, 先程の頂角とおなじである. また, DA=DE=mだから, DAEはCABと1:√2の相似形であった. 従って, AEはABの1/√2であり, 右側も同じなので, EABは直角二等辺三角形である. ゆえにEのy座標, EHはABの半分, つまり(x1-x0)/2である.

y座標は, x0≤x1なら正だが, 反対だと負になり, 基線より下になることに注意しよう.


こうして作った減算表(x1-x0)が次のものだ. 8-3=5と3-8=-5を示している. もうアニメーションを作る必要はないと思う.


2010年9月26日日曜日

学者猿コンサル

2010年9月 Brisbaneで開催されたIFIP WCC2010でHistory of Computingのシンポジウムがあった. そこでオーストラリアのMonash大学のJudy Sheardさんが同大学のコンピュータ博物館を紹介した. そのスライドの中に, おや?と思う絵があった. 一瞬の内に次に進んだが, 同行の山田さんがその絵を写真に撮っておられたので, 頂いた.

Consul, the Educated Monkeyという計算関連の教育玩具である. ウェブページで調べると, 1916年頃にアメリカで売り出されたものらしい.


(出典http://www.rechenwerkzeug.de/consul.htm)

使い方はこうだ. 猿の両足を, 図のように下の目盛の3と9に合わせると, 猿の手が示す枠の中に積の27が現れるのである. 目盛の右端の12の右には四角が見えるが, 片足をそこに合わせると, 他方の足の自乗が現れる.

これは乗算表であるが, この表は差し換えられ, 加算にも使える.

こういうものがあると知ったら, プログラムしたくなるのは当然である.

http://playground.iijlab.net/~ew/consul/consul.htmlを見て欲しい. これは十六進の乗算表である. 下の目盛は0からfまであり, 目盛に乗っている足の辺りをマウスで横に動かすと, リンク機構がつられて動き, 赤印の交点の直ぐ上に積が現れるようになっている.


多少の設計ミスで, 0とfの積などでは, 赤印が頭の上に行ってしまうのは, ご愛敬である.

なお, Consulのシミュレータもウェブにあった.

http://www.edumedia-sciences.com/de/a572-consul-the-educated-monkey

2010年9月16日木曜日

入れ子のかっこ

前回のブログの点記法の続きである. とりあえず練習をしよう. 私の手元のPaul Rosenbloom, The Elements of Mathematical Logic (Dover 1950)に点記法の論理式が沢山出てくる. それでテストしてみた. まずSchemeでBoole値が0と1のnot, or, impを定義する.

(define (not p) (- 1 p))
(define (or p q) (quotient (+ p q 2) 3))
(define (imp p q) (or (not p) q))

テストをするには, mapが便利.

(map not '(0 1)) => (1 0)
(map or '(0 0 1 1) (0 1 0 1)) => (0 1 1 1)
(map imp '(0 0 1 1) '(0 1 0 1)) => (1 1 0 1)


上の本では, 沢山並ぶ -> には特にかっこを(点で)示さない. -> はleft associativeであって, (p -> q -> r) は ((p -> q) -> r) なのだ.

ではやってみよう.

I4 p -> .q -> r. -> .p -> q -> .p -> r
かっこに変えると
((p -> (q -> r)) -> ((p -> q) -> (p -> r)))
Schemeの定義は
(define (i4 p q r)
(imp (imp p (imp q r)) (imp (imp p q) (imp p r))))
実行
(map i4 '(0 0 0 0 1 1 1 1) '(0 0 1 1 0 0 1 1)
'(0 1 0 1 0 1 0 1))
=> (1 1 1 1 1 1 1 1)

もう1つ.

T2 q -> r -> .p -> q -> .p -> r
かっこに変えると
((q -> r) -> ((p -> q) -> (p -> r)))
Schemeの定義は
(define (t2 p q r)
(imp (imp q r) (imp (imp p q) (imp p r))))
実行
(map t2 '(0 0 0 0 1 1 1 1) '(0 0 1 1 0 0 1 1)
'(0 1 0 1 0 1 0 1))
=> (1 1 1 1 1 1 1 1)

とうまくいく.

かっこ記法と点記法の変換だが, まずかっこから点へは, すべての2項演算子をかっこでくくることにし, つまり

<primary>==<letter>|(<expression>)
<expression>==<primary>|<expression>*<expression>

だけとする. expressionの例は a, a * b, (a * b) * c, ...など.

expression * expression を点記法にするには, expression' lp * rp expression とする. expression'はexpressionを点記法に変えたものである. lpとrpは, 左右のexpressionをひとまとまりにする点である. lpは左のexpression'で使った最大の右点の数より多く, rpは右のexpressionで使った最大の左点の数より多くなければならない. 従って, 下請けの変換は, expression'を返すと同時に, 自分の使った右点, 左点を返すことにする.

letterの場合は, letterの他に, 右点,左点として, 0,0を返す.

* の場合は, 左の式を変換て置き, その右点+1の左点を置き, 演算子を置き, 右の式を変換し, その左点+1の右点を置き, 右の式を置く. また自分で使った左点, 右点も返す.

(define (dotconv exp)
(display (list exp))
(if (symbol? exp) (list '(0 0) exp)
(let* ((l (dotconv (car exp)))
(r (dotconv (caddr exp)))
(op (cadr exp))
(rlp (+ (cadar l) 1))
(le (cadr l))
(lrp (+ (cadar r) 1))
(re (cadr r)))
(list (list rlp lrp)(list le rlp op lrp re)))))


(dotconv 'a) => ((0 0) a)
(dotconv '(a * b)) => ((1 1) (a 1 * 1 b))
(dotconv '((a * b) * c)) => ((2 1) ((a 1 * 1 b) 2 * 1 c))
(dotconv '((a * b) * (c * d))) =>
((2 2) ((a 1 * 1 b) 2 * 2 (c 1 * 1 d)))

この後は ((a 1 * 1 b) 2 * 2 (c 1 * 1 d)) を a * b . * . c * d にしたい. flattenし, 整数はそれ引く1の点を出力する.

(flatten '((a 1 * 1 b) 2 * 2 (c 1 * 1 d))) => (a 1 * 1 b 2 * 2 c 1 * 1 d)

(define (convstream l)
(apply string-append (apply append
(map (lambda (x)
(list (if (number? x) (make-string (- x 1) #\.)
(symbol->string x)) " "))
(flatten l)))))

(convstream '((a 1 * 1 b) 2 * 2 (c 1 * 1 d)))

(define (par->dot exp) (convstream (cdr (dotconv exp))))

(par->dot 'a) => "a "
(par->dot '(a * b)) => "a * b "
(par->dot '((a * b) * c)) => "a * b . * c "
(par->dot '((a * b) * (c * d))) => "a * b . * . c * d "


一方, 私の考えた逆変換はこうだ.


1.(((a * b) * (c * d)) * ((e * f) * (g * h)))
2."a * b . * . c * d .. * .. e * f . * . g * h "

1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
3.(a 0 * 0 b 1 * 1 c 0 * 0 d 2 * 2 e 0 * 0 f 1 * 1 g 0 * 0 h)
4.29
5.((-1 5) (-1 13) (15 21) (23 29) (15 29) (7 13))
6.(< < < a * b > * < c * d > > * < < e * f > * < g * h > > >)
7.(((a * b) * (c * d)) * ((e * f) * (g * h)))


上の例で, 1. は元のかっこ記法の式. 2. はそれを点記法にしたもの. 逆変換はここから始まる. まず各演算子に左点と右点があるものとし, 3のように変換する. その上の2行は, 各要素の位置を示す. 0から28まであるから, lengthをとると, 4. のように, 29.

位置 1,5,9,..のように, 4を法として1の位置は左点. 3の位置は右点である. さらに, 演算子は2(mod 4), 変数は0(mod 4)である.

次に各右点>0にはこの右方にある相棒の左点を探し, また左点>0にはこの左方にある右点を探し, 対にする. 上の例では 5. が対のリストである. この読み方は, 5の位置の左点を越える右点は, 左方にはないので, -1とし, (-1 5)とする. 13の位置の左点も同じ. 21の位置の左点は, 15の位置の右点の方が大きいので, スコープはここまでとなり, (15 21)が出来る. 3. と5. の情報から, 6. を作るのだが, (-1 5)のような対があれば, -1に左かっこ, 5に右かっこを置く. この挿入で, 位置がずれると困るから, 挿入は番号の多い右端から行う. 右かっこと左かっこの区別は, 4を法とした剰余の1か3で決る. まだこの段階は記号列であるが, 通常のかっこを記号として挿入すると, 分かり難いから, 角かっこを使っている. 出来たのは6. である.後は, 入れ子の式の読込みルーチンを書けばよい. それにより, 7. が得られる.

(define (iconv s) ;2. -> 3.
(define (char->symbol c)
(string->symbol (list->string (list c))))
(define (reads n s)
(cond ((null? s) s)
((char=? (car s) #\Space) (reads n (cdr s)))
((char=? (car s) #\.) (reads (+ n 1) (cdr s)))
(else (cons n
(cons (char->symbol (car s)) (reads 0 (cdr s)))))))
(let ((ss (string->list s)))
(cons (char->symbol (car ss)) (reads 0 (cdr ss)))))

(define (makepair s) ;3. -> 5.
(let ((len (length s)) (ps '()))
(do ((i 3 (+ i 4))) ((>= i len))
(let ((r (list-ref s i)) (k len))
(do ((j (- len 4) (- j 4))) ((< j i))
(let ((l (list-ref s j)))
(if (< r l) (set! k j))))
(if (> (- k i) 2) (set! ps (cons (list i k) ps)))))
(do ((i (- len 4) (- i 4))) ((< i 0))
(let ((l (list-ref s i)) (k -1))
(do ((j 3 (+ j 4))) ((> j i))
(let ((r (list-ref s j)))
(if (> r l) (set! k j))))
(if (> (- i k) 2) (set! ps (cons (list k i) ps)))))
ps))

(define (makestr ps s len) ;5. 3. (length 3) -> 6.
(define (insert l n a)
(if (<= n 0) (cons a l)
(cons (car l) (insert (cdr l) (- n 1) a))))
(set! ps (sort (apply append ps) >))
(for-each (lambda (x) (set! s (insert s x
(if (= (modulo x 4) 3) '< '>)))) ps)
(append '(<) (filter symbol? s) '(>)))

(define (str->sexp str) (define i 0) ;6. -> 7.
(define (getch) (let ((ch (list-ref str i)))
(set! i (+ i 1)) ch))
(define (read) (let ((ch (getch)))
(cond ((eq? ch '<) (readtail))
((eq? ch '>) '())
(else ch))))
(define (readtail) (let ((x (read)))
(if (null? x) x (cons x (readtail)))))
(read))

2010年9月5日日曜日

入れ子のかっこ

Lispの好きな人は, かっこだらけのS式を何とも思わない. 反対にhtmlのようなタグでの入れ子には耐えられない.

しかし, S式を声を出して読む時, 「かっこ開く」「かっこ閉じる」や「左かっこ」「右かっこ」というのは煩わしい. 私は昔から,左かっこを「かっこ」, 右かっこを「こっか」と読むことにしている. (Algol 68で, 添字に使う [ と ] を, sub symbol, bus symbolと呼んでいたのをまねした.)

ところで, 今回の話題は, 自然言語の構文解析である. 構文解析木を図で表わすのは容易だが, かっこ付きでも表わせる.

Time flies like an arrow は 光陰矢の如し と構文解析するのが普通だが, 時間の蝿は矢が好きだ という笑い話もある. 前者は Time (flies (like an arrow)), 後者は (Time flies) like an arrow と表現すればよい.

SICPに簡単な自然言語解析の話がある. その問題4.45は, The professor lectures to the student in the class with the cat を5通りに構文解析せよ, だ. やってみると

1 ((the professor)
(((lectures
(to (the student)))
(in (the class)))
(with (the cat))))
2 ((the professor)
((lectures
(to (the student)))
(in ((the class)
(with (the cat))))))
3 ((the professor)
((lectures
(to ((the student)
(in (the class)))))
(with (the cat))))
4 ((the professor)
(lectures
(to (((the student)
(in (the class)))
(with (the cat))))))
5 ((the professor)
(lectures
(to ((the student)
(in ((the class)
(with (the cat))))))))

それぞれの和訳は

1 教授は(猫を連れて(教室で(学生に講義する)))
2 教授は((猫を連れた教室)で(学生に講義する))
3 教授は(猫を連れて((教室の学生)に講義する))
4 教授は((猫を連れた(教室の学生))に講義する)
5 教授は(((猫を連れた教室)の学生)に講義する)

猫を連れているのは, 1と3は教授. 2と5は教室. 4は学生である.

ウェブを眺めていて, H.B.Curryの書いたページを見つけた. ただで見られるのは1ページ目だけだが, 今はそれだけ見られれば充分である.

論理の式には, かっこの代りに点が打ってあるものがある. 件のページには, その提案が書いてある.

Let us suppose that a group of dots on the right of an operation or prefix denotes the beginning of a bracket which extends to the right until it meets a group with an equal or larger number of dots on the left of an operation; and that the scope of a group of dots on the left of an operation shall extend to the left unitl it reaches a larger group of dots on right of some operation.


つまり,
p -> q . -> . q -> r .. -> . p -> r

((p -> q) -> (q -> r)) -> (p -> r)
のことである.

この方式を何と言うか知らないが, dot notation つまり 点記法ということにする.

上の和訳の入れ子のかっこ構造から, 点記法を使い, かっこを外したい. それには, 演算子がどれか決めたい. 演算子は左かっこの右, 右かっこの左にあるのだから,

教授猫を連れ教室学生講義する

の赤字の助詞類を演算子と考える. (猫を連れた, 教室の は形容詞句の時で, 副詞句の時は, 猫を連れて, 教室で になる.)

すると, それぞれの例文は

1 教授は . 猫を連れて . 教室で . 学生に講義する
2 教授は .. 猫を連れた教室 . で . 学生に講義する
3 教授は . 猫を連れて .. 教室の学生 . に講義する
4 教授は ... 猫を連れた . 教室の学生 .. に講義する
5 教授は .. 猫を連れた教室 . の学生 . に講義する

となる.

この点を , 2点を ,, に変えると
1 教授は, 猫を連れて, 教室で, 学生に講義する
2 教授は,, 猫を連れた教室, で, 学生に講義する
3 教授は, 猫を連れて,, 教室の学生, に講義する
4 教授は,,, 猫を連れた, 教室の学生,, に講義する
5 教授は,, 猫を連れた教室, の学生, に講義する
のようになる.

点記法に慣れると, これで読めなくもない. では声を出して読むにはどうするか.

Shakespeareの時代, 劇の台本には句読点が何種類かあり, それぞれで間の取り方が違うという話を読んだことがある. そのように, カンマ2つはカンマ1つより長く間をとれば, この例は構文木が分かるのではないかと考えるが, どうだろうか.