Введение

Парадигма программирования, основанная на формальной логике

Логическое программирование — это парадигма программирования, баз данных и представления знаний, основанная на формальной логике. Логическая программа — это набор предложений в логической форме, представляющий знания о некоторой проблемной области. Вычисления выполняются путем применения логических рассуждений к этим знаниям для решения проблем в области. К основным семействам языков логического программирования относятся Prolog, Answer Set Programming (ASP) и Datalog. Во всех этих языках правила записываются в виде предложения:

A : B1, …, Bn. и читаются как декларативные предложения в логической форме:

A если B1 и … и Bn. A называется головой правила, B1, …, Bn называется телом, а Bi называются литералами или условиями. Когда n = 0, правило называется фактом и записывается в упрощенной форме:

A.

Запросы (или цели) имеют тот же синтаксис, что и тела правил, и обычно записываются в форме:

? B1, …, Bn. В простейшем случае клауз Хорна (или "определенных" клауз), все A, B1, …, Bn являются атомными формулами вида p(t1, …, tm), где p — предикатный символ, обозначающий отношение, например, "материнство", а ti — термы, обозначающие объекты (или индивидуумы). Термы включают как константные символы, такие как "charles", так и переменные, такие как X, которые начинаются с заглавной буквы. Рассмотрим, например, следующую программу клауз Хорна:

mother(child(elizabeth, charles)).
father(child(charles, william)).
father(child(charles, harry)).
parent(child(X, Y)) : mother(child(X, Y)).
parent(child(X, Y)) : father(child(X, Y)).
grandparent(child(X, Y)) : parent(child(X, Z)), parent(child(Z, Y)).

При заданном запросе программа выдает ответы. Например, для запроса ? parent(child(X, william)), единственный ответ:

X = charles.

Можно задавать различные запросы. Например, программа может быть запрошена как для генерации бабушек и дедушек, так и для генерации внуков. Ее можно использовать даже для генерации всех пар бабушек и дедушек и внуков, или просто для проверки, является ли данная пара такой парой:

? grandparent(child(X, william)).
X = elizabeth.

? grandparent(child(elizabeth, Y)).
Y = william;
Y = harry.

? grandparent(child(X, Y)).
X = elizabeth,
Y = william;
X = elizabeth,
Y = harry.

? grandparent(child(william, harry)).
no.

? grandparent(child(elizabeth, harry)).
yes.

Хотя логические программы клауз Хорна являются Тьюринг-полными, для большинства практических приложений программы клауз Хорна необходимо расширить до "нормальных" логических программ с отрицательными условиями. Например, определение брата/сестры использует отрицательное условие, где предикат = определяется клаузой X = X:

sibling(X, Y) : parent(child(Z, X)), parent(child(Z, Y)), not(X = Y).

Логические языки программирования, которые включают отрицательные условия, обладают возможностями представления знаний немонотонной логики. В ASP и Datalog логические программы имеют только декларативное прочтение, и их выполнение осуществляется посредством процедуры доказательства или генератора моделей, поведение которых не предназначено контролироваться программистом. Однако в семействе языков Prolog логические программы также имеют процедурную интерпретацию как процедуры редукции цели. С этой точки зрения, клауза A : B1, …, Bn понимается как:

чтобы решить A, решить B1, и … и решить Bn.

Отрицательные условия в телах клауз также имеют процедурную интерпретацию, известную как отрицание как отказ: отрицательный литерал not B считается истинным, если и только если положительный литерал B не удается доказать. Большая часть исследований в области логического программирования была посвящена попыткам разработать логическую семантику для отрицания как отказа и разработке другой семантики и других реализаций для отрицания. Эти разработки, в свою очередь, были важны для поддержки разработки формальных методов логической верификации программ и трансформации программ.

История

