Логическое программирование - Logic programming

Логическое программирование - это парадигма программирования, которая в значительной степени основана на формальной логике . Любая программа, написанная на языке логического программирования, представляет собой набор предложений в логической форме, выражающих факты и правила о некоторой проблемной области. Основные семейства языков логического программирования включают Prolog , программирование наборов ответов (ASP) и Datalog . На всех этих языках правила написаны в виде предложений :

H :- B1, …, Bn.

и декларативно читаются как логические следствия:

H if B1 and … and Bn.

Hназывается главой правила и ... называется телом . Факты - это правила, не имеющие тела и записанные в упрощенной форме: B1Bn

H.

В простейшем случае H, когда ,, ..., все атомарные формулы , эти предложения называются определенными предложениями или предложениями Хорна . Однако есть много расширений этого простого случая, наиболее важным из которых является случай, когда условия в теле предложения также могут быть отрицанием элементарных формул. Языки логического программирования, которые включают это расширение, обладают возможностями представления знаний немонотонной логики . B1Bn

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

решать H, решать и ... и решать .B1Bn

Рассмотрим в качестве примера следующий пункт:

fallible(X) :- human(X).

основан на примере, использованном Терри Виноградом для иллюстрации языка программирования Planner . В качестве предложения в логической программе его можно использовать как в качестве процедуры для проверки того, Xесть ли fallible, проверяя, Xесть ли human, так и в качестве процедуры для поиска того, Xчто есть, fallibleпутем нахождения того, Xчто есть human. Даже факты имеют процедурную интерпретацию. Например, пункт:

human(socrates).

может использоваться как процедура для демонстрации того, что socratesесть human, и как процедура для поиска того, Xчто есть, humanпутем «присвоения» socratesему X.

Декларативное чтение логических программ может использоваться программистом для проверки их правильности. Кроме того, логика на основе преобразования программы метода также может быть использована для преобразования логических программ в логически эквивалентные программы , которые являются более эффективными. В семействе языков логического программирования Prolog программист может также использовать известное поведение механизма выполнения при решении проблем для повышения эффективности программ.

История

Использование математической логики для представления и выполнения компьютерных программ также является особенностью лямбда-исчисления , разработанного Алонзо Черчем в 1930-х годах. Однако первое предложение использовать клаузальную форму логики для представления компьютерных программ было сделано Корделлом Грином . При этом использовалась аксиоматизация подмножества LISP вместе с представлением отношения ввода-вывода для вычисления отношения путем моделирования выполнения программы в LISP. Абсис Фостера и Элкока , с другой стороны, использовал комбинацию уравнений и лямбда-исчисления на языке программирования утверждений, который не налагает ограничений на порядок выполнения операций.

Логическое программирование в его нынешней форме можно проследить до дебатов в конце 1960-х - начале 1970-х годов о декларативном и процедурном представлении знаний в искусственном интеллекте . Сторонники декларативного представления особенно работали в Стэнфорде , связанном с Джоном Маккарти , Бертрамом Рафаэлем и Корделлом Грином, и в Эдинбурге с Джоном Аланом Робинсоном (академиком из Сиракузского университета ), Пэтом Хейсом и Робертом Ковальски . Сторонники процессуального представительства в основном работали в Массачусетском технологическом институте под руководством Марвина Мински и Сеймура Паперта .

Хотя он был основан на логических методах доказательства, Planner , разработанный в Массачусетском технологическом институте, был первым языком, появившимся в рамках этой процедурной парадигмы. В планировщике реализован управляемый образцом вызов процедурных планов из целей (например, уменьшение цели или обратная цепочка ) и из утверждений (например, прямая цепочка ). Наиболее влиятельной реализацией Planner была подмножество Planner, называемое Micro-Planner, реализованное Джерри Сассманом , Юджином Чарняком и Терри Виноградом . Он использовался для реализации программы Винограда для понимания естественного языка SHRDLU , которая была знаковой для того времени. Чтобы справиться с очень ограниченными системами памяти в то время, Planner использовал структуру управления с возвратом, так что единовременно нужно было хранить только один возможный путь вычисления. Planner дал начало языкам программирования QA-4, Popler, Conniver, QLISP и параллельному языку Ether.

