Добавил:
vk.com СтудСклад КубГУ vk.com/studskladrn Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Архив С / 8 семестр / Жаркова / Laboratornaya_rabota_10

.pdf
Скачиваний:
21
Добавлен:
11.08.2019
Размер:
263.9 Кб
Скачать

Лабораторная работа 10.

Тема: «Методы поиска решений в интегрированной среде разработки

Visual Prolog 8».

Цель работы: освоить методы поиска решений в пространстве состояний в среде Visual Prolog 8.

Введение

Сопоставление и унификация. Запускаемый во время попытки сопоставления вызова (из подцели) с предложением (в разделе программы clauses) процесс поиска включает связывание определенного вызова с конкретным предложением и называется унификацией (unification). В ViP унификация реализует процедуры, которые известны из других языков программирования, например, такие, как передача параметра, выбор варианта (case), создание структуры, доступ к структуре, присваивание.

Управление поиском в Visual Prolog (ViP) включает в себя методы, позволяющие программе найти решение в случае сложности его нахождения иным способом, большой длительности поиска или ограничения ресурсов компьютера. В таких случаях применим предикат, который можно использовать для поддержки поиска с возвратом, а также предикат, который можно использовать для проверки того, удовлетворено ли то или иное ограничение в программе.

Рассмотрим код программы на ViP, в которой осуществляется поиск всех решений следующей цели: произведение(X, Y).

Выполняя целевое утверждение произведение(X, Y), ViP должен проверить каждое предложение произведение в программе. Сопоставляя аргументы X и Y с аргументами каждого предложения произведение, ViP выполняет поиск от начала программы до ее конца. Найдя предложение, соответствующее целевому утверждению, ViP присваивает значения свободным переменным таким образом, что целевое утверждение и предложение становятся идентичными; говорят, что целевое утверждение унифицируется с предложением (выполняемая операция сопоставления называется унификацией).

2

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

ViP устанавливает соответствие, X становится связанным с "Пушкин", а Y – c "Руслан и Людмила". Поскольку goal ищет все решения для заданной цели, целевое утверждение также будет унифицировано и со вторым предложением произведение:

произведение(X, "Герой нашего времени").

Пусть программе задано целевое утверждение:

произведение("Лермонтов", "Герой нашего времени"). ViP произведет сопоставление с

первым предложением произведение:

Так как "Руслан и Людмила" и "Герой нашего времени" не соответствуют друг

другу, попытка унификации завершается неудачно, после чего ViP проверяет

следующий факт в программе: произведение("Лермонтов", "Герой нашего времени").

Этот факт действительно унифицируется, и X становится связанным с "Лермонтов". Рассмотрим, как ViP выполнит следующее целевое утверждение:

большая_книга(X).

Когда ViP пытается выполнить целевое утверждение, он проверяет, действительно ли обращение может соответствовать факту или заголовку правила. В данном примере устанавливается соответствие с большая_книга(Название). ViP проверяет предложение для большая_книга, пытаясь завершить сопоставление унификацией аргументов. Поскольку в целевом утверждении X – свободная

3

переменная, то она может быть унифицирована с любым другим аргументом. Название также не является связанным в заголовке предложения большая_книга. Целевое утверждение соответствует заголовку правила, и унификация выполняется. Впоследствии ViP будет пытаться согласовывать подцели с правилом.

большая_книга(Название) :- произведение(_, Название), книга(Название, Страниц),

Страниц > 200.

Пытаясь выполнить согласование тела правила, ViP обратится к первой подцели в теле правила – произведение(_, Название). Поскольку авторство книги является несущественным, то на месте аргумента Автор появляется анонимная переменная (_). Обращение произведение(_, Название) становится текущей подцелью, и ViP ищет решение для этого обращения.

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

