Laverテーブルの計算とZFCで終了することが知られていないアルゴリズム


12

海苔テーブルは数学の標準公理システムに終了することが示されていないプログラムの例を提供ZFC 1は非常に巨大基数公理を前提としたときに終了しますけど。

前書き

古典的なLaverテーブルは、基になるセットと、アイデンティティーを満たし、どこで、どこで満たす操作を行うユニークな有限代数です。An{1,...,2n}*x * (y * z)=(x * y) * (x * z)x*1=x+1x<2n2n*1=1

古典的な海苔テーブルの詳細については、Patrick Dehornoyの書籍Braids and Self-Distributivityを参照してください。

チャレンジ

1*32従来のLaverテーブルで計算し、nwith が見つかったときに正確に終了する最短のコード(バイト単位)は何ですか?言い換えると、with が見つかった場合にのみプログラムは終了しますが、それ以外の場合は永久に実行されます。1*32<2nn1*32<2n

動機

ランクにランクカーディナル(また、I3-カーディナルと呼ばれる)は、非常に大きい無限のレベルと1つのランクにランクカーディナルの存在を前提とした場合、その後、一つ一つがない場合よりも多くの定理を証明することができますランクからランクへの枢機existenceの存在を想定します。ランクからランクへの枢機inalが存在する場合、古典的な海苔の表があります。ただし、ZFCでの既知の証拠はありません。さらに、最小の場所がより大きいことが知られています(アッカーマン関数は急速に成長する関数であるため、これは非常に大きな数です)。したがって、このようなプログラムは非常に長い時間続きます。An1*32<2n1*32<2nn1*32<2nAck(9,Ack(8,Ack(8,254)))Ack

プログラムが標準の公理システムZFCを使用して終了するかどうかはわからないが、プログラムが最終的にはるかに強力な公理システム、つまりZFC + I3で終了することがわかるように、プログラムがどれくらい短く書けるかを見たいです。この質問は、スコットアーロンソンの最近の投稿に触発されたもので、アーロンソンとアダムイディディアが8000未満の状態でチューリングマシンを構築したため、ZFCはチューリングマシンが終了しないことを証明できませんが、大きな基数仮説を仮定しても終了しないことがわかっています。

古典的な海苔表の計算方法

海苔のテーブルを計算する場合には、代数であるという事実を使用することが通常便利である、我々が持っているすべてのためにあるの。An2n * x=xxAn

次のコードは、古典的な海苔表を計算します An

#table(n、x、y)はA nに x * yを返します
table:= function(n、x、y)
x = 2 ^ nの場合、yを返します。
elif y = 1の場合、x + 1を返します。
それ以外の場合は、table(n、table(n、x、y-1)、x + 1)を返します。fi; 終わり;

たとえば、入力table(4,1,2)はを返し12ます。

のコードtable(n,x,y)はかなり非効率的であり、妥当な時間内にLaverテーブルでのみ計算できます。幸いなことに、古典的な海苔の表を計算するアルゴリズムは、上記のものよりもはるかに高速です。A4


1
PPCGへようこそ!素晴らしい投稿!
-NoOneIsHere

1
ウィキペディアによると、Ack(9、Ack(8、Ack(8,254)))はnの下限であり、その期間は16を超えています。そのため、1 * 32ではなく1 * 16をチェックできます。それに応じてプログラムを修正します。
ジョントロンプ

1
これを行うためにチューリングマシンの作成を開始しましたが、2分の1の誤差が見つかったと思います。Dougherty Ack(9,Ack(8,Ack(8,254)))は、最初の行の期間が 32 である最初のテーブルの下限であることを証明しませんでした1*16 < 2^n
ピーターテイラー

1
Ackermannの20状態の2シンボルマシンをお持ちの場合は、リンクをお願いします。おそらくアイデアを盗むことができるからです。計算する44の状態がありtable(n,x,y)、定数と外側のループを設定するには25〜30の状態が必要だと思います。esolangs.orgで見つけられるTMの直接的な表現はesolangs.org/wiki/ScripTurのみであり、実際にはそれほどゴルフではありません。
ピーターテイラー

1
cheddarmonk.org/papers/laver.pdfは、今週旅行する予定なので、今週の予定どおりです。
ピーターテイラー

回答:


3

バイナリラムダ計算、215ビット(27バイト)

