Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Сборник заданий по программированию на языках Лисп, ФРЛ и Пролог.doc
Скачиваний:
52
Добавлен:
28.06.2014
Размер:
226.82 Кб
Скачать

ГОСУДАРСТВЕННЫЙ КОМИТЕТ РОССИЙСКОЙ ФЕДЕРАЦИИ

ПО ВЫСШЕМУ ОБРАЗОВАНИЮ

----------------------

МОСКОВСКИЙ ЭНЕРГЕТИЧЕСКИЙ ИНСТИТУТ

-----------------------------------------------------

Утверждено

учебным управлением МЭИ

МЕТОДИЧЕСКИЕ УКАЗАНИЯ

по курсу

Языки и методы программирования

СБОРНИК ЗАДАНИЙ ПО ПРОГРАММИРОВАНИЮ

НА ЯЗЫКАХ ЛИСП, ФРЛ И ПРОЛОГ

Москва Издательство МЭИ 1997

.

- 2 -

УДК

621.398

М 545

УДК: 681.3.06(072)

 Сборник заданий по программированию на языках ЛИСП,

 ФРЛ и ПРОЛОГ. Байдун В.В., Чернов П.Л. / Под ред. Чернова

 П.Л. - М.: Изд-во МЭИ, 1996 - 40 с.

В методических указаниях приводятся задания по прог-

раммированию на языках ЛИСП, ФРЛ и ПРОЛОГ. Рассматрива-

ются вопросы методики написания программ на этих языках

"искуственного интеллекта", применяемых при построении

баз знаний на основе сетевых и логических моделей пред-

ставления знаний. Приводятся пояснительные примеры.

Указания предназначены для слушателей ФПКП и студен-

тов специальности "Прикладная математика", выполняющих

практические задания и типовой расчет с применением пер-

сональных ЭВМ, а также для аспирантов, занимающихся

практическими вопросами разработки и реализации систем,

ориентированных на знания.

─────────────────────

С Московский энергетический институт, 1997 г.

.

- 3 -

ВВЕДЕНИЕ

Проблема представления и обработки знаний является ключевой

для области искусственного интеллекта. От ее успешного решения не-

посредственно зависят эффективность и "интеллектуальность" приклад-

ных программных систем.

В рамках второй части курса "Языки и методы программирования"

рассматриваются и изучаются инструментальные средства разработки

интеллектуальных систем, основанных на сетевых и логических моделях

представления знаний. Практическое освоение языков программирования

ЛИСП ( LISP - LISt Processing ), ФРЛ ( FRL - Frame Representation

Language ) и ПРОЛОГ ( PROLOG - PROgramming in LOGic ) выполняется

на практических и лабораторных занятиях, а также самостоятельно при

выполнении курсовой работы.

.

- 4 -

1. ЗАДАНИЯ ДЛЯ ПРАКТИЧЕСКИХ ЗАНЯТИЙ

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

рования задач, в том числе и однотипных, на различных языках прог-

раммирования. В каждом разделе приводится пример написания програм-

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

1.1. Задания по языку программирования ЛИСП

Язык программирования ЛИСП является функциональным языком, од-

ной из главных особенностей которого является ориентация на рекур-

сивные вычисления. Программа на языке ЛИСП представляет собой как

правило определение ряда относительно небольших по объему функцио-

нально законченных функций, из которых как из кирпичиков может быть

собрана большая программная система, удовлетворяющая требованиям

конкретного пользователя.

При разработке программ на ЛИСП может быть рекомендована мето-

дика написания рекурсивных функций, изложенная ниже.

1. Определение необходимых входных параметров и выбор парамет-

ра(ов), по которому(ым) будет проводиться рекурсия. Выходное значе-

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

результат вычисления этой функции.

2. В рамках функции COND или IF последовательно рассматривать

вырожденные (тривиальные) случаи в порядке возрастания их общности

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

3. Для более общих случаев также в порядке возрастания их общ-

ности формировать рекурсивные вызовы, редуцируя при этом пара-

метр(ы), по которым проводится рекурсия, к уже рассмотренным их вы-

рожденным случаям.

При определении рекурсивных функций рекомендуется особое вни-

мание обращать на необходимость остановки рекурсии, так как некор-

ректное задание ее условий может привести к бесконечному цикличес-

кому процессу.

1.1.1. Рекурсивная обработка числовой информации

Данный класс задач содержит множество вычислительных задач по

формулам, связанным, например, с различными рекурентными соотноше-

- 5 -

ниями. Рассмотрим, как может быть реализована на ЛИСП функция вы-

числения факториала, задаваемая следующим соотношением:

0! = 1

1! = 1 * 0!

2! = 2 * 1 = 2 * 1!

3! = 3 * 2 * 1 = 3 * 2!

.....................

N! = N * (N - 1) * (N - 2) * ... * 1 = N * (N - 1)!

