Каковы основные технические различия между Prolog и miniKanren в плане логического программирования? [закрыто]


124

Когда я хочу прочитать о логическом программировании, я всегда натыкаюсь на два «основных» способа сделать это в настоящее время:

  • miniKanren , мини-язык, представленный в The Reasoned Schemer и популярный в настоящее время благодаря core.logic .
  • Пролог , первый «большой» язык логического программирования.

Что меня сейчас интересует: каковы основные технические различия между ними? Они очень похожи по подходу и реализации, или они используют совершенно разные подходы к логическому программированию? Из каких разделов математики они берут начало и каковы теоретические основы?


3
Печально, что этот вопрос закрыт. Как показывает очень убедительный ответ и большое количество положительных отзывов, это совершенно полезный вопрос. Я проголосовал за открытие ....
nealmcb

Вопросы @nealmcb, которые когда-то были по теме с большим количеством голосов, больше не актуальны, количество голосов не является тем, что определяет его действительность или нет.
Tiago Martins Peres 李大仁

Ответы:


281

Во-первых, позвольте мне поздравить вас с прекрасным значком pw0n1e.

На этот вопрос сложно ответить, в основном потому, что существует множество вариантов как miniKanren, так и Prolog. miniKanren и Prolog - это действительно семейства языков, что затрудняет сравнение их возможностей или даже того, как они используются на практике. Из-за этого, пожалуйста, относитесь ко всему, что я собираюсь сказать, с осторожностью: если я скажу, что Prolog использует поиск в глубину, имейте в виду, что многие реализации Prolog поддерживают другие стратегии поиска, и что альтернативные стратегии поиска также могут быть закодированы в мета -уровень переводчика. Тем не менее, miniKanren и Prolog придерживаются разных принципов проектирования и идут на разные компромиссы.

Пролог - один из двух классических языков программирования символического искусственного интеллекта (другим классическим языком является Лисп). Prolog превосходно реализует символьные системы на основе правил, в которых декларативные знания закодированы в логике первого порядка. Язык оптимизирован для выразительности и эффективности для этих типов приложений, иногда за счет логической чистоты. Например, по умолчанию Пролог не использует "проверку на наличие" в унификации. С точки зрения математики и логики эта версия унификации неверна. Однако проверка срабатывания обходится дорого, и в большинстве случаев отсутствие проверки срабатывания не является проблемой. Это очень прагматичное дизайнерское решение, так же как и использование Prolog поиска в глубину и использование cut (!) для управления возвратом. Я уверен, что эти решения были абсолютно необходимы при работе на оборудовании 1970-х годов, а сегодня они очень полезны при работе над большими проблемами и при работе с огромными (часто бесконечными!) Пространствами поиска.

Prolog поддерживает множество «экстра-логических» или «нелогических» функций, в том числе вырезание assertи retractпроекция переменных для арифметики с использованиемis, и так далее. Многие из этих функций упрощают выражение сложного потока управления и управление глобальной базой данных Prolog. Одна очень интересная особенность Пролога заключается в том, что код Пролога сам хранится в глобальной базе данных фактов, и его можно запрашивать во время выполнения. Это делает тривиальным написание мета-интерпретаторов, которые изменяют поведение кода Пролога при интерпретации. Например, в Прологе можно кодировать поиск в ширину с помощью метаинтерпретатора, который изменяет порядок поиска. Это чрезвычайно мощный метод, малоизвестный за пределами мира Пролога. «Искусство Пролога» подробно описывает эту технику.

Огромные усилия были вложены в улучшение реализаций Пролога, большинство из которых основано на абстрактной машине Уоррена (WAM). WAM использует модель побочных эффектов, в которой значения деструктивно присваиваются логическим переменным, причем эти побочные эффекты отменяются при возврате. Многие функции могут быть добавлены в Prolog путем расширения инструкций WAM. Одним из недостатков этого подхода является то, что документы по реализации Prolog могут быть трудночитаемыми без твердого понимания WAM. С другой стороны, у разработчиков Prolog есть общая модель для обсуждения вопросов реализации. Параллельно с Prolog было проведено множество исследований, кульминацией которых стал Andorra Prolog в 1990-х годах. По крайней мере, некоторые из этих идей живут в Ciao Prolog. (Ciao Prolog полон интересных идей, многие из которых выходят далеко за рамки стандарта Prolog.)

В Prolog есть прекрасный синтаксис в стиле «сопоставления с образцом», основанный на унификации, что позволяет создавать очень сжатые программы. Прологеры любят свой синтаксис, так же как лисперы любят свои s-выражения. В Prolog также есть большая библиотека стандартных предикатов. Благодаря всем инженерным разработкам, направленным на то, чтобы сделать WAM быстрым, существуют очень эффективные и зрелые реализации Prolog. В результате многие большие системы, основанные на знаниях, были полностью написаны на Прологе.

