3. Структура программ Турбо-Пролога
Существует множество реализации языка Пролог для разных классов вычислительных систем. В этом пособии за основу принимается программный продукт компании Borland International 'Турбо-Пролог" для IBM-совместимых компьютеров. Программа на Турбо-Прологе состоит из нескольких секций, каждая из которых идентифицируется ключевым словом и имеет следующую обобщенную структуру:Обязательным в программе является присутствие двух секций с именами predicates и clauses. В первой из них описываются структуры используемых в программе отношений, а во второй эти отношения опред(деклnbsp; Для набора фактов и правил, рассмотренных выше, один из возможных примеров программы на Турбо-Прологе будет иметь вид:
- domains
- /* секция объявления доменов */
- database
- /* секция объявления динамических баз данных */
- predicates
- /* секция объявления предикатов */
- goal
- /* подцель_1, подцель_2, и т. д. */
- clauses
- /* предложения (факты и правила) */
/* программа 1 */В этой программе предикат likes описывает структуру, отношения, домены которого имеют тип строки символов. Факты и правила записаны в виде предложении Пролог-программы, каждое из них заканчивается точкой, а текст заключенный в /* ... */ - это комментарии. Отсутствие в программе секции goal предполагает, что запросы к программе будут осуществляться из оболочки Турбо-Пролога. Так, например, при запросе о поиске всех любителей пива, цель должна быть сформировала в окне диалога Турбо-Пролога в виде:
- predicates
likes(string,string) - clauses
likes ("Иван","Марья").
likes ("Петр","пиво")
likes ("Иван",X) if likes ("Петр",X)
/* описание предиката */
/* факт */
/* факт */
/* правило */
Goal: likes(Who,"пиво").В ответ на этот запрос в том же окне диалога Турбо-Пролог выведет всех тех, кто любит пиво, связывая их с переменной Who.
3.1. Секция domains Пролог-программы
В секции domains объявляются любые нестандартные домены, используемые для аргументов предикатов. Домены в Прологе являются аналогами типов в других языках. Основными стандартными доменами Турбо-Пролога являются:Пример. Требуется разработать структуру данных для хранения информации о компьютерах. При этом каждый компьютер будет рассматриваться как набор входящих в него устройств, среди которых могут быть: процессоры с указанием их наименования и частоты, НЖМД с указанием их объема и фирмы изготовителя, также мониторы определенного типа. Область определения доменов для этого примера будет иметь вид
- а) name = stanDom ,
- где stanDom - один из стандартных доменов: int, char, real, string или symbol, name - одно или несколько имен доменов. Например, fio = symbol или year, height = integer ;
- б) mylist = elementDom* ,
- где mylist - область, состоящая из списков элементов из области elementDom, которая может быть определена пользователем или иметь стандартный тип.Например, numberh5t = integer* или letter = char* ;
- в) myCompDom = functor1(d11,…,d1n) ; functor2(d21,..., d2n) ; ... functorm(dm1,...,dmq) ,
- где myCompDom - область, которая состоит из составных объектов, описываемых указанием функтора и областей для всех компонентов. Правая часть такого описания может определять несколько альтернатив, разделенных ";" или "or". Каждая альтернатива должна содержать единственный Функтор functor, и описание типов для компонентов dij.Например,
auto = car(symbol,integer) ,описывает две области auto и packing. Область auto соответствует двухкомпонентной структуре с функтором car, а область packing соответствует одной из двух возможных структур box и bottle, которые различаются не только именами, но и количеством компонент.
packing = box(integer, integer, integer) ; bottle(integer)- г) file = name1; name2 ; ... namen
- используется, когда пользователю необходимо ссылаться на файлы по их символическим именам.
В этом описании домен computer является списком элементов типа device, то есть каждый элемент этого списка может иметь структуру типа либо processor, либо disk, либо monitor, содержащих одну или две компоненты, каждая из которых имеет стандартный символьный ют целый тип. В секции predicates объявляются предикаты и типы (домены) аргументов этих предикатов. Имена предикатов должны начинаться со строчной латинской буквы, за которой следует последовательность букв, цифр и символов подчеркивания (до 250 знаков). В именах предикатов нельзя использовать символы пробела, минуса, звездочки, обратной (и прямой) черты. Объявление предикатов имеет форму:
- domains
- name , firm , type = symbol
freq , vol = integer
device = processor(name,freq);disk(firm,vol);monitor(type)
computer = device*
Здесь domenij - либо стандартные домены, либо домены, объявленные в секции domains. Объявление домена аргумента и описание типа аргумента - суть одно и то же. Количество доменов (аргументов) предиката определяют арность (размерность) предиката. Предикат может не иметь аргументов и указываться только именем. Обычно выбирается такое имя предиката, чтобы оно отражало определенный вид взаимосвязи между аргументами предиката. Пример описания предикатов:
- predicates
- predicateName1 (domen11, domen12,..., domen1m)
predicateNamen (domenn1, domenn2,..., domennk)
Можно использовать несколько описаний одного и того же предиката. При этом все описания должны следовать одно за другим и должны иметь одно и то же число аргументов. Пусть требуется определить отношение между тремя аргументами, первые два из которых соответствуют слагаемым, а третий - сумме двух первых. Этот предикат может быть описан в следующем виде
- predicates
- student( string,real)
start
good_student( string)
и позволит его аргументам принимать значения как из области целых, так и действительных чисел. В секции clauses размещаются факты и правила, с которыми будет работать Турбо-Пролог, пытаясь разрешить цель программы.
- predicates
- add(integer,integer,integer)
add(real,real,real)
где predicateNamel - имена предикатов, описанных в секции predicates , a term11, ... , term11 - аргументы предикатов (термы), количество которых должно соответствовать арности описания предиката. Пример фактов, определяющих отношение, заданное предикатом student, может иметь вид:
- clauses
predicateName1 (term11, term12,..., term1к). ,
...
predicateNameN (termN1, terniN2,..., termNL).
Правила содержат утверждения, истинность которых зависит от некоторых условий (подцелей), образующих тело правила. В Прологе правила представляются в виде
- clauses
- student("Петров" ,4.5).
student("Сидоров" ,3.75).
Для того, чтобы заголовок правила оказался истинным, необходимо, чтобы каждая подцель, входящая в тело правила, была истинной. Переменные в заголовке правила, квантифицированы универсально. Это означает, что правило, заголовок которого содержит переменные, будет истинным для любых термов, удовлетворяющих подцелям правила. С другой стороны переменные, входящие только в тело правила, квантифицированы экзистенциально. Если учесть такую квантификацию, то приведенное выше правило можно прочитать так:good_student( Name ) :- student( Name , В ) , В > 4.
Множество правил, заголовки которых содержат одинаковые имена предикатов и количество аргументов, называются процедурой. В Прологе предикаты определяются (реализуются) при помощи процедур. Так следующие два правила
Для любого лица Name, Name является хорошим студентом ЕСЛИ существует средний балл В такой, что Name является студентом со средним баллом В И средний балл В больше 4.
max( Х , Y , X) :- Х >=Y.реализуют процедуру нахождения наибольшего из двух чисел, определяемую предикатом вида max(number1, number2, max_number). Считается, что между этими двумя правилами неявно присутствует соединительный союз "или".
max( Х , Y , Y) :- Х < Y.
/* Программа 2 */В этой программе формируется на экране окно, заданного размера и цвета, запрашивается Ваше имя, а затем оно выводится на экран.
- predicates
- hello
- goal
- hello.
- clauses
hello :-
makewindow(l,7,7,"My first programm",4,54,10,22),
nl, write("Please, type your name "),
cursor(4,5),
readln(Name) ,nl,
write(" Welcome ",Name).