Prolog (PROgramming in LOGic) - язык программирования специального назначения для генерирования умозаключений в соответствии с правилами формальной логики (дизъюнктов Хорна) на основе вводимых утверждений.
Историческая справка о языке Prolog
Проект зародился во Франции в начале 1970-х гг. В Марсельском университете группой ученых под руководством Алена Колмероэ (Alain Colmerauer) предпринималась одна из первых попыток создания искусственного интеллекта на основе бурно развивавшейся в предыдущее десятилетие теории автоматического доказательства. В основе ее лежал последовательный обход узлов графа, к которому сводились полученные от пользователя условия. Задача в рамках этой теории решалась не полностью, а за счет сведения теоремы к нескольким хорошо алгоритмизируемым частным случаям. Тем не менее, этого оказалось вполне достаточно для практического применения.
Первый релиз Prolog увидел свет в 1972 г. Дальнейшее развитие языка было неравномерным. Иногда оно почти совсем прекращалось, иногда происходили всплески интереса к этому языку, как, например, в Японии 1980-х гг., где его пытались задействовать в рамках национальной программы компьютеризации. Prolog был достаточно известен в СССР, где изучался в рамках вузовских и школьных курсов информатики, а также логики.
В наши дни (конец 2010-х гг.) Prolog остается актуальным в связи с новым всплеском интереса к искусственному интеллекту. Выходят свежие версии реализаций языка для различных платформ, в том числе и распространяющиеся под свободными лицензиями. Prolog стандартизирован в рамках международной системы ISO (1996 г.).
Среди коммерческих реализаций интерес представляют CProlog, Prolog–2, Тurbo Prolog, Visual Prolog и др.
Prolog дал толчок развитию логики ограничений (Constraint Logic Programming, CLP). Эта методика позволяет эффективно решать задачи, связанные с логистикой, планированием, материально-техническим снабжением.
Программирование на Prolog
Факты и правила
Специфика программы на Prolog заключается в том, что его инструкции формируют базу данных об объектах (факты), между которыми устанавливаются некоторые отношения (правила). Примеры описания фактов:
animal(dog). /* Собака - это животное*/
bird(hen). /* Курица - это птица.*/
vehicle(motorbike). /* Мотоцикл - средство передвижения.*/
Факты могут включать в себя несколько аргументов:
likes(john,apples). /* Джон любит яблоки.*/
Правила описывают взаимоотношения между объектами. Например, некто Z
является дедушкой X
, если он является родителем родителя X
(родитель объекта X
обозначен здесь как Y
).
grandparent(X,Z) :- parent(X,Y) , parent(Y,Z).
Такие выражения могут быть рекурсивными. Например, можно заменить в предыдущем выражении слово "дедушка" на слово "предок":
ancestor(X,Y) :- parent(Z,Y) , ancestor(X,Z).
Работая с Prolog, программист не заботится о том, как осуществляются взаимосвязи внутри базы данных. Эту задачу выполняет сам язык. Следует лишь четко формулировать факты и правила.
Связь Prolog с предикативной логикой
Prolog разрабатывался на базе предикативной логики (т.н. логики первого порядка). Этот раздел математики исследует высказывания относительно переменных, функций и суждений. Например, вышеописанные взаимоотношения между X
, Y
и Z
(внуком (сыном), отцом и дедушкой)
grandparent(X,Z) :- parent(X,Y) , parent(Y,Z).
в терминах предикативной логики можно описать как
$P(x, y) \wedge P(y, z) \implies G(x, z)$
Запросы
Конечной целью Prolog является получение ответов на запросы, которые формируются с помощью синтаксиса языка. Создадим небольшую базу данных:
parent(hank,ben).
parent(hank,denise).
parent(irene,ben).
parent(irene,denise).
parent(alice,carl).
parent(ben,carl).
parent(denise,frank).
parent(denise,gary).
parent(earl,frank).
parent(earl,gary).
grandparent(X,Z) :- parent(X,Y) , parent(Y,Z).
ancestor(X,Y) :- parent(X,Y).
ancestor(X,Y) :- parent(Z,Y) , ancestor(X,Z).
Это часть программы на языке Prolog. Ее можно ввести в интерпретатор в интерактивном режиме построчно или сохранить в файл (например, family.pro
) и указать при запуске интерпретатора в качестве аргумента:
gprolog family.pro
Теперь можно задавать вопросы:
| ?- parent(hank,denise). /* Является ли Хэнк родителем Дениса? */
yes
| ?- parent(denise,hank). /* Является ли Денис родителем Хэнка? */
no
При описании сложных взаимоотношений могут возникать логические ошибки, причины которых трудно выявить. В таких случаях можно применить трассировку, которая покажет все известные в данной программе взаимоотношения между исследуемыми фактами, например:
Рисунок 1. Трассировка программы на Prolog. Автор24 — интернет-биржа студенческих работ