Лабораторная работа 1.
Работа с простейшими программами в системе Турбо-Пролог

Цель работы:
1. Знакомство со структурой Пролог-программ, использующих внешние или внутренние цели.
2. Получение навыков работы в оболочке системы Турбо-Пролога.
3. Знакомство с методикой отладки и трассировки программ.
4. Разработка простейших программ с использованием стандартных предикатов Турбо-Пролога.

1. Введение

       Разработка простейших программ и их выполнение в среде системы Турбо-Пролог требуют начальных сведений по основным конструкциям языка Пролог и структуре Пролог-программ, которые должны содержать как минимум две секции:
- predicates - секцию описания структур отношений, используемых в программе, в виде предикатов,
- clauses -секцию определения предикатов в виде набора фактов и правил.

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

       Работа в системе программирования предполагает наличие у пользователя элементарных знаний по работе в Турбо-оболочках таких, как загрузка, ввод и редактирование программных файлов, запуск их на выполнение, а также отладка программ и конфигурирование системы.

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

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

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

       Каждая программа на Прологе представляет собой текстовый файл, который для запуска из системы Турбо-Пролог должен иметь расширение .PRO.

       Содержимое какого-либо текстового файла или программы на языке Пролог может быть включено в другую программу на режиме ее компиляции. Для такой текстовой подстановки режима компиляции используется директива компилятора include, которая имеет следующий синтаксис:
include "dos_file_name"
где dos_file_name - имя текстового файла системы DOS, включаемого в текущий программный файл. Имя файла может включать путь доступа к нему.

       Включаемые файлы могут быть использованы только в естественных границах программы. Таким образом, ключевое слово include может появиться только там, где допускается одно из ключевых слов domains, predicates, clauses или goal.

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

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

2. Загрузка системы Турбо-Пролог, ввод и запуск программ

       2.1. Войдите в свой рабочий каталог и, находясь в нем, загрузите систему программирования Турбо-Пролог. Далее, пользуясь сведениями, изложенными в разделе 4 вводной части данного пособия:
1. ознакомьтесь с опциями главного меню и изучите их назначение;
2. установите режим компиляции в память компьютера;
3. сконфигурируйте, если необходимо, размеры и цветовые палитры всех окон;
4. определите пути доступа к файлам, установив нужные для вас каталоги;
5. выполненные установки запишите в файл конфигурации.

       2.2. Войдите в режим редактирования системы Турбо-Пролог, воспользовавшись командой "Ред" главного меню, и введите программу 1 из раздела 3 вводной части. Закончив ввод, выйдите из редактора в главное меню системы, нажав клавишу "Esc".

       2.3. Запустите программу на выполнение, выбрав команду "Вып" главного меню. В данной программе нет секции goal, т.е. в программе отсутствует внутренняя цель, определяющая решение конкретной задачи. Такие программы могут использоваться только в среде системы Турбо-Пролога. Поэтому, после ее запуска на выполнение системой активизируется окно "Диалог" и появляется приглашение на ввод внешней цели (GOAL:)

3. Работа с Пролог-программами в режиме диалога

       3.1 Внешние цели - это запросы к программе, формируемые пользователем в окне "Диалог". Введите запрос
GOAL: likes(Who,"пиво").
       Объясните: что обозначает данный запрос, к каким элементам языка Турбо-Пролога следует отнести такие объекты запроса, как "пиво". Who и likes.

       3.2. Активизируйте введенный Вами запрос. Для этого надо после окончания его набора нажать клавишу "Enter". До нажатия "Enter" запрос можно редактировать. В ответ на Ваш запрос в окне "Диалог" должны появиться сообщения.
Who=Петр
Who=Иван
2
GOAL:
       Объясните полученный результат и смысловое назначение выводимых в окне "Диалог" сообщений.

       3.3. Система запоминает последний из введенных запросов. Для того, чтобы вызвать повторно предыдущий запрос, следует нажать функциональную клавишу F8. Вызовите повторно предыдущую цель и отредактируйте ее так, чтобы она имела вид
GOAL: likes(Who,"пиво","Марья").
Запустите ее на выполнение и объясните полученный результат.

       3.4. Аналогичные действия проделайте по вводу и запуску запроса вида:
GOAL: likes(Иван, Х)
       Объясните полученный результат, внесите изменения в запрос, чтобы он удовлетворял синтаксису языка Турбо-Пролог и повторно запустите запрос на выполнение.

       3.5. Измените описание предиката так, чтобы было ясно, между какими объектами реального мира отношение likes устанавливается. В частности, для рассматриваемого примера, отношение likes определяется между некоторым лицом (person) и некоторым другим лицом или вещью (thing). Для учета введенного дополнения, измените в секции predicates описание предиката на новое
