Скачиваний:
51
Добавлен:
01.05.2014
Размер:
257.54 Кб
Скачать

Часть IV

Приложения

Язык Пролог имеет широкую сферу применений: экспертные системы, восприятие текстов на естественном языке, символьные вычисления, разработка компиляторов, создание языков для встроенных систем, архитектурное проектирование и др. В этой части книги представлен «букет» прикладных программ, написанных на Прологе.

В гл. 20рассмотрены игровые программы для трех игр: «Выдающийся ум». Ним и Калах. В гл. 21описана экспертная система для проверки кредитных требований. В гл. 22представлена программа для решения уравнений, заданых в символьном виде. В гл. 23показан компилятор для паскалеподобного языка.

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

Глава 20

Игровые программы

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

20.1. «Выдающийся ум»

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

Мы рассматриваем «детский» вариант игры «Выдающийся ум», который отличается от коммерческого варианта минимумом технических средств (только карандаш и бумага). Игрок Авыбирает секретный код, представляющий собой последовательность из Nразличных десятичных цифр (обычно начинающие игроки выбирают Nравным 4,опытные - 5).ИгрокВпытается угадать задуманный код и спрашивает игрокаАо числе «быков» (число «быков» количество совпадающих цифр в одинаковых позициях предполагаемого и задуманного кодов) и числе «коров» (число «коров» количество совпадающих цифр, входящих в предпола-

Игра имеет второе название «Быки и коровы».Прим. pi'().

гаемый и задуманный код, но находящихся в разных позициях). Код угадан, если число быков равно N.

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

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

Алгоритм «играет» в силу опытных игроков: для раскрытия кода из 4цифр ему требуется в среднем 4-6попыток, наблюдавшийся максимум-8попыток. Однако человеку эту стратегию применить нелегко,поскольку она требует значительной счетной работы. С другой стороны, управляющая структура Пролога -недетерминированный выбор, моделируемый поиск с возвратами, - представляется идеальной для реализации этого алгоритма.

Опишем программу, начиная с верхнего уровня. Программа 20.1-полная программа рассматриваемой игры. Процедура верхнего уровня в игре представлена следующим правилом:

выдающийся_ум(Код)

чистка,предположение(Код),проверка(Код),сообщение.

Сердцевиной процедуры верхнего уровня является цикл «образовать и проверить».

выдающийся_ум(Код) 

чистка, предположение (Код), проверка (Код), сообщение.

предположение(Код) 

Код =[Х1,Х2,ХЗ,Х4], выбор(Код,[1,2,3,4,5,6,7,8,9,0]).

Проверка предложенного предположения

проверка (Предположение) 

notпротиворечивое (Предположение), вопрос (Предположение).

противоречивое (Предположение) 

запрос (Старое Предположение, Быки, Коровы),

notсоответствуют_быки_и_коровы (Старое Предположение, Предположение,

Быки, Коровы)

соответствуют_быки„и коровы (Старое Предположение, Предположение, Быки,

Коровы) 

точное_совпадение (Старое Предположение, Предположение, N 1),

Быки = : = N1, %Правильное число быков

общие_члены (Старое Предположение, Предположение, N2),

Коровы = : = N2 -Быки,%Правильное число коров

точное_совпадение(Х,Y,N) 

размер(А,одинаковая._позиция(А,Х,Y),N).

общие_члены(Х,Y,N) 

размер (А, (член (А,Х), член (A, Y)), N).

одинаковая_позиция (X, [X| Xs], [X| Ys]).

одинаковая_позиция (А, [X| Xs], [Y | Ys]) одинаковая. позиция(А, Xs,Ys).

Запрос предположения

вопрос(Предположение) 

repeat,

writeln(['Сколько быков и коров в', Предположение,‘?']])

геаd((Быки, Коровы)),

sensible(Быки,Коровы),!,

assert(запрос, (Предположение, Быки, Коровы)), Быки = 4.

допустимо (Быки, Коровы) 

integer(Быки),integer(Kopoвы), Быки +Коровы 4.

Счетная работа

чистка отменить(запрос,3). сообщение 

размер(Х, А (В(запрос (Х,А, В))), N),

writeln(['Ответнайден после', N,'запросов']). размер (X,G,N) См. программу 17.1.

вы6op(X,Xs,Ys)См. программу 7.7.

отменить(F,N) См. упражнение 12.4(1).

Программа 20.1. Игра «Выдающийся ум».

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

предположение(Код) 

Код= [Х1,Х2,ХЗ,Х4], выбор(Код,[1,2,3,4,5,б.7,8.9,0]).

Процедура проверка (Предположение)испытывает предложенный кодПредположение.Сначала проверяется, чтоПредположениене противоречит всем ранее полученным ответам (т. е. непротиворечиво с каждым из них); затем задается вопрос о числе быков и коров в кодеПредположение.Кроме того, процедуравопрос (Предположение)управляет циклом «образовать и проверить», который завершается только тогда, когда число быков равно 4,что является признаком отыскания правильного кода.

проверка(Предположение) 

notпротиворечивое(Предположение),вопрос(Предположение)

Процедура вопросзапоминает предыдущие ответы на вопросы в отношениизапрос(X,В,С),где Х - предположение,Ви С - число быков и коров в нем соответственно. Предположение противоречит предыдущему запросу, если число быков и число коров не соответствуют предыдущему запросу:

противоречивое(Предположение) 

запрос(СтароеПредположение,Быки,Коровы),

notсоответствуют_быки_и_коровы (СтароеПредположение,Быки,Коровы).

Предыдущее предположение (Старое Предположение)и высказываемое предположение(Предположение)согласуются по числу быков, если количество цифр на одних и тех же позициях в этих двух предположениях равно числу быков(Быки)в пред­положенииСтарое Предположение.Это соответствие определяется предикатомточное_совпадение (Старое Предположение, Предположение, Быки).Предыдущее и высказываемое предположения согласуются по числу коров, если количество одинаковых цифр в предположениях без учета порядка расположения цифр соответствует сумме быков(Быки)и коров(Коровы).Данное соответствие проверяется процедуройсоответствие быков_и_.коров.Количество совпадающих цифр и общих цифр в двух

запросах легко подсчитать, применяя системный предикат size_of/3.

Процедура вопрос(Предположение)является функцией запоминания, которая регистрирует ответ на запрос и с помощью процедурыразумный (Ответ)выпол­няет ограниченный контроль на входе. Она завершается успешно, если только число быков в ответе равно 4.Ответ играющего представляется упорядоченной парой (Быки, Коровы).

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

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

точное_совпадение(Хs,Ys,N) точное_совпадение(Xs,Ys,0,N).

точное_совпадение([Х | Xs], [X | Ys],K,N) 

К1 : =К + 1,точное совпадение(Хs,Ys,K1,N).

точное совпадение ([X| Xs], [Y | Ys],К, N) 

Х  Y, точное_совпадение(Xs,Ys,K,N).

точное_совпадение ([ ],[ ],N,N).

общие_члены (Xs,Ys,N)  общие_члены(Xs,Ys,0,N).

общие_члены ([X | Xs],Ys,K,N) 

member(X,Ys),К1 :=К + 1,общие_члены(Хs,Ys,К1,N).

общие_члены([Х | Хs],Ys,К,N)

общие_члены (Xs, Ys,К, N).

общие_члены([ ],Ys,N,N).

Использование более эффективных версий процедур точное_совпадениеиобщие_членыприводит к уменьшению времени выполнения программы на 10-30%.

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