回答:
さまざまなアプローチの利点と制限は何ですか?
深い埋め込みの長所:式の構造の帰納法によって、物事を証明し定義することができます。関心の例は、式のサイズです。
深い埋め込みの短所:変数のバインドを明示的に処理している。それは通常非常に面倒です。
使用するものを決定するためのガイドラインはありますか?
浅い埋め込みは、オブジェクトロジックで証明された結果をインポートするのに非常に便利です。たとえば、小さなロジック(例:分離ロジック)で何かを証明した場合、浅い埋め込みはCoqに結果をインポートするための選択ツールになります。
反対に、オブジェクトロジックに関するメタ定理(たとえば、カット除去など)を証明する場合、ディープ埋め込みはほとんど必須です。
2つの表現を体系的に切り替えることは可能ですか?
浅い埋め込みの背後にある考え方は、オブジェクト式のモデルで直接作業することです。通常、人々はオブジェクト式Pを(表記法を使用するか、手動で翻訳することにより)Propの住民に直接マップします。もちろん、オブジェクトロジックの式を埋め込むことで取得できないPropの住民もいます。したがって、何らかの完全性を失います。
したがって、解釈機能を使用して、深い埋め込み設定で得られたすべての結果を送信することができます。
ここに小さなcoqの例があります:
帰納式:セット:= Ftrue:式 | Ffalse:式 | Fand:数式->数式->数式 | フォーミュラ->フォーミュラ->フォーミュラ。 修正点の解釈(F:数式):Prop:=一致F Ftrue => True | Ffalse => False | Fand ab =>(解釈a)/ \(解釈b) | ab =>(aを解釈)\ /(bを解釈) 終わり。 帰納的誘導可能:公式->プロップ:= deep_axiom:導出可能なFtrue | deep_and:forall ab、derivable a-> derivable b-> derivable(Fand ab) | deep_or1:forall ab、derivable a-> derivable(abの場合) | deep_or2:forall ab、derivable b-> derivable(abの場合)。 誘導sderivable:プロップ->プロップ:= shallow_axiom:sderivable True | shallow_and:forall ab、sderivable a-> sderivable b-> sderivable(a / \ b) | shallow_or1:forall ab、sderivable a-> sderivable(a \ / b) | shallow_or2:forall ab、sderivable b-> sderivable(a \ / b)。 (*次の補題を証明できます:*) 補題shallow_deep: forall F、導出可能F-> sderivable(解釈F)。 (*次の補題を証明することはできません:*) 補助定理: forall P、sderivable P-> Fが存在、F = Pと解釈
大まかに言うと、ロジックを深く埋め込むと、(1)ロジックの構文を表すデータ型を定義し、(2)構文のモデルを与え、(3)構文に関する公理が尊重されていることを証明します。モデルに。浅い埋め込みでは、ステップ(1)と(2)をスキップし、モデルから始めて、式間の含意を証明します。これは、浅い埋め込みは、通常は深い埋め込みで通常はやらなければならない作業を表すため、通常、地面から降りる作業が少ないことを意味します。
ただし、深い埋め込みがある場合、実際には再帰可能な構文を持つ式で作業しているため、通常、反射的な決定手順を記述する方が簡単です。また、モデルが奇妙で複雑な場合、通常はセマンティクスを直接操作したくないでしょう。(たとえば、双直交性を使用して許容可能なクロージャを強制する場合、またはKripkeスタイルモデルを使用して分離ロジックまたは同様のゲームのフレームプロパティを強制する場合)。 、これはあなたの心を怒りで満たします。これは、(a)些細なことであり、(b)終わりのない不快感の源だからです。
正しい順序は次のとおりです。(1)浅い埋め込みで取得しようとします。(2)それが蒸気を使い果たしたら、戦術と見積もりを使用して、実行したい決定手順を実行してみてください。(3)それも蒸気が足りない場合、あきらめて、深い埋め込みのために依存型の構文を使用します。
また、はしごを徐々に上に行こうとしないでください。複雑さを増すことを決めたら、一度に全一歩を踏み出します。少しずつ物事を行うと、奇妙で使いものにならない定理がたくさん得られます(たとえば、複数の半分主張された構文や、構文とセマンティクスを奇妙な方法で混ぜ合わせた定理が得られます)。最終的に捨てなければなりません。
編集:ここでは、なぜはしごを上るのが非常に魅力的であり、なぜそれが(一般的に)苦しみにつながるのかを説明するコメントがあります。
具体的には、接続詞とユニットして、分離ロジックの浅い埋め込みがあるとします。次に、やなどの定理を証明します。さて、実際にロジックを使用してプログラムが正しいことを証明しようとすると、ようなものになり、実際に。I A ⋆ B(A ⋆ B )⋆ C(I ⋆ A )⋆ (B ⋆ C )A ⋆ (B ⋆ (C ⋆ I ))
この時点で、式を手動で再関連付けする必要があることに悩まされ、「わかっています!リストのデータ型を個別の式のリストとして解釈します。そのように、ように解釈できます。これらのリストを連結すると、上記の式は定義的に等しくなります!」
これは事実であり、機能します!ただし、接続詞はACUIでもあり、選言でもあることに注意してください。したがって、異なるリストデータ型を使用して、他の証明で同じプロセスを実行し、分離ロジックの異なるフラグメントに対して3つの構文を使用し、それぞれのメタ定理を使用します。そして、分離のために接続詞を分離するために証明したメタ定理を望んでいることに気付くでしょう。そして、構文を混ぜて、それからあなたは狂気になります。
妥当な労力で処理できる最大のフラグメントをターゲットにした方がよいでしょう。
深いところから浅いところまでスペクトルがあることを理解することが重要です。言語の構成について何らかの帰納的な議論に何らかの形で参加する必要がある言語の部分を深くモデル化します。残りは、ロジックの基盤の直接的なセマンティクスの浅い見方に残しておく方が良いでしょう。
たとえば、Hoare Logicについて推論する場合、式言語を浅い方法でモデル化できますが、assign-if-while言語の概要は具体的なデータ型である必要があります。x + yまたはa <bの構造を入力する必要はありませんが、while
などで作業する必要があります。
他の回答では、依存型の暗示がありました。これは、可能な限り浅いようにバインダーを使用して言語を表現するという古代の問題を思い起こさせますが、それでもいくつかの帰納的な議論を認めています。私の印象では、審査員は、このテーマに関して過去10〜20年に登場したさまざまなアプローチや論文について、まだ審査中です。さまざまな証明アシスタントコミュニティの「POPLmarkチャレンジ」もある程度それについてでした。
奇妙なことに、依存型のない古典的なHOL では、C。UrbanによるHOL-Nominalアプローチは浅いバインディングに非常にうまく機能しましたが、これらのプログラミング言語形式化のコミュニティにおける文化的変化に追いついていませんでした。