Перетворити логічний вираз у сполучну нормальну форму


10

Мета:

Напишіть повну програму або функцію, яка приймає формулу в пропозиційній логіці (відтепер її називають логічним виразом або виразом ) і виводить цю формулу у сполучній нормальній формі . Є дві константи, і які представляють справжні і несправжні, унарний оператор , ¬який представляє заперечення і бінарні оператори , , , і представляють імплікації, еквівалентності, кон'юнкції і диз'юнкції, відповідно , які підпорядковуються всі звичайні логічні операції ( закон де Моргана , усунення подвійного заперечення тощо).

Норма кон'юнктивної форми визначається так:

  1. Будь-який атомний вираз (включаючи і ) має кон'юнктивну нормальну форму.
  2. Заперечення будь-якого раніше побудованого виразу має кон'юнктивну нормальну форму.
  3. Диз'юнкція будь-яких двох раніше побудованих виразів є у сполучній нормальній формі.
  4. Сполучення будь-яких двох раніше побудованих виразів має кон'юнктивну нормальну форму.
  5. Будь-який інший вираз не є в сполучній нормальній формі.

Будь-який логічний вираз може бути перетворений (неоднозначно) у логічно еквівалентний вираз у сполучній нормальній формі (див. Цей алгоритм ). Вам не потрібно використовувати саме цей алгоритм.

Вхід:

Ви можете приймати дані в будь-якому зручному форматі; наприклад, символічний логічний вираз (якщо ваша мова його підтримує), рядок, якась інша структура даних. Вам не потрібно використовувати ті самі символи для істинних, хибних та логічних операторів, як я, але ваш вибір повинен бути послідовним, і ви повинні пояснити свій вибір у своїй відповіді, якщо це не зрозуміло. Ви не можете приймати будь-який інший вхід або кодувати будь-яку додаткову інформацію у форматі введення. Ви повинні мати певний спосіб вираження довільної кількості атомних виразів; наприклад цілі числа, символи, рядки тощо

Вихід:

Формула в кон'юнктивному звичайному вигляді, знову в будь-якому зручному форматі. Він не повинен бути у тому ж форматі, що і ваш вхід, але слід пояснити, чи є якісь відмінності.

Тестові приклади:

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, тому я б запропонував відмовитись від цієї вимоги і поставити перед собою свою проблему.
Лайконі

@Laikoni Дуже правда. Я оновив питання, щоб сказати, що це можливі результати для тавтологій та протиріч, а не потрібні результати.
ngenisis

Відповіді:



8

Ти будеш ненавидіти мене ...

Математика, 23 байти

#~BooleanConvert~"CNF"&

Вхід буде використовувати Trueі Falseзамість і , але в іншому випадку буде виглядати дуже схожі на позначення питання: все символи ¬, , , і визнається в Mathematica (якщо вхід з UTF-8 символів 00AC, F523, 29E6, 2227 та 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

Формат вводу / виводу (у порядку пріоритетності):

  • (: (
  • ): )
  • : 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)))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.