Министерство образования Российской Федерации Северо-Западный государственный заочный технический университет Кафедра пр...
68 downloads
91 Views
890KB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
Министерство образования Российской Федерации Северо-Западный государственный заочный технический университет Кафедра процессов управления и информационных систем
ВВЕДЕНИЕ В ИСКУССТВЕННЫЙ ИНТЕЛЛЕКТ Рабочая программа Методические указания к изучению дисциплины Задания на контрольную работу Методические указания к выполнению контрольной работы Методические указания к проведению лабораторных работ Факультет информатики и систем управления Специальность 220100 - вычислительные машины, комплексы, системы и сети Направление 654600 – информатика и вычислительная техника
Санкт-Петербург 2002
УДК 681.3 Введение методические контрольную контрольной лабораторных
в искусственный интеллект: Рабочая программа, указания к изучению дисциплины, задания на работу, методические указания к выполнению работы и методические указания к проведению работ. - СПб.: СЗТУ, 2002, - 60 с.
Методический сборник предназначен для студентов специальности 220100 - Вычислительные машины, комплексы, системы и сети направления подготовки дипломированных специалистов 654600 – Информатика и вычислительная техника. В нем содержатся сведения, необходимые для самостоятельного изучения дисциплины "Введение в искусственный интеллект", выполнения контрольной и лабораторных работ. Рассмотрено на заседании кафедры процессов управления и информационных систем 10 декабря 2001 г., одобрено методической комиссией факультета информатики и систем управления 17 декабря 2001 г. Рецензенты: кафедра процессов управления и информационных систем СЗТУ (зав. кафедрой О.И. Золотов, канд. техн. наук, доц., Г.И. Анкудинов, доктор. тех. наук, проф.), Ю.Н. Сидоров, канд. техн. наук, доцент каф. МО ЭВМ СПГЭТУ Составитель: О.А. Петухов, канд. техн. наук, проф. Северо – Западный государственный заочный технический университет, 2002
2
ПРЕДИСЛОВИЕ Дисциплина "Введение в искусственный интеллект" рассчитана на изучение в 10-м семестре (5-й курс). Целью изучения является ознакомление студентов с комплексным представлением о системах искусственного интеллекта (СИИ), основными методами их построения, получение практических навыков в использовании методов и средств программирования на языке PDC Prolog - языке систем искусственного интеллекта. В результате изучения дисциплины студенты должны: ЗНАТЬ теоретические основы СИИ, принципы построения и функционирования экспертных и обучающих систем, естественноязыкового интерфейса, распознавания образов и генерации изображений, анализа и синтеза речи; и УМЕТЬ применять на практике инструментальные средства СИИ, программировать на языке PDC Prolog. Дисциплина связана с предшествующими ей дисциплинами: «Информатика», «Дискретная математика», «Программирование на языке высокого уровня», «Моделирование» и «Базы данных». Лабораторный практикум осуществляется на персональных ЭВМ, а для сокращения потерь машинного времени необходима предварительная теоретическая проработка материала. Контрольная работа выполняется, а отчет по лабораторным работам составляется индивидуально каждым студентом и защищается в установленном порядке. На обложках контрольной и отчета, помимо названия, должны быть указаны фамилия, инициалы, шифр студента и номер группы.
РАБОЧАЯ ПРОГРАММА (объем курса 130 часов)1
1
Блок-схема дисциплины представлена в таблице 1.
3
ВВЕДЕНИЕ (4 часа) [7], c.3...32. Цель и задачи курса. Тенденции развития СИИ. Краткий исторический очерк развития . Области использования СИИ. Таблица 1 Введение в искусственный интеллект
Теоретические основы СИИ
Системы технического зрения и генерации изображений
Языки программирования СИИ Системы распознавания и генерации речи
Инструментальные средства СИИ
Системы естественноязыкового интерфейса
Экспертные системы
1. ТЕОРЕТИЧЕСКИЕ ОСНОВЫ СИСТЕМ ИСКУССТВЕННОГО ИНТЕЛЛЕКТА (28 часов) [2], с. 6...36; [5], c.249...261; [6], c.7...49; [7], c.93...132; [8], c.20...54, 66...98, 127...141. Представление знаний. Понятие данных и знаний. Предметная область. База знаний. Методы представления знаний. Деклаpативные и импеpативные языки. СИСТЕМЫ ТЕХНИЧЕСКОКО ЗРЕНИЯ И ГЕНЕРАЦИИ ИЗОБРАЖЕНИЙ. Задачи и классификация. Понятие образа и изображения. Системы полного и ограниченного восприятия. Распознавание и генерация двумерных и трехмерных объектов. Анализ сцен. Алгоритмы обработки и генерации изображений. 4
СИСТЕМЫ РАСПОЗНАВАНИЯ И ГЕНЕРАЦИИ РЕЧИ. Анализ и запоминание речи в ЭВМ. Разбивка слов на фонемы. Амплитудночастотные характеристики фонем. Форматный синтез речи. Анализ естественно-языковых (неформатных) сообщений (НС). Постановка задачи распознавания НС. Модели НС. Алгоритмы управления процессом распознавания НС. СИСТЕМЫ ЕСТЕСТВЕННО-ЯЗЫКОВОГО ИНТЕРФЕЙСА. Задачи естественно-языкового (интеллектуального) интерфейса в диалоговых системах. Классификация систем интеллектуального интерфейса. Структура интеллектуального интерфейса. Форматные системы. Системы с ограниченной логикой. Системы с текстовой основой. Системы с общим выводом. Стадии преобразования текста. Лингвистический процессор. Морфологический, синтаксический и семантический анализ. Системы машинного перевода. ЭКСПЕРТНЫЕ СИСТЕМЫ. Архитектура ЭС. Модель знаний. диалогом. Интерфейс пользователя.
Основы функционирования. Машина вывода. Управление
2. ЯЗЫКИ ПРОГРАММИРОВАНИЯ СИИ ( 66 часов) [1], с. 3...154; [2], с. 37...97; [3] c.111...171; [4], c.14...543. Анализ языков программирования для СИИ. Языки LISP, PROLOG, FRL, РЕФАЛ. Основные понятия языка PDC Prolog. Упpавление пpогpаммой. Цели пpогpаммы. Pешение задачи. Результат доказательства цели. Цели и подцели. Внутpенние подпpогpаммы унификации. Пpедставление данных пpи помощи фактов и пpавил. Обpаботка пpавил и фактов во вpемя внутpенней унификации. Откат. Основы пpогpаммиpования на языке PDC Prolog. Стpуктуpа пpогpаммы. Описание доменов и пpедикатов. Пpедикаты и утвеpждения. Использование внешних и внутpенних целей. Пpедикаты и утвеpждения pазных аpностей. Использование пpавил в запpосах. Пpостые базы данных. Отpицание. 5
Использование составных объектов. Использование альтеpнативных доменов. Аpифметика и структуры данных. Реализация арифметических и логических операций. Составные объекты. Базовые предикаты вводавывода. Управление поиском решения. Повторение средствами языка Prolog. Метод отката после неудачи. Метод отсечения и отката. Построение рекурсивных правил. Простая рекурсия. Обобщенное правило рекурсии. Обработка списков. Представление списков. Операции над списками: поиск элемента в списке, деление списка, объединение списков, определение количества элементов в списке, сортировка списков. Обработка строк. Использование кодов ASCII. Определение длины строки. Конкатенация строк. Создание подстрок. Преобразование данных. Преобразование строк в список символов. Формирование атомов из строк. Использование окон, графики и звука. Создание динамических баз данных. Создание экспертных систем. Программирование процедур общения с компьютером на естественном языке. Создание игр и головоломок. 3. ИНСТРУМЕНТАЛЬНЫЕ СРЕДСТВА СИИ (28 часов) [2], с.97...215; [5], c.290...342, 388...399. Технология создания СИИ, их программного и информационного обеспечения. Особенности инструментальных средств разработки СИИ. Особенности программирования экспертных и автоматизированных обучающих систем. Особенности построения и применения "пустых" экспертных и обучающих систем. ЗАКЛЮЧЕНИЕ (4 часа) [8], c.10...19. 6
Перспективы развития СИИ. ПЕРЕЧЕНЬ ЛАБОРАТОРНЫХ РАБОТ (12 часов) 1. Использование составных объектов (2 часа). 2. Реализация арифметических и логических операций (2 часа). 3. Управление поиском решения (2 часа). 4. Обработка списков (2 часа). 5. Обработка строк (2 часа). 6. Хранение файлов на внешних носителях (2 часа). ЛИТЕРАТУРА основная 1. Петухов О.А. PDC Prolog - язык систем искусственного интеллекта: Учебн. пособие. - СПб.: СЗПИ, 1999, - с. 2. Экспертные системы: Инструментальные средства разработки: Учебн. пособие. Под ред. Ю.В. Юдина. - СПб.: Политехника, 1996. - 220 с. 3. Бакаев А.А., Гриценко В.И., Козлов Д.Н. Экспертные системы и логическое программирование. - Киев: Наукова думка, 1992.- 220 с. 4. Ин Ц., Соломон Д. Использование Турбо-Пролога/ Пер. с англ. - М.: Мир, 1993. - 608 с. дополнительная
5. Искусственный интеллект. - В 3-х кн. Кн. 1. Системы общения и экспертные системы: Справочник /Под ред. Э.В. Попова. - М.: Радио и связь, 1990. - 464 с. 6. Искусственный интеллект. - В 3-х кн. Кн. 2. Модели и методы: Справочник/ Под ред. Д.А. Поспелова - М.: Радио и связь, 1990. - 304 с. 7. Перспективы развития вычислительной техники: В 11 кн.: Справ.пособие/ Под ред Ю.М. Смирнова. Кн. 2. Интеллектуализация 7
ЭВМ/ Е.С. Кузин, А.И. Ройтман, И.Б. Фоминых, Г.К. Хахалин. - М.: Высш. школа, 1989. - 159 с. 8. Робототехника и гибкие автоматизированные производства. В 9-ти кн. Кн.6. Техническая имитация интеллекта: Учебн. пособие для втузов/В.М. Назаретов, Д.П. Ким/ Под ред. И.М. Макарова. - М.: Высш. школа, 1986. - 144 с. 9. Марселлус Д. Программирование экспертных систем на Турбо-Прологе/ Пер. с англ. - М.: Финансы и статистика, 1994. 256 с. 10. Петухов О.А. Объектно-реляционные модели данных: Учеб. пособие. - Л.: СЗПИ, 1987, - 80 с. 11. Программные средства интеллектуальных систем / А.Е. Городецкий, В.В. Дубаренко, И.Л. Тарасова, А.В. Шереверов. СПб.: Изд-во СПбГТУ, 2000, 171 с. 12. Джексон П. Введение в экспертные системы.: Пер. с англ.: Уч. Пос. – М.: Издательский дом «Вильямс», 2001. – 624 с.
ПЛАН ЛЕКЦИЙ 1. Введение. Тенденции развития СИИ ...................................2 часа 2. Понятия данных и знаний ....................................................... -"3. Реализация подсистем СИИ.................................................... -"4. Основные понятия языка PDC Prolog............. ........................ -"5. Управление программой. Цели и подцели............................... -"6. Внутренние подпрограммы унификации................................. -"7. Структура программы. Описание доменов и предикатов....... -"8. Реализация арифметических и логических операций............. -"9. Повторение и откат.................................................................... -"10. Методы организации рекурсии................................................ -"11. Обработка списков.................................................................... -"12. Обработка строк......................... .............................................. -"13. Создание динамических баз данных...... ................................ -"14. Общение с компьютером на естественном языке................... -"15. Технология разработки ЭС....................................................... -"16. Заключение. Перспективы использования СИИ .................... -"8
МЕТОДИЧЕСКИЕ УКАЗАНИЯ К ИЗУЧЕНИЮ ДИСЦИПЛИНЫ Искусственный интеллект (ИИ) это направление в информатике, областью исследования которого является выявление того, как система обработки информации - будь то человек или машина - способна воспринимать, анализировать, передавать и обобщать то, чему ее обучают, а также методы формализации с помощью полученных сведений описаний конкретных, не полностью определенных ситуаций принятия решений и методы оптимизации решений не полностью определенных задач. Предмет изучения в искусственном интеллекте - это любая интеллектуальная деятельность человека, подчиняющаяся заранее неизвестным законам, а создаваемая продукция - любые системы (аппаратные и программные), способные выполнять работу или решать задачи подобно человеку в условиях неполной определенности. Взлет исследований по искусственному интеллекту с 50-х гг. XX века связан с развитием электронных вычислительных машин, являющихся замечательным инструментальным средством исследования и моделирования. Исследования в области искусственного интеллекта сопровождаются разработкой языков программирования новых поколений и созданием все более изощренных систем программирования. Это дает возможность при разработке программ для ЭВМ использовать обычные методы рассуждений и обычный словарный запас. Более того, такой язык, как Пролог, позволяет с помощью концепций цели и утверждения моделировать и формализовать логический вывод в решении задач. В последнее время стало общепринятым относить к области искусственного интеллекта всякую задачу, для которой неизвестен общий алгоритм решения. Под алгоритмом понимается вся последовательность заданных действий, которые хорошо определены и выполнимы на современных ЭВМ, причем 9
решение задачи должно получаться в приемлемое время. Так, например, неизвестен алгоритм для игры в шахматы, хотя эта игра имеет конечное число ситуаций, но рассмотрение их всех потребовало бы тысячелетий. Также не существует общего алгоритма медицинской диагностики, составления резюме текста или перевода его на иностранный язык. К сфере искусственного интеллекта относятся те различные области, где мы действуем, не имея абсолютно точного метода решения проблемы, и которые обладают двумя характерными особенностями. Во-первых, в них используется информация в символьной форме: буквы, слова, знаки, рисунки. Это отличает область искусственного интеллекта от областей, в которых традиционно компьютерам доверяется обработка данных в числовой форме. Во-вторых, предполагается наличие выбора, когда отсутствие четкого алгоритма приводит к необходимости выбора между многими вариантами в условиях неопределенности и этот недетерминизм, который носит фундаментальный характер, эта свобода действий являются существенной составляющей интеллекта. Первая проблема. С которой сталкиваются исследователи в области искусственного интеллекта, - это проблема восприятия и обработки информации. Возможности сенсорных механизмов, присущих человеку в области зрения, восприятия звуков и запахов, а также в понимании речи и распознавании образов, еще не достигнуты в современных технических системах. Интеллектуальные информационные системы должны не только воспринимать информацию, кодировать и заносить в память, но и обеспечивать ее понимание и построение на ее базе логических рассуждений. Проблема понимания и построения логических рассуждений является основной проблемой искусственного интеллекта на данном этапе развития. Вторая проблема, с которой сталкиваются исследователи в области искусственного интеллекта, - это проблема синтеза или принятия решений в условиях неопределенности. Возможности мозга человека в области решения задач и планирования поведения также еще не достигнуты в современных технических системах. Первыми областями, в которых работали исследователи искусственного интеллекта, были математика и различные игры. 10
Обе эти сферы оказались подходящими областями приложения методов искусственного интеллекта в силу того, что связанные с ними задачи и проблемы хорошо формализованы, а сами они являются примерами высших достижений человеческого разума. Задачи проектирования образцов новой техники, формулируемые и обсуждаемые на начальном этапе на профессиональном языке данной предметной области, являющимся подмножеством естественного языка и отображающим специфику указанной предметной области, стали сферой приложения методов искусственного интеллекта сравнительно недавно благодаря развитию теории нечетких множеств, нечеткой логики и достигнутому прогрессу в области «понимания естественного языка» [5 - 8]. Для поддержания функциональной эффективности интеллектуальных систем управления (ИСУ) они должны обладать многоуровневой иерархией и развитыми интеллектуальными возможностями по анализу и распознаванию обстановки, формированию стратегий целесообразного поведения, планированию последовательности действий (тактов) и синтезу исполнительных законов для их реализации с необходимыми показателями качества. Следовательно, ИСУ сложных динамических объектов, например роботов, должны иметь стратегический, тактический и исполнительный уровни управления, а также сенсорную информационно-измерительную систему, обеспечивающую анализ состояния окружающей среды (среды функционирования) и объекта управления. Проблема интеллектуализации стратегического уровня, обеспечивающего планирование целесообразного поведения, связана с решением задач выбора стратегий выполнения требуемого задания и формирования последовательности действий, необходимых для его реализации. Кроме того, данный уровень должен обеспечивать оперативную коррекцию поведения в зависимости от изменений внешней среды и в самом объекте управления, например. из-за повреждений. Функционирование ИСУ требует наличия развитых способностей к приобретению знаний о закономерностях окружающей обстановки, к интерпретации, классификации и идентификации возникающих 11
ситуаций, к анализу и запоминанию последствий своих действий, исходя из опыта работы 9свойство самообучения). Проблема интеллектуализации управления тактического уровня в первую очередь касается поиска путей решения одной из ключевых задач, связанной с планированием траекторий движения объекта управления в среде, в том числе и с препятствиями, с учетом динамики исполнительных подсистем и текущих изменений среды функционирования. При этом должно обеспечиваться не только движение объекта вдоль априорно задаваемых траекторий, но и необходимые производные перемещения к заданному целевому объекту. Проблема интеллектуализации управления исполнительного уровня связана с обеспечением активной адаптации управления исполнительными механизмами к изменениям нагрузочных характеристикам, к вариациям собственных параметров, а также параметров среды функционирования. Интеллектуальная сенсорная информационно-измерительная система должна обеспечивать замыкание контуров управления различных уровней путем формирования соответствующих афферентных потоков. Основной проблемой интеллектуализации этой системы является определение степени адекватности преобразуемой сенсорной информации целям функционирования управляемого объекта и степени достоверности отображения как его внешней среды, так и внутреннего состояния объекта управления, а также обеспечения системы способностью к адаптации и выживанию. Проблема человеко-машинного интерфейса связана прежде всего с анализом и формализацией технофизиологического, эргадического и социологического характера поведения человека как целеуправляемой системы. Особые сложности возникают при попытке формализации таких свойств поведения человека, как «рациональный выбор», «компромисс» или «справедливость». В настоящее время наибольший прогресс достигнут в области создания так называемых систем нечеткого управления, работа которых основана на использовании нечеткой логики и нечетких множеств. Однако интеллектуальные возможности таких систем весьма ограничены. Фактически они обеспечивают только исполнительный уровень управления [2, 3, 7, 9, 12]. 12
Наибольшее распространение при создании систем искусственного интеллекта (и в частности при создании экспертных систем) получило использование языка Пролог. В качестве примера можно рассмотреть построение игрушечной экспертной системы. Язык Пролог считается системой продукций: 1. Он создает базу данных, в которой можно расположить продукции в виде Заключение ЕСЛИ предусловие 1 И предусловие 2. В «логической» интерпретации языка Пролог это означает Чтобы доказать заключение доказать предусловие 1 и доказать предусловие 2. Для этого в языке Пролог используется простой синтаксис, в котором: «:-» обозначает ЕСЛИ, а «,» - И. 2. Пролог позволяет хранить также и факты в форме правил, но у которых нет предусловий. 3. Управляющий механизм, обеспечиваемый системой Пролог, известен как поиск в глубину или рассуждение в обратном направлении. Процесс управления также зависит и от порядка, в котором в базе данных расположены факты и правила. Однако, в системе пролог не требуется какой-либо нумерации правил или фактов в базе данных. Поэтому приводимая ниже нумерация строк использована только для удобства описания основных идей. Рассматриваемая экспертная система, предназначенная для различения животных и записанная на языке Пролог с использованием правил, имеет следующий вид: 1.1.0 это - (обезьяна):1.1.1 это - (млекопитающее), 1.1.2 это - (хищник), 1.1.3 имеет (рыжевато-коричневый-цвет), 1.1.4 имеет (темные-пятна). 1.2.0 это - (тигр):13
1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.7.0 1.7.1 1.7.2
это - (млекопитающее), это - (хищник), имеет (рыжевато-коричневый-цвет), имеет (черные-полосы). это - (жираф):это - (копытное), имеет - (длинную-шею), имеет (длинные-ниги), имеет (темные-пятна). это - (зебра):это - (копытное), имеет - (черные-полосы). это - (страус):это - (птица), (не-летает) имеет (длинную-шею), имеет (длинные-ноги), имеет (черно-белый цвет). это - (пингвин):это - (птица), (не-летает), (плавает), имеет (черно-белый-цвет). это - (альбатрос):это - (птица), (хорошо-летает).
Также необходимы следующие правила: 2.1.0 это - (млекопитающее):2.1.1 имеет (волосы). 2.2.0 это - (млекопитающее):2.2.1 (дает-молоко). 2.3.0 это - (птица):2.3.1 имеет (перья). 2.4.0 это - (птица):2.4.1 (летает) 2.4.2 (откладывает-яйца). 2.5.0 это - (хищник):14
2.5.1 (ест-мясо). 2.6.0 это - (хищник):2.6.1 имеет (острые-зубы), 2.6.2 имеет (когти), 2.6.3 имеет (глаза-смотрящие-вперед). 2.7.0 это - (копытное):2.7.1 это - (млекопитающее), 2.7.2 имеет (копыта). 2.8.0 это - (копытное):2.8.1 это - (млекопитающее), 2.8.2 (жует-жвачку). В базе данных,. основанной на системе продукций, вначале нет никаких фактов о текущей ситуации. Поэтому необходимо включить простой подраздел в эту программу, позволяющий в ходе беседы получить информацию от пользователя: 3.1.0 имеет (У):3.1.1 написать (‘имеет ли оно ’), 3.1.2 написать (У), nl, 3.1.3 прочесть (Ответ), 3.1.4 положительный (Ответ), 3.1.5 внести (Имеет (У)). 4.1.0 (У):4.1.1 написать (‘умеет ли оно ’), 4.1.2 написать (У), nl, 4.1.3 прочесть (Ответ), 4.1.4 положительный (Ответ), 4.1.5 внести ((У)). 5.1.0 положительный (да)????? Наконец, нужно определить всю задачу в целом: 6.1.0 запуск:6.1.1 это - (У), 6.1.2 написать (‘Я думаю, что это ’), 6.1.3 написать (У), nl, nl. 6.2.0 запуск:6.2.1 написать (‘Я не знаю такое животное ’), nl. 15
Если теперь пользователь наберет на терминале команду «запуск», то система начнет работу. В силу механизма управления, присущего системе Пролог, результатом работы будет поиск в базе данных смысла команды «запуск». Он содержится в строке 6.1.0. Для того чтобы выполнить такую команду пользователя, система Пролог должна доказать то, что появляется в строках 6.1.1 -6.1.3. Система начинает с первой из них. Это приводит к другому поиску в базе данных, начинающемуся со строки 1.1.0, где У принимает значение «обезьяна», и управление передается строке 1.1.1, чтобы доказать «это - млекопитающее». Другой поиск в базе данных ведет к строке 2.1.0, причем на этот раз значением У становится «млекопитающее», что и является предметом поиска в настоящий момент. У элемента 2.1.0 всего лишь одно предусловие «имеет (волосы)». Следующий этап поиска в базе данных ведет к строке 3.1.0. Предусловие 3.1.1 удовлетворяется посредством встроенного оператора, что приводит к тому, что на терминале пользователя появляются слова «имеет ли оно». Предусловие 3.1.2 ведет к тому, что там же печатается слово «волосы», и курсор переходит на новую строку. Предусловие 3.1.3 также удовлетворяется с помощью встроенного в систему оператора, который читает то, что печатает на терминале пользователь, и подставляет это в качестве значения переменной «Ответ». Заметим, что переменные величины в языке Пролог всегда начинаются с прописной буквы, а постоянные со строчной, значения же для переменных устанавливаются лишь в пределах действия одного правила. Теперь у пользователя на терминале появляется первый вопрос: «Имеет ли оно волосы». Пусть для начала мы ответим согласием и скажем «да». Благодаря этому переменная «Ответ» получит значение «да». Предусловие 3.1.4 снова приводит к поиску в базе данных, пока не будет обнаружено 5.1.0, которое безусловно выполняется, и никаких других предусловий не возникает. В предусловии 3.1.5 используется другой встроенный оператор, который вносит новый факт в базу данных, размещая его перед другими подобными фактами. В нашем случае «имеет (волосы)» будет добавлено непосредственно перед строкой 5.1.0. 16
Система таким образом установила первый факт, касающийся обсуждаемого животного. Теперь можно вернуться назад и посмотреть, какие предусловия на более высоком уровне остались непроверенными. Управляющий механизм системы пролог поместил все такие невыполненные предусловия в стек, который обрабатывается по схеме «последний вошел - первый вышел», что приводит к удовлетворению 2.1.0, откуда мы возвращаемся назад к 1.1.1. Теперь мы готовы проверить 1.1.2. Предусловие 1.1.2 ведет к 2.5.0 и такой же цепочке шагов, которые мы проделали выше. В результате терминала будет напечатано «ест ли мясо». Предположим, что на этот раз мы ответили отрицательно, сказав «нет». Это приводит к поиску в базе данных»положительных (нет)». В базе данных не найдется такого, что системой Пролог рассматривается как неудача, так что 4.1.0 также будет считаться неудачей вследствие того, что неудачей закончилось доказательство одного из его предусловий. Следовательно, и предусловие 2.5.0 заканчивается неудачей. Однако, когда некоторое предусловие заканчивается неудачей и происходит «возвращение назад» к тем предусловиям, вы вызывали, то при наличии других альтернатив они также будут подвергнуты проверке. Следовательно, в нашем случае будет проверено 2.6.0, что приведет к другому вопросу: «имеет ли оно острые зубы». Предположим, что мы снова говорим «нет». Это приведет к неудаче 1.1.2. Пролог попытается проверить еще одну альтернативу для 1.2.1, прежде чем отказаться от 1.2.0. Новый вариант 1.2.1 приводит к 2.2.0, что, в свою очередь, приведет к вопросу «дает ли оно молоко». Пусть мы сказали «да», что привело к успеху 1.2.1. это означает, что мы готовы двигаться дальше. Система Пролог реализует такое сообщение: «Может быть, к настоящему моменту ситуация изменилась, так что можно ожидать успеха». Проверка 1.2.2 приведет к тому, что опять появится вопрос, который мы уже однажды задавали: «ест ли оно мясо». Это происходит потому, что наша программа довольно проста и не запоминает отрицательные факты, так как она запоминает положительные. Тем не менее, чтобы не противоречить самим себе, снова скажем «нет». Это приводит к неудаче для 1.2.2. 17
Поскольку теперь все альтернативы для 1.2.1 опробованы, то и 1.1.0 терпит неудачу. Таким образом, все, что нам удалось сделать, - это доказать. Что обсуждаемое животное не является обезьяной, и при этом мы узнали, что животное имеет волосы! Затем мы попытаемся доказать, что это тигр и т.д. в том порядке, в котором заданы правила, пока не будет достигнут успех, зависящий от того, как будут чередоваться положительные и отрицательные ответы пользователя. Описанная программа на языке Пролог достаточно простая, далека от совершенства и приведена нами лишь для иллюстрации использования языка Пролог для решения различных задач, в том числе для создания экспертных систем. В реальных экспертных системах, конечно, используются более сложные структуры для представления фактов, механизмы запоминания отрицательных фактов и дополнительных встроенных операторов, например оператор cut (отсечение), обеспечивающий подрезание дерева поиска, приводящее к более эффективному поиску путей решения. Более того, описанная здесь программа содержит лишь одну из характеристик экспертных систем вообще, а именно «вопросы, порождаемые в процессе вывода» [1, 2, 4, 9]. Результаты и социальные последствия исследований в области искусственного интеллекта приобретают все более важное значение. Многие научные дисциплины оказываются взаимосвязанными: психология (человеческий мозг остается обязательным объектом исследования в искусственном интеллекте), логика, лингвистика, биология (модели передачи информации с помощью генов), информатика (самоорганизующиеся системы, поиск в базах данных, автоматическое программирование), медицина (помощь в диагностике), теория образования и обучения во всех научных дисциплинах (уровень детализации, достигнутый в программах искусственного интеллекта, выявляет недостатки традиционного образования и делает очевидными пробелы преподавания), кибернетика (интеллектуальное управление целесообразным поведением). 18
Число исследователей, посвятивших себя целиком искусственному интеллекту, постоянно растет, достигаемы ими результаты впечатляют и касаются каждого из нас, о чем постоянно сообщают средства массовой информации. Нередко можно слышать о роботах будущего и новой информационной революции. На самом деле необходимо хорошо представлять себе, что эти исследования долгие и трудные, так как исследователи в области искусственного интеллекта пытаются постепенно воссоздать и ввести в ЭВМ опыт и знания специалистов всех областей знаний. В общем случае такая информация отсутствует и нужна длительная работа с экспертом, чтобы выявить все, что было неосознанно и запомнено им за время своего совершенствования в какой-то конкретной области деятельности. Для решения этой проблемы разработаны специальные языки и системы представления информации. Но для ее решения необходимо также собрать больше информации, чем ее содержится в какомлибо словаре или энциклопедии. Эта задача не является невыполнимой, так как уже разработаны и разрабатываются все новые и новые методы и средства сбора и сжатия информации. Кроме того, она привлекает все больше и больше специалистов и можно быть уверенным, что по мере ее решения программы искусственного интеллекта будут иметь самостоятельную ценность независимо от современных компьютеров [2, 11, 12]. ЗАДАНИЕ НА КОНТРОЛЬНУЮ РАБОТУ Каждый студент выполняет состоящую из двух задач.
одну
контрольную
работу,
ЗАДАЧА 1. Реализовать все ПРИМЕРЫ программ, разбираемых в тексте учебного пособия [1]. То есть необходимо реализовать примеры 1.1, 2.1-2.3, 3.1-3.5, 4.1-4.7, 5.1-5-8, 6.1-6.6, 7.1-7.8, 8.1-8.4. ЗАДАЧА 2. Выполнить все ЗАДАНИЯ, приводимые в тексте учебного пособия [1]. Они находятся на страницах: 13, 25, 33, 19
36, 39-41, 43, 46, 49, 53-55, 61, 63, 66, 68, 70, 72, 74, 77, 81, 85, 87, 94, 96, 130, 134-135. При выполнении задач 1 и 2 контрольной работы может оказаться, что по смысловому содержанию они похожи или, даже, совпадают. Поэтому обе задачи выполняются совместно и отчет по контрольной работе оформляется в соответствии с логическим ходом одновременной и последовательной реализации всех примеров и заданий в учебном пособии [1]. В отчете приводятся распечатки текстов программ и результатов их реализаций. МЕТОДИЧЕСКИЕ УКАЗАНИЯ К ВЫПОЛНЕНИЮ КОНТРОЛЬНОЙ РАБОТЫ Пусть необходимо, например, при выполнении задачи 1 реализовать пример 2.3, находящийся на стр. 34 учебного пособия [1]. Содержание примера: Сформировать базу данных, содержащую сведения о планетах солнечной системы Земле и Марсе, а также о спутниках Земли и Марса - Луне, Фобосе и Деймосе. Программа: /*Пример 2.3 Файл 2_3.pro*/ domains name = symbol predicates star(name) planet(name) revolve(name, name) satellite(name, name) goal satellite(X, «Марс»), write(X, « спутник Марса»), nl. clauses star(«Солнце»). /*Солнце - звезда*/ planet(«Земля»)./*Земля - планета*/ planet(«Марс»). 20
revolve(«Земля», «Солнце»)./*Земля вращается вокруг Солнца*/ revolve(«Марс», «Солнце»). revolve(«Луна», «Земля»). revolve(«Фобос», «Марс»). revolve(«Деймос», «Марс»). satellite(X,Y):- planet(Y), revolve(X,Y). /*Х является спутником Y, если Y - планета и X вращается вокруг Y*/ Цель решения задачи: найти спутники Марса. А результат выполнения программы: Фобос спутник Марса. Где же сведения о втором спутнике Марса? Найти второй спутник Марса с такой целью невозможно, т.к., найдя первый правильный ответ, программа поиск прекращает. Для получения правильного ответа необходимо использовать встроенный предикат fail (см. раздел 4.1) учебного пособия [1] и цель будет выглядеть, например, так: goal: write («Спутники Марса:»), satellite(X, «Марс»), write(« », X), fail. Результат: Спутники Марса: Фобос Деймос Реализации программы с внешними целями (стр. 36): goal: satellite(X, «Марс»). /*Какие спутники у Марса?*/ Результат: X = Фобос Х = Деймос 2 Solutions goal: satellite(X,_). /*Перечислите все спутники.*/ Результат: Х = Луна Х = Фобос Х = Деймос 3 Solutions goal: star(«Земля»). /*Является ли Земля звездой?*/ Результат: No 21
Внимание! Так реализуется пример 2.3. Но аналогичное задание необходимо реализовать при выполнении задачи 2 (ЗАДАНИЕ на странице 36, пункт 1. Поэтому во избежание дублирование при выполнении задач 1 и 2 нужно реализовывать все программы и задания в учебном пособии [1] начиная с первой страницы и до последней.
Еще один пример. Реализуется пример 5.6 на стр.72. Программа: /*Пример 5.6 Файл 5_6.pro*/ /*Определение количества элементов списка.*/ domains list = integer* predicates length(list, integer) clauses length([],0). length([H|T], Sum):length(T,Sum1), Sum = Sum1 + 1. В соответствии такая:
с
ЗАДАНИЕМ 1 пусть внешняя цель будет
goal: length([4,7,15,28],N). Результат выполнения программы: N= 4 1 Solution Для выполнения ЗАДАНИЯ 2 на той же странице 72 необходимо составить и реализовать программу, осуществляющую подсчет количества элементов символьного списка. Программа: 22
/*Пример 5.6a Файл 5_6a.pro*/ /*Определение количества элементов символьного списка.*/ domains list = symbol* predicates length(list, integer) clauses length([],0). length([H|T], Sum):length(T,Sum1), Sum = Sum1 + 1. Т.е. необходимо всего лишь изменить тип данных элементов списка: goal: length([«Prolog», «Turbo Prolog», «PDC Prolog», «Visual Prolog»], N). Результат: N = 4. УКАЗАНИЯ К ПРОВЕДЕНИЮ ЛАБОРАТОРНЫХ РАБОТ Лабораторные работы проводятся на IBM PC в среде любой операционной системы, в которой реализован язык PDC Prolog.. Для лучшего понимания предмета и сокращения потерь машинного времени при выполнении работ на РС необходима предварительная теоретическая проработка материала. Для этого в предварительно студентом прорабатывается весь теоретический материал, изложенный, например, в учебном пособии [1], а затем выполняется контрольная работа в полном объеме. После проверки контрольной работы и проверки теоретических знаний студента, он допускается к лабораторным работам. При этом каждому студенту по каждой из шести работ выдаются преподавателем индивидуальные задания. Методические указания к каждой лабораторной работе обычно состоят из четырех разделов: цели работы, основных теоретических положений, порядка выполнения работы и содержания отчета. Два последних раздела во всех шести 23
работах одинаковые. Поэтому они излагаются предварительно и отдельно. ПОРЯДОК ВЫПОЛНЕНИЯ РАБОТЫ 1. Получить задание у преподавателя. 2. Написать программу (или программы), реализующую полученное задание. 3. Реализовать программу, получить результаты, дать пояснения. СОДЕРЖАНИЕ ОТЧЕТА 1. Наименование и цель работы. 2. Основные этапы выполнения работы и их результаты. 3. Выводы. Примечание. Лабораторный практикум может быть выполнен студентом самостоятельно при наличии персонального компьютера по месту работы или дома. В этом случае необходимо предварительное согласование индивидуального задания с преподавателем. Во всех случаях содержание отчета по каждой работе должно включать задание, распечатки программ и результатов реализаций. Работа 1. ИСПОЛЬЗОВАНИЕ СОСТАВНЫХ ОБЪЕКТОВ I.
ЦЕЛЬ РАБОТЫ
Ознакомление с основными использования составных объектов.
положениями
методики
II. ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ ПОЛОЖЕНИЯ Язык Prolog позволяет создавать объекты, содержащие другие объекты. Они называются СОСТАВНЫМИ (сложными) объектами. Составные объекты дают возможность рассматривать 24
некоторые множества объектов данных как единое целое. Например, дата 1 января 2000 года, состоящая из трех частей, может быть представлена в виде одного составного объекта: date(1, «января»,2000). Сложные объекты состоят из функтора и соответствующих ему подобъектов: functor (object1, object2, ..., objectN). Функтор - это просто имя, которое определяет вид составного объекта данных и объединяет его аргументы. Функтор без объектов записывается так: functor() или functor. Из этого следует, что простой объект является частным случаем составного объекта. Аргументы составного объекта сами могут быть составными объектами. Например, «2 сентября 1992 года - день рождения Мишы Кукушкина»: birthday(person(«Кукушкин», «Миша»), date(1,«сентября»,1992)). Все составные объекты можно изображать в виде деревьев (см. рис.1). Корнем дерева служит функтор, ветвями, выходящими из него, - компоненты. Если некоторая компонента тоже является составным объектом, тогда ей соответствует поддерево в дереве, изображающем весь составной объект. birthday person «Миша»
«Кукушкин»
date 2
«сентября»
1992
Рис. 1. Пример составного объекта Целесообразность использования составных объектов обычно демонстрируется на следующем примере: пусть у Бори есть Мон-моренси. Это отношение записывается так: 25
owner(«Боря», «Монморенси»). Оба объекта утверждения owner простые и структура, составленная из этих объектов, называется простой структурой. Однако, объект «Монморенси» может быть другом однокласником, или собакой, или каким – то другим домашним животным. Для разделения этих случаев можно записать более конкретные утверждения: owner(«Боря»,friend(«Монморенси»)). /*У Бори есть друг Монморенси*/ или owner(«Боря»,dog(«Монморенси»)). /*У Бори есть собака Монморенси*/. Cтруктура предиката owner будет иметь вид owner (name, article). Если у Бори есть еще книга «Монморенси» автора Марса Мерседесова, лодка (boat) и 10 килограммов картошки, то типы данных описываются в разделе domains так: article = friend (name); dog (name); book (name, name1, name2); boat; potato (weight) name, name1, name2 = symbol weight = integer Примеры составных объектов из области определения article можно использовать в утверждениях, определяющих отношение owner: owner(«Боря», friend(«Монморенси»)). owner(«Боря», dog(«Монморенси»)). owner(«Боря»,book(«Монморенси»,«Марс», «Мерседесов»)). owner(«Боря», boat). owner(«Боря», potato(10)). При введении цели: owner(«Боря», Have). Будет получен ответ: Have = friend(«Монморенси») Have = dog («Монморенси») Have = book («Монморенси», «Марс», «Мерседесов») Have = boat Have = potato(10) Таким образом, описание домена в случае использования 26
составного объекта имеет вид: compDom = f1(d1_1, d1_2,..., d1_n); f2(d2_1, d2_2,..., d2_m); ...; fM(dM_1, dM_2, ..., dM_k), где fi - функтор i-ой альтернативы, {di_j} – множество компонентов i-й структуры.
Составные объекты могут сравниваться с использованием предиката «равенство» (пример 1.1). /*Пример 1.1.*/ domains d = pair(integer, integer); single(integer); none predicates equal(d, d) clauses equal(X, X). При вводе следующих целей имеем: equal(single(1), pair(1,2)). ложно, equal(pair(3,4)), pair(3,4)). истинно, equal(none, none). истинно. Однако, equal(5, 4). - дает ошибку, так как имеется несоответствие доменов. Для удовлетворения последней цели необходимо добавить следующее описание предиката equal: equal(integer, integer), тогда equal(5,4). - ложно, equal(5,5) - истинно. При сравнении объектов типа real нужно быть особенно осторожным (точное сравнение во многих случаях невозможно). Однако, можно, видимо, ввести следующий вариант предиката equal: equal(X,Y):- X/Y < 1.1, X/Y >0.9. Вопросы для самопроверки. 27
1. Структура сложного объекта. 2. Описания домена. 3. Особенности выполнения логических операций.
Работа 2. РЕАЛИЗАЦИЯ ЛОГИЧЕСКИХ ОПЕРАЦИИ
АРИФМЕТИЧЕСКИХ
И
I. ЦЕЛЬ РАБОТЫ Изучение способов реализации арифметических вычислений и логических операций. II. ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ ПОЛОЖЕНИЯ Язык Prolog обладает всеми арифметическими возможностями, присущими другим языкам программирования (Pascal, С). Для этого используется мощный набор математических функций и стандартных предикатов. Реализация арифметических операций Выполнение четырех основных арифметических операций с указанием соответствия типов операндов и результатов выполнения приведены в табл. 2.1. Таблица 2.1. Операнд 1 Оператор Операнд 2 Результат Integer integer +,-,* integer Real real +,-,* integer Real integer +,-,* real Real real +,-* real integer integer Real или / или 28
real
real
Необходимо отметить, что числа можно представлять в различных системах счисления: десятичной или шестнадцатиричной. Последние начинаются со знака доллара ($), например: $2ЕА = 2*16*16+14*16+10 =746. В простом примере 3.1 осуществляется сложение двух чисел, представленных в различных системах счисления. /* Пример 2.1.*/ goal write("AA="),readint(AA),nl, A=-$2EA+AA, write("A=",A). Математические функции языка приведены в табл. 2.2. Причем аргумент X этих функций является арифметическим выражением. АРИФМЕТИЧЕСКИЕ ВЫРАЖЕНИЯ, такие, например, как 4, W или X = (cos(Y) - 1.5) / 3 + 2.5, это константа, или переменная, или конструкция, построенная из них путем использования операторов, функций, или скобок и предиката равенства (=). Таблица 2.2. Предикат Описание abs(X) Абсолютное значение числа Х exp(X) ln(X) lg(X) sqrt(X) sin(X) cos(X) tan(X) arctan(X) random(X)
Вычисляется число е в степени Х Натуральный логарифм Х Десятичный логарифм (X) Квадратный корень из Х
X
(е )
Тригонометрические функции (Х – число, выражающее угол в радианах) Арктангенс действительного числа Х Устанавливает Х, как псевдослучайное вещественное число с равномерным распределением: 0<=X<1 random(Y,X) Cлучайное целое число Х с равномерным 29
round(X) trunc(X) X mod Y X div Y
распределением 0<=X
Использование функции random(RandomReal) позволяет получать последовательность величин RandomReal, равномерно распределенных в интервале 0<= RandomReal <1. А для установления правого граничного значения для случайных величин используется функция randominit(Y). Функция же random(MaxValue,Randomint) выдает последовательность псевдослучайных величин равномерно распределенных в интервал 0<=Randomint<MaxValue. При необходимости получить случайные вещественные числа Z в диапазоне от А до В включительно, нужно воспользоваться следующей целью: random(X), Z = A + X * (B-A+1). Для получения случайных целых чисел Z в диапазоне от А до В включительно можно воспользоваться целью: random(Y,X), Z = A + Y +1. Значение арифметического выражения может быть вычислено только тогда, когда все переменные, находящиеся в правой части, станут конкретизированными. Вычисления осуществляются с учетом приоритета арифметических операций в следующем порядке: - вычисляются выражения в скобках, - во всем выражении реализуются слева направо операции умножения и/или деления, - выполняются слева направо операции сложения и/или вычитания. В примере 2.2. реализуется вычисление значений арифметического выражения. При A=2 и B=0,3 X будет равен - 2,1815545036. Это пример, демонстрирующий программу на языке Prolog, содержащую лишь один раздел (раздел goal). Использование предикатов ввода-вывода будет пояснено ниже. 30
/*Пример 2.2.*/ goal write(«A=»), readint(A), nl, write(«B=»), readreal(B),nl, X = -A + ((cos(B) - 1.5) / 3), write("X=",X). Примеры 2.1 и 2.2 показывают, что язык Prolog может использоваться просто в режиме калькулятора. Для этого, не вводя никакой программы, необходимо войти в окно диалога и набрать то арифметическое выражение, значение которого необходимо вычислить. Пусть необходимо написать программу (пример 2.3), реализующую арифметические операции сложения, вычитания, умножения и деления. Величины, над которыми производятся операции имеют тип real, т.е. они могут быть представлены в любой форме записи целой или вещественной. Запись самой операции имеет тип symbol. Тогда предикат ОПЕРАЦИЯ (operation) имеет, например, следующий вид: operation(symbol, real, real). В разделе clauses описаны правила выполнения операций с выводом результатов вычислений на экран. /*Пример 2.3.*/ predicates operation(symbol,real,real) clauses operation(«+»,X,Y):Z=X+Y, write(X, «+»,Y, «=»,Z),nl. operation(«-»,X,Y):Z=X-Y, write(X, «-»,Y, «=»,Z),nl. operation(«*»,X,Y):Z=X*Y, write(X, «*»,Y, «=»,Z),nl. operation(«/»,X,Y):Z=X/Y, write(X, «/»,Y, «=»,Z),nl. 31
Цели внешние и имеют, например, следующий вид: operation(«/»,5.5,3.4). Результат: 5.5 / 3.4 = 1.6176470588. operation(«+»,3.4,0.006E2) Результат: 3.4 + 0.6 = 4.
Реализация логических операций Язык Prolog позволяет выполнять бинарные операции отношений между арифметическими выражениями, символами, строками и идентификаторами. Для этого используются следующие операторы сравнения: =, <, <=, >, >=, <>(><). Пример сравнения: Y + 2 > 8 - X . Операция «=» устанавливает соответствие между левой и правой частями выражения. При согласовании переменных действуют следующие правила: - если Х неконкретизированная переменная, а Y конкретизированная, то Х и Y равны, целые числа и атомы всегда равны самим себе: например, 613 = 613 , book = book являются верными утверждениями, а 245 = 45, abc = bcd неверными. - две структуры равны, если они имеют один и тот же функтор и одинаковое число аргументов, причем все соответствующие аргументы равны. Когда для сравнения вещественных величин используется предикат равенства, нужно позаботиться о том, чтобы приближенное представление вещественных чисел не привело к непредсказуемым результатам. Так цель 4.9999999999 = 5.0000000000 не будет удовлетворена. Это указывает на то, что при проверке на равенство двух вещественных чисел лучше определять, лежит ли их разность в заранее определенных пределах. 32
Кроме числовых выражений можно также сравнивать простые символы, строки и символические имена, например: ‘a’ < ‘w’, /*тип char*/ «MISHA» < «MASINA», /*string*/ X1=misha, X2=masha, X1>X2 /*symbol*/ При этом Prolog преобразует ‘a’ < ‘w’ в выражение 97 < 119, т.е. сравнивает значения кодов ASCII, и отношение истинно. Сравнение «MISHA» < «MASINA » ложно, т.к. первые отличающиеся символы в сравниваемых строках I и A, а их коды 73 и 65. Соответственно сравнение «bb» > «b» истинно. Cимволические строки нельзя сравнивать непосредственно. В примере X1=misha, X2=masha символическое имя misha не может быть сравнено непосредственно с masha . Они должны быть связаны с переменными или записаны как строки (тип string). В примере 2.4 осуществляется проверка принадлежности целых чисел Z интервалу (Х,Y), где Х - минимальная граница интервала, а Y - максимальная. /*Пример 2.4.*/ predicates include(integer, integer, integer) clauses include(X,Y,Z):Z>=X, Z<=Y, nl, write(«Число »,Z, « лежит в интервале от »,X,« до », Y,«.»). Вопросы для самопроверки 1. Какое назначение предиката random(RandomReal)? 2. Как использовать язык Prolog в режиме калькулятора? 3. Перечислире основные правила установления соответствия между левой и правой частями выражения при выполнении операции «=». Работа 3. УПРАВЛЕНИЕ ПОИСКОМ РЕШЕНИЯ I. ЦЕЛЬ РАБОТЫ 33
Изучение способов реализации рекурсивных зависимостей. II. ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ ПОЛОЖЕНИЯ В языке Prolog используются две конструкции правил, реализующих многократное выполнение задачи. Это ПОВТОРЕНИЕ и РЕКУРСИЯ. Структура правила, реализующего повторение, такая: repetitive_rule:<предикаты и правила>, fail. /*неудача*/. Структура правила, реализующего рекурсию: recursive_rule:<предикаты и правила>, recursive_rule. В правиле, реализующем повторение, используется встроенный предикат fail (неудача). Это всегда ложный предикат, вызывающий откат для поиска других утверждений, которые бы обеспечили вычисление цели. В теле правила рекурсии последним правилом является само правило recursive_rule. Используемая конструкция <предикаты и правила> в теле правил содержит предикаты и правила программы. МЕТОД ОТКАТА ПОСЛЕ НЕУДАЧИ Для управления вычислением внутренней цели ПРИ ПОИСКЕ ВСЕХ ВОЗМОЖНЫХ РЕШЕНИЙ используется метод отката после неудачи. Правило repetitive_rule:<предикаты и правила>, fail. будет выполняться столько раз, сколько существует альтернатив для введенной цели. Для демонстрации использования предиката fail и метода ОПН можно привести пример 3.1 о городах. В результате выполнения этой программы выводится небольшой перечень городов северозапада России, включенных в базу данных. /*Пример 3.1.*/ 34
domains name=symbol predicates town(name) show_towns goal write("Города северо-запада России:"),nl, show_towns. clauses town ("Петербург"). town ("Новгород"). town("Псков"). town ("Петрозаводск"). town ("Выборг"). town ("Ивангород"). town ("Ладога"). town ("Вологда"). show_ towns:town (Town), write(" ", Town),nl, fail. На рис. 3.1 изображен процесс отката при реализации примера 3.1. База данных примера содержит 8 альтернативных утверждений для предиката town(name). Prolog ищет в базе данных сопоставимые утверждения, при этом внутренние унификационные программы (ВУПы) сначала означивают переменную Town объектом первого утверждения Петербург. Но существуют и другие утверждения в базе, которые могли бы быть использованы при вычислении подцели town(Town). Поэтому для запоминания места возможного отката ВУПы устанавливают указатель отката (1) (рис. 3.1) на следующее Goal: town(Town),write(Town),nl,fail. База данных town("Петербург"). 1 town("Новгород").
write("Петербург") Town =Петербург Откат к отметке 1 Town =Новгород 35
2 town("Псков").
Повторение для каждого утверждения.
... Рис. 3.1. Схема работы программы о городах утверждение базы данных - town("Новгород"). Значение Петербург переменной Town выводится на экран монитора, предикат fail вызывает неуспешное завершение правила, переменная Town освобождается, а ВУПы осуществляют откат в точку 1 и так далее. Этот пример показывает применение метода ОПН для извлечения данных из каждого утверждения базы данных при использовании внутренней цели. МЕТОД ОТСЕЧЕHИЯ И ОТКАТА Для того, чтобы пpи выполнении пpогpаммы была возможность ОГРАHИЧИТЬ ПОИСК В БАЗЕ ДАННЫХ, используют сpедства упpавления откатом. Это сpедство называется МЕТОДОМ ОТСЕЧЕHИЯ И ОТКАТА (ОО) и позволяет, используя встpоенный пpедикат cut, котоpый обозначается символом восклицательного знака (!), осуществлять «фильтpацию данных» по некотоpым условиям, т.е. УПРАВЛЯТЬ МЕХАHИЗМОМ АВТОМАТИЧЕСКИХ ОТКАТОВ. Этот пpедикат, вычисление котоpого всегда успешно, заставляет ВУПы заблокиpовать все указатели откатов, установленные пpи вычислении пpедыдущих подцелей. Hапpимеp, имеется некотоpое пpавило: pr:-aa,bb,!,cc и пpедикату аa соответствуют факты и пpавила а1, а2, a3; пpедикату bb - b1, b2; cc - c1, c2, c3, c4. Если бы отсутствовал пpедикaт cut, то было бы пpедпpинято 3*2*4=24 попытки поиска pешений. Hо пусть осуществляется последовательный поиск pешения с откатом до тех поp, пока факт а1 не удовлетвоpит пpедикату aа, а b1 - пpедикату bb, далее пpоисходит успешное завеpшение пpедиката cut. Затем пpи пеpебоpе фактов, соответствующих пpедикату сс, делается попытка отката на пpедыдущий пpедикат bb, но cut (отсечение) не позволяет это сделать и пpоцесс поиска альтеpнативных pешений в пpавиле заканчивается. 36
В связи с отсутствием в языке Prolog констpукций, аналогичных опеpатоpам циклов пpоцедуpных языков, отличительной его особенностью от большинства языков пpогpаммиpования является шиpокое использование РЕКУРСИИ. Рекуpсией называется пpавило, содеpжащее само себя в качестве компоненты. Обычно Prolog-пpогpамма пpедставляет собой совокупность pекуpсивных или взаимоpекуpсивных опpеделений. ПРОСТАЯ РЕКУРСИЯ Пpежде всего необходимо показать подводные камни, возникающие пpи использовании pекуpсии. Следующее пpавило pr:- pr имеет такой смысл: "pr истинно, если pr истинно". Hепосpедственное использование этого пpавила может пpивести к бесконечному циклу (бесконечной pекуpсии), а это пpиведет к пеpеполнению стека, что нежелательно, т.к. могут быть потеpяны пpомежуточные pезультаты вычислений. Hиже пpиводится пpимеp пpогpаммы с использованием бесконечной pекуpсии: predicates write_string goal write_string. clauses write_string:write("Изучайте PDC Prolog!"),nl, write_string. Пpи запуске этой пpогpаммы на экpан выдается стpока "Изучайте PDC Prolog!", а т.к. последняя компонента пpавила write_string является самим пpавилом, то опять осуществляется выдача на экpан той же стpоки и т.д. Такая pекуpсия называется БЕСКОHЕЧHОЙ и пpактического пpименения не имеет. Рекуpсия может стать конечной, если в пpавило включается УСЛОВИЕ ВЫХОДА. Пусть, например, генерируется последовательность целых случайных величин, равномерно 37
распределенных в интервале от 0 до 9, до тех пор пока не будет получено число 5. В этом случае процесс генерации и выполнение программы завершается (пример 3.2). /*Пpимеp 3.2.*/ predicates write_number goal write_number. clauses write_number:random(9,Randomint), Randomint < > 5, write(« »,Randomint), write_number. Первой компонентой правила write_number является встроенный предикат random, генерирующий последовательность случайных величин. Значение случайной величины присваивается переменной Randomint. Следующее подправило проверяет, является ли означенное значение переменной Randomint числом 5. Если нет, то подправило успешно, число выводится на экран и производится рекурсивный вызов write_number. Процесс продолжается до тех пор, пока не будет сгенерировано число 5. После этого выполнение программы завершается. ОБОБЩЕHHОЕ ПРАВИЛО РЕКУРСИИ Схематически обобщенное пpавило pекуpсии (ОПР) записывается следующим обpазом: <имя пpавила pекуpсии>:<список пpедикатов>, <пpедикат, опpеделяющий условие выхода>, <список пpедикатов>, <имя пpавила pекуpсии>, <список пpедикатов>. Пpинцип pаботы этого пpавила идентичен pаботе пpавила пpостой pекуpсии. Тpи констpукции <список пpедикатов> на pекуpсию не оказывают влияния. Успешное выполнение пpедиката, 38
опpеделяющего условие выхода, вызывает пpодолжение pекуpсии, а неуспешное - ее пpекpащение. Констpукция в теле пpавила <имя пpавила pекуpсии> - это само pекуpсивное пpавило и его успех вызывает (пpодолжает) pекуpсию. Для получения навыков использования ОПР-метода необходимо pассмотpеть еще два пpимеpа: генеpации (без использования предиката random) pяда чисел (пpимеp 3.3) и вычисления фактоpиала (3.4). Пусть тpебуется сгенеpиpовать последовательность целых чисел от 1 до 5 (пpимеp 3.3). /*Пpимеp 3.3.*/ predicates number(integer) goal write("Числовой pяд:"), number(1), write(" . Конец!"). clauses number(6). number(Number):Number<6, write(" ", Number), New_number=Number+1, number(New_number). В pассматpиваемом пpимеpе пеpвая и последняя констpукции <список пpедикатов> общего пpавила pекуpсии не используются. Именем пpавила pекуpсии является: number(Number). В этом пpавиле пpедикатом, опpеделяющим, условие выхода, является Number<6 и, когда Number=6, пpавило успешно, а пpогpамма завеpшается. Сpедняя констpукция <список пpедикатов> выводит на экpан значение пеpеменной Number и затем увеличивает ее на единицу New_number=Number+1. Пpичем для нового числа используется новая пеpеменная New_number. И, наконец, пpогpамма завеpшается именем пpавила pекуpсии в теле пpавила number(New_number). Пpи запуске пpогpаммы осуществляется попытка вычислить 39
подцель number(1) и для этого она безуспешно сопоставляется с утвеpждением number(6). Затем эта подцель сопоставляется с головой пpавила number(Number) и сопоставление успешно, а пеpеменная Number пpинимат значение 1. Сpавнение 1<6 успешно, поэтому условие выхода не выполняется, и значение пеpеменной Number=1 выводится на экpан, а пеpеменная New_number становится pавной 2. Затем пpавило number(New_number) со значением паpаметpа 2, пpисвоенным пеpеменной New_number, вызывает само себя. Hесовпадение имен пеpеменных Number и New_number не имеет значения, т.к. они указывают пpи пеpедаче значений только на позицию в списке паpаметpов. Далее пpодолжается выполнение пpогpаммы пока New_number не станет pавным 6, а это значит, что условие выхода выполняется успешно и пpогpамма завеpшается. Результат на экpане такой: Числовой pяд: 1,2,3,4,5. Конец! Следующий пpимеp посвящен вычислению факториала n! = n * (n-1) * (n-2) *...* 3 * 2 * 1. Причем n! = n * (n-1)!, a 1! = 1. Например 6! = 6 * 5 * 4 * 3 * 2 * 1 = 720. /*Пример 3.4.*/ domains n=integer f=real predicates factor(n,f) goal write("n="),readint(N),nl,write(N,"!="), factor(N,F), write(F),nl. clauses factor(0,1):-!. factor(N,F):NN=N-1,factor(NN,PF),F=N*PF. Вопросы для самопроверки 1. Объясните назначение предикатов fail и cut. 40
2. Как реализуется метод отсечения и отката? 3. Объясните структуру обобщенного правила рекурсии. Работа 4. ОБРАБОТКА СПИСКОВ I. ЦЕЛЬ РАБОТЫ Изучение приемов задания списков и способов реализации операций над списками. II. ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ ПОЛОЖЕНИЯ СПИСОК - это динамическая структура, элементами которой могут быть атомы, списки или структуры. Список является еще одним типом данных наравне с основными типами char, integer, real, string, symbol и file. Это упорядоченная последовательность равноправных объектов, которая может иметь произвольную длину. Список - это набор объектов одного и того же типа. Элементом списка может быть атом, переменная, составной терм или список. Основное отличие списков от массивов, используемых в процедурных языках заключается в том, что в списке никогда не задается количество элементов (массив же обычно имеет фиксированную длину), в него не могут входить элементы разных типов данных. Элементы списка заключаются в квадратные скобки и отделяются друг от друга запятыми. Ниже приведены примеры списков с элементами типа real, integer и symbol: [1.4,2.4,3.5,3.6,4.7], [0,1,2,3,4,5,6], ["Информатика", "Программирование", "Интеллект"]. Важно, что все элементы списка принадлежат к одному типу доменов. Поэтому список [a,'b',"c"] некорректен, т.к. состоит из элементов разных типов. Количество элементов списка называется его длиной. Длина списка ["Миша", "Маша", "Вася"] равна 3. Пустым или нулевым списком называется список, не 41
содержащий элементов. В этом случае он называется атомом и обозначается так: []. Использование списка требует его описания по крайней мере в трех разделах программы. В разделе domains описывается используемый тип данных. Например: domains town_list=town*/*объявляется список городов*/ town=symbol/* объявляются элементы town списка town_list; их тип symbol*/ или объявление типа данных может быть таким: town_list=symbol*. Если список состоит, например, из списков целых чисел [[1,2,3],[2,3,4],[3,6,7],[]] , то его объявление ничем не отличается от предыдущего: listList = integer* . В разделе predicates указывается имя предиката и в скобках имя списка towns(town_list) или numbers(listList). В разделе clauses, как всегда, приводятся утверждения, т.е. конкретные значения предикатов. Пример 4.1 иллюстрирует описание списка городов. /* Пример 4.1.*/ domains town_list=town* town=symbol predicates towns(town_list) clauses towns([«Петербург»,«Псков»,«Новгород»,«Ладога»,«Ямбург»]). Реализация такой программы возможна при использовании, например, следующих внешних целей: towns(All). или towns([X,_,_,Y,_]). Список не имеет никаких предикатов для своей обработки. Для снятия этого неудобства введена единственная операция над элементами списка, называемая МЕТОДОМ РАЗДЕЛЕНИЯ 42
СПИСКА НА ГОЛОВУ И ХВОСТ. При этом непустой список рассматривается как структура, состоящая из двух частей: [Head|Tail]. Переменная Head (голова списка) это его первый элемент или фиксированное количество элементов, отделенных символом "|" (вертикальная черта). А переменная Tail (хвост) это список оставшихся элементов списка. В таблице 4.1 приведены примеры деления списка на голову и хвост. При этом видно, что хвост списка - всегда список, а Таблица 4.1 Список Голова Хвост [2,3,4] 1 [1,2,3,4] [] abcd [abcd] ["PDC","Prolog"] Изучайте ["Изучайте","PDC","Prolog"] [C-D] A*B [A*B,C-D] [h,[i,J]] [E,F,G] [[E,F,G],h,[i,J]] Не определено Не определено [] голова - элемент списка, и разделение списка на голову и хвост не зависит от длины списка. Последовательное применение этого метода позволяет легко осуществлять различные операции над списками и написать практически любую программу по обработке любого мыслимого списка. Как осуществляется сопоставление списков? Варианты результатов сопоставления представлены в таблице 4.2. Список 1 [A] [5] [A,B,C] [a,b,c,d] [a,A,b] [x,y,z] [x|[y|[z|[]]]] [A|B] [x,X,B]
Список 2 [2] [A1|A2] [0,1,2] [A,[B|B1]] [B,c,C] [A,B,C|D] X [] [A,w,A]
Таблица 5.2 Результат A=2 A1=5, A2=[] A=0, B=1, C=2 A=a, B=b, B1=[c,d] B=a, A=c, C=b A=x, B=y, C=z, D=[] X=[x,y,z] Ошибка A=x, X=w, B=x 43
Пример 4.2 показывает использование метода разделения списка для осуществления доступа к его элементам. В этом примере используется рекурсивное правило для реализации доступа к элементам списка. Если ввести цель towns([«Петербург»,«Псков»,«Новгород»,«Ладога»,«Ямбург»]). то в результате будет выведен на экран монитора список городов по одному на каждой строке. /*Пример 4.2.*/ domains town_list=town* town=symbol predicates towns(town_list) clauses towns([]). towns([H|T]):write(H),nl,towns(T). ОПЕРАЦИИ НАД СПИСКАМИ Для успешного использования списковых структур необходимо освоить наиболее распространенные операции: поиск элементов в списке, деление списка, определение количества элементов, присоединение списков, сортировка списка, компоновка данных в список. Эти операции осуществляются, как правило, путем использования правил рекурсии. Ниже приводится реализация одной из этих операций. Так как список - динамическая структура, которая может иметь произвольное количество элементов, то часто желательно знать это количество. Определение количества элементов (пример 4.3) реализуется путем использования метода разделения списка на голову и хвост и одновременного увеличения счетчика количества элементов на единицу. 44
/*Пример 4.3.*/ domains list=integer* predicates length(list,integer) clauses length([],0). length([H|T],Sum):length(T,Sum1),Sum=Sum1+1. При вводе внешней цели length([4,7,15,28],N). будет получен результат N = 4. Вопросы для самопроверки 1. Проиллюстрируйте на примере метод разделения списка на голову и хвост. 2. Как реализуется операция поиска элемента в списке? 3. Напишите программу разделения списка на три части. Работа 5. ОБРАБОТКА СТРОК I.
ЦЕЛЬ РАБОТЫ
Изучение способов представления символов и строк, а также реализаций операций над строками. II. ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ ПОЛОЖЕНИЯ СТРОКА (string) - это один из типов данных, с которыми работает Prolog. Это набор символов английского или русского алфавита, цифры, специальные символы %, $, @ и многие другие, а также управляющие символы. Строка является самым распространенным объектом в программировании. Это последовательность символов, набираемых на клавиатуре, команды управления программами и обрабатываемые данные. 45
Поэтому очень важно освоить все многообразие операций, выполняемых над строками. ПРЕДСТАВЛЕНИЕ СИМВОЛОВ И СТРОК Система числовых кодов, используемая при программировании, имеет единый стандарт и называется Американским стандартным кодом для обмена информацией (American Standard Coding for Information interchange (ASCII)). Обычно таблица кодов ASCII подразделяется на две части, две половины. Первая из них содержит коды от 0 до 127 и, как правило, не изменяется. Во второй, с кодами от 128 до 255, помещены буквы национальных алфавитов и специальные символы. Первые 32 кода (от 0 до 31) являются управляющими и служат, как правило, для передачи команд управления, например: код 3 - прерывание выполнения программы (Ctrl-C) , код 10 - конец строки (Ctrl-J), код 13 - возврат каретки (Ctrl-M), код 20 - включение и выключение трассировки (Ctrl-T), код 27 - Esc и т.д. С 32-го кода кодируются служебные символы (пробел -32, запятая - 44 и т.д.), затем цифры от 0 до 9 с кодами от 48 до 57. С 65 по 90 кодируются прописные буквы латинского алфавита от A до Z. С 97 по 122 - строчные буквы от a до z. Русские строчные буквы - А, Б, В, ..., Я - коды 128, 129, 130, ..., 159, прописные русские буквы а, б, в, ..., м, н, о, п - 160-175, р, с, т, ..., я - 224 - 239, е - 240. Для представления с помощью кодов ASCII одиночного символа используется его код (N), перед которым ставится обратный слэш (\), и все заключается в одиночные кавычки: ‘\N’ . А для представления строки символов коды каждого символа записываются один за другим и вся последовательность заключается в двойные кавычки: «\N\N\N\N» . Например, десятичный код символа Я есть 159, поэтому этот единичный символ представляется так: ‘\159’ , строка РОССИЯ «\144\142\145\145\136\159» , PDC Prolog «\80\68\67\32\80\114\111\108\111\103» . Десятичное число 1937.48 46
«\49\57\51\55\46\52\56» . Все эти записи символов и строк с помощью кодов ASCII могут широко использоваться в различных задачах. ОПЕРАЦИИ НАД СТРОКАМИ Все многообразие операций над строками можно условно разделить на две группы: операции над структурой самих строк (определение длины строки, конкатенация, создание подстрок, преобразование строк в списки) и операции преобразования типов. Для реализации первой группы операций используется несколько встроенных предикатов. Большинство стандартных предикатов могут использоваться для выполнения нескольких функций в зависимости от того, как эти предикаты вызываются. В зависимости от ситуации определенный параметр может иметь известное значение. В другой ситуации некоторые параметры могут быть неизвестны. А для определенных целей некоторые параметры должны иметь значение в момент вызова предиката. Известные параметры называют входными (in), а неизвестные – выходными (out). Сочетание входных и выходных параметров в момент вызова предиката определяет характер его выполнения. Это сочетание параметров называют текущим состоянием параметров (flow pattern). Если предикат имеет два параметра, то возможны четыре текущих состояния: (i,i), (i,o), (o,i), (o,o). Где “i” означает входной параметр, а “o” – выходной. Не имеет смысла использовать каждый предикат для всех возможных состояний входных параметров. Например, не следует вызывать предикат readchar(X) c переменной Х, имеющей значение, т.е. со входным (i) параметром. В этой работе описание стандартных предикатов будет сопровождаться указанием возможных текущих состояний. ОПРЕДЕЛЕНИЕ ДЛИНЫ СТРОКИ Длина строки - это количество символов в строке. Для этого используется встроенный предикат str_len (String_value, String_length), (i,i),(i,o),(o,i) где String_value - переменная со строковым значением, а 47
String_length - длина этой строки. Например, при обработке предиката str_len(«Россия»,Z) переменная Z означивается значением длины строки «Россия» (Z=6). Результат обработки предиката str_len(S,L) успешен, если S=ABC, а L=3 и неуспешен, например, если S=1999, а L=2. Пример 5.1 демонстрирует использование этого предиката. /*Пример 5.1.*/ predicates st (string) find_length /* найти длину строки st */ goal find_length. clauses st(« Темы практических занятий:»). st(« - введение в язык PDC Prolog;»). st(« - правила;»). st(« - структуры;»). st(« - арифметика;»). st(« - рекурсия;»). st(« и т.д.»). find_length:st (S), str_len (S,L), write(S, «(», L, «)»), nl, fail. КОНКАТЕНАЦИЯ СТРОК Под этой операцией подразумевается объединение исходных строк с целью образования одной новой строки: concat (String1, String2, String3) (i,i,o),(o,i,i),(i,o,i),(i,i,i). При использовании по «прямому» назначению встроенного предиката concat объекты String1 и String2 являются входными строками, а String3 - объединенная выходная строка. Следующий пример 5.2 демонстрирует объединение четырех строк: - 191186, - Санкт-Петербург, - ул. Миллионная, 5, - СЗПИ. 48
В этом примере строки переменными: A, B, C,...
представлены
односимвольными
/*Пример 5.2.*/ predicates pr goal pr. clauses pr:nl,nl, A= «191186,», B= « Санкт-Петербург,», С= « ул. Миллионная, 5,», D= « СЗПИ», concat (A,B,E), concat (C,D,F), concat (E,F,G), write (G). Встроенный предикат frontchar(Str1, Char, Str2) (i,o,o),(i,i,o),(i,o,i),(i,i,i),(o,i,i) аналогичен предикату concat. Отличие заключается в том, что frontchar присоединяет значение переменной Char ( а она имеет тип char) только К НАЧАЛУ СТРОКИ. При этом возможно три варианта использования предиката frontchar, а условно эти варианты можно представить так: Str1 = Char + Str2, Char = Str1 - Str2, Str2 = Str1 - Char. Объединяя работу этого предиката с рекурсивной обработкой списка можно реализовать расщепление строки в последовательность символов, или, наоборот, для создания строки из последовательности символов, или, наконец, для проверки символов в строке. Пример 5.3 демонстрирует преобразование строки в список символов с использованием предиката frontchar. /*Пример 5.3.*/ 49
domains charlist = char* str = string predicates str_list (str, charlist) clauses str_list («», []). str_list (S, [H|T]):frontchar (S, H, S1), str_list (S1,T). В правиле str_list первым параметром является строка, а вторым - список. Предикат frontchar рекурсивно извлекает первый символ из S и помещает его в список. В разделе domains объект charlist является списком символов, а str -строкой. При вводе цели str_list(«СЗПИ», A) переменная A связывается со списком [’С’,’З’,’П’,’И’]. СОЗДАНИЕ ПОДСТРОК Подстрока - это строка, являющаяся копией некоторой части исходной строки. Для создания подстрок используется встроенный предикат frontstr (N, Str1, StartStr, EndStr) (i,i,o,o). Аргументу StartStr присваивается подстрока из N первых символов исходной строки Str1, а EndStr присваивается остаток строки Str1. Например, утверждение frontstr( 13, «Искусственный интеллект», StartStr, EndStr). Присваивает StartStr значение «Искусственный», а EndStr «интеллект», т.к. N = 13 соответствует числу символов слова «Искусственный». Кроме рассмотренных в этом параграфе встроенных предикатов, широко используемых для преобразования строк, можно перечислить еще целый ряд предикатов: subchar (String, Position, Char) (i,i,o) - переменной Char присваивается элемент строки String в позиции Position. 50
substring (String, Position, Length, Substring) (i,i,i,o) переменной Substring присваивается часть строки String, начинающейся с позиции Position и имеющей длину Length. searchchar (String, Char, Position) (i,i,o) - переменной Position присваивается номер позиции в строке String, в которой впервые встречается символ Char. searchstring (String, Substring, Position) (i,i,o) - переменной Position присваивается номер позиции в строке String, с которой начинается подстрока Substring. ОПЕРАЦИИ ПРЕОБРАЗОВАНИЯ ТИПОВ Для преобразования данных из одного типа в другой используются следующие предикаты char_int, str_char, str_int, str_real, upper_lower. Их применение целесообразно при выполнении преобразований между символом и его значением в коде ASCII, между строкой и символом, строкой и целым, строкой и вещественным, символами верхнего и нижнего регистра. Все предикаты преобразования типов содержат два объекта, а имена предикатов показывают тип выполняемого преобразования: char_int (Char, Integer), (i,o),(o,i),(i,i), str_char (String, Char), (i,o),(o,i),(i,i), str_int (String, Integer), (i,o),(o,i),(i,i), str_real (String, Real), (i,o),(o,i),(i,i), upper_lower (Upper, Lower).(i,i),(i,o),(o,i). Все эти предикаты осуществляют преобразование в прямом и обратном направлении (например, str_char: String Æ Char, или Char ÆString) или проверяется соответствие аргументов друг другу (в случае соответствия - Yes, в противном случае -No). Пример 5.4 демонстрирует преобразования типов. /* Пример 5.4.*/ predicates do_conversions
использование
предикатов
/*выполнить преобразования*/ 51
goal do_conversions. clauses do_conversions:write («ПРЕОБРАЗОВАНИЯ ТИПОВ:»),nl,nl, char_int (‘W’,N1), write (« », ‘W’, «-->», N1), nl, write («Для продолжения нажимайте любую клавишу!»), readchar (_), str_char («B»,N2), write («\10\10\32\32», «B», «-->», N2, ‘\10’), readchar (_), str_int («\53», N3), write («\32\32\32\32», «Код ASCII=53», «-->», N3), readchar (_), str_real (N4,33), write («\10\32\32\32\32», «33», «-->»,N4,), readchar (_), upper_lower («PROLOG», N5), write (« PROLOG», «-->»,N5). Вопросы для самопроверки 1. Как представляется строка символов с помощью кодов ASCII? 2. Какой предикат используется для конкатенации строк? 3. Перечислите предикаты, используемые для преобразования типов.
Работа 6. ХРАНЕНИЕ НОСИТЕЛЯХ
ФАЙЛОВ
НА
ВНЕШНИХ
I. ЦЕЛЬ РАБОТЫ Ознакомиться с принципами файловой организации данных в языке Prolog. 52
II. ОСНОВНЫЕ ТЕОРЕТИЧЕСКИЕ ПОЛОЖЕНИЯ Файловая система языка Prolog включает стандартные предикаты открытия и закрытия файлов, чтения из файла и записи в файл, изменение данных в файле, а также дозаписи в существующий файл. Тем самым обеспечиваются великолепные возможности эффективной обработки файлов. Обычно клавиатура является устройством чтения (ввода) информации, а текущим устройством записи (вывода) - экран монитора. Однако, можно определить и другие устройства ввода или вывода в процессе выполнения программы. Например, ввод - из файла, а вывод - на устройство печати. Для всех устройств ввода(вывода) ввод(вывод) производится идентично. Сначала файл должен быть открыт и сделать это можно одним из следующих способов: для чтения, записи, добавления и модификации. Файл, открытый для любого действия, кроме чтения, необходимо закрыть после окончания работы. В противном случае информацию можно потерять. Одновременно могут быть открыты несколько файлов. Открытие и закрытие файлов при каждом обращении занимает много больше времени, чем обращение к открытым файлам с целью записи или чтения информации из них. При открытии файла производится связывание символического имени с действительным именем, принятым в MS DOS. Это символическое имя и используется для направления ввода/вывода. Символическое имя файла (оно называется еще и логическим именем) должно начинаться со строчной (маленькой) латинской буквы и объявляется в описании домена file. Это описание должно быть единственным в программе. Например: file=mybase1 или file=database1;dfile2;dfile3, т.е. во втором случае объявлено три логических имени для отождествления их с реальными файлами DOS. Это описание несколько отличается от обычного, когда слева пишется имя домена, а справа - его тип, например man,woman = symbol. Ниже описываются стандартные предикаты для открытия и 53
закрытия файлов. ЗАПИСЬ В ФАЙЛ Открытие файла для записи начинается с его создания. Файл DOSFileName открывается для записи по логическому имени SymbolFileName: openwrite(SymbolFileName, DOSFileName). Например: openwrite(myfile1, «file1.dat»). Т.е. устанавливается связь между объектами myfile1 и file1.dat, а ссылка на myfile1 означает обращение к file1.dat. Если файл file1.dat уже существует, то его содержимое будет утеряно. Для избежания этого сначала проверяется наличие этого файла existfile(«file1.dat»). Назначение файла myfile1 в качестве устройства записи реализует предикат writedevice(myfile1). Собственно запись в файл реализуется любыми предикатами write или writef. При этом ввод будет происходить не на экран, а в файл. И, наконец, закрытие файла myfile1 реализует предикат closefile(myfile1). Т.о. вся процедура записи в файл складывается из следующих этапов: открытие файла, назначение файла в качестве устройства записи, сама запись и закрытие его. Например: openwrite(myfile1, «file1.dat»), writedevice(myfile1), <предикаты и правила записи в файл>, <любые другие предикаты и правила>, closefile(myfile1). ЧТЕНИЕ ИЗ ФАЙЛА Если файл уже создан, то он готов для осуществления некоторых операций: считывание всех данных или выборочно, модификация данных, добавление данных в конец файла. Уже созданный файл DOSFileName открывается для чтения по логическому имени SymbolFileName: 54
openread(SymbolFileName, DOSFileName). Например: openread(myfile1, «file1.dat»). Предикат readdevice(SymbolFileName) назначает файл DOSFileName устройством чтения. Предикат closefile(SymbolicFileName) закрывает файл. Например: openread(myfile1, «file1.dat»). writedevice(myfile1). <предикаты и правила записи в файл>, <любые другие предикаты и правила>, closefile(myfile1). МОДИФИКАЦИЯ СУЩЕСТВУЮЩЕГО ФАЙЛА Эта операция несколько отличается от предыдущих. Сначала существующий файл открывается для модификации (чтения и записи) с помощью следующего предиката: openmodify(SymbolFileName, DOSFileName). Нужно учитывать, что позиция символа в файле определяется его удаленностью от самого первого символа: в нулевой позиции - 1-й символ, в первой - 2-й символ и т.д. При открытии или модификации файла указатель находится в начале. Но указатель символа можно устанавливать и в любую позицию файла при использовании предиката filepos. Вся процедура модификации файла складывается из следующих этапов: открытие, назначение файла в качестве устройства записи, запись в файл и закрытие его. Например: openmodify(myfile1, «file1.dat»), writedevice(myfile1), <правила выборочной записи в файл>, <любые другие предикаты и правила>, closefile(myfile1). ДОЗАПИСЬ В КОНЕЦ СУЩЕСТВУЮЩЕГО ФАЙЛА Для реализации этой операции используется предикат 55
openappend(SymbolFileName, DOSFileName). Вся процедура дозаписи очевидна из описаний предыдущих операций. Например: openappend(myfile1, «file1.dat»), writedevice(myfile1), <правила дозаписи>, <любые другие предикаты и правила>, closefile(myfile1). В примере 6.1 демонстрируется вывод информации статической БД в файл на диске и на экран монитора.
из
/*Пример 6.1.*/ domains file=myfile predicates data(symbol) write_lines goal openwrite(myfile, «PETER.DAT»), write_lines, closefile(myfile). clauses data(«Люблю тебя, Петра творенье,»). data(«Люблю твой строгий, стройный вид,»). data(«Невы державное теченье,»). data(«Береговой ее гранит.»). write_lines:data(«Line»), write(« »,Line),nl, writedevice(myfile), write(« »,Line),nl, writedevice(screen), fail. write_line. В примере 6.2 демонстрируется чтение данных из файла PETER.DAT и вывод прочитанной информации на экран и принтер. 56
/*Пример 6.2.*/ domains file=myfile1 predicates write_data goal openread(myfile1, «PETER.DAT»), write_data, closefile(myfile1). clauses write_data:readdevice(myfile1), not(eof(myfile1)), readln(Line), writedevice(screen), write(« »,Line), readln(Line), writedevice(printer), write(« »,Line), write_data. fail. write_data. В программе применен встроенный предикат eof. Он дает успех, когда найден признак конца файла. Использование логического отрицания not(eof(myfile1)) означает следующее: «Продолжать пока не будет достигнут конец файла». Вопросы для самопроверки 1. Поясните назначение символического имени файла. 2. Перечислите стандартные предикаты, используемые при открытии и закрытии файлов. 3. Приведите последовательность предикатов при записи данных в файл.
57
СОДЕРЖАНИЕ Предисловие....................................................................................3 Рабочая программа.........................................................................4 Перечень лабораторных работ.......................................................7 Литература.......................................................................................7 План лекций....................................................................................8 Методические указания к изучению дисциплины……………9 Задание на контрольную работу..................................................20 Методические указания к выполнению контрольной работы...21 Указания к проведению лабораторных работ............................24 Работа 1. Использование составных объектов ……………25 Работа 2. Реализация арифметических и логических операций …………………………………………29 Работа 3. Управление поиском решения…………………34 Работа 4. Обработка списков………………………………42 Работа 5. Обработка строк ………………………………...46 Работа 6. Хранение файлов на внешних носителях…….54
58
ЛР N 020308
от 14.02.97.
Редактор Подписано к печати . . 2002 г. Бумага оберточная. П.л. , . Б.л. , . РТП РИО СЗТУ. Тираж 100 экз. Заказ . Редакционно-издательский отдел Северо-Западного государственный заочного технического университет 191186, Санкт-Петербург, Миллионная, 5
59