Создание и декомпозиция атомов



 

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

name( A, L)

истинно, если L — список кодов ASCII, кодирующих атом. Например,

name( zx232, [122, 120, 50, 51, 50] )

истинно. Существуют два типичных способа использования name:

(1) дан атом, разбить его на отдельные символы;

(2) дан список символов, объединить их в один атом.

Примером первого случая применения предиката является программа, которая имеет дело с заказами такси и водителями. Все это представлено в программе атомами

заказ1, заказ2, водитель1, водитель2, такси1, таксилюкс

Предикат

такси( X)

проверяет, относится ли атом X к тем атомам, которые представляют такси:

такси( X) :-

name( X, Хспис),

nаmе( такси, Тспис),

конк( Тспис, _, Хспис).

 

конк( [], L, L).

конк( [А | L1], L2, [А | L3] ) :-

конк( L1, L2, L3).

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

Наш следующий пример иллюстрирует применение объединения отдельных символов в один атом. Мы определим предикат

читпредложение( Списслов)

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

Мэри было приятно видеть неудачу робота.

то цель читпредложение( Предложение) вызовет конкретизацию

Предложение=['Мэри', было, приятно, видеть, неудачу, робота]

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

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

(1) Симв — точка, тогда все сделано.

(2) Симв — пробел, — игнорировать его и читпредложение от остального ввода.

(3) Симв — буква, — сначала считать слово Слово, которое начинается с Симв, а затем запустить читпредложение, чтобы считать оставшуюся часть предложения, породив при этом Списслов. Общим результатом этого будет список [Слово | Списслов].

Процедура, считывающая символы одного слова, такова:

читбуквы( Буква, Буквы, Сделсимв)

Ее три аргумента:

(1) Буква — текущая буква (уже считанная) читаемого слова.

(2) Буквы — список букв (начинающийся с буквы Буква), оставшихся до конца слова.

(3) Следсимв — входной символ, непосредственно следующий за читаемым словом. Следсимв не должен быть буквой.

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

 

/*

Процедура читпредложение считывает предложение

и из его слов создает список атомов. Например,

читпредложение( Списслов)

порождает

Списслов=['Мэри', было, приятно, видеть, неудачу, робота]

если входным было предложение

Мэри было приятно видеть неудачу робота.

*/

читпредложение( Списслов) :-

gеt0( Симв),

читостальное( Симв, Списслов).

 

читостальное( 46, []) :- !.

% Конец предложения: 46 = ASCII-код для '.'

читостальное( 32, Списслов) :- !,

% 32 = ASCII-код для пробела

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

% Пропустить пробел

 

читостальное( Буква, [Слово | Списслов]) :-

читбуквы( Буква, Буквы, Следсимв),

% Считать буквы текущего слова

nаmе( Слово, Буквы),

читостальное( Следсимв, Списслов).

 

читбуквы( 46, [], 46) :- !.

% Конец слова: 46 = точка

читбуквы( 32, [], 32) :- !.

% Конец слова: 32 = пробел

читбуквы( Бкв, [Бкв | Буквы], Следсимв) :-

get0( Симв),

читбуквы( Симв, Буквы, Следсимв).

Рис. 6.4. Процедура для преобразования предложения в список атомов.

 

 

Упражнения

 

6.4. Определите отношение

начинается( Атом, Символ)

для проверки, начинается ли Атом с символа Символ.

6.5. Определите процедуру plural, которая преобразует английские существительные из единственного числа во множественное, добавляя к слову окончание s. Например:

?- plural( table, X).

X = tables

6.6. Напишите процедуру

поиск( Ключслово, Предложение)

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

 

6.5. Ввод программ: consult, reconsult

 

Передавать программы пролог-системе можно при помощи двух встроенных предикатов: consult и reconsult. Чтобы система считала программу из файла F, нужно поставить цель

?- consult( F).

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

Для того, чтобы запустить программу, не обязательно записывать ее в файл, а затем "консультироваться" с ним. Вместо чтения файла система может принимать программу прямо с терминала, который соответствует псевдофайлу user. Добиться этого можно так:

?- consult( user).

После этого система будет ожидать ввода предложений программы с терминала.

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

?- [файл1, файл2, файл3].

Это в точности эквивалентно следующим трем целям:

?- соnsult( файл1), соnsult( файл2), соnsult( файл3).

Встроенный предикат reconsult аналогичен consult. Цель

?- reconsult( F).

даст тот же эффект, что и consult( F) с одним исключением. Если в F есть предложения, касающиеся отношений, которые уже были определены ранее, старые определения заменяются на новые из F. Разница между consult и reconsult в том, что consult всегда добавляет новые предложения, в то время как reconsult переопределяет ранее введенные определения. Однако reconsult не произведет никакого эффекта на те отношения, о которых в F ничего не сказано.

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

 

Резюме

 

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

• Файлы являются последовательными. Существуют текущие входной и выходной потоки . Пользовательский терминал рассматривается как файл с именем user.

• Переключение между потоками осуществляется с помощью процедур:

sее( Файл)

Файл становится текущим входным потоком

tell( Файл)

Файл становится текущим выходным потоком

seen

закрывается текущий входной поток

told

закрывается текущий выходной поток

• Файлы читаются и записываются двумя способами:

как последовательности символов

как последовательности термов

Встроенные процедуры для чтения и записи символов и термов таковы:

rеad( Терм)

вводит следующий терм

write( Терм)

выводит Терм

put( КодСимвола)

выводит символ с заданным ASCII-кодом

get0( КодСимвола)

вводит следующий символ

gеt( КодСимвола)

вводит ближайший следующий "печатаемый" символ

• Две процедуры облегчают форматирование:

nl начинает новую строку

tab( N) выводит N пробелов

• Процедура nаmе( Атом, СписокКодов) осуществляет синтез и декомпозицию атомов. СписокКодов — список ASCII кодов символов, образующих Атом.

 

 

Глава 7

Другие встроенные процедуры

 

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

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

 

Проверка типов термов

 


Дата добавления: 2018-05-01; просмотров: 422; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!