非専門的シンギュラリティー研究所

無限に動き続けるシステムを表す方法を AI なども使って考えていきます。

関数プログラミングの帰納的関数(7)

次に終了する  x について調べてみます。 x を表す用語があるかと思ったのですが、ChatGPT では出てこないようです。

F# の再帰的呼び出しで無限に繰り返される関数を  f とします(再帰的呼び出し以外は有限回で終わるとする)。

関数の列  f_n

  •  f_0 は None を返す
  •  f_{n+1}  f の定義の  f の呼び出しを  f_n で置き換えたもの

とします(None を含む式の値は None とします)。

 f_n(x) の値が None ではない  n が存在するような  x は何ですか

と入力すると以下の結果となりました。

関数  f が無限に再帰を繰り返すという仮定のもとで、関数列  f_n の性質を考えます。

1. 定義の整理

  •  f_0(x) = \text{None}
  •  f_{n+1}  f の定義の  f の呼び出しを  f_n に置き換えたもの

つまり、 f の定義における再帰的な部分は、 f_n によって有限の回数しか呼び出されません。
そのため、 f_n は深さ  n までの再帰しか展開せず、それ以上は None を返します。

2.  f_n(x) の値が None でない場合

 f_n(x) \neq \text{None} となるには、 f_n の計算が None に到達せずに終了する必要があります。
つまり、 f の定義において再帰が発生しない場合、または再帰が深さ  n 以内で止まる場合、 f_n(x) は None ではない値を持つ可能性があります。

したがって、ある  n に対して  f_n(x) が None でない  x は、

  •  f の定義において、 f(x) の計算が有限回のステップで終了するような  x である。

これは、 f(x) が無限再帰に入らずに結果を返すような  x です。

3. 具体的な例

たとえば、F# で次のような関数を考えます:

let rec f x =
    if x = 0 then 0
    else f (x - 1)

この場合、 f_n(x)

  •  f_0(x) は None を返す
  •  f_1(x) は `if x = 0 then 0 else None` となる
  •  f_2(x) は `if x = 0 then 0 else if x - 1 = 0 then 0 else None` となる

よって、 x = 0 または  x = 1 ならば  f_n(x) \neq \text{None} となる  n が存在します。

4. 結論

一般に、 f の定義において「ある入力  x に対して、有限回のステップで計算が終わる」場合、そのような  x は存在する  n に対して  f_n(x) \neq \text{None} となります。
逆に、 f(x) が常に無限ループに陥るような  x に対しては、すべての  n  f_n(x) = \text{None} になります。