2011年2月24日木曜日

対称関数

対称関数の続きである. そのブログの中程にある図に示すように, 2変数対称関数は8個, 3変数対称関数は16個ある.

n変数のBoole関数は, 定数関数も含めて22n(2の2のn乗乗)あるが, n変数の対称関数は2n+1しかない.



3変数対称関数の図を眺めると, 各立方体で, 同じ色の対称同士の点は, 000の(赤の)点から, 等距離にあることが分かる. 距離の計測法は, 000から立方体の稜にそって目的地まで進む最短距離, いわゆるマンハッタン距離である.



改めて眺めると, 赤までの距離は0, 緑までは1, 橙までは2, 青までは3である.

つまり対称の要素は4個あり, その要素を採用するか, しないかの問題であった. n変数は000...0の点から111...1まで行く辺の種類はn個なので, 要素の数は両端を含めてn+1, 従って2n+1になるのであった.

2011年2月21日月曜日

乗算表

「昔のウクライナの人たちはこうやって計算した」と話し出したのはMike Williamsさんだ.



指を出し, 小指の外から指の間を順に0,1,2,...と数える. 親指を飛び越えると5になる. そこで折り返し, 6,7,...と続ける. 小指を過ぎると10になる.

さて, 7×8をウクライナの人はどう計算するか. 片手(左とする)の指をさっき7と数えたところで, 上下に開く. 反対の手(右とする)でも, 8と数えたところで, 上下に開く. 左の上の指が2本. 右の上の指が3本. 左の下の指が3本. 右の下の指が2本となる.

10×(上+上)+(下×下)と計算する. つまり 10×(2+3)+(3×2)=56 が答だ.

下の指は最大で5だから, 5×5までを知っていれば良いのだ.

これで5<M,N≤10について, M×Nが計算出来る理由を, 下の色付きの図で説明する.




まず上左の図. 縦軸がMで, 中央に5があるから, Mは中央より上にある. 横軸がNで, Nも中央より右にある. この場合, Mの上(upper) MuとMの下(lower) Ml, Nの上(upper) NuとNの下(lower) Nlはそれぞれ図に示す範囲だ. 従ってMu×10は, 途中で色が変っているが, 横ハッチの部分である. 一方, Nu×10は, 縦ハッチの部分だ. そしてMl×Nlは, 斜めハッチの赤い部分である.

ところで, この図の右上の4半分は, 図の中心で180度回転すると, 左下に移すことが出来て, 右の図のようになる. Dと書いてある縦ハッチと横ハッチが重なっている部分は, 面積の計算で2回足しているが, 右上のD'のところへ移動することが出来, 全体がちょうどM×Nになるのである.

下の, 白黒の淋しい図は, 乗算の一方が≤5の時の方法である. 今, Mの方が5より小さいとする. M×Nは, 図では, ハッチに囲まれた左下の小さい白い部分である. この場合は 50−(10×Mu+Ml×Nl)と計算することになるが, これは面倒な気もする.


昔のウクライナ人に聞いてみたい.

2011年2月14日月曜日

水計算器

計算機にディジタルとアナログがあるのは周知のことだ.

アナログは計算尺のように物理量を使うといわれるが, 殆んどの機械は長さが基本である. しかし, もっと違う物理量を使うものはないか.

小学校のとき, 曲線で囲まれた面積を計測しようという課題があった. 私は, その形を厚紙から切抜き, 重さを測ればよいと考えたが, 先生の用意した解は方眼紙にコピーして, 桝目を数えるのだった.

面積計の話題は, このブログに何回も登場したが, 毛色が違うのは, ボストンの科学博物館にあった, 液体を使うPithagorasの定理の証明である.

ガラスで被われた一様な厚さの正方形の箱が3個, 3:4:5のPithagoras三角形の形においてあり, 色のついた水がはいっている. 箱の繋ぎ目は水が通れる. 全体の装置は垂直面になっていて, 中央あたりの水平の軸で回転できる.




まず3と4の箱が下に来るようにすると, その2つの箱に丁度いっぱいに水が入る. 次にそれを180度回転すると, 水はすべて5の箱に収まる.

「水は器に従いて」の歌の通り, 面積を保ちながら, 形が変えられるのを利用したものだ.

それなら体積は使えないかと考えたのが, 次の立方根計算器である.





右の円筒の途中まで水が入っている. 上まで満杯の時, 水面の高さを1とする. 図では0.5になっている. この水をそのまま, 左の円錐へ移す. そうすると円錐の母線に沿った目盛で, 先ほどの量の立方根0.79が読める仕掛けである.

