Применение предиката "findall"

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

суммировать ([], 0).

суммировать ([X | R], Итог): —

суммировать (R, Сумма),

Итог is X+ Сумма.

Запрос, предназначенный для вычисления итоговой суммы, будет иметь вид:

|? - findall (Окл, служащий (Имя, 100, Долж, Окл), Список),

суммировать (Список, Итог).

Список = [20000, 71500, 29000]

Итог = 120500

Данное решение, в котором употребляется предикат "findall", будет более общим (и будет обладать более широкой областью применения), чем решение, основанное на использовании правила "итог_окл" (см. выше).

Библиографические заметки

Существуют различные способы объяснения принципов работы решателя задач, реализованного в Прологе. Наиболее полно это изложено в работах [25] и [55]. Различные реализации языка Пролог обсуждаются в работах [14] и [105].

Понятие отрицания как неудачи запроса впервые было сформулировано в работе [17]. Предположение о замкнутости мира рассматривается в работах [89] и [78].

Во многих статьях отмечается "коварство" предиката "сократить". Среди наиболее интересных работ, предостерегающих об опасности употребления этого предиката, следует назвать доклад [81]. В работе [58] рассказывается об опасностях, связанных с использованием предикатов "assert" и "retract". Ковальски считает, что применение предиката "assert" более оправданно, чем употребление предиката "retract", поскольку добавление новых фраз во время выполнения программы в определенной степени сходно с генерированием лемм (метод доказательства в исчислении предикатов). В работах [46] и [58] сравниваются алгоритмы поиска с возвратом и рекурсивные алгоритмы. В работе [76] дается обзор "findall "-подобных предикатов.

Упражнения

1. Запустите интерпретатор языка Пролог и введите факты "путешествие/4" из разд. 1. 4. Напишите при помощи предиката "сократить" составной запрос, который будет находить только один город, в который можно добраться из Нью-Йорка на транспорте компании Амтрак, а затем будет отыскивать все города, в которые можно отправиться из найденного города транспортом данной компании.

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

3. Предположим, что имеются две базы данных:

возраст (мери, 16).

возраст (брайен, 17).

возраст (кейт, 15).

возраст (сюзан, 15).

шоферские_курсы (кейт).

шоферские_курсы (мери).

шоферские_курсы (брайен).

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

|? - шоферские_курсы (X), возраст (X, Y), Y>=16. %А

|? - шоферские_курсы (X),!, возраст (X, Y), Y > = 16. %Б

|? - шоферские_курсы (X), возраст (X, Y),!, Y > = 16. %В

|? - шоферские_курсы (X), один_раз (возраст (X, Y)), Y > = 16. %Г

Обратитесь к приведенным выше базам данных "возраст" и "шоферские_курсы". Напишите процедуру "права", которая определяет, что человек может получить водительские права, если ему 16 лет дли более, и он прошел обучение на курсах шоферов, либо если ему 17 лет или более.

4. Придумайте несколько отношений, которые можно описать негатив но, например:

Такси служит транспортным средством для передвижения

из пункта А в пункт Б, если

А и Б - это нью-йоркские адреса, и

ни автобус, ни поезд не курсирует между А и Б.

Машина находится в нормальном состоянии, если

аварийные сигналы не включены.

Х является клиентом компании AT & Т, если

у Х есть телефон, и

Х не является клиентом ни компании MCI, ни компании Sprint.

Напишите Пролог-программу, в которой будет представлено одно из этих отношений, при этом воспользуйтесь предикатом "not".

5. Напишите с использованием предиката "repeat" составной запрос, который спрашивает у пользователя имена школьных товарищей и добавляет каждое имя в базу данных в виде факта:

школьный_товарищ (Имя).

После того, как пользователь введет слово "конец", запрос должен прекратить задавать вопросы и выдать на дисплей все только что введенные имена.

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

7. Воспользуйтесь отладочными средствами, чтобы понаблюдать за выполнением Вашей программы "советник_по_транспорту".

8. Преобразуйте базу данных "путешествие" в список структур. Напишите версию процедуры "можно_путешествовать", которая обеспечит работу с этим списком структур.

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

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

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

11. Определите операции"--" и "-->" и перепишите процедуру "можно_путешествовать5" из разд. 2. 2 так, чтобы она выдавала ответ в следующем виде:

путешествие (амтрак, нью_йорк, бостон, поезд).

путешествие (амтрак, бостон, портленд, поезд).

|? — можно_путешествовать5 (нью_йорк, портленд, М).

М = нью_йорк - - поезд - -> бостон - - поезд - -> портленд

Соседние файлы в папке Гл.0,1,2,3,4,5,Предисловие