Переменная Название связывается с "Руслан и Людмила", и к следующей подцели книга(Название, Страниц) обращение выполняется уже с обновленным значением переменной. Далее ViP начинает очередной процесс поиска, пытаясь найти соответствие с обращением к книга. Так как Название связан с "Руслан и Людмила", фактическое обращение выглядит как книга("Руслан и Людмила", Страниц). Процесс поиска опять начинается с вершины программы. Заметим, что первая попытка сопоставления с предложением книга("Руслан и Людмила", 96) завершится неудачно, и ViP перейдет ко второму предложению книга в поиске соответствия. Здесь заголовок книги соответствует подцели, и ViP связывает переменную Страниц с величиной 224.

Теперь третье предложение в теле большая_книга становится текущей подцелью: Страниц > 200. ViP выполняет сравнение, завершающееся успешно: 224 больше, чем 200. В этот момент все подцели в теле правила выполнены, и, следовательно, обращение большая_книга(X) успешно. Так как X в обращении был унифицирован с переменной Название в правиле, то значение, с которым связывается Название при подтверждении правила, возвращается и унифицируется с переменной X. Переменная Название в случае подтверждения правила имеет значение

"Герой нашего времени".

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

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

4

вернется к точке отката и попробует проверить другую подцель. Разберем нижеследующий листинг.

Данная программа составлена из двух множеств фактов и одного правила. Правило, представленное отношением любит, утверждает, что "Борис" любит вкусную пищу. Чтобы увидеть, как работает поиск с возвратом, зададим программе для решения следующее целевое утверждение: любит("Борис", Что).

В данном случае ViP будет искать решение, производя с вершины программы поиск соответствия с подцелью любит("Борис", Что). Он обнаруживает соответствие с первым предложением в программе и переменная Что унифицируется с переменной X. Сопоставление с заголовком правила заставляет ViP попытаться удовлетворить это правило. Производя это, он двигается по телу правила и обращается к первой находящейся здесь подцели: пища(X).

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

Поскольку переменная X связана с "брюссельская капуста", следующее обращение будет выполняться так: вкус("брюссельская капуста", "плохой") и ViP вновь начнет поиск с вершины программы, пытаясь согласовать это обращение. Поскольку

пища("брюссельская капуста").

5

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

Когда ViP отступает к точке поиска с возвратом, он освобождает все переменные, связанные после этой точки, и будет искать другое решение для исходного обращения. Обращение было пища(X), так что связанность "брюссельская капуста" с X отменена. Теперь ViP пытается заново произвести решение для этого обращения. Он обнаруживает соответствие с фактом пища("пицца"); на этот раз переменная X связывается со значением "пицца".

ViP переходит к следующей подцели в правиле, имея при этом новую связанную переменную. Производится новое обращение, вкус("пицца", "хороший"), и начинается поиск (опять от вершины программы). На этот раз соответствие найдено, и целевое утверждение успешно выполняется. Поскольку переменная Что в целевом утверждении унифицирована с переменной X в правиле любит, а переменная X связана со значением "пицца", переменная Что отныне связана со значением "пицца".

Поиск всех решений. Как было описано выше, при помощи поиска с возвратом ViP не только найдет первое решение задачи, но также способен найти все возможные решения. Далее рассмотрим программу, которая содержит сведения об именах и возрастах нескольких игроков в теннисном клубе:

Планируется турнир по пинг-понгу между девятилетними членами теннисного клуба. Каждая пара игроков должна провести между собой две игры. Задача – найти все возможные пары из тех игроков клуба, кому по девять лет. На естественном языке это прозвучало бы так: найти Личность1 в возрасте 9 лет и Личность2 в возрасте 9 лет, отличное от Личность1. Разберем действия ViP:

1. Попытается найти решение для первой подцели игрок(Личность1, 9) и перейдет к следующей подцели только после того, как первая будет достигнута.

6

Первая подцель согласуется сопоставлением Личность1 с "Пётр". Затем ViP попытается согласовать следующую подцель: игрок(Личность2, 9). Аналогично, Личность2 сопоставляется с "Пётр". Далее ViP переходит к третьей и последней

подцели: Личность1<>Личность2.