\io. let
  zero = \f\x. x;
  one = \x. x;
  two = \f\x. f (f x);
  sixteen = (\x. x x x) two;
  pred = \n\f\x. n (\g\h. h (g f)) (\h. x) (\x. x);
  laver = \mx.
    let laver = \b\a. a (\_. mx (b (laver (pred a))) zero) b
    in laver;
  sweet = sixteen;
  dblmin1 = \n\f\x. n f (n f (f x)); -- map n to 2*n-1
  go2 = \mx. laver mx sweet mx (\_. mx) (go2 (dblmin1 mx));
in go2 one

コンパイル先(https://github.com/tromp/AITのソフトウェアを使用)

000101000110100000010101010100011010000000010110000101111110011110010111
110111100000010101111100000011001110111100011000100000101100100010110101
00000011100111010100011001011101100000010111101100101111011001110100010

このソリューションは、主にhttps://github.com/int-eが原因です


2
スコアをどのように取得したかはわかりませんが、デフォルトでは、コードのバイト数に基づいて提出をスコアリングする必要があります。この送信には375バイトをカウントします。また、言語名と、オプションで言語のインタープリターへのリンクを含める必要があります。
アレックスA.

おそらく、投稿に長さ234ビットの正確なコードを含める必要があります。
CalculatorFeline

2
エンコーディングはウィキペディアで見つけることができます。このインタプリタへのリンクもあります(テストされていません)。ただし、これらはチェックする必要があり、バイナリエンコーディングも投稿に含める必要があります。
PurkkaKoodari

コンパイルされた言語の場合、生成されたバイナリのバイト数ではなく、ユーザーが作成したコードをスコアリングします。
アレックスA.

4
@AlexA。それは必要ありません...コンパイラーまたはインタープリターが理解できるコードの形式は問題ありません。
-feersum

4

CJam(36 32バイト)

1{2*31TW$,(+a{0X$j@(@jj}2j)W$=}g

実際には、コールスタックがオーバーフローするため、このエラーはすぐにエラーになりますが、理論上の無制限のマシンでは正しいので、この質問の前提となることを理解しています。

のコードtable(n,x,y)はかなり非効率的であり、妥当な時間内にLaverテーブルA 4でしか計算できません。

計算された値をキャッシュして再計算を回避する場合、実際には正しくありません。それが、j(メモ化)演算子を使用して私が取ったアプローチです。ミリ秒でA 6をテストし、A 7をテストするスタックをオーバーフローさせます-そして実際に最適化を解除しました table、ゴルフの利益のためました。

解剖

n文脈から理解されると仮定すると、代わりに

f(x,y) =
    x==2^n ? y :
    y==1 ? x+1 :
    f(f(x,y-1),x+1)

最初の特別なケースを削除して、

f(x,y) =
    y==1 ? x+1 :
    f(f(x,y-1),x+1)

そしてそれはまだ動作します

f(2^n, 1) = 2^n + 1 = 1

その他のy場合は、

f(2^n, y) = f(f(2^n, y-1), 1) = f(2^n, y-1) + 1

したがって、帰納法によって得られf(2^n, y) = yます。

CJamの場合、パラメーターの順序を逆にする方が便利であることがわかりました。そして、範囲1 .. 2^nを使用するのではなく、0 .. 2^n - 1各値をデクリメントして範囲を使用しているため、実装している再帰関数は

g(y,x) =
    y==0 ? x+1
         : g(x+1, g(y-1, x))

1           e# Initial value of 2^n
{           e# do-while loop
  2*        e#   Double 2^n (i.e. increment n)
  31T       e#   table(n,1,32) is g(31,0) so push 31 0
  W$,(+a    e#   Set up a lookup table for g(0,x) = x+1 % 2^n
  {         e#   Memoisation function body: stack is 2^n ... y x
    0X$j    e#     Compute g(0,x) = x+1 % 2^n
            e#     Stack is 2^n ... y x (x+1%2^n)
    @(      e#     Bring y to top, decrement (guaranteed not to underflow)
            e#     Stack is 2^n ... x (x+1%2^n) (y-1%2^n)
    @jj     e#     Rotate and apply memoised function twice: g(x+1,g(y-1,x))
  }
  2j        e#   Memoise two-parameter function
            e#   Stack: 2^n g(31,0)
  )W$=      e#   Test whether g(31,0)+1 is 2^n
}g          e# Loop while true

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.