プログラミング再入門

プログラミングをもう一度ちゃんと勉強する読書ノート

Scheme手習い 第9章 ……もう一度、もう一度、もう一度、……(その3)

Collatzの予想、Ackermann関数、チューリングの停止性問題について触れられます。

ノート:

Collatzの問題

次の関数はCollatzの予想に登場する関数との事。

その前に、one?を以下の様に定義する。

(define one?
  (lambda (n)
    (eq? n 1)))

Collatzの予想とは、0でない任意の自然数nに対し

  1. nが偶数の場合、n/2
  2. nが奇数の場合、3n + 1

と定義される関数を再帰的に用いて数列を作った時に必ず1に到達すると言う予想。

Collatzの関数を再帰的に適用しnが1になったら1を返して停止する関数がC。この関数は数列を作る訳でも1に達するか否かを返す命題でもない。そこで数列をリストにして返すCollatzSequenceを定義してみる。

(define CollatzSequence
  (lambda (n)
    (cond ((one? n) '(1))
          (else (cons n (cond ((even? n) (CollatzSequence (/ n 2)))
                              (else (CollatzSequence (+ 1 (* n 3))))))))))

評価してみる。

> (CollatzSequence 5)
(5 16 8 4 2 1)
> (CollatzSequence 29)
(29 88 44 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1)
> (CollatzSequence 27)
(27
 82
 41
 124
 62
 31
 94
 47
 142
 71
 214
 107
 322
 161
 484
 242
 121
 364
 182
 91
 274
 137
 412
 206
 103
 310
 155
 466
 233
 700
 350
 175
 526
 263
 790
 395
 1186
 593
 1780
 890
 445
 1336
 668
 334
 167
 502
 251
 754
 377
 1132
 566
 283
 850
 425
 1276
 638
 319
 958
 479
 1438
 719
 2158
 1079
 3238
 1619
 4858
 2429
 7288
 3644
 1822
 911
 2734
 1367
 4102
 2051
 6154
 3077
 9232
 4616
 2308
 1154
 577
 1732
 866
 433
 1300
 650
 325
 976
 488
 244
 122
 61
 184
 92
 46
 23
 70
 35
 106
 53
 160
 80
 40
 20
 10
 5
 16
 8
 4
 2
 1)
> 

途中で元の数よりも大きくなってしまうにも関わらず、どこかで必ず1に収束する数列のどこかに捕まり万事休す。

Ackermann関数

定義は、二つの負でない整数mとnを取り、

  1. mが0の時、n+1
  2. nが0の時、m-1と1にAckermann関数を適用した値
  3. それ以外、m-1と、mとn-1にAckermann関数を適用したものの二つにAckermann関数を適用した値

本ではnとmが逆になっている。

実際に評価してみる。

> (A 1 0)
2
> (A 1 1)
3
> (A 2 2)
7
> 

Aは常に答えを返しますか。

はい、全関数です。

mが3までは答えは出て来るが、mが4になるとnが1でも短時間には計算が終わらない。
Aが常に答えを返す全関数かどうかは俄には分からない。

will-stop?

Wikipediaによるとチューリングの停止性問題とは「停止性問題を解くチューリング機械の存在を仮定すると、自身が停止すると判定したならば無限ループを行い、停止しないと判定したならば停止するような別のチューリング機械が構成できるという矛盾が導かれる。」事からこのようなチューリング機械は定義出来ないと言う結論。

last-tryは上記をそのまま関数として定義している。

Wikipediaによると停止性問題の証明は「ゲーデル(Gödel)の第一不完全性定理」の証明と似ているらしい。