Хейс и Ковальски в Эдинбурге пытались совместить декларативный подход, основанный на логике, к представлению знаний с процедурным подходом Planner. Хейс (1973) разработал эквациональный язык Golux, в котором различные процедуры могут быть получены путем изменения поведения средства доказательства теорем. Ковальский, с другой стороны, разработал разрешение SLD , вариант SL-разрешения, и показал, как оно рассматривает последствия как процедуры уменьшения цели. Ковальский сотрудничал с Колмерауэром в Марселе, который развил эти идеи при разработке и реализации языка программирования Prolog .

Ассоциация логического программирования была создана для содействия логического программирования в 1986 году.

Пролог породил языки программирования ALF , Fril , гёделевское , Mercury , Oz , Ciao , Visual Prolog , XSB и λProlog , а также множество параллельных логических языков программирования , ограничения логического программирования языков и Datalog .

Концепции

Логика и контроль

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

Алгоритм = Логика + Управление

где «Логика» представляет собой логическую программу, а «Управление» представляет различные стратегии доказательства теорем.

Решение проблем

В упрощенном пропозициональном случае, когда логическая программа и атомарная цель верхнего уровня не содержат переменных, обратное рассуждение определяет дерево и / или , которое составляет пространство поиска для решения цели. Цель верхнего уровня - корень дерева. Для любого узла в дереве и любого предложения, заголовок которого соответствует этому узлу, существует набор дочерних узлов, соответствующих подцелям в теле предложения. Эти дочерние узлы сгруппированы знаком «и». Альтернативные наборы дочерних элементов, соответствующие альтернативным способам решения узла, группируются знаком «или».

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

В более общем случае, когда подцели имеют общие переменные, могут использоваться другие стратегии, такие как выбор подцели, которая является наиболее точной или достаточно конкретизированной, так что применяется только одна процедура. Такие стратегии используются, например, в параллельном логическом программировании .

Отрицание как неудача

Для большинства практических приложений, а также для приложений, которые требуют немонотонных рассуждений в искусственном интеллекте, логические программы с предложением Хорна должны быть расширены до обычных логических программ с отрицательными условиями. Положение в нормальной логической программе имеет вид:

H :- A1, …, An, not B1, …, not Bn.

и декларативно читается как логическое следствие:

H if A1 and … and An and not B1 and … and not Bn.

где Hи все и являются атомарными формулами. Отрицание в отрицательных литералах обычно упоминается как « отрицание как сбой », потому что в большинстве реализаций отрицательное условие выполняется, показывая, что положительное условие не выполняется. Например: AiBi not Bi not Bi Bi

canfly(X) :- bird(X), not abnormal(X).
abnormal(X) :- wounded(X).
bird(john).
bird(mary).
wounded(john).

Учитывая цель найти что-то, что умеет летать:

:- canfly(X).

есть два возможных решения, которые решают первую подзадачу bird(X), а именно X = johnи X = mary. Вторая подцель not abnormal(john)первого возможного решения терпит неудачу, потому что wounded(john)успешна и, следовательно, abnormal(john)успешна. Однако вторая подзадача второго варианта not abnormal(mary)решения оказывается успешной, потому что wounded(mary)терпит неудачу и, следовательно, abnormal(mary)терпит неудачу. Следовательно, X = maryэто единственное решение цели.

В Micro-Planner была конструкция под названием «thnot», которая при применении к выражению возвращает значение «истина», если (и только если) оценка выражения не выполняется. Эквивалентный оператор обычно существует в современных реализациях Пролога . Обычно он записывается как или , где программа должна доказать некоторую цель (предложение). Этот оператор отличается от отрицания в логике первого порядка: отрицание, например, не выполняется, когда переменная привязана к атому , но успешно во всех других случаях, в том числе когда не привязана. Это делает рассуждения Пролога немонотонными : всегда терпит неудачу, а может быть успешным, привязка к , в зависимости от того, была ли изначально привязана (обратите внимание, что стандартный Пролог выполняет цели в порядке слева направо). not(Goal)\+ GoalGoal\+ X == 1X1XX = 1, \+ X == 1\+ X == 1, X = 1X1X

