論理式を論理積正規形に変換する


10

ゴール:

命題論理式(以降、論理式またはと呼ぶ)の式を取り、その式を論理積標準形で出力する完全なプログラムまたは関数を記述します。そこの2つの定数があり、そして単項演算子、真と偽を表す¬否定を表す、およびバイナリ演算子は、と暗に、同値、接続詞、および論理和を表す、それぞれどの(通常の論理演算のすべてに従わドモルガンの法則を二重否定の除去など)。

結合標準形は次のように定義されます。

  1. アトミック表現(およびを含む)は、連言正規形です。
  2. 以前に作成された式の否定は、接続詞の正規形です。
  3. 以前に作成された2つの式の分離は、接続詞の正規形です。
  4. 以前に作成された2つの式の結合は、接続詞の正規形です。
  5. 他の表現は、接続型の通常の形式ではありません。

すべての論理式は、論理的に等価な論理積形式に変換できます(一意ではありません)(このアルゴリズムを参照)。その特定のアルゴリズムを使用する必要はありません。

入力:

入力は任意の形式で行うことができます。たとえば、シンボリック論理式(言語でサポートされている場合)、文字列、その他のデータ構造。ここで説明するように、true、false、および論理演算子に同じ記号を使用する必要はありませんが、選択は一貫している必要があり、明確でない場合は、回答で選択を説明する必要があります。他の入力を受け入れたり、入力形式で追加情報をエンコードしたりすることはできません。任意の数の原子式を表現する方法が必要です。例:整数、文字、文字列など

出力:

連想標準形の数式。これも便利な形式です。入力と同じ形式である必要はありませんが、違いがあるかどうかを説明する必要があります。

テストケース:

P ∧ (P ⇒ R) -> P ∧ R
P ⇔ (¬ P) -> ⊥
(¬ P) ∨ (Q ⇔ (P ∧ R)) -> ((¬ P) ∨ ((¬ Q) ∨ R)) ∧ ((¬ P) ∨ (Q ∨ (¬ R)))

ノート:

  1. 入力式がトートロジーの場合、有効な出力になります。同様に、入力式が矛盾している場合は、有効な出力になります。
  2. 入力形式と出力形式の両方で、考えられるすべての論理式を表現できる明確に定義された操作順序が必要です。ある種の括弧が必要になるかもしれません。
  3. 論理演算には、インフィックス、プレフィックス、またはポストフィックス表記の明確に定義された選択を使用できます。選択が標準と異なる場合(否定は接頭辞、残りは接頭辞です)、回答でそれを説明してください。
  4. 連言正規形は一般に一意ではありません(並べ替えまでは)。あなたは出力にのみ必要な有効な形式を。
  5. ただし、アトミック式を表す場合、それらは論理定数、演算子、およびグループ化記号(ある場合)とは異なる必要があります。
  6. 連言正規形を計算する組み込み関数が許可されています。
  7. 標準の抜け穴は禁止されています。
  8. これはです。最短の回答(バイト単位)が優先されます。


1
CNFは並べ替えまで一意ではありません。同等の式でPあり(P ∨ Q) ∧ (P ∨ (¬Q))、両方とも論理積形式です。
グレッグマーティン

1
トートロジー/矛盾のチェックはCNF変換とは無関係の2番目のタスクなので、この要件を削除して独自の課題に取り組むことをお勧めします。
Laikoni 2017年

@Laikoniとてもそうです。私は質問を更新して、これらは必要な出力ではなくトートロジーと矛盾の可能な出力であると述べました。
ngenisis 2017年

回答:



8

あなたは私を憎むだろう...

Mathematica、23バイト

#~BooleanConvert~"CNF"&

入力が使用されますTrueと、False代わりにのすべての文字を:が、それ以外の質問の表記と非常に似ています¬、とするとき、入力UTF-8文字を00AC、F523、29E6、2227(Mathematicaで認識されています、および2228のそれぞれ)、および括弧は期待どおりに機能します。

デフォルトでは、出力はMathematicaの優先シンボルを使用します:例えば、最後のテストケースはの(! P || ! Q || R) && (! P || Q || ! R)代わりに出力します((¬ P) ∨ ((¬ Q) ∨ R)) ∧ ((¬ P) ∨ (Q ∨ (¬ R)))。ただし、関数を

TraditionalForm[#~BooleanConvert~"CNF"]&

出力はきれいに見え、これらの通常のシンボルに準拠します:

伝統的な形


2

JavaScript(ES6)、127バイト

f=(s,t='',p=s.match(/[A-Z]/),r=RegExp(p,'g'))=>p?'('+f(s.replace(r,1),t+'|'+p)+')&('+f(s.replace(r,0),t+'|!'+p)+')':eval(s)?1:0+t

I / O形式は次のとおりです(優先順位順)。

  • ((
  • ))
  • 1
  • 0
  • ¬!
  • <=
  • ==
  • &
  • |

例:

P&(P<=R) -> ((1)&(0|P|!R))&((0|!P|R)&(0|!P|!R))
P==(!P) -> (0|P)&(0|!P)
(!P)|(Q==(P&R)) -> (((1)&(0|P|Q|!R))&((0|P|!Q|R)&(1)))&(((1)&(1))&((1)&(1)))

関数は、選言的な正規形を生成するために自明に書き直されます:

f=(s,t='',p=s.match(/[A-Z]/),r=RegExp(p,'g'))=>p?'('f(s.replace(r,1),t+'&'+p)+')|('+f(s.replace(r,0),t+'&!'+p)+')':eval(s)?1+t:0

出力でも上記の優先順位を仮定することが許可されていれば、このバージョンから8バイトを節約できます。これにより、出力例からすべての括弧が削除されます。

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