チューリングマシンがシミュレートできる小さなCのような言語


11

私は、チューリングマシンが十分に一般的なコンピューティングモデルであることを学生に「納得させる」のに役立つ小さな言語を探しています。つまり、使用されている言語のように見えるが、チューリングマシンで簡単にシミュレートできる言語です。

Papadimitriouはこの仕事にRAMマシンを使用しますが、奇妙な(チューリングマシンとしての)ものを別の奇妙なもの(基本的にはアセンブリ言語)と比較することは、多くの学生にとってあまりにも説得力がないと思います。

どんな提案でも大歓迎です(特に、いくつかの推奨文献が付属している場合)


7
コンピューターが元々アセンブリ言語でプログラムされていたのには理由があります...コンパイラーやインタープリターを書くのは簡単ではありません。また、Turingマシン用のコンパイラーまたはインタープリターの作成は、おそらくさらに困難です。
ピーターショー

PSに多少同意する必要があります。TMコンパイラは、ファクタリングインスタンスをSATやその他の学部課程に変換するなど、それほど難しくありません。ウェブ上のトップチューリングマシンシミュレーターもご覧ください。サンプルソースコード(高級言語用)を使用してrubyで記述されたTuringマシンコンパイラの例を次に示します。残念ながら、より洗練されたものは入手できないようです。それは素晴らしいオープンソースプロジェクトになるでしょう。
vzn

2
@OmarShehab、編集は質問を最初のページにポンプアップします。編集によって問題が大幅に改善されない場合は、古い質問を編集しないでください。また、最初のページにない多数の質問を編集すると、最初のページから新しい質問が押し出されるため、良くありません。ありがとう。
カベ

@kaveh理解した。
オマールシェハブ

回答:


15
  • 学生が関数型プログラミングを行った場合、私が知っている最も良いアプローチは、型なしラムダ計算から始め、ブラケット抽象化定理を使用してそれをSKIコンビネータに変換することです。次に、および定理を使用して、チューリングマシンが部分的組み合わせ代数を形成し、SKIコンビを解釈できることを示すことができます。u t msmnutm

    これが可能な限り単純なアプローチであるとは思いませんが、計算可能性の最も基本的な定理に基づいていることは気に入っています(他の理由でカバーしたいと思うかもしれません)。

    と思われるアンドレイ・バウアーがMathoverflowに同様の質問に答え、数ヶ月前。

  • Cライクな言語に設定されている場合、パスはかなり複雑になります。セマンティクスがかなり複雑であるためです。

    1. チューリングマシンがスタックとヒープを同時にシミュレートできることを示します。
    2. スタックを使用して変数を実装する方法を示します。
    3. プロシージャコールをスタックで実装できることを示します。

    正直なところ、これはコンパイラクラスの内容の多くです。


7

私の学部のコンプ教授の理論は、シングルテープチューリングマシンがマルチテープチューリングマシンを実装できることを証明することから始まりました。これは変数宣言を処理します。プログラムに6つの変数宣言がある場合、7テープチューリングマシン(各変数のテープ、および算術および等値チェックなどのタスクを実行するための「登録」テープテープ)。次に、基本的なFORループとWHILEループを実装する方法を示しました。その時点で、基本的なチューリング完全なCのような言語ができました。とにかく満足のいくものでした。


6

私は今、チューリングマシンが計算の一般的なモデルであることを自分自身に納得させる方法について考えています。私は、いくつかの標準教科書、例えばSipserの教会チューリング論文の標準的な扱いがあまり完全ではないことに同意します。チューリングマシンからより認識可能なプログラミング言語に移行する方法のスケッチを次に示します。

ifand whileステートメント、非再帰定義関数およびサブルーチン、名前付きブールランダム変数および一般ブール式、および増分または減分できるtape[n]整数配列ポインターを含む単一の無制限ブール配列を持つブロック構造プログラミング言語を検討しnます。n++またはn--。ポインターnは最初はゼロで、配列tapeは最初はすべてゼロです。そのため、このコンピューター言語はCライクでもPythonライクでもかまいませんが、そのデータ型は非常に限られています。実際、それらは非常に制限されているためn、ブール式でポインターを使用する方法すらありません。仮定してtapeが右に無限にある場合、n負の値になった場合、ポインターアンダーフロー「システムエラー」を宣言できます。また、私たちの言語には、exitブール値の答えを出力するために、1つの引数を持つステートメントがあります。