Использование математической логики для представления и выполнения компьютерных программ также является особенностью лямбда-исчисления, разработанного Алонзо Черчем в 1930-х годах. Однако первое предложение использовать клаузальную форму логики для представления компьютерных программ было сделано Корделлом Грином. Это использовало аксиоматизацию подмножества LISP вместе с представлением отношения ввода-вывода для вычисления этого отношения путем моделирования выполнения программы в LISP. Absys, разработанный Фостером и Элкоком, с другой стороны, использовал комбинацию уравнений и лямбда-исчисления в ассерциональном языке программирования, который не накладывает ограничений на порядок выполнения операций. Логическое программирование, с его современным синтаксисом фактов и правил, восходит к дебатам конца 1960-х и начала 1970-х годов о декларативных и процедурных представлениях знаний в искусственном интеллекте. Сторонники декларативных представлений работали в Стэнфорде, в сотрудничестве с Джоном Маккарти, Бертрамом Рафаэлем и Корделлом Грином, а также в Эдинбурге с Джоном Аланом Робинсоном (приглашенным профессором из Сиракузского университета), Пэтом Хейсом и Робертом Ковальски. Сторонники процедурных представлений были сосредоточены главным образом в MIT под руководством Марвина Мински и Сеймура Паперта. Хотя Planner, разработанный Карлом Хьюитом в MIT, и основывался на методах доказательства логики, он стал первым языком, появившимся в рамках этой процедурной парадигмы. Planner включал в себя направленный образцом вызов процедурных планов из целей (т.е. сокращение цели или обратное распространение) и из утверждений (т.е. прямое распространение). Наиболее влиятельной реализацией Planner была его подмножество, Micro Planner, реализованное Джерри Суссманом, Юджином Чарняком и Терри Виноградом. Виноград использовал Micro Planner для реализации знаковой программы понимания естественного языка SHRDLU. Для повышения эффективности Planner использовал структуру управления с возвратом, чтобы одновременно хранить только один возможный путь вычислений. Planner послужил основой для языков программирования QA4, Popler, Conniver, QLISP и языка параллельного программирования Ether. Хейс и Ковальски в Эдинбурге попытались согласовать декларативный подход к представлению знаний, основанный на логике, с процедурным подходом Planner. Хейс (1973) разработал уравнительный язык Golux, в котором различные процедуры можно было получить, изменяя поведение решателя теорем. В то же время Ален Колмерауэр в Марселе работал над пониманием естественного языка, используя логику для представления семантики и разрешение для ответов на вопросы. Летом 1971 года Колмерауэр пригласил Ковальски в Марсель, и вместе они обнаружили, что клаузальная форма логики может быть использована для представления формальных грамматик и что решатели теорем на основе разрешения могут быть использованы для синтаксического анализа. Они заметили, что некоторые решатели теорем, такие как гиперразрешение, ведут себя как восходящие парсеры, а другие, такие как SL-разрешение (1971), ведут себя как нисходящие парсеры. Летом 1972 года Ковальски, снова работая с Колмерауэром, разработал процедурную интерпретацию импликаций в клаузальной форме. Также стало ясно, что такие клаузы могут быть ограничены определенными клаузами или клаузами Хорна, и что SL-разрешение может быть ограничено (и обобщено) до SLD-разрешения. Процедурная интерпретация Ковальского и SLD были описаны в меморандуме 1973 года, опубликованном в 1974 году. Колмерауэр вместе с Филиппом Русселем использовали процедурную интерпретацию в качестве основы для Prolog, который был реализован летом и осенью 1972 года. Первая программа на Prolog, также написанная в 1972 году и реализованная в Марселе, была французской системой ответов на вопросы. Использование Prolog в качестве практического языка программирования получило значительный импульс благодаря разработке компилятора Дэвидом Уорреном в Эдинбурге в 1977 году. Эксперименты показали, что Edinburgh Prolog может конкурировать по скорости обработки с другими символическими языками программирования, такими как Lisp. Edinburgh Prolog стал де-факто стандартом и оказал сильное влияние на определение стандарта ISO Prolog. Логическое программирование получило международное признание в 1980-х годах, когда японское Министерство международной торговли и промышленности выбрало его для разработки программного обеспечения для проекта "Компьютерные системы пятого поколения" (FGCS). Проект FGCS был направлен на использование логического программирования для разработки передовых приложений искусственного интеллекта на массивно-параллельных компьютерах. Хотя проект первоначально исследовал использование Prolog, позже он перешел на использование параллельного логического программирования, поскольку оно было ближе к компьютерной архитектуре FGCS. Однако функция "зафиксированного выбора" в параллельном логическом программировании противоречила логической семантике языка и его пригодности для представления знаний и решения задач. Кроме того, параллельные компьютерные системы, разработанные в рамках проекта, не смогли конкурировать с достижениями в разработке более традиционных компьютеров общего назначения. В совокупности эти два фактора привели к тому, что проект FGCS не достиг своих целей. Интерес как к логическому программированию, так и к искусственному интеллекту во всем мире пришел в упадок. В то же время более декларативные подходы к логическому программированию, включая те, которые основаны на использовании Prolog, продолжали развиваться независимо от проекта FGCS. В частности, хотя Prolog был разработан для объединения декларативных и процедурных представлений знаний, чисто декларативная интерпретация логических программ стала центральной для приложений в области дедуктивных баз данных. Работа в этой области стала заметной примерно в 1977 году, когда Эрве Галлаэр и Джек Минкер организовали семинар по логике и базам данных в Тулузе. Эта область в конечном итоге была переименована в Datalog. Этот акцент на логическом, декларативном прочтении логических программ получил дополнительный импульс благодаря развитию логического программирования с ограничениями в 1980-х годах и программирования с ответами на множества в 1990-х годах. Он также получает новое подтверждение в современных приложениях Prolog.

