Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Рлп.doc
Скачиваний:
3
Добавлен:
18.09.2019
Размер:
279.55 Кб
Скачать

18. Проверка типа терма объект данных

Для проверки типа терма используются встроенные предикаты.

var(+Term) - свободная переменная

nonvar(+Term) - несвободная (конкретизированная) переменная

integer(+Term) - целое число

float(+Term) - вещественное число

number(+Term) - целое или вещественное число

atom(+Term) - атом

atomic(+Term) - атом или число

ground(+Term) -терм не содержит свободных переменных

Если не var(X) и не atomic(X), то X - структура.

  • atom(X) - да, если X-атом.

  • integer(X) - да, если X-целое.

  • atomic(X) - да, если X-целое или атом.

  • var(X) - да, если X-не конкретизированная переменная.

  • nonvar(X) - да, если X- терм, отличный от переменной, или уже конкретизированная переменная.

Пример универсального предиката суммирования:

plus(X,Y,Z):-integer(X),integer(Y),integer(Z),

S is X + Y, S=Z.

plus(X,Y,Z):-integer(X),integer(Y),var(Z),

Z is X + Y.

plus(X,Y,Z):-var(X),integer(Y),integer(Z),

X is Z - Y.

plus(X,Y,Z):-integer(X),var(Y),integer(Z),

Y is Z - X.

Примеры :

?-plus(1,2,Z). Z=3. ?-plus(X,2,4). X=2. ?-plus(1,Y,2). Y=1. ?-plus(1,2,3). no.

19. . Создание и декомпозиция объектов данных.

Существуют встроенные возможности, позволяющие работать на уровне исчисления второго порядка. Так во многих языках логического программирования введена возможность, позволяющая функтор обращать в элемент списка и наоборот. Часто такая возможность обозначается =... Используется для связывания терма и списка.

 

Терм =.. Список

Пример : f(a,b) =.. L ® L=[f,a,b]

Z=..[p,x,f(x,y)] ® Z=p(x,y,f(x,y))

 

òРассмотрим задачу . Изменение размеров геометрических фигур .

квадрат (сторона)

треугольник (сторона1, сторона2, сторона3)

окружность(радиус)

увеличение (фигура,коэфф,фигура1)

 

можно расписать отдельно для каждого тела

 

увеличение (квадрат(А),f,квадрат(А1)):-

А1=А*f.

Увеличение(окружность(R),f, окружность(R1)):-

R1=R*f

Увеличение(Тип(параметр),f, Тип(параметр)):-

Параметр=f* параметр.

Так поступать нельзя .

увеличение (фигура,f,фигура1):-

фигура=..[ Тип ; параметры],

Увеличение(параметр,f, параметр),

Фигура1=..[ Тип ; параметры1].

 

Умножить ([],_,[]).

Умножить ([x|L],f,[x1|L1]):- x1=f*x,

Умножить (L,f,L1).

 

Иногда встраивают предикаты, позволяющие работать отдельно как с самим функтором, так и с отдельными аргументами термов (предикатами).

21.Рекурсии