Количество входных параметров для этой функции равно 1 и зада-

ет значения того числа N, факториал которого необходимо посчитать.

В случае некорректного задания исходного числа ( N < 0 ) результат

функции должен быть равен 0. Тривиальная ситуация, завершающая ре-

курсию, определяется значением N = 0. Все другие возможные ситуации

при N > 0 определяются одним и тем же рекурсивным соотношением.

Объединяя все возможные ситуации с помощью условной функции СОND

имеем следующее определение функции FACT:

 ( DEFUN FACT ( LAMBDA ( N )

 (COND (( MINUSP N ) 0 )

 (( = 0 N ) 1 )

 ( T ( * N ( FACT ( - N 1 ))))) ))

1. Подсчитать сумму квадратов целых чисел в заданном интервале

значений от M до N включительно.

2. Определить наименьшее общее кратное двух заданных чисел.

3. Определить наибольший общий делитель двух заданных чисел.

4. Вычислить квадратный корень из заданного числа.

5. Первые два члена ряда Фибоначчи равны 1 и 2. Каждый следую-

щий член ряда равен сумме двух предыдущих. Определить функцию, вы-

числяющую N-ый член ряда Фибоначчи.

1.1.2. Рекурсивная обработка списковой информации

Данный класс задач содержит множество задач обработки слож-

ноструктурированной информации, представленной в виде списков про-

извольной структуры. Рекурсивная обработка при этом как правило

строится по принципу обработки первого элемента списка и продолже-