Логический статус отрицания как отказа не был решен до тех пор, пока Кейт Кларк [1978] не показал, что при определенных естественных условиях это правильная (а иногда и полная) реализация классического отрицания в отношении завершения программы. Завершение составляет примерно то, что касается набора всех программных предложений с одним и тем же предикатом в левой части, скажем

H :- Body1.
H :- Bodyk.

как определение предиката

H iff (Body1 or … or Bodyk)

где «если и только если» означает «тогда и только тогда». Написание завершения также требует явного использования предиката равенства и включения набора соответствующих аксиом равенства. Однако для реализации отрицания как отказа нужны только если-половинки определений без аксиом равенства.

Например, завершение вышеуказанной программы:

canfly(X) iff bird(X), not abnormal(X).
abnormal(X) iff wounded(X).
bird(X) iff X = john or X = mary.
X = X.
not john = mary.
not mary = john.

Понятие завершения тесно связано с семантикой ограничения Маккарти для рассуждений по умолчанию и с предположением о замкнутом мире .

В качестве альтернативы к семантике завершения, отрицание как неудача может также интерпретироваться эпистемический, как и в модели стабильных семантик в ответ множество программирования . В этой интерпретации not (B i ) буквально означает, что B i неизвестен или в него не верят. Эпистемическая интерпретация имеет то преимущество, что ее можно очень просто комбинировать с классическим отрицанием, как в «расширенном логическом программировании», чтобы формализовать такие фразы, как «обратное не может быть показано», где «противоположное» является классическим отрицанием, а «не может быть доказано». быть показанным »- это эпистемическая интерпретация отрицания как неудачи.

Представление знаний

Тот факт, что предложениям Хорна можно дать процедурную интерпретацию и, наоборот, что процедуры снижения цели можно понимать как предложения Хорна + обратное рассуждение, означает, что логические программы сочетают декларативные и процедурные представления знаний . Включение отрицания как отказа означает, что логическое программирование является разновидностью немонотонной логики .

Несмотря на свою простоту по сравнению с классической логикой, эта комбинация предложений Хорна и отрицания как неудачи оказалась на удивление выразительной. Например, он обеспечивает естественное представление для здравого смысла законов причины и следствия, а формализуется как ситуация исчисления и исчисления событий . Также было показано, что это вполне естественно соответствует полуформальному языку законодательства. В частности, Праккен и Сартор приписывают представление Закона о британском гражданстве как логической программы, оказавшей «огромное влияние на развитие вычислительных представлений законодательства, показывая, как логическое программирование позволяет интуитивно привлекательные представления, которые могут быть непосредственно использованы для создания автоматических выводов». .

Варианты и расширения

Пролог

Язык программирования Prolog был разработан в 1972 году Аленом Колмерауэром . Он возник в результате сотрудничества Колмерауэра в Марселе и Роберта Ковальски в Эдинбурге. Колмерауэр работал над пониманием естественного языка , используя логику для представления семантики и используя разрешение для ответов на вопросы. Летом 1971 года Колмерауэр и Ковальски обнаружили, что клаузальная форма логики может использоваться для представления формальных грамматик, а средства доказательства теорем разрешения могут использоваться для синтаксического анализа. Они заметили, что некоторые средства доказательства теорем, такие как гиперразрешение, ведут себя как анализаторы снизу вверх, а другие, такие как SL-resolution (1971), ведут себя как синтаксические анализаторы сверху вниз.

Следующим летом 1972 года Ковальский, снова работая с Колмерауэром, разработал процедурную интерпретацию импликаций. Эта двойная декларативная / процедурная интерпретация позже была формализована в нотации Пролога.

H :- B1, …, Bn.

который можно читать (и использовать) как декларативно, так и процедурно. Кроме того , стало ясно , что такие положения могут быть ограничены определенными пункты или Хорн , где H, , ..., являются всеми атомными предикатными логическими формулами, а SL-разрешение может быть ограниченно (и обобщенно) для LUSH или SLD-разрешения . Процедурная интерпретация Ковальского и LUSH были описаны в меморандуме 1973 года, опубликованном в 1974 году. B1Bn

