Рейтинговые книги
Читем онлайн Программирование на языке Пролог для искусственного интеллекта - Иван Братко

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 29 30 31 32 33 34 35 36 37 ... 94

6.2. Пусть f — файл термов. Напишите процедуру

найтивсетермы( Терм)

которая выводит на экран все термы из f, сопоставимые с Tepм'ом. Обеспечьте при этом, чтобы во время поиска Терм не конкретизировался (это могло бы помешать ему сопоставиться с другими термами дальше по файлу).

6.3. Обработка символов

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

put( С)

где С — символ, который нужно вывести, в кодировке ASCII (число от 0 до 127), например, вопрос

?- put( 65), put( 66), put( 67).

породит следующий вывод:

АВС

65 — ASCII-код 'А', 66 — 'В', 67 — 'С'.

Одиночный символ можно считать из текущего входного потока при помощи цели

get0( С)

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

get( С)

вызовет пропуск всех непечатаемых символов (в частности пробелов) от текущей позиции во входном потоке до первого печатаемого символа. Этот символ затем тоже считывается и С конкретизируется его ASCII-кодом.

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

Робот    пытался     налить    вина    из     бутылки.

Цель сжатие выведет его в таком виде:

Робот пытался налить вина из бутылки.

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

сжатие :-

 get0( С),

 put( С).

сделатьостальное( С).

 сделатьостальное( 46) :- !.

  % 46 -АSСII-код точки, Все сделано

сделатьостальное( 32) :- !,

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

 get( С),

 put( С),

 сделатьостальное( С).

сделатьостальное( Буква) :-

 сжатие.

Упражнение

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

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

Часто желательно информацию, считанную как последовательность символов, иметь в программе в виде атома. Для этой цели существует встроенный предикат 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. Например:

1 ... 29 30 31 32 33 34 35 36 37 ... 94
На этой странице вы можете бесплатно читать книгу Программирование на языке Пролог для искусственного интеллекта - Иван Братко бесплатно.
Похожие на Программирование на языке Пролог для искусственного интеллекта - Иван Братко книги

Оставить комментарий