そして、最初のポイントは、このプログラミング言語がチューリングマシンの優れた仕様言語であることです。テープ配列を除いて、コードには、宣言されたすべての変数の状態、現在の実行行、およびそのサブルーチンスタックという有限の状態しかありません。後者は、再帰関数が許可されていないため、有限量の状態しかありません。このタイプのコードから「実際の」チューリングマシンを作成する「コンパイラ」を想像できますが、その詳細は重要ではありません。ポイントは、かなり良い構文を備えたプログラミング言語ですが、非常に原始的なデータ型があることです。

残りの構成は、これをライブラリ関数とプリコンパイル段階の有限リストを備えたより住みやすいプログラミング言語に変換することです。次の手順を実行できます。

  1. プリコンパイラを使用すると、ブールデータ型を、ASCIIなどの大きくても有限のシンボルアルファベットに拡張できます。tapeこの大きなアルファベットの値をとると仮定できます。ポインタのアンダーフローを防ぐためにテープの先頭にマーカーを残し、テープの端にTMが誤って無限に滑ってしまうのを防ぐためにテープの端に可動マーカーを残すことができます。シンボル間の任意のバイナリ演算、およびブールfor ifおよびwhileステートメントへの変換を実装できます。(実際に使用できなかった場合ifでも実装whileできます。)

  2. テープのランダムアクセスと(正の)整数演算の両方を実装するには、無制限の整数データ型が必要です。この目的のために、我々はシミュレートいくつかの固定用-tapeのTM、我々が持っていることを1本のテープでを。この構造は、Sipserの定理として与えられます。アイデアは、エミュレートされたテープを、ヘッドポジションを表すマーカーシンボルで低レベルテープにインターリーブすることです。低レベルテープポインターがゼロの場合、位置移動し、一度にステップジャンプして、番目のサブテープを処理します。読み取りまたは書き込みが行われるたびに、低レベルのテープポインターは0に戻ります。前の段階と同様に、これをプリコンパイラとして実装する方が簡単です。k i i kkkiik

  3. 1つのテープをシンボル値の「メモリ」として指定し、他のテープを符号なしの整数値の「レジスタ」または「変数」として指定します。整数を終端マーカー付きのリトルエンディアンバイナリに格納します。まず、レジスタのコピーとレジスタのバイナリデクリメントを実装します。それとメモリポインタの増分および減分を組み合わせて、シンボルメモリのランダムアクセスシークを実装できます。また、整数のバイナリ加算と乗算を計算する関数を作成できます。ビット演算を使用したバイナリ加算関数と、左シフトを使用して2を乗算する関数を記述するのは難しくありません。(または、リトルエンディアンであるため、本当に右にシフトします。)これらのプリミティブを使用して、長い乗算アルゴリズムを使用して2つのレジスタを乗算する関数を作成できます。

  4. 我々は、一次元のシンボル列からメモリテープを再編成することができるsymbol[n]二次元のシンボル列にsymbol[x,y]式を用いてn = (x+y)*(x+y) + y。メモリの各行を使用して、符号なし整数を終了記号付きのバイナリで表現し、1次元のランダムアクセス整数値メモリを取得できますmemory[x]。メモリから整数レジスタへの読み取りと、レジスタからメモリへの書き込みを実装できます。符号付きおよび浮動小数点演算、シンボル文字列などの多くの機能を関数で実装できるようになりました。

  5. 厳密にプリコンパイラ、つまり再帰関数が必要な基本機能はもう1つだけです。これは、インタープリター言語の実装に広く使用されている手法を使用して実行できます。各高レベルの再帰関数に名前文字列を割り当て、低レベルコードを1つの大きなwhileループに編成します。このループは、通常のパラメーター(呼び出しポイント、呼び出された関数、引数のリスト)で呼び出しスタックを維持します。

この時点で、構築には高度なプログラミング言語の十分な機能があり、さらなる機能はCS理論というよりもプログラミング言語とコンパイラのトピックです。また、この開発された言語でチューリングマシンシミュレータを作成するのも簡単です。この言語用のセルフコンパイラを書くことは、正確ではありませんが、確かに標準です。もちろん、このようなC言語またはPython言語のコードから外部TMを作成するには、外部コンパイラが必要ですが、これはどのコンピューター言語でも実行できます。