нию рекурсии с остатком списка без первого элемента ( "рекурсия

вширь" ). Если текущий первый элемент представляет собой в свою

- 6 -

очередь список, то для его обработки может быть также применен

принцип рекурсии ( "рекурсия вглубь" ). Как правило, при работе со

списками тривиальным случаем, используемым для остановки рекурсии,

считается случай достижения списком-параметром состояния "пустой

список".

Рассмотрим, как может быть реализована на ЛИСП функция вычис-

ления количества подсписков на всех уровнях исходного списка.

Количество входных параметров для этой функции равно 1 и зада-

ет значение входного списка L, в котором необходимо посчитать коли-

чество подсписков. Тривиальная ситуация, завершающая рекурсию, оп-

ределяется значением L = NIL, при этом количество подсписков для

такого L равно 0. Все другие возможные ситуации означают, что в

списке L есть как минимум один элемент. Если текущий первый элемент

не является подсписком, то результат будет определяться количеством

подсписков в остатке списка. Если же этот элемент - подсписок, то

результат будет равен сумме количества подсписков в остатке списка,

количества подсписков в самом этом текущем элементе плюс 1 за этот

текущий элемент-подсписок. Объединяя все возможные ситуации с по-

мощью условной функции СОND имеем следующее определение функции

SUBLIST_AMOUNT, использующей как рекурсию вширь, так и вглубь.

 ( DEFUN SUBLIST_AMOUNT ( LAMBDA ( L )

 (COND (( NULL L ) 0 )

 (( LISTP (CAR L)) ( + 1

 (SUBLIST_AMOUNT (CAR L))

 (SUBLIST_AMOUNT (CDR L))

 ) )

 ( T (SUBLIST_AMOUNT (CDR L))) ) ) )

6. Определить предикат, распознающий списки, имеющие четное

(нечетное) количество элементов.

7. Подсчитать сумму всех числовых атомов в списке произвольной

структуры.

8. Определить максимальную глубину списка произвольной струк-

туры.

9. Найти максимальный элемент в числовом списке произвольной

структуры.

10. Написать функцию, выполняющую вычисление арифметических

выражений, заданных в виде списка. Используемые операции - умножить

- 7 -

(*), разделить (/), сложить (+), вычесть (-). При вычислении учиты-

вать приоритет операций и скобочные выражения.

 Пример-пояснение: (eval-expr '(4 + (-2 + 4) * 3)) => 10

1.1.3. Конструирующая рекурсия

Данный класс задач содержит множество задач обработки информа-

ции, представленной в виде списков, в том числе и произвольной

структуры, и формирования на их основе в качестве результата других

списков. Рекурсивная обработка при этом как правило не отличается

от методов, описанных в двух предыдущих параграфах. Основное отли-

чие заключается в том, что на обратном шаге рекурсии при формирова-

нии результата используются функции-конструкторы CONS, APPEND,

LIST.

Рассмотрим, как может быть реализована на ЛИСП функция, удаля-

ющая из списка произвольной структуры все атомы, кроме положитель-

ных чисел.

Формирование алгоритма для этой задачи аналогично представлен-

ному в 1.1.2. При формировании результата на обратном шаге рекурсии

будем использовать функцию CONS для включения в результат либо по-

ложительных чисел, либо подсписков, которые могут также содержать

положительные числа. Все другие элементы будут на этом шаге пропус-

каться. Необходимо помнить, что использование конструктора CONS

сохраняет в результирующем списке порядок элементов исходного спис-

ка.

 ( DEFUN LIST_POSITIVE_NUMBER ( LAMBDA ( L )

 (COND ((NULL L) NIL )

 ((LISTP (CAR L))

 (CONS (LIST_POSITIVE_NUMBER (CAR L))

 (LIST_POSITIVE_NUMBER (CDR L)) ) )

 ((PLUSP (CAR L))

 (CONS (CAR L) (LIST_POSITIVE_NUMBER (CDR L))))

 ( T   (LIST_POSITIVE_NUMBER (CDR L)) ) ) ) )

11. Сформировать список простых множителей заданного числа.

12. Реверсировать элементы списка произвольной структуры на

всех уровнях.

 Пример-пояснение:  исходный список -  (A (B C) D (E (F G)))

результирующий список -  (((G F) E) D (C B) A)

- 8 -

13. Линеаризовать список произвольной структуры.

 Пример-пояснение:  исходный список -  (A (B C) D (E (F G)))

результирующий список -  (A B C D E F G)

14. Сформировать список, являющийся пересечением двух заданных

линейных списков. Повторяющиеся в исходных списках элементы должны

входить в результирующий список не более одного раза.

15. Сформировать список чисел ряда Фибоначчи (см. задание N 5)

от первого числа до числа с заданным номером включительно.

1.1.4. Последовательные, циклические и итерационные вычисления

Рекурсия не всегда является удобной для решения некоторых за-

дач, по своей природе последовательных или циклических. Большая

размерность задачи тоже может быть препятствием для эффективного

решения ее рекурсивным методом из-за того, что требуется дополни-

тельная память на каждом шаге рекурсии для запоминания всех пара-

метров. В таких случаях в ЛИСП используются специальные функции

PROG и LOOP соответственно для последовательных и циклических вы-

числений, которые позволяют писать программы практически в стан-

дартной операторной форме.

Особенности, которые надо иметь в виду при использовании LOOP,

заключаются как в необходимости самостоятельно отслеживать измене-

ние параметра цикла ( списка ), так и в необходимости самостоятель-

ного формирования результата. Для этой цели часто используют допол-

нительный формальный параметр, не указываемый при вызове функции.

Это требует корректного задания его начального значения до входа в

функцию LOOP. Кроме того, необходимо помнить о том, что неявный

COND в теле LOOP может быть условием завершения цикла, поэтому все

проверки в теле цикла необходимо выполнять с помощью явного COND.

Рассмотрим, как может быть реализована на ЛИСП с использовани-

ем механизма LOOP функция, удаляющая из списка произвольной струк-

туры все атомы, кроме положительных чисел. Сравните ее с рекурсив-

ным определением в предыдущем параграфе.

 ( DEFUN LIST_POSITIVE_NUMBER_LOOP ( LAMBDA ( L R )

 ( SETQ R NIL)

 ( LOOP

 ((NULL L) R )

 (COND  ((LISTP (CAR L))

- 9 -

 (PUSH (LIST_POSITIVE_NUMBER_LOOP (CAR L)) R ))

 ((PLUSP (CAR L))

 (PUSH (CAR L) R )) )

 (POP L ) ) ) )

16. Посчитать с заданной точностью сумму бесконечного ряда,

каждый член которого задается формулой:  k

 X   /   k ! , где k изменяется

от 1 до бесконечности, а значение Х задано.

17. Найти последний элемент линейного списка.

18. Реализовать с помощью LOOP задание N 12 из 1.1.3.

19. Удалить из числового линейного списка все элементы, не

входящие в заданный интервал значений.

20. Задан список символьных атомов. Заменить во всех атомах

заданный символ на другой заданный символ, но не более чем заданное

число раз вхождений в каждом атоме.

1.1.5. Функционалы

Данный класс задач содержит множество задач однотипной обра-

ботки информации, содержащих в качестве входного параметра имя дру-

гой функции, использующейся в процессе вычисления.

Рассмотрим, как может быть реализована на ЛИСП функция, прове-

ряющая, какие элементы исходного списка удовлетворяют заданному ус-

ловию F, с использованием функционала FUNCALL.

 ( DEFUN CONTROL_LIST (LAMBDA ( L F )

 (COND ((NULL L) NIL )

 ((FUNCALL F (CAR L)) (CONS T (CONTROL_LIST (CDR L) F)))

 ( T (CONS NIL (CONTROL_LIST (CDR L) F)))) ))

 Примеры-пояснения:

 (CONTROL_LIST '(5 -7 12 -3 -77) 'MINUSP) => (NIL T NIL T T)

 (CONTROL_LIST '(5 -7 12 -3 -77) 'PLUSP) => (T NIL T NIL NIL)

Реализация той же самой функции с помощью MAP-функционалов бу-

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

списков при вызове MAP-функции должно равняться арности функции F):

- 10 -

 ( DEFUN CONTROL_LIST_MAP (LAMBDA ( L F )

 ( MAPCAR F L) ))

21. Сформировать список, содержащий номера позиций элементов

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

22. Задан линейный числовой список. Сформировать список сумм

подмножеств элементов исходного списка таким образом, что на первом

месте должна стоять сумма всех элементов списка, на втором - сумма

элементов без первого, на третьем - сумма элементов без первых двух

и т.д.

23. Удалить из исходного линейного списка все вхождения задан-

ного элемента.

24. Оставить в исходном линейном списке не более одного вхож-

дения каждого элемента.

25. Даны два исходных списка одинакового размера. Сформировать

из неравных друг другу элементов с одинаковыми порядковыми номерами

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

1.1.6. Ассоциативные списки и списки свойств

26. Извлечь из ассоциативного списка элементы, ключи которых

удовлетворяют заданным условиям.

27. Исходный список содержит имена объектов, списки свойств

которых содержат некоторую информацию. Определить для каждого объ-

екта количество пар <ключ-значение>.

28. Исходный список содержит имена объектов, списки свойств

которых содержат некоторую информацию. Другой список содержит неко-

торое количество ( больше 1 ) флагов. Сформировать список объектов,

содержащих не менее двух флагов из заданного списка.

29. Пусть в списке свойств атома может быть специальное свойс-

тво с ключом ISA, значение которого является именем другого списка

свойств, называемого списком-прототипом, из которого могут наследо-

ваться недостающие свойства. Написать функцию  (GET-ISA  <имя списка

 свойств> <имя свойства> ), которая в случае отсутствия искомого

свойства в исходном списке выдает значение первого найденного тако-

го же свойства среди всех ISA-прототипов данного списка свойств.

30. На складе имеется несколько видов продукции. Ассортимент

каждого вида продукции представлен также несколькими наименования-

ми. Задать информацию о имеющихся на складе товарах и их количестве

- 11 -

с помощью списков свойств. Определить функции, позволяющие получать

информацию о наличии некоторого товара на складе и корректирующие

информацию о наличии при завозе и вывозе заданного количества това-

ра.

1.2. Задания по языку программирования ФРЛ

1.2.1. Создание фреймов и извлечение информации из них

Фрейм представляет собой многоуровневый ассоциативный список,

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

этом каждый слот отражает значение некоторого свойства заданного

объекта. Это значение может быть или явным ( аспект $VALUE ), или

заданным по умолчанию ( аспект $DEFAULT ). Кроме того, значение мо-

жет быть представлено или в декларативной ( описательной ) форме,

или в процедуральной ( комментарий STATUS: со значением EVAL ) фор-

ме, применение которой позволяет вычислять значение свойства каждый

раз при необходимости его использования. Ниже приводится пример

создания фрейма и пополнения его дополнительной информацией.

 ( DEFRAMEQ FRAME_1_2_1

 (SLOT_1 ($VALUE (EX1))

 ($DEFAULT (EX2)) )

 (SLOT_2 ($VALUE (PROC1 (STATUS: EVAL)

 (PARM: :FRAME :SLOT))))

 )

 ( FPRINT '(FRAME_1_2_1))

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 (  FRAME_1_2_1

 ( SLOT_1 2  3($VALUE (EX1))

 ($DEFAULT (EX2))

 )

 ( SLOT_2 ($VALUE (PROC1 2 ( 3STATUS: EVAL)

 (PARM: 2  3:FRAME 2  3:SLOT)))

 )

 )

- 12 -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 ( FASSERTQ FRAME_1_2_1

 (SLOT_3 ($DEFAULT (EX3)))

 (SLOT_1 ($ALUE (EX1) 3  2(EX4)))

 (SLOT_2 ($VALUE (EX5)))

 )

 ( FPRINT '(FRAME_1_2_1))

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 (  FRAME_1_2_1

 (SLOT_3 ($DEFAULT (EX3))

 )

 ( SLOT_1 2  3($VALUE (EX4) (EX1))

 ($DEFAULT (EX2))

 )

 ( SLOT_2 ($VALUE (EX5)

 (PROC1 2 ( 3STATUS: EVAL)

 (PARM: 2  3:FRAME 2  3:SLOT)))

 )

 )

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

31. Создать фреймы, описывающие фрагмент библиотечной системы

( содержащие как декларативную, так и процедуральную ( в том числе

использующую переменные ФРЛ-среды ) составляющие ).

32. Добавить во фреймы, определенные в предыдущем задании, до-

полнительную информацию всеми имеющимися способами.

33. Извлечь из определенных в предыдущих заданиях фреймов ин-

формацию по заданному множеству запросов.

34. Реализовать функцию последовательного просмотра на экране

фреймов из заданного списка. Предусмотреть запрос о направлении

дальнейшего просмотра списка фреймов.

35. Имеются фреймы, описывающие фрагмент системы по обмену

квартир. Реальзовать функцию поиска информации о квартирах, удов-

летворяющих заданному критерию.

1.2.2. Присоединенные процедуры

При работе с фреймами кроме выполнения явно указанных пользо-

вателем операций могут автоматически выполняться также и другие,

- 13 -

скрытые от пользователя, операции обработки при возникновении опре-

деленных ситуаций. Такие ситуации определяются заранее, и при их

возникновении запускаются присоединенные процедуры, связанные с

конкретной ситуацией. Эти своеобразные "демоны" могут выполнять лю-

бую дополнительную обработку данных, в том числе и тех, которые не

входят во фрейм, содержащий описание присоединенной процедуры. Ниже

приводится пример задания присоединенных процедур, автоматически

запускаемых при удалении, добавлении или извлечении данных из фрей-

ма. Необходимо заметить, что действие данных присоединенных проце-

дур распространяется только на те слоты, в которых они определены,

и не распространяется на другие слоты фрейма. Кроме того, в ФРЛ су-

ществуют два типа функций, по разному относящихся к присоединенным

процедурам. Одни из них активизируют присоединенные процедуры, а

другие этого не делают. Эти ситуации особо оговариваются при опре-

делении встроенных функций ФРЛ.

 ( DEFRAMEQ FRAME_1_2_2

 (SLOT_1 ($VALUE (EX1))

 ($IF-ADDED ((SIGNAL 'ДОБАВЛЯЕТСЯ)))

 ($IF-REMOVED ((SIGNAL 'УДАЛЯЕТСЯ))) )

 (SLOT_2 ($VALUE (EX2))

 ($IF-GETED ((SIGNAL 'ИЗВЛЕКАЕТСЯ))) )

 )

 ( PASSERTQ SIGNAL (X)

 (PRINT (LIST X " ДАННОЕ " :VALUE " ИЗ ФРЕЙМА " :FRAME

 " СЛОТА " :SLOT )) )

 ( FPUT FRAME_1_2_2 SLOT_1 3  2 $VALUE 'EX3)

 ( ДОБАВЛЯЕТСЯ ДАННОЕ  EX3  ИЗ ФРЕЙМА  FRAME_1_2_2

 СЛОТА  SLOT_1)

EX3

 ( FPUT FRAME_1_2_2 SLOT_2 3  2 $VALUE 'EX4)

 EX4

 ( FDELETE FRAME_1_2_2 SLOT_1 $VALUE 'EX3)

 EX3

- 14 -

 ( FREMOVE FRAME_1_2_2 SLOT_1 $VALUE 'EX1)

 УДАЛЯЕТСЯ ДАННОЕ  EX1  ИЗ ФРЕЙМА  FRAME_1_2_2

 СЛОТА  SLOT_1)

 EX1

36. Обеспечить автоматический подсчет частоты обращения к за-

данному фрейму с сигнализацией о каждом кратном 10 обращении.

37. Вместимость вагона 40 т. Товарный состав содержит 6 ваго-

нов. Каждый вагон и состав описывается своим фреймом. Кроме того,

есть еще один фрейм, содержащий информацию о количестве и наимено-

вании сформированных и отправленных составов. Реализовать функцию,

моделирующую загрузку вагона определенным количеством груза. При

превышении вместимости вагона груз размещается в следующем вагоне,

при формировании состава информация о нем включается в главный

фрейм и происходит переход к формированию следующего состава. Реа-

лизовать указанный алгоритм с помощью $IF-ADDED на всех уровнях.

38. Ситуация та же, что и в предыдущем задании, только на

станции прибытия требуется отгрузить заданное количество груза.

Корректировку информации о наличии груза, вагонов и составов реали-

зовать с помощью $IF-REMOVED.

39. Обеспечить автоматический контроль корректности информации

о наличии на станции прибытия (см. предыдущее задание) количества

составов, не превышающих количество имеющихся путей.

40. Во фрейме имеется слот с закодированным значением информа-

ции. Обеспечить ее извлечение по паролю ( с использованием

$IF-NEEDED ).

1.2.3. Организация сетей фреймов

Каждый фрейм может представлять собой полностью определенную

закрытую единицу информации, задающую один конкретный объект. Одна-

ко такой подход при проектировании и разработке баз знаний не может

быть признан удовлетворительным из-за того, что это может привести

к дублированию большого количества информации, сложностей с под-

держкой ее обновления и как следствие, к получению противоречивой

информации. Эта проблема решается эффективно в том случае, если

конкретная инфомация ( например, о текущем количестве студентов в

МЭИ ) содержится лишь в одном месте, а все другие объекты, которым

эта информация необходима, просто ссылаются на нее. Такой принцип

- 15 -

построения базы знаний называется наследованием свойств, и в ФРЛ он

реализуется с помощью механизма АКО-иерархии, при котором фреймы

связаны друг с другом в сеть, и поиск необходимой информации, от-

сутствующей в данном фрейме, осуществляется системой автоматически

во всех других фреймах, доступных по АКО-иерархии. Ниже приведен

пример фрагмента сети фреймов АКО-иерархии и показаны примеры поис-

ка информации в ней.

 ( DEFRAMEQ FRAME_1_2_3_1

 (SLOT_1 ($VALUE (EX1)))

 (SLOT_2 ($VALUE (EX2)))

 (INSTANCE ($VALUE (FRAME_1_2_3_2) (FRAME_1_2_3_3)))

 )

 ( DEFRAMEQ FRAME_1_2_3_2

 (SLOT_3 ($VALUE (EX3)))

 (SLOT_2 ($VALUE (EX4)))

 (AKO ($VALUE (FRAME_1_2_3_1)))

 )

 ( FGET FRAME_1_2_3_2 SLOT_2)

 (EX4 EX2)

 ( FGET1 FRAME_1_2_3_2 SLOT_2)

 (EX4)

 ( FGET1 FRAME_1_2_3_2 SLOT_1)

 (EX1)

 ( FGET FRAME_1_2_3_2 SLOT_4)

 NIL

 ( FGET FRAME_1_2_3_2 SLOT_2 '(C))

 ((EX4 (IN: FRAME_1_2_3_2)) (EX2 (IN: FRAME_1_2_3_1)))

41. С помощью косвенного наследования задать часть информации

во фрагменте библиотечной системы (см. задание 31).

42. Задать информацию о фрагменте библиотечной системы с по-

мощью AKO-иерархии.

43. Имеется система фреймов, организованная в циклическую

- 16 -

(круговую) структуру. Обеспечить проход по циклу заданное количест-

во раз в любую сторону, начиная с любого фрейма.

44. Сформировать сетевую структуру фреймов с необходимыми про-

цедурами, описывающую ситуацию на складе (см. задание 30) и обеспе-

чивающую корректировку информации при завозе/вывозе продукции. Пре-

дусмотреть, что склад имеет ограниченный фиксированный объем.

45. Исходный список содержит информацию о студентах факульте-

та. Сформировать AKO-иерархию факультета, предусмотрев автоматичес-

кую генерацию фреймов, описывающих конкретного студента, на основе

фрейма-прототипа, с заданием дополнительной информации о нем ( имя,

возраст и т.д. ) в диалоговом режиме.

 Пример-пояснение:  вид исходного списка -  (АВТФ

 (А-1-95 (ИВАНОВ ПЕТРОВ .... ))

 (А-2-95 (СИДОРОВ ФРОЛОВ .... ))

 ...............

 (А-14-90 (ЕГОРОВ ПОПОВ .... )) )

1.3. Задания по языку программирования ПРОЛОГ

Язык программирования ПРОЛОГ является языком логического прог-

раммирования, активно используемым в исследованиях по искусственно-

му интеллекту. Одной из главных особенностей языка является его

непроцедурная ориентация. Программа на языке ПРОЛОГ представляет

собой множество фактов, описывающих предметную область, и правил,

отражающих взаимодействие объектов в этой предметной области ( в

том числе возможны и рекурсивные определения правил ). Поиск инфор-

мации, удовлетворяющей заданному запросу, интерпретатор системы вы-

полняет автоматически, используя встроенные механизмы сопоставления

объектов и возврат в случае неуспеха.

При разработке программ на ПРОЛОГ может быть рекомендована

следующая методика, изложенная ниже.

 I. Анализ предметной области.

1. Определение необходимых типов и структур данных.

2. Определение множества исходных фактов.

3. Определение множества необходимых правил.

II. Реализация правил

1. Определение для каждого правила необходимых входных и

выходных параметров (связанных или свободных при вызове правила) и

- 17 -

выбор параметра(ов), по которому(ым) будет проводиться рекурсия

( если она требуется ).

2. Определение для каждого правила множества вырожденных

(тривиальных) случаев в порядке возрастания их общности, приводящих

к истинности данного правила, и задание их в виде правил без правой

части.

3. Для более общих случаев также в порядке возрастания их

общности формировать правые части правил, содержащие обращения к

другим правилам ( в том числе, возможно, и к самим себе), редуцируя

при этом входные параметры к уже рассмотренным их вырожденным слу-

чаям. Не забывать при этом обязательно означивать выходные (свобод-

ные) переменные, определенные в левой части правила.

4. Множество всех определений правила с одним именем назы-

вается процедурой, которая может быть истиной на заданом наборе

входных параметров. В этом случае выходные параметры сопоставляются

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

1.3.1. Рекурсивная обработка числовой информации

Рассмотрим на примере вычисления факториала основные моменты,

возникающие при обработке целочисленной информации.

Дополнительные типы данных, как правило, в этих задачах опре-

делять не требуется, достаточно использования стандартных доменов.

Для завершения рекурсии используются факты, исходными данными для

которых являются значения входных переменных, равные 0 или реже 1.

Для факториала при входном параметре N = 0 результат по опре-

делению равен 1, что задается фактом в первой строке секции

clauses. Все другие случаи при N > 0 определяются рекурсивным пра-

вилом во второй строке. При некорректном задании входного параметра

( N < 0 ) ни факт, ни правило в секции clauses не сопоставляются с

исходной целью, поэтому ответом на запрос в этом случае будет сфор-

мированное системой сообщение " No solution ".

 predicates

 fact(integer,integer)

 clauses

 fact(0,1).

 fact(N,F):- N > 0, N1 = N - 1, fact(N1,F1), F = F1 * N, !.

- 18 -

 goal

 a) fact(5,F)

 F=120

 YES

 б) fact(4,24)

 YES

 в) fact(3,12)

 NO

46. См. задание N 1 из 1.1.1. Значения M и N могут быть произ-

вольными целыми числами.

47. См. задание N 2 из 1.1.1.

48. См. задание N 3 из 1.1.1.

49. См. задание N 5 из 1.1.1.

1.3.2. Рекурсивная обработка списковой информации

Представление информации в виде списка в ПРОЛОГ отличается от

представления в ЛИСП в первую очередь невозможностью представления

в одном списке разнотипной информации. Другой особенность является

невозможность прямого представления списка произвольной структуры

(в реализации PDC-Prolog). Поэтому при рекурсивной обработке спис-

ков имеется лишь рекурсия вширь, позволяющая обрабатывать элемент

за элементом до тех пор, пока список не станет пустым. Предикат,

определяющий пустоту списка, может быть представлен в виде элемен-

тарного факта empty, определение которого приведено в примере, или

непосредственно задаваться в конкретных правилах. Необходимо заме-

тить, что при определении правил рекурсивной обработки списков пе-

ременные из списковых доменов в левой части правил, как правило,

являются более сложными списками, чем представленные в левой части

при рекурсивном вызове.

Рассмотрим организацию рекурсии при обработке списковой инфор-

мации на примере объединения элементов двух списков в один. Тип

данных mylist, использованный в данном примере, задает домен, со-

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

ся фактами, являются случаи равенства какого-либо из двух входных

списков L1 или L2 пустому списку. В этом случае третий параметр L3

получает значение непустого списка. В случае, когда оба входных

списка имеют элементы, то результирующий список представляет из се-

- 19 -

бя список, в котором первый элемент совпадает с первым элементом

списка L1, а все остальные элементы получаются при объединении ос-

татка первого списка со вторым. Рекурсивный вызов предиката

append редуцирует в данном случае входной параметр L1 до его триви-

ального случая.

 domains

 mylist = integer*

 predicates

 append(mylist,mylist,mylist)

 empty(mylist)

 clauses

 empty([]).

 append([],L2,L2).

 append(L1,[],L1).

 append([X|L1_rem],L2,[X|L3_rem]):-append(L1_rem,L2,L3_rem).

 goal

 append([1,2,3],[4,5],L3)

 L3=[1,2,3,4,5]

 YES

50. Определить предикат, распознающий списки-палиндромы, т.е.

списки, элементы которых одинаковы как при просмотре с начала, так

и с конца.

51. Найти последний элемент списка.

52. Найти количество и сумму элементов списка.

53. Найти максимальный элемент в заданном списке.

54. См. задание N 14 из 1.1.3.

55. В списке представлены составные объекты, содержащие инфор-

мацию о книгах, имеющихся в библиотеке. Сформировать список, содер-

жащий составные объекты, в которых задается информация об авторах

книг, объем которых превышает заданный, и количестве таких книг у

каждого автора.

1.3.3. Организация ввода-вывода

Работа с внешними носителями в ПРОЛОГ возможна с текстовыми и

двоичными файлами. Различаются файлы для чтения, для записи, для

модификации. В последнем случае возможны два варианта: выходной

- 20 -

файл может быть открыт либо для модификации любых записей, либо

только для добавления новых записей в конец файла. Обычно работа с

любым файлом выполняется в последовательном режиме, но возможна и

работа с записями в режиме прямого доступа к ним по номеру. В каж-

дый момент времени может быть открыто произвольное количество фай-

лов, но предикаты ввода-вывода работают с информацией только того

файла, который является активным в данный момент. Необходимо пом-

нить, что предикаты открытия входного файла терпят неудачу при по-

пытку открыть несуществующий файл. Точно так же терпят неудачу пре-

дикаты ввода, если выполняется считывание некорректной информации

(например, при попытке с помощью readint считать символьную инфор-

мацию).

Рассмотрим пример организации ввода-вывода на примере визуали-

зации вводимой из файла информации на экране монитора. Предикат

control_file организует выполнение вспомогательных операций (про-

верка существования входного файла, его открытие и активизацию, а

также закрытие по завершении работы) и вызов рекурсивного предиката

readfile, осуществляющего собственно считывание файла по записям и

их отображение на экране.

 domains

 filename=symbol

 file=myfile

 predicates

 control_file(filename)

 readfile

 clauses

 control_file(N):-existfile(N), openread(myfile,N),

 readdevice(myfile), writedevice(screen),

 readfile,

 closefile(myfile), readdevice(stdin), !.

 readfile:- readln(X), X<>"<*", !, write(X), readfile.

 readfile.

 goal

 control_file("input.txt")

 ...............................................

 отображение на экране информации из файла input.txt

 ...............................................

 YES

- 21 -

56. Сформировать и записать на внешний носитель список чисел,

задаваемых с клавиатуры в диалоговом режиме.

57. Рассортировать исходный список чисел, созданный в предыду-

щем задании, на положительные и отрицательные числа, и записать их

на внешний носитель.

58. Исходный файл содержит множество составных объектов, со-

держащих информацию о различных предприятиях в разных городах.

Сформировать новые файлы, содержащие информацию о всех предприятиях

каждого города.

1.3.4. Динамическая база данных

Помимо статической информации, представленной в секции clauses

фактами и правилами, ПРОЛОГ обеспечивает возможность работы и с ди-

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

сываемой в секции database. Внутренняя база данных может содержать

только факты, причем их описание не должно повторяться в секции

predicates или других секциях database. ПРОЛОГ интерпретирует фак-

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

обычные предикаты. Рассмотрим пример применения внутренней базы

данных при вычислении факториала.

Фактически при вычислении N! вычисляются и все промежуточные

факториалы. При необходимости вычисления этой функции многократно

может быть более эффективно запоминать все вычисленные значения с

тем, чтобы в дальнейшем вычислять факториал лишь для новых (боль-

ших) значений, а для уже вычисленных ранее сразу брать их значение.

Вычисленные значения запоминаются в динамической базе данных в виде

фактов с именами factdb, а определение правила вычисления факториа-

ла в секции clauses задается именем fact. При попытке вычислить

значение факториаладля заданного числа сначала выполняется поиск в

динамической базе данных и лишь в случае неудачи начинается рекур-

сивное вычисление факториала. При этом на каждом шаге вновь прове-

ряется содержимое динамической базы данных, так что процесс вычис-

ления идет не до факта fact(0,1), а до факта factdb(N_Max,F_Max),

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

они автоматически добавляются в динамическую базу данных.

Предикаты loaddb и savedb позволяют загружать с внешнего носи-

теля накопленную ранее базу данных факториала и запоминать в конце

работы пополненную.

- 22 -

 database

 factdb(integer,integer)

 predicates

 fact(integer,integer)

 loaddb

savedb

 clauses

 loaddb:-existfile("factdb.dbp"), consult("factdb.dbp"), !,

 not(factdb(0,1)), asserta(factdb(0,1)), ! ;

 asserta(factdb(0,1)).

 fact(N,F):- factdb(N,F),!;

 N1=N-1, fact(N1,F1), F=F1*N, asserta(factdb(N,F),!.

 savedb:-save("factdb.dbp").

59. См. задание N 15 из 1.1.3. Для хранения вычисленных чисел

Фибоначчи использовать динамическую базу данных.

60. Имеется база данных родственных отношений, описывающая од-

но семейство. Предусмотреть сохранение текущей информации на внеш-

нем носителе после ее изменения в процессе работы.

61. См. задание N 37 из 1.2.2.

62. См. задание N 38 из 1.2.2.

.

- 23 -

2. ЗАДАНИЯ ДЛЯ ЛАБОРАТОРНЫХ ЗАНЯТИЙ

На лабораторных занятиях студенты получают практические навыки

работы с системами программирования на языках ЛИСП, ФРЛ и ПРОЛОГ,

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

дая лабораторная работа рассчитана на 2 часа

2.1. Задания по языку программирования ЛИСП

ЛАБОРАТОРНАЯ РАБОТА N 1.

Реализовать задания N 1 - 5 из 1.1.1.

 ЛАБОРАТОРНАЯ РАБОТА N 2.

Реализовать задания N 6 - 10 из 1.1.2.

ЛАБОРАТОРНАЯ РАБОТА N 3.

Реализовать задания N 11 - 15 из 1.1.3.

 ЛАБОРАТОРНАЯ РАБОТА N 4.

Реализовать задания N 16 - 20 из 1.1.4.

 ЛАБОРАТОРНАЯ РАБОТА N 5.