2.Так как Личность1 и Личность2 связаны с "Пётр", эта подцель не выполняется. Вследствие чего ViP выполняет поиск с возвратом к предыдущей подцели и ищет другое решение для второй подцели: игрок(Личность2, 9).

Эта подцель выполняется при сопоставлении Личность2 с "Кирилл".

3.Теперь третья подцель: Личность1<>Личность2

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

4.Поскольку ViP должен найти все возможные решения целевого утверждения, он находит точку поиска с возвратом предыдущей цели в надежде вновь добиться успеха. Так как игрок игрок(Личность2, 9) также может быть согласовано, если принять Личность2 за "Саша", то ViP еще раз проверит третью подцель. Достигается успех (т.к. "Пётр" отличен от "Саша"), и другое решение для всего целевого утверждения найдено.

5.В дальнейшем поиске решений ViP вновь возвращается к точке поиска с возвратом второй подцели, но все возможности для этой подцели уже исчерпаны, и поиск с возвратом теперь выполняется от первой подцели. Она вновь может быть согласована сопоставлением Личность1 с "Кирилл". Вторая подцель теперь имеет успех

врезультате сопоставления Личность2 с "Пётр", так что третья подцель согласована, и все целевое утверждение опять выполнено. Итак, запланирована еще одна встреча, на этот раз между Кириллом и Петром.

6.В поисках еще одного решения целевого утверждения ViP возвращается к точке поиска с возвратом второй подцели в правиле. Здесь Личность2 ставится в соответствие "Кирилл", и при этом условии проверяется третья подцель. Она не выполняется, т.к. Личность1 и Личность2 эквивалентны. Тогда ViP выполняет поиск с возвратом от второй подцели в поисках другого решения: Личность2 сопоставляется с "Саша", третья подцель выполнена. ViP назначает очередную встречу в теннисном

клубе (Кирилл против Саши).

7. И вновь, в связи с необходимостью найти все решения, ViP возвращается ко второй подцели, но на этот раз безуспешно. Когда вторая подцель не выполняется, процесс возвращается к первой подцели, на этот раз, находя соответствие Личность1 с "Саша". Пытаясь выполнить вторую подцель, ViP сопоставляет Личность2 с "Пётр", и впоследствии третья подцель выполнится при этих условиях. Итак, назначена пятая встреча.

8.Снова возврат ко второй подцели, где Личность2 сопоставляется с "Кирилл". Найдено шестое решение задачи о теннисном клубе и, наконец, получено полное множество турнирных пар.

9.Последнее исследуемое решение связывает с "Саша" как Личность1, так и Личность2 и приводит к невыполнению последней подцели. ViP должен вернуться ко второй подцели, но там не осталось никаких новых вариантов. Тогда он возвращается для поиска к первой подцели, но и здесь все возможности для Личность1 уже исчерпаны. Для данного целевого утверждения не может быть найдено других решений, и работа программы завершается.

7

Обратите внимание, как поиск с возвратом может вызывать вывод избыточных решений. В нашем примере ViP не отметил, что Личность1="Пётр" то же самое, что и

Личность2="Пётр".

Четыре основных правила поиска с возвратом:

1.Подцели должны быть согласованы по порядку, сверху вниз.

2.Предикатные предложения проверяются в том порядке, в каком они появляются в программе, сверху вниз.

3.Когда подцель соответствует заголовку правила, далее должно быть согласовано тело того правила: тело правила теперь образует новое множество подцелей для согласования.

4.Целевое утверждение считается согласованным, когда соответствующий факт найден для каждой оконечности (листа) целевого дерева.

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

один, усложненный пример, иллюстрирующий, как в ViP происходит поиск с возвратом:

После того как программа компилирована и запущена (например, с использованием команды меню Build → Run in Window), ViP автоматически начнет выполнение целевого утверждения, пытаясь согласовать все подцели:

1. ViP обращается к предикату может_плавать со свободной переменной Кто. Пытаясь выполнить это обращение, ViP просматривает программу в поисках

8