Ассоциация логического программирования (ALP) была основана в 1986 году для продвижения логического программирования. Ее официальным журналом до 2000 года был The Journal of Logic Programming. Ее главным редактором-основателем был Дж. Алан Робинсон. В 2001 году журнал был переименован в The Journal of Logic and Algebraic Programming, а официальным журналом ALP стал Theory and Practice of Logic Programming, издаваемый Cambridge University Press.

Понятия

Логические программы характеризуются богатым разнообразием семантик и методов решения задач, а также широким спектром применения в программировании, базах данных, представлении знаний и решении проблем.

Программирование логики с одновременными ограничениями

Конкурентное логическое программирование с ограничениями объединяет конкурентное логическое программирование и логическое программирование с ограничениями, используя ограничения для управления конкуренцией. Клауза может содержать охранное условие – набор ограничений, которые могут блокировать применимость этой клаузы. Когда охранные условия нескольких клауз выполнены, конкурентное логическое программирование с ограничениями делает однозначный выбор в пользу использования только одной из них.

Логическое программирование высшего порядка

Несколько исследователей расширили логическое программирование возможностями программирования высшего порядка, заимствованными из логики высшего порядка, такими как переменные предикатов. К таким языкам относятся расширения Prolog HiLog и λProlog.

Линейное логическое программирование

Основание логического программирования на линейной логике привело к созданию логических языков программирования, которые значительно более выразительны, чем языки, основанные на классической логике. Программы, построенные на клаузах Хорна, могут представлять изменение состояния только посредством изменения аргументов предикатов. В логическом программировании с использованием линейной логики можно использовать окружающую линейную логику для поддержки представления изменения состояния. К ранним разработкам логических языков программирования, основанных на линейной логике, относятся LO, Lolli, ACL и Forum. Forum предоставляет целеориентированную интерпретацию всей линейной логики.

Объектно-ориентированное логическое программирование

F-логика расширяет логическое программирование за счет объектов и синтаксиса фреймов. Logtalk расширяет язык программирования Prolog поддержкой объектов, протоколов и других концепций ООП. Он поддерживает большинство стандартно-совместимых систем Prolog в качестве бэкэнд-компиляторов.

Программирование транзакционной логики

Логическая система обработки транзакций. Другие прототипы также имеются в наличии.

Другие источники

Джон Маккарти. "Программы с здравым смыслом". Симпозиум по механизации мыслительных процессов. Национальная физическая лаборатория. Теддингтон, Англия. 1958. Эхуд Шапиро (редактор). Concurrent Prolog. Издательство MIT. 1987. Джеймс Слэгл. "Эксперименты с дедуктивной программой для ответов на вопросы". CACM. Декабрь 1965. Габбай, Дов М.; Хоггер, Кристофер Джон; Робинсон, Дж. А., редакторы (1993–1998). Handbook of Logic in Artificial Intelligence and Logic Programming. Тома 1–5, Oxford University Press.