このスケッチされた実装は、論理関数の再帰関数クラスのチャーチチューリング論文だけでなく、決定論的計算に適用される拡張(すなわち、多項式)チャーチチューリング論文もサポートすることに注意してください。つまり、多項式のオーバーヘッドがあります。実際、RAMマシンまたは(私の個人的なお気に入りの)ツリーテープTMが与えられた場合、これはRAMメモリを使用したシリアル計算の多対数オーバーヘッドに減らすことができます。


5

LLVMコンパイラを使用すると、新しいアーキテクチャをかなり簡単に「プラグイン」できます。彼らはこれを呼び出して新しいバックエンドを書き、そして与える詳細な手順と例にそれを行う方法についてを。RAMチューリングマシンをターゲットにしたくない場合、ランダムアクセスメモリに関していくつかのフープをジャンプする必要があると思いますが、LLVMを生成する多くのプロジェクトを見たように、これは間違いなく実行可能ですVHDLまたは他の非常に異なるマシン言語。

これは、チューリングマシン用のコードを生成する最先端の最適化コンパイラ(多くの点でLLVMはGCCよりも高度です)を持つという興味深い効果があります。


1

私はCS理論ではありませんが、役に立つかもしれない何かを持っています。私は別のアプローチを取りました。Cの小さなサブセットで直接プログラム可能な単純なプロセッサを設計しました。アセンブリコードはなく、Cのようなコードのみがあります。私が使用したのと同じツールを使用し、このプロセッサを変更してチューリングマシンシミュレータを設計できます。このプロセッサの設計、シミュレーション、テストに4日かかりました。使用したツールにより、実際のVHDL合成可能コードを生成することさえできました。それは真の作業プロセッサです。

プログラムは次のようになります。 Cライクアセンブリプログラムの例

以下は、これらのツールを使用したプロセッサの写真です。 プロセッサ回路

ツール「Novakod Studio」は、高レベル言語のハードウェア記述言語を使用します。例として、プログラムカウンターのコードを次に示します。 psC-並列および同期C-コードサンプル 話が十分です。興味のある方は、こちらに連絡してください。https//repertoire.uqac.ca/Fiche.aspx?id = JjstNzsH0&link = 1

リュック


メモリのアドレス指定では、固定ビット数を使用してアドレスを見つけますか?
vzn

。はい、それは(INTがDataMemory [SIZE]言語サポート可変長整数(INT変化メモリサイズに簡単である:10)しかし、それは、FPGAをターゲットにするので、アレイは、静的および寸法定数である。。
リュックモリン

1

ユーザーGMBが表すアイデアをここで取り上げてみてください(1本のテープを持つチューリングマシンは、Nテープを1本のテープにインターレースし、一度にN個の場所をジャンプしてそれらのテープのいずれかを読み取ることで、Nテープのチューリングマシンをシミュレートできます、チューリングNテープを備えたマシンは...を実装でき、単純なRAMマシンを実装するチューリングマシンプログラムを記述できます。RAMマシンは、実際には、使用可能なLLVMまたはGCCバックエンドを備えた、単純化された実際のCPUです。次に、GCC / LLVMを使用して、そのCPUのCプログラムとRAMマシンをシミュレートするチューリングマシンプログラムをクロスコンパイルし、シミュレートされたRAMマシンにGCC / LLVM出力を実行させることにより、RAMマシンシミュレーションを実行できます。チューリングマシンの実装は、小さなCファイルに適合する非常に単純なCコードである場合があります。

RAMマシンに関しては、8ビットマイクロコントローラーによって32ビットCPUがシミュレートされ、シミュレートされた32ビットCPUがLinuxを起動するデモプロジェクトがあります。地獄のように遅いが、著者、ドミトリー・グリンバーグによると、それは働いた。たぶん、Zylin CPU (GitHubユーザーzylin)は、シミュレート可能なRAMマシンの実行可能な選択肢かもしれません。別のRAМマシンの候補は、Niklaus WirthによるProjectOberonドットコムです。

(私のテキストの「ドット」と「com」は、2015_10_21、cstheory.stackexchangeで自分のアカウントを登録しただけであり、web-appは、事実にもかかわらず、初心者ユーザーに2つ以上のリンクを許可していません。彼らは私の他のstackexchangeアカウントから私が愚かかもしれないことを自動的に見ることができるが、私は荒らしではない。)

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