しかしびしょびしょして, 実用にはなりそうもない. 粉体も無理だが, 微小な球の粒を, Pitagorasの機械のように, 閉じ込めて使うことなら出来そうである.

体積2倍の立方体をつくるのに, 使えたかもしれない.

2011年2月13日日曜日

対称関数

TAOCP V4F1にきれいな絵があった. 元の絵はもちろん白黒である.



これは3変数対称関数のBDD(二分決定図)ベースの図である.

そもそも対称関数とは, 変数をとりかえても値が変らないものである.

以下に2変数(xとy), 3変数(xとyとz)の対称関数を示す. 頂点にある色つきの丸は関数値が1の点で, 同じ色は対称の相手を表わす.



上の方の2変数対称関数は, それぞれの図で, 左下がx=0, y=0. 右上がx=1, y=1の点で, 破線は対称軸. 従って対称関数は, 同じ色の丸が対称軸について対称であるものである.

2変数関数が16あるうち, 対称なのはここにある0番から7番の8個である.

3変数のx, y, zは, 左上の0番の図に示す通りで, 3変数の場合も, 同じ色の丸は対称軸について3回対称である.

3変数関数は全部で256あり, 対称なのは0番から15番の16個である.

Boole関数は, こういう図の他, その真理値表で表わすことも出来る. x, y, zの各値に対し, 関数値を並べて書く. 例えば3番は多数決関数で


x 00001111
y 00110011
z 01010101
f 00010111


である. 図からは右下の経路で頂点をたどり1と0を書き取ればよい.


ところで, TAOCP 7.1.4項は, BDDが話題であった. BDDは下に示すような図で, 変数を調べる節点を実線と破線で繋げたものである.

一番上の入口(根)から出発し, 丸で示す変数の値を調べ, 値が1なら実線方向へ, 0なら破線方向へ進み, 次の変数をチェックする. 四角に⊥は, 関数の値が0で確定する, 四角にTは, 1で確定し, BDDの出口である.

下の図は, 3変数の16個の対称関数のうち16個のBDDで, 0番のオール0, 15番のオール1は定数関数なので, 省いてある.




最上段の右端の3番が, 話題の多数決関数で, 根の1番変数(xのこと)の脇に先ほどの真理値表が書いてある. xが0なら左下の2番変数へ進み, yを調べる. ここでyも0ならzと無関係に0なので, 0の出口になる. yが1なら, 決定はzによる. そこで3番へ進む. 上へもどり, xが1なら右下の2番変数へ進み, 2も1なら1の出口. 2が0なら3番の変数をしらべる. BDDはこのような図である.


ところでそれぞれの図の節点の数は, 0と1の出口は1個と数えるので, 1番から順に, 5, 7, 6, 7, 7, 7, 5, 5, 7, 7, 7, 6, 7, 5 で合計88個ある. 1の節点は14個あるが, 1段下の2の節点は6種類, 3の節点は2種類しかない. 同じものをまとめてメモリーにいれれば節約になるといってまとめたのが最初に掲げたBDDベースである. ここには節点は24しかない.

1の節点の左下の青の番号は, 対称関数の3変数の番号と一致している. 一番上の3番は, 実線で左の2へ, 破線で右の2に進むが, それぞれの2の左に青で1と3とあるのは, BDDの2の添字に合っている.

もう一度対称関数の絵で3番をみると, xが1の手前の四角の丸は, 直ぐ上の2変数の3番と同じ. xが0の向こうの四角は, 2変数の1番と同じであり, さきほどの添字はそれを表わしている.

変数の図はyの値で1変数の図に分解できる. 下の図が1変数の(対称)関数の図と, その右が0変数の図である.

2011年1月24日月曜日

乗算表

TAOCP V4F1にnim multiplicationという話題がある(演習問題7.1.3-10).

結論からいうとこういう乗算表を作るのだ.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2 0 2 3 1 8 10 11 9 12 14 15 13 4 6 7 5
3 0 3 1 2 12 15 13 14 4 7 5 6 8 11 9 10
4 0 4 8 12 6 2 14 10 11 15 3 7 13 9 5 1
5 0 5 10 15 2 7 8 13 3 6 9 12 1 4 11 14
6 0 6 11 13 14 8 5 3 7 1 12 10 9 15 2 4
7 0 7 9 14 10 13 3 4 15 8 6 1 5 2 12 11
8 0 8 12 4 11 3 7 15 13 5 1 9 6 14 10 2
9 0 9 14 7 15 6 1 8 5 12 11 2 10 3 4 13
10 0 10 15 5 3 9 12 6 1 11 14 4 2 8 13 7
11 0 11 13 6 7 12 10 1 9 2 4 15 14 5 3 8
12 0 12 4 8 13 1 9 5 6 10 2 14 11 7 15 3
13 0 13 6 11 9 4 15 2 14 3 8 5 7 10 1 12
14 0 14 7 9 5 11 2 12 10 4 13 3 15 1 8 6
15 0 15 5 10 1 14 4 11 2 13 7 8 3 12 6 9