В отличие от традиционных языков программирования, в которых основным средством организации повторяющихся действий являются циклы, в Прологе для этого используются процедура поиска с возвратом (откат) и рекурсия. Откат дает возможность получить много решений в одном вопросе к программе, а рекурсия позволяет использовать в процессе определения предиката его самого. При изучении рекурсии частенько вспоминается случай с бароном Мюнхгаузеном, который сам себя за волосы вытаскивал из болота. Про откат мы подробнее поговорим в шестой лекции, а в этой займемся изучением рекурсии. Заметим, что рекурсию используют не только в Прологе, но и в обычных императивных языках программирования. Но для Пролога, в отличие от императивных языков, рекурсия является основным приемом программирования. Более того, Пролог позволяет определять рекурсивные структуры данных. Работе с ними будет посвящено несколько лекций нашего курса. Начнем изучение рекурсии в Прологе с классического примера. Предположим, что в базе знаний есть набор фактов, описывающий родственные связи людей через отношение "быть родителем". Предикат родитель имеет два аргумента. В качестве его первого аргумента указывается имя родителя, в качестве второго - имя ребенка. Мы хотим создать отношение "быть предком", используя предикат родитель. Для того чтобы один человек был предком другого человека, нужно, чтобы он либо был его родителем, либо являлся родителем другого его предка. Запишем эту идею: предок(Предок,Потомок):- родитель(Предок,Потомок).  /* предком является родитель */ предок(Предок,Потомок):- родитель(Предок,Человек), предок(Человек,Потомок).  /* предком является родитель предка */ Отношение предок является транзитивным замыканием отношения родитель, то есть это наименьшее отношение, включающее отношение родитель и обладающее свойством транзитивности. Напомним, что отношение называется транзитивным, если для любых пар (А,В) и (В,С), находящихся в этом отношении, пара (А,С) также находится в этом отношении. Очевидно, что отношение предок содержит отношение родитель. Это следует из первого предложения, в котором записано, что всякий родитель является предком. Второе предложение дает транзитивность. По аналогии с математической индукцией, на которую рекурсия немного похожа, любая рекурсивная процедура должна включать в себя базис и шаг рекурсии. Базис рекурсии - это предложение, определяющее некую начальную ситуацию или ситуацию в момент прекращения. Как правило, в этом предложении записывается некий простейший случай, при котором ответ получается сразу даже без использования рекурсии. Так, в приведенной выше процедуре, описывающей предикат предок, базисомрекурсии является первое правило, в котором определено, что ближайшими предками человека являются его родители. Это предложение часто содержит условие, при выполнении которого происходит выход из рекурсии или отсечение. Шаг рекурсии - это правило, в теле которого обязательно содержится, в качестве подцели, вызов определяемого предиката. Если мы хотим избежать зацикливания, определяемый предикат должен вызываться не от тех же параметров, которые указаны в заголовке правила. Параметры должны изменяться на каждом шаге так, чтобы в итоге либо сработал базис рекурсии, либо условие выхода из рекурсии, размещенное в самом правиле. В общем виде правило, реализующее шаг рекурсии, будет выглядеть так: <имя определяемого предиката>:- [<подцели>], [<условие выхода из рекурсии>], [<подцели>], <имя определяемого предиката>,  [<подцели>].  В некоторых ситуациях предложений, реализующих базис рекурсии, и предложений, описывающих шаг рекурсии, может быть несколько. Как правило, это бывает в сложных случаях, например, когда выполняемые в процессе реализации шага рекурсии действия зависят от выполнения или невыполнения какого-либо условия. Такие задачи встретятся нам в последующих лекциях, когда речь пойдет об обработке рекурсивных структур данных. В этой же лекции мы будем иметь дело в основном с простыми случаями рекурсии, когда рекурсивная процедура имеет один базис и один шаг рекурсии.

22. Обобщения

23.

24. Отладка

 Turbo Prolog 2.0 не обладает таким разветвленными средствами отладки программ по сравнению с другими системами программирования, здесь они практически отсутствуют. Однако язык программирования Turbo Prologпредоставляет пользователю возможность трассировки программы. Для того, чтобы задействовать это средство, необходимо включить в программный файл директиву trace, которая должна размещаться в программе перед разделомpredicates. Лучше всего разместить ее перед разделом domains.

    Общий вид директивы trace следующий:

    trace <список предикатов>,

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

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

    Выполнение директивы трассировки приостанавливает выполнение программы после каждой попытки удовлетворить подцель. В этот момент в окне трассировки (окно Trace среды программирования) печатаются значения переменных и некоторая другая информация (рис.1):

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

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

       REDO - после этого служебного слова размещается предикат, являющийся подцелью. Данное сообщение появляется тогда, когда осуществляется переход от одной реализации предиката к другой;

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

       F10 - выполнение следующего шага программы;

       Shift+F10 - изменение размеров и местоположения текущего окна;

       Alt+T - изменение работы режима отладки. При нажатии этой комбинации клавиш на экране появляется "плавающее" окно, содержащее значения трех пунктов. Изменить значения можно с помощью клавиши Enter, убрать окно с экрана - клавиша F10. Перечислим пункты этого окна (по умолчанию все они имеют значения On):

Status - отключить режим отладки;

       Trace Window - режим отладки работает, только не изменяется содержимое окна Trace;

       Edit Window - режим отладки работает, но в окне редактора кода (окне Editor) отсутствует курсор, указывающий выполняемый предикат;

       End - завершение выполнения программы.

    Если нужно продолжить выполнение программы в обычном режиме, то для выключения трассировки применяется директива trace(off).

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

25. Эффективность.