Колмерауэр и Филипп Руссель использовали эту двойную интерпретацию предложений в качестве основы Пролога, который был реализован летом и осенью 1972 года. Первая программа Пролога, также написанная в 1972 году и реализованная в Марселе, была французской системой ответов на вопросы. . Использование Пролога в качестве практического языка программирования дало большой импульс разработкой компилятора Дэвидом Уорреном в Эдинбурге в 1977 году. Эксперименты показали, что Эдинбургский Пролог может конкурировать по скорости обработки с другими языками символьного программирования, такими как Лисп . Эдинбургский Пролог стал стандартом де-факто и сильно повлиял на определение Пролога стандарта ISO .

Абдуктивное логическое программирование

Абдуктивное логическое программирование - это расширение обычного логического программирования, которое позволяет некоторым предикатам, объявленным как сокращаемые предикаты, быть «открытыми» или неопределенными. Предложение в программе абдуктивной логики имеет форму:

H :- B1, …, Bn, A1, …, An.

где H- атомарная формула, которая не сводится, все - литералы, предикаты которых не сводятся, и атомарные формулы, предикаты которых сводимы. Приводимые предикаты могут быть ограничены ограничениями целостности, которые могут иметь форму: BiAi

false :- L1, …, Ln.

где - произвольные литералы (определенные или сводимые, атомарные или инвертированные). Например: Li

canfly(X) :- bird(X), normal(X).
false :- normal(X), wounded(X).
bird(john).
bird(mary).
wounded(john).

где предикат normalприводим.

Решение проблем достигается путем вывода гипотез, выраженных в терминах сводимых предикатов, как решений проблем, которые необходимо решить. Эти проблемы могут быть либо наблюдениями, которые необходимо объяснить (как в классическом абдуктивном рассуждении ), либо целями, которые необходимо решить (как в нормальном логическом программировании). Например, гипотеза normal(mary)объясняет наблюдение canfly(mary). Более того, та же гипотеза влечет за собой единственное решение X = maryзадачи найти что-то, что может летать:

:- canfly(X).

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

Металогическое программирование

Поскольку математическая логика имеет давнюю традицию различать объектный язык и метаязык, логическое программирование также допускает метауровневое программирование. Простейшая программа металогики - это так называемый " ванильный " метаинтерпретатор :

    solve(true).
    solve((A,B)):- solve(A),solve(B).
    solve(A):- clause(A,B),solve(B).

где истина представляет собой пустую конъюнкцию, а предложение (A, B) означает, что существует предложение уровня объекта в форме A: - B.

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

Программирование логики ограничений

Constraint логическое программирование объединяет Horn дизъюнкцию логическое программирование с ограничением решения . Он расширяет предложения Horn, позволяя некоторым предикатам, объявленным как предикаты ограничений, встречаться как литералы в теле предложений. Программа логики ограничений - это набор предложений вида:

H :- C1, …, Cn ◊ B1, …, Bn.

где Hи все атомарные формулы, а - ограничения. Декларативно такие предложения читаются как обычные логические следствия: BiCi

H if C1 and … and Cn and B1 and … and Bn.

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

С процедурной точки зрения подцели, предикаты которых определены программой, решаются путем редукции целей, как в обычном логическом программировании, но ограничения проверяются на выполнение с помощью решателя ограничений, зависящего от предметной области, который реализует семантику предикатов ограничений. Исходная проблема решается путем сведения ее к выполнимой совокупности ограничений.

Следующая программа логики ограничений представляет собой игрушечную временную базу данных john'sистории как учителя:

teaches(john, hardware, T) :- 1990  T, T < 1999.
teaches(john, software, T) :- 1999  T, T < 2005.
teaches(john, logic, T) :- 2005  T, T  2012.
rank(john, instructor, T) :- 1990  T, T < 2010.
rank(john, professor, T) :- 2010  T, T < 2014.

Здесь и <представлены предикаты ограничений с их обычной предполагаемой семантикой. Следующее целевое предложение запрашивает базу данных, чтобы узнать, когда johnи учили, logicи когда были professor:

:- teaches(john, logic, T), rank(john, professor, T).

Решение есть 2010 ≤ T, T ≤ 2012.

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

Параллельное логическое программирование