likes(person,thing)
и запустите программу на выполнение.

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

       Так как областью изменения обоих, вновь определяемых, доменов являются символьные данные (точнее данные типа строки символов), то в программу должна быть добавлена секция domains, где должны быть объявлены нестандартные домены и их типы. Для данной программы она может иметь один из двух возможных видов:
domains
person = string
thing = string
или
domains
person,thing = string
       Введите эти добавления в программу, запустите ее на выполнение и задайте любой, из ранее вводимых запросов. Результат должен соответствовать предыдущему.

4. Трассировка программ в среде системы Турбо-Пролога

       Познакомиться с тем, как Пролог-система осуществляет поиск ответов на запросы, а также отследить последовательность согласования фактов и правил Пролог-программы можно, используя пошаговый режим ее выполнения. Для перехода в режим пошагового выполнения программы (трассировки) необходимо в программе использовать директиву trace

       4.1. Вставьте первой строкой программы директиву trace, которая при выполнении программы обеспечит трассировку всех предикатов. Запустите программу на выполнение и задайте один из ранее выполнявшихся запросов. Помните о возможности вызова предыдущего запроса с помощью Fs-

       4.2. Осуществите, с использованием клавиши F10, пошаговое выполнение программы, тщательно отслеживая все перемещения курсора в окне редактирования и регистрируя все выводимые в окне трассировки сообщения.

       4.3. Разберитесь в последовательности доказательства цели Пролог-системой. Для этого записать все сообщения режима трассировки и дать им подробное толкование в отчете по лабораторной работе.

5. Работа с программами, содержащими внутреннюю цель

       5.1. Измените программу таким образом, чтобы один из ранее использованных запросов, явился бы внутренней целью программы. Для этого в программу надо добавить еще одну секцию goal, где должна быть описана основная цель, решаемая программой. Пусть, для нашего примера, она будет иметь вид:
goal    
likes(Who,"пиво").
и аналогична запросу из 3.1 данной лабораторной работы.

       5.2. Модифицированную программу запустите на выполнение. Если при запуске на решение у Вас появилось сообщение о синтаксической ошибке, при мигающем курсоре в соответствующем месте экрана, то посмотрите - не забыли ли Вы о том, что каждое предложение Турбо-Пролога должно заканчиваться точкой.

       5.3. Если в программе отсутствуют синтаксические ошибки, то после запуска ее на выполнение в окне диалога появится сообщение "Нажмите ПРОБЕЛ", которое свидетельствует о том, что программа отработала и запрос выполнен. Но тогда возникает вопрос, а где же результаты запроса? А все дело в том, что в сформированной цели дается запрос о согласовании переменной Who с предложениями программы, а об отображении или выводе полученных результатов ничего не говорится.

       5.4. В отличие от диалогового режима работы, когда внешняя цель формулируется в виде запроса к программе, а Турбо-система сама управляет процессом поиска и отображения результатов в некотором стандартном виде, при формировании внутренней цели все эти функции возлагаются на пользователя.
       Формирование внутренней цели программы требует от пользователя не только задания запроса, но и обеспечения отображения его результатов на экране. Поэтому изменим цель, добавив еще одну подцель, обеспечивающую отображение терма на экране дисплея:
goal    
likes(Who,"пиво"), write(Who).
Запустим на выполнение программу, в которой цель представляет собой уже конъюнкцию двух подцелей. В результате выполнения этой программы в окне диалога выдается сообщение об одном из любителей пива,
Диалог
Петр
Нажмите ПРОБЕЛ
а после нажатия клавиши пробел, происходит остановка программы и выход в главное меню системы.
       Связано это с тем, что при значении Who="Петр" каждая из подцелей принимает значение "истина" и вся цель становится истинной, что приводит к окончанию процесса вывода. Таким образом, мы обнаружили еще одно существенное отличие в формулировке одного и того же запроса в виде внешней или внутренней цели. Если при внешней цели система сама, управляя поиском, ищет все удовлетворяющие запрос ответы, то при использовании внутренней цели ищется только первый из них.

       5.5. Если цель решения задачи должна полностью соответствовать запросу и ее требуется включить в тело программы, а домены отношения, для большей определенности, должны быть поименованы, то в этом случае программа 1 может быть представлена в виде:
/* Программа 3 */
domains
person,thing = string
predicates
likes(person,thing)
goal
likes(Who,"пиво"), write(Who), nl, fail. /* цель */
clauses
likes("Иван","Марья") . /* факт */
likes("Петр","пиво") . /* факт */
likes("Иван",X) :- likes("Пeтp",X) . /* правило */
       В этой программе домены отношения likes имеют имена person и thing, которые имеют тип строки символов. Цель решения состоит из четырех подцелей, соединенных между собой запятыми. Запятая в предложениях Пролога равносильна логической функции "И" (and), т.е. цель решения задачи представляется конъюнкцией подцелей. Цель будет достигнута, т.е. примет значение "истина" (true), если каждая из подцелей будет истинной. Подцели данной программы содержат: один определенный пользователем предикат likes и три встроенных стандартных предиката Турбо-Пролога:
- write(Term) - выводит терм на дисплей,
- nl - обеспечивает переход на новую строку,
- fail - вызывает состояние неудачи при доказательстве целевого утверждения.

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

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

       Отредактируйте Вашу программу до состояния программы 3 и запустите ее на выполнение. Если цель достигнута, сохраните программу в Вашем рабочем каталоге на диске под именем "LAB1_1.PRO"

6. Простейшая программа ввода-вывода данных

       Рассмотрим еще один пример программы с внутренним описанием цели, которая демонстрирует простейшие возможности Турбо-Пролога по организации интерфейса с пользователем на основе использования стандартных предикатов Турбо-Пролога.

       6.1. Загрузить программу 2 из раздела 3 вводной части данного пособия. Разобраться в ее структуре и запустить на выполнение. Используя приложение 1, познакомиться с синтаксисом, семантикой и назначением стандартных предикатов, используемых в данной программе.
       Установив режим трассировки, ознакомиться с последовательностью выполнения программы и действием стандартных предикатов.

       6.2. Модифицировать программу таким образом, чтобы окно создавалось в середине экрана и в другой цветовой палитре. Для этого по приложению 1 изучить описание предиката makewindow и воспользоваться приложением 2 по вычислению параметров цветовой палитры.

       6.3. Исключить из программы внутреннюю цель, а описание и определение предиката hello изменить таким образом, чтобы можно было использовать внешнюю цель, задавая в режиме диалога, например, hello("Torn") или hello("").

       6.4. Отлаженную по п.6.3. программу записать на диск с именем "LAB1_2.PRO".

7. Построение простейшего интерфейса для вывода результатов запросов

       Если Вы правильно сформировали и хорошо отладили предикат hello(person) в программе "LAB1_2.PRO", то его можно использовать для вывода в окно любых, определенных в нем термов, что позволяет использовать его в качестве интерфейса для ранее разработанной программы "LAB1_1.PRO". Возможно два варианта совместного использования предикатов из этих двух программ:
- режим переноса в исходный модуль описаний и определений предиката путем копирования из другого файла;
- режим текстовой подстановки в исходный модуль файла, содержащего описание и определение требуемых предикатов.

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

       7.1. Загрузить программу "LAB1_1.PRO". Войти в режим редактирования и используя режим "копия извне", вызываемый по нажатию клавиши F9, перенести в исходный файл описание и определение предиката hello из файла "LAB1_2.PRO". В исходную внутреннюю цель вставить в качестве первой подцели, например:
goal
hello("Любители пива: \n"), ... , ... , ... , ... .
где последовательность символов \n - это стандартная константа "перевод строки",
Изменив текст программы, отладить ее и записать в файл "LAB1_3.PRO".        7.2. Загрузить программу "LAB1_1.PRO". Войти в режим редактирования и в первой строке программы ввести директиву:
include "LAB1_2.PRO"
В исходную внутреннюю цель в качестве первой подцели вставить предикат, аналогичный п.7.1. или любой другой. Для совместной отладки основного и подгружаемого программных модулей использовать двухоконный режим работы редактора (F5 - вход в дополнительное окно редактирования, F10 - выход из него).
       Выполнив необходимую модификацию, отладить программу и записать ее в файл "LAB1_4.PRO".

       7.3. Исследовать возможность применения пользовательского предиката hello() вместо стандартного предиката write() в разработанных программах.

8. Содержание отчета по лабораторной работе

       Отчет по лабораторной работе должен содержать:
1. Результаты исследований по п.3.1.-п.3.5.
2. Протокол трассировки программы по п.4 и пояснения к ней.
3. Тексты программ LAB1_1.PRO, LAB1_2.PRO,. LAB1_3.PRO, LAB1_4.PRO.