乗算法はここにある.

2と4と16と...,つまり22nはFermat 2-powerといって, 特別の数である. 特別の数の2乗はそれを1.5倍する. 22=3, 42=6,... 特別の数同士の積は, 通常の積で計算する. 2.4=8.

0×n=0, 1×1=nである. 残りは分配則やnim addition(二進法の排他的論理和)で計算する.

こうなるかと思い, 始めの方を計算してみる. 赤字はnim additionのところだ.

2の段:
2.2=3, 2.3=2.(2+1)=2.2+2=3+2=11+10=1, 2.4=8, 2.5=
2.(4+1)=8+2=1000+10=10, 2.6=2(4+2)=8+2.2=8+3=11, 2.7=2(4+2+1)=8+2.2+2=8+3+2=1000+11+10=9, 2.8=2.2.4=3.4=(2+1)4=8+4=12, 2.9=2(2.4+1)=12+2=1100+10=14, 2.10=2(2.4+2)=12+2.2=12+3=15, 2.11=2(2.4+3)=
12+2.3=12+1=13, 2.12=2(2.4+4)=12+8=1100+1000=4, 2.13=2(2.4+5)=12+10=6, 2.14=2(2.4+6)=12+11=1100+1011=7, 2.15=2(2.4+7)=12+9=1100+1001=5.
3の段:
3.3=(2+1)(2+1)=2.2+2+2+1=3+1=10+1=2, 3.4=2(2+1)=2.2+2=
3+2=11+10=1, 3.5=(2+1)(4+1)=2.4+2+4+1=8+2+4+1=15,
3.6=(2+1)(4+2)=2.4+2.2+4+2=8+3+4+2=1000+11+100+10=13, 3.7=(2+1)(4+3)=2.4+2.3+4+3=8+1+4+3=14, 3.8=(2+1)8=
2.8+8=1100+1000=4, 3.9=(2+1)(8+1)=2.8+2+8+1=
1100+10+1000+1=7, 3.10=(2+1)(8+2)=2.8+2.2+8+2=
1100+11+1000+10=5, 3.11=(2+1)(8+3)=2.8+2.3+8+3=
1100+1+1000+11=6, 3.12=(2+1)(8+4)=2.8+2.4+8+4=
1100+1000+1000+100=8, 3.13=(2+1)(8+5)=2.8+2.5+8+5=
1100+1010+1000+101=11, 3.14=(2+1)(8+6)=2.8+2.6+8+6=
1100+1011+1000+110=9, 3.15=(2+1)(8+7)=2.8+2.7+8+7=
1100+1001+1000+111=10.

すでに計算した積の値は利用している.


ところで, 上の表はこのようにして作ったものではない. TAOCPの方法を説明しよう. この方法が, なぜ上の乗算法と同じになるかは, 今は私の理解の範囲外である.

演習問題7.1.3-8に, 非負の整数の有限集合Sのminimum excludantというのがある.

mex(S) = min {k | k ≥ 0 and k ∉ S}

つまり mex({0,1,2})=3, mex({0,1,2,3,5,7})=4.

これを使い nim multiplication x ⊗ y は

x ⊗ y = mex {(x ⊗ j) ⊕ (i ⊗ y) ⊕ (i ⊗ i) | 0 ≤ i < x, 0 ≤ j < y}

で計算する.




上の図で, x ⊗ y (赤丸)を計算するには, 緑の範囲内の i と j に対して, 青丸で示す x ⊗ j, i ⊗ y, i ⊗ iのnim和をとり, その緑の範囲のすべての値のmexをとると, それが赤丸の値になるのである.

上から順に横向きにnim productが計算してあれば, 赤丸まで来たとき, オレンジ色の値はすべて分かっているから, 再帰計算はせずに済む.

mexはこう計算する.

(define (mex xs) ;関数mex
(define (mx n)
(if (member n xs) (mx (+ n 1)) n))
(mx 0))


表の(x,y)の値をとる関数を(get x y)とすると, nim productは以下のようだ.

