Добрый день, мальчики и девочки, мужчины и женщины, дамы и господа.
Если Вы в первый раз столкнулись с необходимостью написать программу на Prolog, то это статья для Вас.
Prolog – это язык логического программирования, который отличается от стандартных языков императивного программирования (Pascal, Basic, С и т.д.), но он не так сложен в понимании, как может сначала показаться.
Первым делом нужно решить, какую систему логического программирования Вы будете использовать. Самая простая, созданная еще в далеких 80х, является TurboProlog.
Она похожа, например, на TurboPascal, TurboBasic. И если Вы встречались с такими компиляторами, то особых затруднений с TurboProlog не возникнет. Есть, конечно, более современные компиляторы, которые Вы можете использовать (Visual Prolog, Amzi! Prolog, ALS Prolog).
TurboProlog не запустится на ОС 64-bit. Поэтому придется искать альтернативные варианты.
Качаем нашу программу (например здесь ) и запускаем PROLOG.EXE.
Конечно же, забываем про мышь, всё управление на клавиатуре. При нажатии «Esc» происходит переключение в меню. Сначала у нас загружается пустой файл WORK.PRO.
Выберем Files -> Write to и тем самым создадим новый файл со своим именем, например Prog.pro. Сохраняется файл в данном случае в той же папке, где находится программа TurboProlog, иначе нужно прописывать полный путь.
Для перехода в режим редактирования в меню выбираем Edit, «Enter», и можем творить.
Разбираем основы Prolog
Основные секции программы Prolog это — PREDICATES и CLAUSES.
Так же есть директивы:
CONSTANTS — раздел описания констант;
DOMAINS — раздел описания доменов;
DATABASE — раздел описания предикатов внутренней базы данных;
GOAL — раздел описания внутренней цели.
В секции DOMAINS объявляются домены, они подобны типам данных. Используется для удобства, при описании разных объектов с одинаковыми типами. Этот раздел можно опустить.
Стандартные типы Prolog:
char — символ
integer — целое число
real — действительное число
string — последовательность символов типа char, которая заключена в кавычки
symbol — последовательность букв латинского алфавита, цифр и знаков подчеркивания, которая начинается со строчной буквы или заключена в кавычки.
Формат объявлений:
<имя домена1>,…,<имя домена n> = <стандартный тип 1> <имя домена2> = <стандартный тип 2 >
Например:
name = symbol count = integer price = integer
В секции PREDICATES перечисляются объявления предикатов с их типами. По сути это похоже на прототипы функций в императивных языках. Мы задаем шаблоны для последующего определения фактов (истинных утверждений) и правил, то есть процедур над переменными.
Формат объявлений:
<имя предиката1> (<домен 1 >, …, <домен n >) <имя предиката2> (<домен 1 >, …, <домен n >)
Пример:
sum(integer,integer) book(name, count, price) search(name) search(price, price)
Здесь можно увидеть удобство использования ранее объявленных доменов, все параметры наглядны. Без использования доменов выглядело бы так:
book(symbol, integer, integer) search(symbol) search(integer, integer)
Предикат может быть без перечисления доменов, например:
all_info
Заметьте, никаких символов в конце инструкций нет.
В секции CLAUSES помещаются факты и правила. Каждое предложение должно заканчиваться точкой.
Сначала мы задаем известные истинные утверждение.
Формат объявлений:
<имя предиката>(<объект 1>, …, <объект 2>).
Например предложение “Книга «Война и мир» имеется в 3 экземплярах, стоимость одной книги 50” , исходя из того, что есть предикат book(name, count, price)
факт будет выглядеть так:
book("War and peace", 3, 50).
После задания фактов, задаем правила определения истинности задаваемого нами предложения, или просто последовательность каких-то действий.
Формат объявлений:
<имя предиката>(<переменная 1>, …, <переменная 2>) :– <действия>.
Например, поиск книг по имени:
search(X):- book(X,C,P), write("`", X, "`", " count: ", C, " price: ", P), nl.
X – приходящая переменная с типом name (symbol). С, P – локальные переменные, nl – переход на следующую строку.
Как происходит работа программы?
При задании целей используется директива GOAL, или если ее нет, цели задаются в диалоговом окне при запуске программы.
Например, задавая цель: search(“War and peace”) , происходит последовательная проверка по условиям, то есть всё, что стоит после CLAUSES.
- book(«War and peace», 3, 50). – не подходит
- search(X):- book(X,C,P), write(«`», X, «`», » count: «, C, » price: «, P), nl. – подходит.
- Вызывается book(«War and peace»,C,P), и заново происходит поиск с начала.
- book(«War and peace», 3, 50). – подходит
- В С попадает 3, а в P – 50.
- Наш вывод: ‘War and peace’ count: 3, price: 5
Вернемся к TurboProlog.
Напишем такую программу.
PREDICATES bird(symbol) parent(symbol,symbol) CLAUSES % Воробей – это птица. bird(sparrow). %X – это птица, если у него есть родитель, который является птицей. bird(X):–parent(Y,X), bird(Y). % Воробей – родитель птенца. parent(sparrow,nestling).
Теперь для запуска жмем «Esc», Run . И если Вы написали без ошибок, должны увидеть диалоговое окно.
И начинаем вводить наши данные, жмем «Enter» и программа на них отвечает либо Yes, либо No, или ошибку с ее описанием.
Так же запрашиваемые предложения можно писать в коде, после директивы GOAL, тогда при запуске будет сразу выводиться ответ.
Существуют еще анонимные переменные, которые задаются в виде нижнего подчеркивания _, то есть, это может быть всё что угодно. В данной программе при попадании в bird(X):–, предикат parent(Y,X) вызывается с анонимным параметром Y например, parent(_, pigeon). Это можно увидеть при трассировке.
Для отладки программы можно использовать трассировку. («Esc», Edit) Для этого в начале нашей программы напишем trace , запустим. Вводим предложение -> «Enter» -> F10.
Попадаем в наш код и проходим по нему с помощью F10 ,в нижнем правом углу выводятся данные трассировки.
Сообщения в окне трассировки могут быть следующими:
− CALL – вывод имени предиката и значений его параметров;
− FAIL – вывод имени неудачно завершившегося предиката;
− REDO – вывод сообщения о том, произведен поиск с возвратом;
− RETURN – вывод имени удачно завершившегося предиката и значений его параметров.
Не забываем сохранять: Files -> Save.
Для правильного выхода: Files -> Quit.
Ставим лайки, подписываемся на рассылку =)
Удачи в написании своих программ!