TurboProlog с нуля

Добрый день, мальчики и девочки, мужчины и женщины, дамы и господа.

Если Вы в первый раз столкнулись с необходимостью написать программу на 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.

  1. book(«War and peace», 3, 50).  – не подходит
  2. search(X):- book(X,C,P), write(«`», X, «`», » count: «,  C, » price: «, P), nl. – подходит.
  3. Вызывается book(«War and peace»,C,P), и заново происходит поиск с начала.
  4. book(«War and peace», 3, 50).  – подходит
  5. В С попадает 3, а в P – 50.
  6. Наш вывод: ‘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.

 

Ставим лайки, подписываемся на рассылку =)

Удачи в написании своих программ!

Автор статьи: Leomana. Категория: Разное
Дата публикации: 15.04.2013