соответствия. Он обнаруживает соответствие с предложением, определяющим может_плавать, и переменная Кто унифицируется с переменной Y.

2.Затем ViP пытается согласовать тело правила. При этом происходит обращение к первой подцели в теле правила, тип(X, "животное"), и поиск соответствия для этого обращения. Он обнаруживает соответствие с первым фактом, определяющим отношение тип.

3.В этот момент X связывается с "копытное". Поскольку здесь налицо более чем одно возможное решение, ViP проставляет точку возврата возле факта

тип("копытное", "животное").

4.Имея X, связанным с "копытное", ViP производит обращение ко второй подцели в правиле (это(Y, "копытное")) и снова ищет соответствие. Он находит его с первым фактом, это("Зебра", "копытное"). Y связывается с "Зебра", и ViP выставляет точку возврата возле факта это("Зебра", "копытное").

5.Теперь, имея X, вязанным с "копытное", и Y – с "Зебра", ViP пытается согласовать последнюю подцель, живет("Зебра", "в_воде"). ViP проверяет каждое предложение живет, но в программе нет предложения живет("Зебра", "в_воде"), поэтому обращение завершается неудачно, и далее начинается поиск с возвратом другого решения.

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

возврата была поставлена у второй подцели в правиле, на факте

это("Зебра", "копытное").

7. При достижении точки возврата ViP освобождает переменные, которым были присвоены новые значения после последней точки возврата, и пытается найти другое решение для обрабатываемого обращения. В данном случае обращение было

это(Y, "копытное").

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

9.Теперь в качестве последней точки возврата рассматривается

тип("копытное", "животное").

10.ViP освобождает переменные, использованные в исходном обращении, и пытается найти другое решение для обращения тип(X, "животное"). Поиск начинается после точки возврата. ViP находит соответствие со следующим фактом тип в программе (тип("рыба", "животное")); X связывается с "рыба", и новая точка возврата ставится возле этого факта.

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

12.ViP находит соответствие для этого обращения, и Y становится вязанным с

"Сельдь".

13.Так как Y теперь связан с "Сельдь", следующая подцель, к которой происходит обращение, суть живет("Сельдь", "в_воде"). Это новое обращение – поиск начинается с вершины программы.

14.ViP исследует каждый факт живет, но не находит соответствия, и подцель не выполняется.

15.ViP возвращается к последней точке возврата это("Сельдь", "рыба").

9

16.Переменные, которые были связаны этим сопоставлением, теперь освобождены. Начиная с того места, где процесс был прекращен, ViP ищет новое решение для обращения это(Y, "рыба").

17.ViP находит соответствие со следующим предложением это, Y становится связанным с идентификатором "Акула".

18.ViP опять исследует последнюю подцель, имея переменную Y, связанную с

"Акула". Он выполняет обращение живет("Акула", "в_воде"); поиск начинается с вершины программы (новое обращение) и обнаруживает соответствие. Последняя подцель для правила выполняется.

19.К этому моменту тело правила может_плавать(Y) согласовано. ViP возвращает Y вызову может_плавать(Кто). Так как Кто связана с Y, a Y – с "Акула", то в целевом утверждении Кто связывается с "Акула".

20.ViP продолжает процесс с того места, где он был остановлен, и обращается ко второй подцели в целевом утверждении.

21.ViP завершает программу выводом: «Акула может плавать», и программа завершается успешно.

Управление поиском решения в ViP осуществляется посредством соответствующих предопределенных предикатов.

Задание:

Написать программу на ViP решения следующих задач (выбора альтернативы) по 6-ти критериям (вводимым значениям) в соответствии с вариантом.

№ варианта

Задача

1Определение подходящего предложения по кредитованию.

2Выбор квартиры.

3Определение подходящего предложения по вкладу.

4Выбор автомобиля.

5Определение подходящей для претендента должности.

В отчете по выполнению лабораторной работы представить: решение задачи — программный код, снимок экрана консольного приложения программы с вариантом(ами) решения(й), готовый файл проекта.

Соседние файлы в папке Жаркова