Пролог — это язык логического программирования , берущий свое начало в искусственном интеллекте , автоматизированном доказательстве теорем и компьютерной лингвистике . [1] [2] [3]
Prolog имеет свои корни в логике первого порядка , формальной логике , и в отличие от многих других языков программирования , Prolog задуман в первую очередь как декларативный язык программирования : программа представляет собой набор фактов и правил , которые определяют отношения . Вычисление инициируется запуском запроса по программе. [4]
Prolog был одним из первых языков логического программирования [5] и остается самым популярным таким языком сегодня, с несколькими бесплатными и коммерческими реализациями. Язык использовался для доказательства теорем , [6] экспертных систем , [7] переписывания терминов , [8] систем типов , [9] и автоматизированного планирования , [10] а также его первоначальной предполагаемой области использования, обработки естественного языка . [11] [12]
Prolog — это полный по Тьюрингу язык программирования общего назначения, который хорошо подходит для приложений интеллектуальной обработки знаний.
В Prolog логика программы выражается в терминах отношений, а вычисление инициируется запуском запроса по этим отношениям. Отношения и запросы строятся с использованием единственного типа данных Prolog, термина . [ 4] Отношения определяются предложениями . При наличии запроса механизм Prolog пытается найти опровержение резолюции отрицаемого запроса. Если отрицаемый запрос может быть опровергнут, т. е. найдена инстанциация для всех свободных переменных, которая делает объединение предложений и синглтон-множество, состоящее из отрицаемого запроса, ложными, то из этого следует, что исходный запрос с примененной найденной инстанциацией является логическим следствием программы. Это делает Prolog (и другие языки логического программирования) особенно полезными для приложений баз данных, символической математики и анализа языка. Поскольку Prolog допускает нечистые предикаты , проверка истинностного значения некоторых специальных предикатов может иметь некоторый преднамеренный побочный эффект , такой как вывод значения на экран. Из-за этого программисту разрешено использовать некоторое количество обычного императивного программирования, когда логическая парадигма неудобна. У него есть чисто логическое подмножество, называемое «чистым Прологом», а также ряд экстралогических особенностей.
Единственный тип данных Prolog — это терм . Термины — это атомы , числа , переменные или составные термы . [примечание 1]
x
, red
, 'Taco'
, 'some atom'
, и 'p(a)'
.person_friends(zelda,[tom,jim])
.Особые случаи сложных терминов:
[]
. Например, [1,2,3,4]
или [red,green,blue]
.double_quotes
. Например, "to be, or not to be"
. [13]Программы Prolog описывают отношения, определяемые с помощью предложений. Чистый Prolog ограничен предложениями Хорна . Для определения программ Prolog используются два типа предложений Хорна: правила и факты. Правило имеет вид
Голова :- Тело .
и читается как "Head is true if Body is true". Тело правила состоит из вызовов предикатов, которые называются целями правила . Встроенный логический оператор (имеется в виду оператор,/2
арности 2 с именем ) обозначает конъюнкцию целей и обозначает дизъюнкцию . Конъюнкции и дизъюнкции могут появляться только в теле, но не в заголовке правила.,
;/2
Предложения с пустыми телами называются фактами . Пример факта:
человек ( сократ ).
что эквивалентно правилу:
человек ( сократ ) :- правда .
Встроенный предикат true/0
всегда истинен.
Учитывая вышеизложенный факт, можно задать вопрос:
Сократ — человек?
?- человек ( сократ ). Да
что такое люди?
?- человек ( X ). X = Сократ
Предложения с телом называются правилами . Пример правила:
смертный ( X ) :- человек ( X ).
А если мы добавим это правило и спросим, какие вещи смертны?
?- смертный ( X ). X = Сократ
Предикат (или определение процедуры ) — это набор предложений, заголовки которых имеют одинаковое имя и арность. Мы используем обозначение имя/арность для обозначения предикатов. Логическая программа — это набор предикатов. Например, следующая программа на Прологе, которая определяет некоторые семейные отношения, имеет четыре предиката:
мать_ребенок ( труда , салли ).отец_ребенок ( том , салли ). отец_ребенок ( том , эрика ). отец_ребенок ( майк , том ).брат/сестра ( X , Y ) :- родитель_ребенок ( Z , X ), родитель_ребенок ( Z , Y ).родитель_ребенок ( X , Y ) :- отец_ребенок ( X , Y ). родитель_ребенок ( X , Y ) :- мать_ребенок ( X , Y ).
Предикат father_child/2
состоит из трех предложений, каждое из которых является фактом, а предикат parent_child/2
состоит из двух предложений, каждое из которых является правилом.
Из-за реляционной природы многих встроенных предикатов их обычно можно использовать в нескольких направлениях. Например, length/2
можно использовать для определения длины списка ( length(List, L)
, задан список List
), а также для генерации скелета списка заданной длины ( length(X, 5)
), а также для генерации скелетов списка и их длин вместе ( length(X, L)
). Аналогично, append/3
можно использовать как для сложения двух списков ( append(ListA, ListB, X)
заданных списков ListA
и ListB
), так и для разделения заданного списка на части ( append(X, Y, List)
, заданного списка List
). По этой причине для многих программ Prolog достаточно сравнительно небольшого набора библиотечных предикатов.
Как язык общего назначения, Prolog также предоставляет различные встроенные предикаты для выполнения рутинных действий, таких как ввод/вывод , использование графики и иное взаимодействие с операционной системой. Эти предикаты не имеют реляционного значения и полезны только для побочных эффектов, которые они проявляют в системе. Например, предикат write/1
отображает термин на экране.
Итеративные алгоритмы могут быть реализованы с помощью рекурсивных предикатов. [14]
Рассмотрим parent_child/2
предикат, определенный в программе семейного отношения выше. Следующая программа Prolog определяет отношение предка :
предок ( X , Y ) :- родитель_ребенок ( X , Y ). предок ( X , Y ) :- родитель_ребенок ( X , Z ), предок ( Z , Y ).
Он выражает, что X является предком Y, если X является родителем Y или X является родителем предка Y. Он рекурсивен, поскольку определяется в терминах самого себя ( ancestor/2
в теле второго предложения есть вызов предиката).
Выполнение программы Prolog инициируется отправкой пользователем единственной цели, называемой запросом. Логически, движок Prolog пытается найти опровержение резолюции отрицаемого запроса. Метод резолюции, используемый Prolog, называется разрешением SLD . Если отрицаемый запрос может быть опровергнут, то из этого следует, что запрос с соответствующими привязками переменных является логическим следствием программы. В этом случае все сгенерированные привязки переменных сообщаются пользователю, и запрос считается успешным. С точки зрения эксплуатации, стратегию выполнения Prolog можно рассматривать как обобщение вызовов функций в других языках, одно отличие состоит в том, что несколько заголовков предложений могут соответствовать данному вызову. В этом случае система создает точку выбора, объединяет цель с заголовком предложения первой альтернативы и продолжает с целями этой первой альтернативы. Если какая-либо цель не достигается в ходе выполнения программы, все привязки переменных, которые были сделаны с момента создания последней точки выбора, отменяются, и выполнение продолжается со следующей альтернативой этой точки выбора. Такая стратегия выполнения называется хронологическим возвратом . Например, учитывая программу семейных отношений, определенную выше, следующий запрос будет оценен как истинный:
?- брат ( Салли , Эрика ). Да
Это получается следующим образом: изначально единственным соответствующим заголовком предложения для запроса sibling(sally, erica)
является первый, поэтому доказательство запроса эквивалентно доказательству тела этого предложения с соответствующими переменными связываниями на месте, т. е. конъюнкцией (parent_child(Z,sally), parent_child(Z,erica))
. Следующая цель, которую нужно доказать, — самая левая цель этого соединения, т. е. parent_child(Z, sally)
. Два заголовка предложения соответствуют этой цели. Система создает точку выбора и пробует первую альтернативу, тело которой — father_child(Z, sally)
. Эта цель может быть доказана с помощью факта father_child(tom, sally)
, поэтому привязка Z = tom
генерируется, а следующей целью, которую нужно доказать, является вторая часть вышеуказанного соединения: parent_child(tom, erica)
. Опять же, это может быть доказано соответствующим фактом. Поскольку все цели могут быть доказаны, запрос выполняется успешно. Поскольку запрос не содержал переменных, никакие привязки не сообщаются пользователю. Запрос с переменными, например:
?- father_child ( Отец , Ребенок ).
перечисляет все допустимые ответы при возврате назад.
Обратите внимание, что с кодом, указанным выше, запрос ?- sibling(sally, sally).
также выполняется успешно. При желании можно вставить дополнительные цели для описания соответствующих ограничений.
Встроенный предикат Пролога \+/1
предоставляет отрицание как неудачу , что допускает немонотонное рассуждение. Цель \+ illegal(X)
в правиле
законно ( X ) :- \+ незаконно ( X ).
оценивается следующим образом: Prolog пытается доказать illegal(X)
. Если доказательство для этой цели может быть найдено, исходная цель (т. е. \+ illegal(X)
) терпит неудачу. Если доказательство не может быть найдено, исходная цель достигает цели. Поэтому \+/1
префиксный оператор называется «недоказуемым» оператором, поскольку запрос ?- \+ Goal.
выполняется успешно, если Цель не доказуема. Этот вид отрицания является обоснованным , если его аргумент является «основным» (т. е. не содержит переменных). Обоснованность теряется, если аргумент содержит переменные, а процедура доказательства завершена. В частности, запрос ?- legal(X).
теперь не может использоваться для перечисления всех допустимых вещей.
В Prolog загрузка кода называется консультированием . Prolog можно использовать интерактивно, вводя запросы в командной строке Prolog ?-
. Если решения нет, Prolog пишет no
. Если решение существует, оно выводится на экран. Если существует несколько решений запроса, их можно запросить, введя точку с запятой ;
. Существуют рекомендации по хорошей практике программирования для повышения эффективности кода, читаемости и удобства обслуживания. [15]
Ниже приведены несколько примеров программ, написанных на Прологе.
Пример простого запроса на нескольких популярных диалектах Пролога:
Это сравнение показывает, что приглашение («?-» против «| ?-») и статус разрешения («истина» против «да», «ложь» против «нет») могут различаться в разных реализациях Prolog.
Любое вычисление может быть выражено декларативно как последовательность переходов состояний. Например, оптимизирующий компилятор с тремя проходами оптимизации может быть реализован как отношение между исходной программой и ее оптимизированной формой:
program_optimized ( Prog0 , Prog ) :- проход_оптимизации_1 ( Prog0 , Prog1 ), проход_оптимизации_2 ( Prog1 , Prog2 ), проход_оптимизации_3 ( Prog2 , Prog ).
или эквивалентно с использованием нотации DCG :
программа_оптимизирована --> проход_оптимизации_1 , проход_оптимизации_2 , проход_оптимизации_3 .
Алгоритм быстрой сортировки, связывающий список с его отсортированной версией:
раздел ([], _ , [], []). раздел ([ X | Xs ], Pivot , Smalls , Bigs ) :- ( X @< Pivot -> Smalls = [ X | Rest ], раздел ( Xs , Pivot , Rest , Bigs ) ; Bigs = [ X | Rest ], раздел ( Xs , Pivot , Smalls , Rest ) ).быстрая сортировка ([]) --> []. быстрая сортировка ([ X | Xs ]) --> { partition ( Xs , X , Меньше , Больше ) }, быстрая сортировка ( Меньше ), [ X ], быстрая сортировка ( Больше ).
Шаблон проектирования — это общее повторно используемое решение часто встречающейся проблемы в разработке программного обеспечения . Некоторые шаблоны проектирования в Prolog — это скелеты, методы, [16] [17] клише, [18] схемы программ, [19] схемы описания логики, [20] и программирование высшего порядка . [21]
Предикат высшего порядка — это предикат, который принимает один или несколько других предикатов в качестве аргументов. Хотя поддержка программирования высшего порядка выводит Prolog за пределы области логики первого порядка, которая не допускает квантификации по предикатам, [22] ISO Prolog теперь имеет некоторые встроенные предикаты высшего порядка, такие как call/1
, call/2
, call/3
, findall/3
, setof/3
, и bagof/3
. [23] Кроме того, поскольку произвольные цели Prolog могут быть построены и оценены во время выполнения, легко писать предикаты высшего порядка, такие как maplist/2
, который применяет произвольный предикат к каждому члену заданного списка, и sublist/3
, который фильтрует элементы, удовлетворяющие заданному предикату, также допуская каррирование . [21]
Для преобразования решений из временного представления (замены ответов при возврате) в пространственное представление (термины) в Prolog есть различные предикаты всех решений, которые собирают все замены ответов заданного запроса в список. Это можно использовать для понимания списка . Например, совершенные числа равны сумме своих собственных делителей:
perfect ( N ) :- между ( 1 , inf , N ), U is N // 2 , findall ( D , ( между ( 1 , U , D ), N mod D =:= 0 ), Ds ), sumlist ( Ds , N ).
Это можно использовать для перечисления совершенных чисел и для проверки того, является ли число совершенным.
В качестве другого примера предикат maplist
применяет предикат P
ко всем соответствующим позициям в паре списков:
maplist ( _ , [], []). maplist ( P , [ X | Xs ], [ Y | Ys ]) :- вызов ( P , X , Y ), maplist ( P , Xs , Ys ).
Когда P
— предикат X
, который для всех P(X,Y)
объединяется Y
с одним уникальным значением, maplist(P, Xs, Ys)
что эквивалентно применению функции map в функциональном программировании как Ys = map(Function, Xs)
.
Стиль программирования высшего порядка в Prolog впервые был применен в HiLog и λProlog .
Для программирования в больших масштабах Prolog предоставляет модульную систему , которая находится в стандарте ISO. [24] Однако, хотя большинство систем Prolog поддерживают структурирование кода в модули, практически ни одна реализация не придерживается модульной части стандарта ISO. Вместо этого большинство систем Prolog решили поддерживать как фактический стандарт модулей модульную систему Quintus / SICStus . Однако дополнительные удобные предикаты, касающиеся модулей, предоставляются только некоторыми реализациями и часто имеют тонкие различия в своей семантике. [25]
Некоторые системы решили реализовать концепции модулей как компиляцию «из источника в источник» в базовый ISO Prolog, как в случае Logtalk . [26] GNU Prolog изначально отклонился от модулей ISO, выбрав вместо этого контекстное логическое программирование, в котором загрузка и выгрузка единиц (модулей) может осуществляться динамически. [27] Ciao разработал строгую модульную систему, которая, будучи в основном совместимой с фактическим стандартом, используемым другими системами Prolog, поддается точному статическому анализу, поддерживает сокрытие терминов и облегчает программирование в целом. [28] XSB использует другой подход и предлагает модульную систему на основе атомов . [29] Последние две системы Prolog позволяют контролировать видимость терминов в дополнение к видимости предикатов. [25]
Существует специальная нотация, называемая грамматиками определенных предложений (DCG). Правило, определенное с помощью -->/2
вместо , :-/2
расширяется препроцессором ( expand_term/2
, средство, аналогичное макросам в других языках) в соответствии с несколькими простыми правилами переписывания, что приводит к обычным предложениям Prolog. В частности, переписывание снабжает предикат двумя дополнительными аргументами, которые могут использоваться для неявного потокового состояния вокруг, [ необходимо разъяснение ] аналогично монадам в других языках. DCG часто используются для написания парсеров или генераторов списков, поскольку они также предоставляют удобный интерфейс для списков различий.
Prolog — гомоиконический язык, предоставляющий множество возможностей для рефлексивного программирования (рефлексии). Его неявная стратегия выполнения позволяет написать краткий метациклический оценщик (также называемый метаинтерпретатором ) для чистого кода Prolog:
решить ( истина ). решить (( Подцель1 , Подцель2 )) :- решить ( Подцель1 ), решить ( Подцель2 ). решить ( Голова ) :- предложение ( Голова , Тело ), решить ( Тело ).
где true
представляет собой пустой союз и clause(Head, Body)
объединяется с предложениями в базе данных формы Head :- Body
.
Поскольку программы Prolog сами по себе являются последовательностями терминов Prolog ( :-/2
является инфиксным оператором ), которые легко читаются и проверяются с помощью встроенных механизмов (например, read/1
), можно писать настраиваемые интерпретаторы, которые дополняют Prolog специфичными для предметной области функциями. Например, Стерлинг и Шапиро представляют метаинтерпретатор, который выполняет рассуждения с неопределенностью, воспроизведенный здесь с небольшими изменениями: [30] : 330
решить ( истина , 1 ) :- !. решить (( Подцель1 , Подцель2 ), Определенность ) :- !, решить ( Подцель1 , Определенность1 ), решить ( Подцель2 , Определенность2 ), Определенность равна мин ( Определенность1 , Определенность2 ). решить ( Цель , 1 ) :- встроенная ( Цель ), !, Цель . решить ( Голова , Определенность ) :- clause_cf ( Голова , Тело , Определенность1 ), решить ( Тело , Определенность2 ), Определенность равна Определенность1 * Определенность2 .
Этот интерпретатор использует таблицу встроенных предикатов Пролога вида [30] : 327
встроенный ( A is B ). встроенный ( read ( X )). % и т. д.
и предложения, представленные как clause_cf(Head, Body, Certainty)
. Учитывая это, его можно вызвать как solve(Goal, Certainty)
для выполнения Goal
и получения меры уверенности относительно результата.
Чистый Пролог основан на подмножестве логики предикатов первого порядка , Хорновских предложениях , которые являются полными по Тьюрингу . Полноту по Тьюрингу Пролога можно показать, используя его для моделирования машины Тьюринга:
Тьюринг ( Tape0 , Tape ) :- выполнить ( q0 , [], Ls , Tape0 , Rs ), обратить ( Ls , Ls1 ), добавить ( Ls1 , Rs , Tape ).выполнить ( qf , Ls , Ls , Rs , Rs ) :- !. выполнить ( Q0 , Ls0 , Ls , Rs0 , Rs ) :- символ ( Rs0 , Sym , RsRest ), один раз ( правило ( Q0 , Sym , Q1 , NewSym , Действие )), действие ( Действие , Ls0 , Ls1 , [ NewSym | RsRest ], Rs1 ), выполнить ( Q1 , Ls1 , Ls , Rs1 , Rs ).символ ([], b , []). символ ([ Sym | Rs ], Sym , Rs ).действие ( влево , Ls0 , Ls , Rs0 , Rs ) :- влево ( Ls0 , Ls , Rs0 , Rs ). действие ( остаться , Ls , Ls , Rs , Rs ). действие ( вправо , Ls0 , [ Sym | Ls0 ], [ Sym | Rs ], Rs ).слева ([], [], Rs0 , [ b | Rs0 ]). слева ([ L | Ls ], Ls , Rs , [ L | Rs ]).
Простой пример машины Тьюринга определяется следующими фактами:
правило ( q0 , 1 , q0 , 1 , вправо ). правило ( q0 , b , qf , 1 , остаться ).
Эта машина выполняет приращение на единицу числа в унарной кодировке: она проходит по любому количеству ячеек «1» и добавляет дополнительную «1» в конец. Пример запроса и результат:
?- Тьюринг ([ 1 , 1 , 1 ], Ts ). Ts = [ 1 , 1 , 1 , 1 ] ;
Это иллюстрирует, как любое вычисление может быть декларативно выражено в виде последовательности переходов состояний, реализованной в Прологе как отношение между последовательными интересующими состояниями.
Технический стандарт Prolog Международной организации по стандартизации (ISO) состоит из двух частей. ISO/IEC 13211-1, [23] [31], опубликованный в 1995 году, направлен на стандартизацию существующих практик многих реализаций основных элементов Prolog. Он прояснил аспекты языка, которые ранее были неоднозначными, и привел к переносимым программам. Существует три исправления: Cor.1:2007, [32] Cor.2:2012, [33] и Cor.3:2017. [34] ISO/IEC 13211-2, [23], опубликованный в 2000 году, добавляет поддержку модулей в стандарт. Стандарт поддерживается рабочей группой ISO/IEC JTC1 / SC22 /WG17 [35] . ANSI X3J17 является технической консультативной группой США по стандарту. [36]
Для эффективности код Prolog обычно компилируется в абстрактный машинный код, часто на который влияет набор инструкций Warren Abstract Machine (WAM) на основе регистров. [37] Некоторые реализации используют абстрактную интерпретацию для получения информации о типе и режиме предикатов во время компиляции или компилируют в реальный машинный код для высокой производительности. [38] Разработка эффективных методов реализации для кода Prolog является областью активных исследований в сообществе логического программирования, и в некоторых реализациях используются различные другие методы выполнения. К ним относятся бинаризация предложений и виртуальные машины на основе стека . [ требуется ссылка ]
Системы Prolog обычно реализуют известный метод оптимизации, называемый оптимизацией хвостового вызова (TCO) для детерминированных предикатов, демонстрирующих хвостовую рекурсию или, в более общем смысле, хвостовые вызовы: кадр стека предложения отбрасывается перед выполнением вызова в хвостовой позиции. Таким образом, детерминированные хвостовые рекурсивные предикаты выполняются с постоянным стековым пространством, как циклы в других языках.
Поиск предложений, которые унифицируются с термином в запросе, линейный по количеству предложений. Индексация терминов использует структуру данных , которая позволяет выполнять сублинейный поиск. [39] Индексация влияет только на производительность программы, но не на семантику. Большинство Prolog используют индексацию только для первого термина, поскольку индексация для всех терминов является дорогостоящей, но методы, основанные на закодированных в полях словах или наложенных кодовых словах, обеспечивают быструю индексацию по всему запросу и заголовку. [40] [41]
Некоторые системы Prolog, такие как WIN-PROLOG и SWI-Prolog, теперь реализуют хеширование, чтобы помочь более эффективно обрабатывать большие наборы данных. Это, как правило, дает очень большой прирост производительности при работе с большими корпусами, такими как WordNet .
Некоторые системы Prolog ( B-Prolog , XSB , SWI-Prolog , YAP и Ciao ) реализуют метод мемоизации , называемый табулированием , который освобождает пользователя от необходимости вручную сохранять промежуточные результаты. Табулирование — это компромисс между пространством и временем ; время выполнения можно сократить, используя больше памяти для хранения промежуточных результатов: [42] [43]
Подцели, обнаруженные при оценке запроса, сохраняются в таблице вместе с ответами на эти подцели. Если подцель обнаружена повторно, оценка повторно использует информацию из таблицы, а не повторно выполняет разрешение против положений программы. [44]
Таблирование может быть расширено в различных направлениях. Оно может поддерживать рекурсивные предикаты через разрешение SLG или линейное табулирование. В многопоточной системе Prolog результаты табулирования могут быть сохранены в тайне для потока или совместно использоваться всеми потоками. А в инкрементальном табулировании табулирование может реагировать на изменения.
В ходе проекта Fifth Generation Computer Systems были предприняты попытки реализовать Prolog на аппаратном уровне с целью достижения более быстрого выполнения с помощью специализированных архитектур. [45] [46] [47] Кроме того, Prolog обладает рядом свойств, которые могут позволить ускориться за счет параллельного выполнения. [48] Более поздний подход заключался в компиляции ограниченных программ Prolog в программируемую пользователем вентильную матрицу . [49] Однако быстрый прогресс в области аппаратного обеспечения общего назначения постоянно обгоняет более специализированные архитектуры.
В 1982 году компьютеры работали со скоростью около 10 000–100 000 LIPS [логических выводов в секунду]. FGCS планировала производить компьютеры, работающие со скоростью от 0,1 до 1 GLIPS. [50] По оценкам Института компьютерных технологий нового поколения, 1 LIP требовал около 100 операций на обычном компьютере. План состоял в том, чтобы в конце проекта (в 1992 году) создать машину с 1000 процессорами, достигающую 1 GLIPS, что подразумевает не менее 1 MLIPS на процессор. [51]
Sega реализовала Prolog для использования с Sega AI Computer, выпущенным для японского рынка в 1986 году. Prolog использовался для чтения естественного языкового ввода на японском языке с помощью сенсорной панели . [52]
Хотя Prolog широко используется в исследованиях и образовании, [53] Prolog и другие языки логического программирования не оказали значительного влияния на компьютерную индустрию в целом. [54] Большинство приложений невелики по промышленным стандартам, и лишь немногие превышают 100 000 строк кода. [54] [55] Программирование в больших масштабах считается сложным, поскольку не все компиляторы Prolog поддерживают модули, и существуют проблемы совместимости между модульными системами основных компиляторов Prolog. [26] Переносимость кода Prolog между реализациями также была проблемой, но разработки с 2007 года означают: «переносимость в пределах семейства реализаций Prolog, полученных от Edinburgh/Quintus, достаточно хороша, чтобы обеспечить поддержку переносимых реальных приложений». [56]
Программное обеспечение, разработанное на Prolog, критиковалось за высокую производительность по сравнению с традиционными языками программирования. В частности, недетерминированная стратегия оценки Prolog может быть проблематичной при программировании детерминированных вычислений или даже при использовании "безразличного недетерминизма" (когда делается единственный выбор вместо возврата ко всем возможностям). Для достижения желаемой производительности, возможно, придется использовать сокращения и другие языковые конструкции, что уничтожит одну из главных привлекательных сторон Prolog — возможность запускать программы "вперед и назад". [57]
Prolog не является чисто декларативным: из-за конструкций, таких как оператор cut , для его понимания требуется процедурное чтение программы Prolog. [58] Порядок предложений в программе Prolog имеет значение, поскольку от него зависит стратегия выполнения языка. [59] Другие языки логического программирования, такие как Datalog , являются действительно декларативными, но ограничивают язык. В результате многие практические программы Prolog написаны так, чтобы соответствовать порядку поиска в глубину Prolog , а не как чисто декларативные логические программы. [57]
Различные реализации были разработаны на основе Prolog для расширения возможностей логического программирования во многих направлениях. Они включают типы , режимы, программирование логики ограничений (CLP), объектно-ориентированное логическое программирование (OOLP), параллелизм, линейную логику (LLP), функциональные и более высокого порядка возможности логического программирования, а также взаимодействие с базами знаний :
Prolog — нетипизированный язык. Попытки ввести и расширить Prolog с помощью типов начались в 1980-х годах, [60] [61] и продолжаются по состоянию на 2008 год [обновлять]. [62] Информация о типах полезна не только для безопасности типов , но и для рассуждений о программах Prolog. [63]
Синтаксис Prolog не определяет, какие аргументы предиката являются входными, а какие — выходными. [64] Однако эта информация важна, и ее рекомендуется включать в комментарии. [65] Режимы предоставляют ценную информацию при рассуждениях о программах Prolog [63] и также могут использоваться для ускорения выполнения. [66]
Программирование логики ограничений расширяет Prolog, включая концепции из удовлетворения ограничений . [67] [68] Программа логики ограничений допускает ограничения в тексте предложений, например: A(X,Y) :- X+Y>0.
Она подходит для крупномасштабных задач комбинаторной оптимизации [69] и, таким образом, полезна для приложений в промышленных условиях, таких как автоматизированное составление расписаний и производственное планирование . Большинство систем Prolog поставляются по крайней мере с одним решателем ограничений для конечных областей, а часто также с решателями для других областей, таких как рациональные числа .
Flora-2 — это объектно-ориентированная система представления знаний и рассуждений, основанная на F-логике и включающая HiLog , транзакционную логику и отменяемые рассуждения .
Logtalk — это объектно-ориентированный язык логического программирования, который может использовать большинство реализаций Prolog в качестве внутреннего компилятора. Как многопарадигменный язык, он включает поддержку как прототипов, так и классов.
Oblog — небольшое, переносимое, объектно-ориентированное расширение Prolog, разработанное Маргарет Макдугалл из EdCAAD, Эдинбургского университета.
Objlog — язык на основе фреймов, объединяющий объекты и Prolog II из CNRS, Марсель, Франция.
Prolog++ был разработан Logic Programming Associates и впервые выпущен в 1989 году для ПК с MS-DOS. Была добавлена поддержка других платформ, и вторая версия была выпущена в 1995 году. Книга о Prolog++ Криса Мосса была опубликована Addison-Wesley в 1994 году.
Visual Prolog — это многопарадигмальный язык с интерфейсами, классами, реализациями и объектными выражениями.
Системы Пролога, предоставляющие графическую библиотеку : SWI-Prolog , [70] Visual Prolog , WIN-PROLOG и B-Prolog .
Prolog-MPI — это расширение SWI-Prolog с открытым исходным кодом для распределенных вычислений через интерфейс передачи сообщений . [71] Также существуют различные параллельные языки программирования Prolog. [72]
Некоторые реализации Prolog, в частности Visual Prolog , SWI-Prolog и Ciao , поддерживают серверное веб-программирование с поддержкой веб-протоколов, HTML и XML . [73] Существуют также расширения для поддержки семантических веб- форматов, таких как Resource Description Framework (RDF) и Web Ontology Language (OWL). [74] [75] Prolog также был предложен в качестве клиентского языка. [76] Кроме того, Visual Prolog поддерживает JSON-RPC и Websockets .
Cedar Архивировано 2010-10-19 в Wayback Machine — бесплатный и базовый интерпретатор Prolog. Начиная с версии 4 и выше Cedar поддерживает FCA (Flash Cedar App). Это обеспечивает новую платформу для программирования на Prolog через ActionScript .
Существуют фреймворки, которые могут стать связующим звеном между Prolog и другими языками:
Название Prolog было выбрано Филиппом Русселем по предложению его жены в качестве сокращения от programmation en logique ( по-французски — программирование в логике ). [78] Он был создан около 1972 года Аленом Кольмерауэром и Филиппом Русселем на основе процедурной интерпретации предложений Хорна Робертом Ковальски . Это было отчасти мотивировано желанием примирить использование логики как декларативного языка представления знаний с процедурным представлением знаний, которое было популярно в Северной Америке в конце 1960-х и начале 1970-х годов. По словам Роберта Ковальски , первая система Prolog была разработана в 1972 году Кольмерауэром и Филиппом Русселем. [79] [80] [81] Первой реализацией Prolog был интерпретатор, написанный на Фортране Жераром Баттани и Анри Мелони. Дэвид HD Уоррен взял этот интерпретатор в Эдинбургский университет и там реализовал альтернативный фронтенд, который стал определять синтаксис «Эдинбургского Пролога», используемый большинством современных реализаций. Уоррен также реализовал первый компилятор для Пролога, создав влиятельный DEC-10 Prolog в сотрудничестве с Фернандо Перейрой. Позже Уоррен обобщил идеи, лежащие в основе DEC-10 Prolog, чтобы создать абстрактную машину Уоррена .
Европейские исследователи искусственного интеллекта отдавали предпочтение Prolog, в то время как американцы отдавали предпочтение Lisp , что, как сообщается, вызвало множество националистических дебатов о достоинствах языков. [82] Большая часть современного развития Prolog произошла под влиянием проекта Fifth Generation Computer Systems (FGCS), в рамках которого была разработана версия Prolog под названием Kernel Language для своей первой операционной системы .
Первоначально Pure Prolog был ограничен использованием доказательной машины теоремы о разрешении с предложениями Хорна следующего вида:
Н :- В 1 , ..., В н .
Применение доказывающего теоремы устройства рассматривает такие предложения как процедуры:
чтобы показать/решить H, показать/решить B 1 и ... и B n .
Однако вскоре чистый Пролог был расширен, включив в него отрицание как неудачу , в котором отрицательные условия формы not(B i ) демонстрируются посредством попыток и неудач решения соответствующих положительных условий B i .
Последующие расширения Prolog, выполненные первоначальной командой, внесли в реализации возможности программирования логики ограничений .
Prolog использовался в Watson . Watson использует программное обеспечение DeepQA от IBM и фреймворк Apache UIMA (Unstructured Information Management Architecture). Система была написана на разных языках, включая Java, C++ и Prolog, и работает на операционной системе SUSE Linux Enterprise Server 11 с использованием фреймворка Apache Hadoop для обеспечения распределенных вычислений. Prolog используется для сопоставления с образцом по деревьям синтаксического анализа естественного языка. Разработчики заявили: «Нам требовался язык, на котором мы могли бы удобно выражать правила сопоставления с образцом по деревьям синтаксического анализа и другим аннотациям (например, результаты распознавания именованных сущностей), и технология, которая могла бы выполнять эти правила очень эффективно. Мы обнаружили, что Prolog был идеальным выбором для языка из-за его простоты и выразительности ». [12] Prolog используется в платформе разработки Low-Code Development Platform GeneXus , которая ориентирована на ИИ. [ требуется цитата ] База данных графов с открытым исходным кодом TerminusDB реализована в Prolog. [83] TerminusDB предназначена для совместного создания и курирования графов знаний .