(define (nimprod x y)
(let ((s '()))
(do ((i 0 (+ i 1))) ((= i x))
(do ((j 0 (+ j 1))) ((= j y))
(set! s (cons (bxor (bxor (get i j) (get x j)) (get i y)) s))))
(mex s)))

表の0 ≤ j < 16 の(0,j)を0, (1,0)も0にし, (1,1)から始められる. こうして作ったのが最初にあった乗算表である.

2011年1月16日日曜日

TAOCP

TAOCP V4F1にこういう問題があった(7.1.3-102).

日, 時, 分, 秒, ミリ秒がそれぞれ3, 1, 1, 1, 2バイトに収まっている. 3バイトで日を表わすと, 224/365=45964年分だから, ここはどうでもいい. こういう時間データ2つを足したり引いたりする方法である. その解答の最後に「`fc81'の`c'が偶数なのは運が良かった.」とあるのはなぜか.

方法はこうである. 2つの数をxとyとする. 減算ならz←x-y, 加算ならz←x+y+#e8c4c4c4fc18とする. 分の桁でいうと, xの分とyの分を足して60になるか60を超えたとき, 256の桁に1を送りたいので, 256-60=196=110001002=#c4を足す. しかし和が60に満たない時はどうするか. 60はバイトサイズ256の半分以下なので, バイトの先頭のビットが1なら繰上げはなかった, 0なら繰上げがあったが分かる. なかった場合は先ほどの#c4を引かなければならない. 従って, 先頭のビットが1ならそのバイトを#c4に, 0ならそのバイトを0にしたものが欲しい. それは簡単だ. バイトを#80で&をとる. その1を左に1ビットシフトしたものから, その1を右に7ビットシフトしたものを引けば, 11111111か00000000になるので, これを#c4を&したものを引く. 時, 分, 秒はそれで良い. ミリ秒はどうするか.

2バイトのミリ秒の区域の先頭が1のとき, 上の伝では 11111111 0000000になってしまう. そこで, 先頭が1の時, この区域ではさらに1を引くのである. するとこの右端の1から引かれて,11111110 11111111が出来る. これとfc18の&をとることになり, うまい具合いにマスクが0になったビットは, cなので0であったわけだ.

なるほど. 運がよかった.

2011年1月15日土曜日

乗算表

乗算の九々は一旦覚えてしまえば後は何の道具もいらないはずだが, 「Napier の骨(Napier's Bones)」のような乗算用具もあるから, 九々を諳じない人も多いかもしれない.



これは以前自作したNapierの骨で, 中央に3本, 2と5と6の棒を置いてみた. 見ての通り, 各棒にはその段の九々が書いてある. 256を4倍するには, 左のIVの行に注目. /8 2/0 2/4になっている. 右端の4から, 積の1の桁は4. その分子の2と, 左隣りの分母の0を足し, 10の桁は2. さらにその分子の2と, 左隣りの分母の8を足し, 100の桁は10. すなわち1024が得られるの図だ.

つい先頃, 「Genailleの棒(Genaille's Rods)」というものがあると教わった. これは九々を図にしたものである.

6×8は以下のとおり.



左に6, 上に8と見出しがあるので, 6×8なのが分かる. 中央の箱の右に上から890123とあるが, 一番上の8が積の1の桁の8を示す. そこから左へ楔状の影があり, その先に4とあるのが積の10の桁の4を示す. その4の上と下の012...は繰上げの数で, 10の桁が4というのは, 繰上げが4と言うことだ. 一方1の桁の8の, その4の高さに2があるのは, 下から4の繰上げがあると, 6×8に繰上げを足すと, 1の桁が2になること, その左の楔の先が5になっているのは, その時の繰上げは5であることを示す.

私も小学生の上級になると, 繰上げ4を思い出しながら, ロクハチゴジュウニなどと唱えたものだが, そういう乗算表になっている.

次の図は, 4×256を示す.



2と5と6の棒を並べ, 4の段を見る. 6の棒の4の段の一番上の4から出発し左へ進む. 楔の影に入ったら, 楔の先に進む. そして通過する数字を読み取る. 従って, 4×256は下の桁から, 4,2,0,1なことが分かる.

これで分かるように, 被乗数は何桁でもよいが, 乗数は1桁である. また被乗数に同じ数字があると, それだけ同じ棒が必要で, そこにこの種の道具の限界が存在する.

棒による乗算とは別に, 棒を順に並べると, 九々の表が出来る. それが下の図だ. 九々の範囲は2から9だが, 被乗数に0もあることから, 棒には0も1もある.



棒に書いてある乗数は, Wikipediaの図などでは1から始まっているが, 乗数1はいらないので, 2から始まるのも目につく. この表も2から9である.

インターネットで探していたら, 除算表というのも見つけた. これも面白い.