miniKanren был разработан как язык программирования с минимальной логикой, с небольшой, легко понятной и легко взломанной реализацией. miniKanren изначально был встроен в Scheme, а за последнее десятилетие был перенесен на десятки других основных языков. Самая популярная реализация miniKanren - это core.logic в Clojure, который теперь имеет множество расширений, подобных Prolog, и ряд оптимизаций. Недавно ядро ​​реализации miniKanren было еще больше упрощено, в результате появилось крошечное «микроядро» под названием «microKanren». Затем miniKanren можно реализовать поверх этого ядра microKanren. Перенос microKanren или miniKanren на новый основной язык стал стандартным упражнением для программистов, изучающих miniKanren. В следствии,

Стандартные реализации miniKanren и microKanren не содержат мутаций или других побочных эффектов, за одним исключением: некоторые версии miniKanren используют равенство указателей для сравнения логических переменных. Я считаю это «благоприятным эффектом», хотя многие реализации избегают даже этого эффекта, передавая счетчик через реализацию. Также нет глобальной базы данных фактов. Философия реализации miniKanren основана на функциональном программировании: следует избегать мутаций и эффектов, а все языковые конструкции должны учитывать лексическую область видимости. Если вы внимательно посмотрите на реализацию, вы можете даже заметить пару монад. Реализация поиска основана на объединении и управлении ленивыми потоками, опять же без использования мутации. Эти варианты реализации приводят к совершенно другим компромиссам, чем в Prolog. В Прологе поиск переменных - это постоянное время, но для поиска с возвратом требуется устранение побочных эффектов. В miniKanren поиск переменных обходится дороже, но поиск с возвратом «бесплатный». Фактически, в miniKanren нет возврата с возвратом из-за того, как обрабатываются потоки.

Один интересный аспект реализации miniKanren состоит в том, что код по своей сути является потокобезопасным и - по крайней мере теоретически - легко распараллеливается. Конечно, распараллеливание кода без его замедления - нетривиальная задача, учитывая, что каждому потоку или процессу нужно дать достаточно работы, чтобы компенсировать накладные расходы на распараллеливание. Тем не менее, это область реализации miniKanren, которая, я надеюсь, получит больше внимания и экспериментов.

miniKanren использует проверку возникновения для унификации и использует полный поиск с чередованием вместо поиска в глубину. Поиск с чередованием использует больше памяти, чем поиск в глубину, но может найти ответы в некоторых случаях, когда поиск в глубину будет расходиться / зацикливаться навсегда. miniKanren делает поддержку несколько экстра-логические операторы --- conda, conduи project, к примеру. condaи conduможет использоваться для имитации сокращения Пролога и projectможет использоваться для получения значения, связанного с логической переменной.

Наличие conda,condu иproject--- и возможность легко изменять стратегию поиска --- позволяет программистам использовать miniKanren как встроенный язык, подобный Prolog. Это особенно верно для пользователей Clojure core.logic, который включает множество расширений, подобных Prolog. Это «прагматичное» использование miniKanren, кажется, составляет большую часть использования miniKanren в промышленности. Программисты, которые хотят добавить систему рассуждений, основанную на знаниях, в существующее приложение, написанное на Clojure, Python или JavaScript, обычно не заинтересованы в переписывании всего своего приложения на Prolog. Встраивание небольшого языка логического программирования в Clojure или Python гораздо привлекательнее. Предположительно, для этой цели подойдет и встроенная реализация Пролога.

