「数学コラム チューリングの停止問題の証明 パート1 (2020/05/02)」


さて。

この数学コラムでも(BX関数のときに)何回か出てきた
  「チューリングの停止問題
を証明します。


コロナ騒動の自宅待機で
時間が余ってるときに
考えてみてください。




例えば、以下のような関数があるときに

void chaotic(double limit)
{
  double c = 0.5;
  for (;;)
  {
    c = 3.8 * c * (1.0-c);
    if (c<=limit)  break;
  }
}


いわゆるカオス関数。
見た目は簡単ですがcは
  c = 0.5000 → 0.9500 → 0.1805 → 0.5620
 → 0.9353 → 0.2297 → 0.6725 → 0.8368 → ...
のように不規則に動きまくり、
与えられた引数limitに対し
 if (c<=limit) break
条件が発動するかの判定は恐ろしく難しい。

実際に「しばらく動かして様子を観察する」以外に方法はなく、
事前的な予測はほぼ無理に近いです。


チューリングの停止問題は
このような場合に
ループの有限/無限 判定は一般には不可能である
と述べています。


(無論、chaotic関数のループ判定も頑張ればできる。
 ただそれは一個一個の問題に対して、
 個別の判定方法を編みだす必要があるわけで。

 「1個のアルゴリズムで全てのループを判定できる」
 万能判定アルゴリズムは存在しないと言っているのがチューリングの停止問題)



そもそも「プログラム」とは、
現代的な視点から考えたら


C#言語で記述された関数コード
 (C、C++、C#、Javascript、BASIC...
言語は何でもいい)

関数に渡す引数の値

のペアと考えることができます


例:
void function(object parameter /*引数の値パート*/)
{
//関数コードのパート
   int i=1;
   for (;;)
   {
       i*=2;
       if (i % 10==parameter)  
    break;
   }
}
なぜなら、
関数コード & 関数に渡す引数の値
の2つを与えられればプログラムの挙動は
完全に確定するので。

「プログラム」 と 「関数コード & 引数の値のペア」 は
等価と考えて差し支えありません。




なので。
もし仮に、プログラムに対しての
停止問題判定アルゴリズムが
存在するとすれば。

それは現代的に言えば

bool isTerminate(
string function,        //関数コードのパート
object parameter  //引数パートのパート
)

{
 ~
 ~判定アルゴリズム
 ~
 ~
 ~
}

のような判定プログラムが
C#で記述できるかと言う意味に等しいです。



・・・何を言ってるか。^_^;
だいぶ難しくなったので一例を出すとこんな感じです

//有限ループ
string functionA =
@"
void fnA(object parameter)
{
   int i=1;
   for (;;)
   {
       i*=2;
       if (i%10==6)  break;
   }
}";

//無限ループ
string functionB =
@"
void fnB(object parameter)
{
   int i=1;
   for (;;)
   {
      i*=2;
      if (i%10==3)  break;
   }
}";

//引数による
string functionC =
@"
void fnC(object parameter)
{
   int i=1;
   for (;;)
   {
      i*=2;
      if (i%10==(int)parameter)  break;
   }
}";


  isTerminate(functionA,null) == true;
  isTerminate(functionB,null) == false;
  isTerminate(functionC,6) == true;
  isTerminate(functionC,3) == false;
  

このように、
IsTerminate関数は
  ・C言語で記述された関数コード string function
  と
  ・関数に渡す引数 object parameter
の2つを引数に取り、
string functionの中に記載されてる関数fn

  fn(parameter)

がコンピューターで実行されたときに
それが有限時間内で終了するのか、
そろとも永久に終了しないのかを

IsTerminate関数は
string function & object prameterの内容を解釈・解析・判定し、
正しい答えをboolで返してくれるはずです。




・・・だいぶ難しそうに見えますが
実は全然難しくありません。

というのもstring functionは「たかがstring型の引数」であり、

//有限ループ
string functionA =
@"
void fnA(object parameter)
{
   int i=1;
   for (;;)
   {
       i*=2;
       if (i%10==6)  break;
   }
}";

isTerminate(functionA,null);

isTerminateの入力に入ってくるfunctionAは、たかがstring。
それ以外の何者でもない。

そしてそのstring functionの内容を解釈・解析するのは
コンパイラが日常的にやってることなので
それ自体は全く問題はありません。
絶対に可能です。

(もしstring functionが不正な構文。正しいC言語になっていないケースについては
 プログラムが異常停止するのでtrueを返すとする)


問題は・・・判定部分の方なんだね。^_^;

string functionの動作を考え、それが
無限ループになっているかそれとも有限時間で終わるのか。
それを判定するプログラムを書くってのは
恐ろしく難しい。


一見すると・・・もしかしたら・・・・
できる~~~かもしれない?
に見えるのですが。

じゃあ実際にやってみると、
これがとてつもない難題だと気付きます。

と言うか無理。



・・・
・・


実はそのような
停止問題判定アルゴリズム
isTerminate
は存在しません!

どれだけの超天才プログラマーでも
絶対に絶対に絶対にisTerminate関数は作成できない。

もし仮に作成できたとしたら、矛盾が発生する。
ゆえにisTerminate関数はこの世に存在しえない。

なぜそうなるのか
次回にそれを示します。