Смекни!
smekni.com

Язык логического программирования Visual Prolog (стр. 4 из 9)

Рассмотрим следующий фрагмент программы:

constants

zеrо = О

one = 1

two = 2

hundred = (10*(10-1)+10)

pi = 3.141592653

ega = 3

slash_fill = 4

red = 4

Перед компиляцией программы VisualProlog заменит каждую константу на соответствующую ей строку.

На использование символических констант накладываются следующие ограничения:

· описание константы не может ссылаться само на себя:

my_number = 2*my_number/2 % не допускается

· это приведет к сообщению об ошибке "Recursioninconstantdefinition" (Рекурсия в описании константы);

· в описаниях констант система не различает верхний и нижний регистры. Следовательно, при использовании в разделе программы clauses идентификатора типа constants, его первая буква должна быть строчной для того, чтобы избежать путаницы между константами и переменными.

· в программе может быть несколько разделов constants, однако объявление константы должно производиться перед ее использованием;

· идентификаторы констант являются глобальными и могут объявляться только один раз. Множественное объявление одного и того же идентификатора приведи к сообщению об ошибке "Constantidentifiercanonlybedeclaredonce" (Идентификатор константы может объявляться только один раз).

Директивы компилятора

VisualProlog поддерживает несколько директив компилятора, которые можно добавлять в программу для сообщения компилятору специальных инструкций по обработке вашей программы при ее компиляции. Кроме этого, вы можете устанавливать большинство директив компилятора с помощью команды меню среды визуальной разработки VisualPrologOptions/Project/CompilerOptions.

Директива include

Для того чтобы избежать многократного набора повторяющихся процедур, вы можете использовать директиву include.

Ниже приведен пример того, как это делается.

1. Создаете файл (например, MYSTUFF.PRO), в котором объявляете свои наиболее I часто используемые предикаты (с помощью разделов domains и predicates) и даете их описание в разделе clauses.

2. Пишете исходный текст программы, которая будет использовать эти процедуры.

3. В "допустимых областях" исходного текста программы размещаете строку:include "mystuff.pro"

"Допустимые области" — это любое место программы, в котором вы можете расположить декларацию разделов domains, facts, predicates, clauses или goal.

При компиляции исходных текстов программы VisualProlog вставит содержание файла MYSTUFF.PRO прямо в окончательный текст файла для компиляции.

Директиву include можно использовать для включения в исходный текст (практически любого) часто используемого фрагмента. Кроме того, любой включаемый в программу файл может, в свою очередь, включать другой файл (однако каждый файл может быть включен в вашу программу только один раз).


II. Унификация и поиск с возвратом

1. Сопоставление и унификация

Рассмотрим программу ch04e01.pro (рис.1) с точки зрения того, как утилита TestGoal будет отыскивать все решения следующей цели written_by(X, Y).

domains

title, author = symbol

pages= unsigned

predicates

book(title, pages)

written_by(author, title)

long_novel (title)

clauses

written_by(fleming, "DR NO").

written_by(melville, "MOBY DICK").

book("MOBY DICK", 250).

book("DR NO", 310).

long_novel (Title) :-

written_by(_, Title),

book(Title, Length),

Length > 300.

Рис. 1. Листинг программы ch04e01.pro

Пытаясь выполнить целевое утверждение written_by(X, Y), VisualProlog должен проверить каждое предложение written_by(X, Y) в программе. Сопоставляя аргументы X и Yс аргументами каждого предложения written_by, VisualProlog выполняет поиск от начала программы до ее конца. Обнаружив предложение, соответствующее целевому утверждению, VisualProlog присваивает значения свободным переменным таким образом, что целевое утверждение и предложение становятся идентичными. Говорят, что целевое утверждение унифицируется с предложением. Такая операция сопоставления называется унификацией.

Поскольку X и Yявляются свободными переменными в целевом утверждении, а свободная переменная может быть унифицирована с любым другим аргументом (и даже с другой свободной переменной), то целевое утверждение может быть унифицировано с первым предложением written_by в программе, как показано ниже:

written_by (X,Y).

¯¯

written_by(fleming,"DR NO").

VisualProlog устанавливает соответствие, X становится связанным с fleming, aY – “drno”. В этот момент VisualProlog напечатает:

X=fleming, Y="DR NO"

Поскольку TestGoal ищет все решения для заданной цели, целевое утверждение также будет унифицировано и со вторым предложением written_by:

written_by(melville, "MOBY DICK").

TestGoal печатает второе решение:

X=melville, Y="MOBY DICK"

2 Solutions

Рассмотрим, как VisualProlog выполнит следующее целевое утверждение:

long_novel(X).

Когда VisualProlog пытается выполнить целевое утверждение, он проверяет, действительно ли обращение может соответствовать факту или заголовку правила. В нашем случае устанавливается соответствие с

long_novel(Title)