Параллельное логическое программирование объединяет концепции логического программирования с параллельным программированием . Его развитие получило большой импульс в 1980-х годах, когда он выбрал язык системного программирования Японского проекта пятого поколения (FGCS) .

Программа параллельной логики - это набор защищенных предложений Horn в форме:

H :- G1, …, Gn | B1, …, Bn.

Конъюнкция называется защитой предложения и является оператором фиксации. Декларативно оговорки Рога с осторожностью читаются как обычные логические следствия: G1, ... , Gn |

H if G1 and … and Gn and B1 and … and Bn.

Однако процедурно, когда есть несколько пунктов, заголовки которых H соответствуют заданной цели, тогда все предложения выполняются параллельно, проверяя, держатся ли их защитные меры. Если придерживаются защитников более чем одного пункта, то один из пунктов считается подтвержденным, и выполнение продолжается с подцелями выбранного пункта. Эти подцели также могут выполняться параллельно. Таким образом, параллельное логическое программирование реализует форму «недетерминизма безразлично», а не «недетерминизма не знаю». G1, ... , Gn B1, ..., Bn

Например, следующая программа параллельной логики определяет предикат shuffle(Left, Right, Merge) , который можно использовать для перемешивания двух списков Leftи Rightобъединения их в один список Merge, сохраняющий порядок двух списков Leftи Right:

shuffle([], [], []).
shuffle(Left, Right, Merge) :-
    Left = [First | Rest] |
    Merge = [First | ShortMerge],
    shuffle(Rest, Right, ShortMerge).
shuffle(Left, Right, Merge) :-
    Right = [First | Rest] |
    Merge = [First | ShortMerge],
    shuffle(Left, Rest, ShortMerge).

Здесь []представляет собой пустой список и [Head | Tail]представляет собой список с первым элементом, Headза которым следует список Tail, как в Прологе. (Обратите внимание, что первое вхождение | во втором и третьем предложениях - это конструктор списка, тогда как второе вхождение | - это оператор обязательства.) Программа может использоваться, например, для перемешивания списков [ace, queen, king]и [1, 4, 2]вызова предложения цели:

shuffle([ace, queen, king], [1, 4, 2], Merge).

Например, программа недетерминированно сгенерирует одно решение Merge = [ace, queen, 1, king, 4, 2].

Возможно, параллельное логическое программирование основано на передаче сообщений, поэтому оно подвержено той же неопределенности, что и другие системы параллельной передачи сообщений, такие как субъекты (см. Неопределенность в параллельных вычислениях ). Карл Хьюитт утверждал, что параллельное логическое программирование не основано на логике в его понимании, что вычислительные шаги не могут быть логически выведены. Однако в параллельном логическом программировании любой результат завершения вычисления является логическим следствием программы, а любой частичный результат частичного вычисления является логическим следствием программы и остаточной цели (технологической сети). Таким образом, неопределенность вычислений означает, что не все логические следствия программы могут быть выведены.

Программирование параллельной логики ограничений

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

Индуктивное логическое программирование

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

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

Некоторые исследователи расширили логическое программирование с помощью функций программирования более высокого порядка, производных от логики более высокого порядка , таких как переменные предиката. К таким языкам относятся расширения Prolog HiLog и λProlog .

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

Основание логического программирования в рамках линейной логики привело к созданию языков логического программирования, которые значительно более выразительны, чем языки, основанные на классической логике. Программы с предложениями Horn могут представлять изменение состояния только путем изменения аргументов предикатов. В линейном логическом программировании можно использовать внешнюю линейную логику для поддержки изменения состояния. Некоторые ранние разработки языков логического программирования, основанные на линейной логике, включают LO [Andreoli & Pareschi, 1991], Lolli, ACL и Forum [Miller, 1996]. Форум дает целенаправленную интерпретацию всей линейной логики.

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

F-logic расширяет логическое программирование за счет объектов и синтаксиса фреймов.

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

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

Логика транзакций - это расширение логического программирования с логической теорией обновлений, изменяющих состояние. Он имеет как теоретико-модельную семантику, так и процедурную. Реализация подмножества логики транзакций доступна в системе Flora-2 . Доступны и другие прототипы .

Смотрите также

Цитаты

Источники

Общие введения

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

дальнейшее чтение

внешние ссылки