Чтение онлайн

ЖАНРЫ

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

Братко Иван

Шрифт:

?- подмножество( [а, b, с], S ).

S = [a, b, c];

S = [b, c];

S = [c];

S = [];

S = [a, c];

S = [a];

...

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

разбиениесписка( Список, Список1, Список2)

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

Список1
и
Список2
и чтобы эти списки были примерно одинаковой длины. Например:

разбиениесписка( [а, b,
с, d, e], [a, с, e], [b, d]).

3.10. Перепишите программу об обезьяне и бананах из главы 2 таким образом, чтобы отношение

можетзавладеть( Состояние, Действия)

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

Действия
будет такой последовательностью, представленной в виде списка ходов:

Действия = [ перейти( дверь, окно),

передвинуть( окно, середина),

залезть, схватить ]

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

линеаризация( Список, ЛинейныйСписок)

где

Список
может быть списком списков, а
ЛинейныйСписок
 — это тот же список, но "выровненный" таким образом, что элементы его подсписков составляют один линейный список. Например:

?- линеаризация( [а, d, [с, d], [], [[[e]]], f, L).

L = [a, b, c, d, e, f]

3.3. Операторная запись (нотация)

В математике мы привыкли записывать выражения в таком виде:

2*a + b*с

где + и * — это операторы, а 2, а, b, с — аргументы. В частности, + и * называют инфиксными операторами, поскольку они появляются между своими аргументами. Такие выражения могут быть представлены в виде деревьев, как это сделано на рис. 3.6, и записаны как прологовские термы с + и * в качестве функторов:

+( *( 2, а), *( b, с) )

Рис. 3.6. Представление выражения 2*а+b*с в виде дерева.

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

2*а + b*с

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

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

а + b
, Пролог поймет эту запись, как если бы написали
+(а, b)
. Для того, чтобы Пролог правильно воспринимал выражения типа
а + b*с
, он должен знать, что
*
связывает сильнее, чем
+
. Будем говорить, что
+
имеет более низкий приоритет, чем
*
. Поэтому верная интерпретация выражений зависит от приоритетов операторов. Например, выражение
а + b*с
, в принципе можно понимать и как

+( а, *( b, с) )

и как

*( +(
а, b), с)

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

+
 и 
*
, понимались в соответствии с обычными соглашениями, то 
+
должен иметь более низкий приоритет, чем 
*
. Тогда выражение
а + b*с
означает то же, что и
а + (b*с)
. Если имеется в виду другая интерпретация, то это надо указать явно с помощью скобок, например
(а+b)*с
.

Программист может вводить свои собственные операторы. Так, например, можно определить атомы

имеет
и
поддерживает
в качестве инфиксных операторов, а затем записывать в программе факты вида:

питер имеет информацию.

пол поддерживает стол.

Эти факты в точности эквивалентны следующим:

имеет( питер, информацию).

поддерживает( пол, стол).

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

:- op( 600, xfx, имеет).

Такая запись сообщит Прологу, что мы хотим использовать "имеет" в качестве оператора с приоритетом 600 и типом '

xfx
', обозначающий одну из разновидностей инфиксного оператора. Форма спецификатора '
xfx
' указывает на то, что оператор, обозначенный через '
f
', располагается между аргументами, обозначенными через '
х
'.

Обратите внимание на то, что определения операторов не содержат описания каких-либо операций или действий. В соответствии с принципами языка ни с одним оператором не связывается каких-либо операций над данными (за исключением особых, редких случаев). Операторы обычно используются так же, как и функторы, только для объединения объектов в структуры и не вызывают действия над данными, хотя само слово "оператор", казалось бы, должно подразумевать какое-то действие.

Имена операторов это атомы, а их приоритеты — точнее, номера их приоритетов — должны находиться в некотором диапазоне, зависящем от реализации. Мы будем считать, что этот диапазон располагается в пределах от 1 до 1200. [1]

Существуют три группы типов операторов, обозначаемые спецификаторами, похожими на

xfx
:

(1) инфиксные операторы трех типов:

xfx xfy yfx

(2) префиксные операторы двух типов:

fx fy

1

Чем выше приоритет, тем меньше его номер. — Прим. перев.

(3) постфиксные операторы двух типов:

хf yf

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

f
' соответствует оператору, а 'x' и '
y
' представляют его аргументы. Расположение '
f
' между аргументами указывает на то, что оператор инфиксный. Префиксные и постфиксные спецификаторы содержат только один аргумент, который, соответственно, либо следует за оператором, либо предшествует ему.

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