VisualProlog проверяет предложение для long_novel, пытаясь завершить сопоставление унификацией аргументов. Поскольку в целевом утверждении X - свободная переменная, то она может быть унифицирована с любым другим аргументом. Title также не является связанным в заголовке предложения long_novel. Целевое утверждение соответствует заголовку правила, и унификация выполняется. Впоследствии VisualProlog будет пытаться согласовывать подцели с правилом

long_novel(Title) :-

written_by(_, Title), book(Title, Length), Length>300.

Пытаясь выполнить согласование тела правила, VisualProlog обратится к первой подцели в теле правила — written_by(_, Title). Поскольку авторство книги является несущественным, на месте аргумента author появляется анонимная переменная (_). Обращение written_by (_, Title) становится текущей подцелью, и Пролог ищет решение для этого обращения.

Пролог ищет соответствие с данной подцелью от вершины и до конца программы. В результате достигается унификация с первым фактом для written_by, а именно:

written_by(_, Title),

¯¯

written_by (fleming, "DR NO").

Переменная Title связывается с "drno", и к следующей подцели book (Title, Length) обращение выполняется уже с этим значением переменной. Далее VisualProlog начинает очередной процесс поиска, пытаясь найти соответствие с обращением к book. Так как Title связан с "drno", фактическое обращение выглядит как book("DRNO", Length). Процесс поиска опять начинается с вершины программы. Заметим, что первая попытка сопоставления с предложением book(“MOBYDICK", 250) завершится неудачно, и VisualProlog перейдет ко второму предложению book в поиске соответствия. Здесь заголовок книги соответствует подцели, и VisualProlog связывает переменную Length с величиной 310.

Теперь третье предложение в теле long_novel становится текущей подцелью:

length > 300.

VisualProlog выполняет сравнение, завершающееся успешно: 310 больше, чем 300. В этот момент все подцели в теле правила выполнены, и, следовательно, обращение long_novel(X) успешно. Так как X в обращении был унифицирован с переменной Title в правиле, то значение, с которым связывается Title при подтверждении правила, возвращается и унифицируется с переменной X. Переменная Title в случае подтверждения правила имеет значение "drno", поэтому VisualProlog выведет:

X="DR NO"

1 Solution.

2. Поиск с возвратом

Часто при решении реальной задачи мы придерживаемся определенного пути для ее логического завершения. Если полученный результат не дает искомого ответа, мы должны выбрать другой путь.

Так, вам, возможно, приходилось играть в лабиринт. Один из верных способов найти конец лабиринта — это поворачивать налево на каждой развилке лабиринта до тех пор, пока вы не попадете в тупик. Тогда следует вернуться к последней развилке и попробовать свернуть вправо, после чего опять поворачивать налево на каждом встречающемся распутье. Путем методичного перебора всех возможных путей вы, в конце концов, найдете выход.

VisualProlog при поиске решения задачи использует именно такой метод проб и возвращений назад; этот метод называется поиск с возвратом. Если, начиная поиск решения задачи (или целевого утверждения), VisualProlog должен выбрать между альтернативными путями, то он ставит маркер у места ветвления (называемого точкой отката) и выбирает первую подцель, которую и станет проверять. Если данная подцель не выполнится, VisualProlog вернется к точке отката и попробует проверить другую подцель.

predicates

likes(symbol,symbol)

tastes(symbol, symbol)

food(symbol)

clauses

likes(bill,X):-

food(X), tastes(X,good) .

tastes(pizza,good).

tastes(brussels_sprouts,bad).

food(brussels_sprouts).

food(pizza).

Рис. 2. Программа ch04e02.pro

Эта маленькая программа составлена из двух множеств фактов и одного правила. Правило, представленное отношением likes, утверждает, что Билл любит вкусную пищу.

Чтобы увидеть, как работает поиск с возвратом, дадим программе для решения следующее целевое утверждение:

likes(bill, What).

Когда Пролог пытается произвести согласование целевого утверждения, он начинает поиск с вершины программы.

В данном случае Пролог будет искать решение, производя с вершины программы поиск соответствия с подцелью likes (bill, what).

Он обнаруживает соответствие с первым предложением в программе и переменная What унифицируется с переменной X. Сопоставление с заголовком правила заставляет VisualProlog попытаться удовлетворить это правило. Производя это, он двигается по телу правила и обращается к первой находящейся здесь подцели: food(X).

Если выполняется новое обращение, поиск соответствия для этого обращения вновь начинается с вершины программы.

Пытаясь согласовать первую подцель, VisualProlog (начиная с вершины) производит сопоставление с каждым фактом или заголовком правила, встреченным в программе.

Он обнаруживает соответствие с запросом у первого же факта, представляющего отношение food. Таким образом, переменная X связывается со значением brussels_sprouts. Поскольку существует более чем один возможный ответ на обращение food(X), VisualProlog ставит точку возврата (маркер) возле факта food(brussels_sprouts). Эта точка поиска с возвратом указывает на то место, откуда Пролог начнет поиск следующего возможного соответствия для food(X).