В дополнение к использованию miniKanren в качестве прагматичного языка программирования встроенной логики, аналогичного по духу Prolog, miniKanren используется для исследований в области «реляционного» программирования. То есть при написании программ, которые ведут себя как математические отношения, а не как математические функции. Например, в Scheme appendфункция может добавлять два списка, возвращая новый список: вызов функции (append '(a b c) '(d e))возвращает список (a b c d e). Однако мы можем рассматривать его appendкак трехместное отношение, а не как функцию с двумя аргументами. Затем вызов (appendo '(a b c) '(d e) Z)связывает логическую переменную Zсо списком (a b c d e). Конечно, все становится интереснее, когда мы помещаем логические переменные в другие позиции. Звонок (appendo X '(d e) '(a b c d e))ассоциируется Xс (a b c), а звонок(appendo X Y '(a b c d e)) партнерамиXи Yс парами списков, которые при добавлении равны (a b c d e). Например, X= (a b)и Y= (c d e)- одна такая пара значений. Мы также можем написать (appendo X Y Z), что будет производить бесконечно много троек списков X, Yи Zтаким образом, что добавление Xк Yпроизводят Z.

Эту реляционную версию appendможно легко выразить в Prolog, и она действительно показана во многих руководствах по Prolog. На практике более сложные программы на Прологе имеют тенденцию использовать по крайней мере несколько дополнительных логических функций, таких как вырезание, которые препятствуют возможности обработки полученной программы как отношения. Напротив, miniKanren специально разработан для поддержки этого стиля реляционного программирования. Более поздние версии miniKanren поддерживают решение символических ограничений ( symbolo,numbero ,absento, ограничения неравенства, номинальное логическое программирование), чтобы упростить написание нетривиальных программ в виде отношений. На практике я никогда не использую никаких дополнительных логических функций miniKanren и пишу все свои программы miniKanren как отношения. Самые интересные реляционные программы - это реляционные интерпретаторы для подмножества Scheme. Эти интерпретаторы обладают множеством интересных способностей, таких как создание миллиона программ Scheme, оценивающих список (I love you), или тривиального создания quines (программ, которые оценивают сами себя).

miniKanren делает ряд компромиссов, чтобы реализовать этот реляционный стиль программирования, которые сильно отличаются от компромиссов, которые делает Пролог. Со временем miniKanren добавил больше символических ограничений, фактически став символьно-ориентированным языком программирования логических ограничений. Во многих случаях эти символические ограничения позволяют избежать использования дополнительных логических операторов, таких как conduи project. В других случаях этих символических ограничений недостаточно. Лучшая поддержка символических ограничений - одна из активных областей исследований miniKanren, наряду с более широким вопросом о том, как писать более крупные и сложные программы как отношения.

Короче говоря, и miniKanren, и Prolog имеют интересные особенности, реализации и способы использования, и я думаю, что стоит изучить идеи обоих языков. Есть и другие очень интересные языки логического программирования, такие как Mercury, Curry и Gödel, каждый из которых имеет свой собственный подход к логическому программированию.

Я закончу несколькими ресурсами miniKanren:

Главный сайт miniKanren: http://minikanren.org/

Интервью, которое я дал о реляционном программировании и miniKanren, включая сравнение с Prolog: http://www.infoq.com/interviews/byrd-relational-programming-minikanren

Ура,

--Будет


9
Извините, если я сейчас в шоке. Я только что начал первые мысленные эксперименты по логике и программированию на основе ограничений и получил такой ответ. :) На самом деле, как вы упомянули в своем ответе, у меня было сильное подозрение, что логическое вычисление было идеальным кандидатом для реализации в качестве монады; Оказывается, это больше похоже на MonadPlus, и действительно есть документ и справочная реализация вашего коллеги Фридмана! Итак, я читаю это и играю с этим сейчас, есть мысли по этому поводу?
Profpatsch

4
Я подозреваю, что вам также будут интересны статья и код microKanren: microKanren webyrd.net/scheme-2013/papers/HemannMuKanren2013.pdf и github.com/jasonhemann/microKanren
Уильям Э. Берд

5
Кроме того, я организую еженедельное мероприятие miniKanren в Google Hangouts, по воскресеньям в 15:00 по восточному времени (GMT -5: 00). Я всегда чирикаю ссылку из моей учетной записи @webyrd в Твиттере, если вы хотите к нам присоединиться. Предыдущие записанные видеовстречи находятся по адресу: youtube.com/playlist?list=PLO4TbomOdn2cks2n5PvifialL8kQwt0aW
Уильям Э. Берд

2
Я думаю, что это в основном та же монада поиска, что и в статье 2005 года. Также см. «Встраивание пролога в Haskell» Сереса и Спайви: spivey.oriel.ox.ac.uk/~mike/silvija/seres_haskell99.pdf
Уильям Э. Берд

1
@ WilliamE.Byrd - Отличный ответ! Предполагая, что он есть, какова лучшая реализация miniKanren, которая может быть встроена в программу C / C ++? Кроме того, имеет ли miniKanren генеративную природу Пролога? То есть, возможность оставить переменную в выражении без обработки, и основной движок сгенерирует все возможные значения для этой переменной с учетом текущих отношений, объявленных программой?
Роберт Ошлер,

4

Предварительный ответ:

AFAIK, «The Reasoned Schemer» представил базовое логическое программирование в синтаксисе Scheme-y и стиле функционального программирования, добавив, в частности, постоянные цели «#u» (сбой) и «#s» (успех) к логическим значениям «#t». "и" #f ". Он использовал тот же подход к логическому программированию, что и Пролог: унификация и поиск с возвратом. Я посмотрю, успею ли я забрать эту книгу с полки на выходных. Раздел математики - это ограниченная форма логики первого порядка, в данном случае предложения Хорна и Разъединение Резолюции. См .: « Вычислительная логика: воспоминания о прошлом и вызовы будущего » Джона Алана Робинсона и Роберта Ковальски «Первые годы логического программирования » для холодного старта.


3
Какое отношение имеют эти две цитаты к Kanren или MiniKanren?
false

2
См. Последний вопрос: «Из каких разделов математики они берут начало и каковы теоретические основы?»
Фрэнк Шеарар
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.