Сибирский университет потребительской кооперации
Опубликован: 04.05.2005 | Доступ: свободный | Студентов: 4322 / 1347 | Оценка: 4.45 / 4.22 | Длительность: 12:28:00
ISBN: 978-5-9556-0034-5
Лекция 3:

Основные понятия Пролога

< Лекция 2 || Лекция 3: 1234 || Лекция 4 >

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

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

Решение можно записать в следующем виде:

max(X,Y,X):-
	X>Y. /* если первое число больше второго, 
	        то первое число - максимум */   
max(X,Y,Y):- 
	X<Y. /* если первое число меньше второго, 
	           то второе число - максимум */  
max(X,Y,Y):-
	X=Y. /* если первое число равно второму, 
	        возьмем в качестве максимума 
	        второе число */

Первое предложение можно объединить со вторым или третьим в одно предложение. Тогда процедура будет состоять не из трех предложений, а всего из двух:

max(X,Y,X):-
	X>Y. /* если первое число больше второго, 
	        то первое число - максимум */   
max(X,Y,Y):-
	X<=Y./* если первое число меньше или равно 
	            второму, возьмем в качестве максимума 
	            второе число */

Однако полученная процедура еще далека от совершенства. С одной стороны, в случае, когда первое проверяемое условие ( X>Y ) не выполнено, будет проверяться второе условие ( X<=Y ), хотя понятно, что если не выполнено X>Y, значит X<=Y. С другой стороны, в случае, если первое условие имело место и первое число оказалось больше второго, Пролог-система свяжет третий аргумент предиката max с первым аргументом, после чего попытается сопоставить второе предложение. Хотя нам очевидно, что после того, как максимум определен, не нужно больше ничего делать. Других вариантов в данной ситуации просто не может быть. И, значит, проверка второго условия избыточна.

В данной ситуации нам пригодится встроенный предикат, который по-английски называется cut, по-русски - отсечение, а в программе на Прологе он обозначается восклицательным знаком " !". Этот предикат предназначен для ограничения пространства поиска, с целью повышения эффективности работы программ. Он всегда завершается успешно. После того, как до него дошла очередь, он устанавливает "забор", который не дает "откатиться назад", чтобы выбрать альтернативные решения для уже "сработавших" подцелей. То есть для тех, которые расположены левее отсечения. На цели, расположенные правее, отсечение не влияет. Кроме того, отсечение отбрасывает все предложения процедуры, расположенные после предложения, в котором находится отсечение .

С использованием отсечения наше решение будет еще короче:

max2(X,Y,X):-
	X>Y,!./* если первое число больше второго, 
	            то первое число - максимум */
max2(_,Y,Y).  /* в противном случае максимумом будет 
	            второе число */

В случае, если сработает отсечение, а это возможно, только если окажется истинным условие X>Y, Пролог-система не будет рассматривать альтернативное второе предложение. Второе предложение "сработает" только в случае, если условие оказалось ложным. В этой ситуации в третий аргумент попадет то же значение, которое находилось во втором аргументе. Обратите внимание, что в этом случае нам уже не важно, чему равнялся первый аргумент, и его можно заменить анонимной переменной.

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

Пример "красного" отсечения имеется в реализации предиката max2 (если убрать отсечение, предикат будет выдавать в качестве максимума второе число, даже если оно меньше первого). Пример "зеленого" отсечения можно получить, если в запись предиката max добавить отсечения (при их наличии предикат будет выдавать те же решения, что и без них).

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

Процедура

S:-
   <условие>,!,P. 
S :-
   P2.

будет соответствовать оператору if <условие> then P else P2, то есть если условие имеет место, то выполнить P, иначе выполнить P2. Например, в случае с максимумом, можно расшифровать нашу процедуру как "если X>Y, то M=X, иначе M=Y ".

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

Подходов к решению этой задачи может быть несколько.

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

max3a(X,Y,Z,X):-
	X>=Y,X>=Z. 
	/* если первое число больше или равно второму 
	   и третьему, то первое число - максимум */
max3a(X,Y,Z,Y):-
	Y>=X,Y>=Z. 
	/* если второе число больше или равно первому
	   и третьему, то второе число является 
	   максимумом */
max3a(X,Y,Z,Z):-
	Z>=X,Z>=Y. 
	/* если третье число больше или равно первому
	   и второму, то максимум - это третье число */

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

Применение отсечения позволит существенно сократить решение:

max3b(X,Y,Z,X):-
	X>Y,X>Z,!. 
	/* если первое число больше второго и третьего,
	   то первое число - максимум */
max3b(_,Y,Z,Y):-
	Y>=Z,!. 
	/* иначе, если второе число больше третьего, 
	   то второе число является максимумом */
max3b(_,_,Z,Z). /* иначе максимум - это третье число */

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

И, наконец, самое короткое решение можно получить, если воспользоваться уже имеющимся предикатом max2. Решение будет состоять всего из одного предложения.

max3(X,Y,Z,M):-
	max2(X,Y,XY), /* XY - максимум из X и Y */
	max2(XY,Z,M). /* M - максимум из XY и Z */

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

Семантические модели Пролога

В Прологе обычно применяются две семантические модели: декларативная и процедурная. Семантические модели предназначены для объяснения смысла программы.

В декларативной модели рассматриваются отношения, определенные в программе. Для этой модели порядок следования предложений в программе и условий в правиле не важен.

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

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

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

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

< Лекция 2 || Лекция 3: 1234 || Лекция 4 >
Виктор Бондарь
Виктор Бондарь

После приведения формулы вида ПНФ к виду ССФ вы получаете формулу, в безквантовой матрице которой дизъюнкт содержит оба контранрных атома:. Как тогда проводить его унификацию, если в случае замены x на f(x) весь дизъюнкт обратится в единицу?

Ольга Потапенко
Ольга Потапенко

никак не могу увидеть тексты самих лекций.