Эффективность программ на Прологе В практическом программировании на Прологе следует обращать внимание на эффективность программ. Для обсуждения этого понятия нам следует установить критерии оценки программ. Основной оцениваемый параметр число выполненных унификаций и число попыток унификации в процессе вычисления. Этот параметр связан с временем работы программы. Если в процессе вычислений глубина станет больше максимально допустимой, то вычисления прервутся. На практике эта проблема является основной. Мы последовательно рассмотрим эти параметры. Можно предположить, что при разумной записи детерминированного последовательного алгоритма в виде программы на Прологе ожидаемая эффективность алгоритма сохранится. Обычно результирующие программы на Прологе не основываются на унификациях общего вида или глубоких возвратах. Сложности могут возникнуть при реализации алгоритмов, связанных с существенной перестройкой структур данных, например при использовании переменных указателей или массивов. Подобные структуры данных можно непосредственно моделировать в Прологе, например используя деревья, при этом затраты будут возрастать логарифмически. Однако во многих случаях более естественно было бы модифицировать сам алгоритм, приспосабливая его к принципу однократного присваивания, присущему логическим переменным. Для указанных алгоритмов применимы обычные методы анализа сложности вычислений. Если не используется полная унификация . Величина константы зависит от программы. Поэтому число выполняемых в программе редукций, как функция от размера ее входа, является хорошей оценкой временной сложности программы. При программировании на Прологе средства, представляемые языком, могут использоваться полностью. Можно писать недетерминированные программы и программы, использующие полную унификацию. Анализ сложности таких программ представляет собой более трудную задачу и требует. Основной способ повышения эффективности программ совершенствование алгоритма. Хотя речь идет о декларативном языке, понятие алгоритма в Прологе остается тем же, что и в других языках программирования. Примеры удачных и неудачных алгоритмов решения одной и той же задачи приведены в предыдущих главах вместе с записью этих алгоритмов на Прологе. Ясно, что линейное обращение списков с использованием накопителей . Помимо выбора наиболее удачного алгоритма можно использовать еще несколько способов для увеличения эффективности программ на Прологе. Один из них состоит в выборе наилучшей реализации. Эффективная реализация характеризуется исходной скоростью, возможностями индексирования, применением оптимизации остатка рекурсии и методом сборки мусора. Единицей измерения скорости выполнения программы на языке логического программирования обычно служит . При вычислениях логический вывод соответствует редукции. При фиксированной реализации сами программы могут быть улучшены за счет . Проблема упорядочения целей рассматривалась в разд. Как было сказано в разд. Даже в программах без остатка рекурсии индексирование может привести к увеличению эффективности, так как оно ограничивает поиск применимых правил. Это может иметь значение в программах, представляющих наборы фактов в виде таблиц, например в синтаксическом анализаторе и компиляторе. В литературе, посвященной Прологу, не много внимания уделяется минимизации числа порождаемых структур данных. Рассмотрим эту проблему на примере. Сравним эффективность двух таких определений, отличающихся порождаемыми структурами данных. При этом ограничимся одним определенным использованием проверкой, является ли один данный список подсписком другого данного списка. Два рассматриваемых варианта определения предиката . Если оба аргумента предиката . Такое вычисление не порождает новых промежуточных структур данных. С другой стороны, выполнение предложения . Далее проверяется, является ли первый список суффиксом этого списка. Если проверка выполнилась неудачно, то происходит возврат и создается новый префикс первого списка. Хотя число редукций в среднем в этим двух программах одинаково, эффективность их выполнения все же различна. Первая программа не создает новых структур данных . Вторая программа создает новые структуры. При анализе программ на Лиспе обычно тщательно исследуется соия. Нам кажется, что этот вопрос столь же важен и для программ на Прологе. Однако искусство анализа больших программ на Прологе, вероятно, не достигло еще должной стадии. Мы приведем несколько полезных трюков для Пролога. Трюками здесь будут предикаты, которые или обрабатывают сопостав ления значений переменным, или демонстрируют использование глобальных переключателей. Интересная особенность предиката . Это связано с явным указанием безуспешности вычисления после выполнения цели, что исключает проведение любых сопоставлений. Указаннаяособенность используется при определении предиката . Этот предикат проверяет, выполнена ли цель . Предикат определяется через двойное отрицание. В качестве курьеза отметим, что реализация отрицания в Прологе имеет что. Например смысл двойного отрицания высказывания не совпадает со смыслом эквивалентного утверждающего высказывания. Полезным системным предикатом . Например, при успешном решении цели . Этот предикат является еще одним примером предиката, анализирующего структуру терма. Счетчики в программе возрастают, а не убывают, и это позволяет нумеровать переменные слева направо в возрастающем порядке. Чтобы не возникла ошибка, следует обращаться к. Нумерация переменных в терме. Этот же предикат можно использовать при определении отношения . В другом полезном примере используется как отношение . Для обоснования этого примера мы вернемся к обсуждению металогического сравнения термов, начатому в разд. В Прологе существует понятие промежуточной эквивалентности, заимствованное из логики, а именно. Напомним, что два терма являются алфавитными вариантами, если они совпадают с точностью до переименования переменных, т. они могут быть сделаны синтаксически идентичными путем последовательного изменения имен переменных в одном из термов.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]