Пролог, родившийся, как и многие языки программирования, в начале 70-х годов, к настоящему времени так и не стал промышленным языком программирования: для написания прикладных систем Пролог используется крайне редко. В своем большинстве программисты-практики Пролога не знают или оценивают его невысоко. Еще в конце 80-х годов такие крупные фирмы программного обеспечения, выпускающие системы программирования, как Borland International, Microsoft прекратили развитие систем программирования на Прологе. Тем не менее, Пролог сохраняет свое значение в структуре подготовки специалиста по информатике, реализуя парадигму дескриптивного программирования, альтернативную процедурной и функциональной парадигмам. Пролог является прекрасной иллюстрацией метода представления знаний на основе продукций в интеллектуальных системах, с ним связаны очень большие ожидания в исследованиях по искусственному интеллекту. Есть уверенность в том, что идеи, реализованные в Прологе, будут в дальнейшем развиваться в промышленных интеллектуальных информационных системах, т. е. будущее этого языка программирования — впереди. Программирование на Прологе включает в себя следующие этапы: 1) объявление фактов об объектах и отношениях между ними; 2) определение правил взаимосвязи объектов и отношений между ними; 3) формулировка вопроса об объектах и отношениях между ними. Основная операция, выполняемая в языке Пролог, — это операция сопоставления (называемая также унификацией или согласованием). Операция сопоставления может быть успешной, а может закончиться неудачно, и определяется так: 1) константа сопоставляется только с равной ей константой; 2) идентичные структуры сопоставляются друг с другом; 3) переменная сопоставляется с константой или с ранее связанной переменной (и становится связанной с соответствующим значением); 4) две свободные переменные могут сопоставляться (и связываться) друг с другом; с момента связывания они трактуются как одна переменная: если одна из них принимает какое-либо значение, то вторая немедленно принимает то же значение. Факты — это предикаты с аргументами-константами, обозначающие отношения между объектами или свойства объектов, именованные этими константами. Факты в программе считаются всегда и безусловно истинными и таким образом служат основой доказательства, происходящего при выполнении программы. Правила — это хорновские фразы с заголовком и одной или несколькими подцелями-предикатами. Правила имеют форму и позволяют определить новые отношения между объектами на основе уже объявленных с помощью фактов. В качестве аргументов в предикатах правила могут использоваться не только константы, но и переменные. На переменные в правилах действуют кванторы общности, поэтому правила концентрированно и лаконично выражают конструкции логического вывода. Переменные в Прологе получают свои значения в результате сопоставления с константами в фактах и правилах. Вопрос — отправная точка логического вывода, происходящего при выполнении программы. На любой вопрос компьютер будет пытаться дать ответ «Да» или «Нет» в зависимости от того, согласуется или нет утверждение, стоящее в вопросе, с фактами и правилами базы знаний. Вопрос, не содержащий переменных, является общим: «имеет ли место факт... ?». Вопрос, в котором имеются переменные, является частным: «для каких значений переменных факт ... имеет место ?». В процессе сопоставлений при выполнении программы переменные конкретизируются — получат значения тех констант, для которых сопоставление запроса в целом успешно, и будут выведены на экран. Для интерпретатора Пролога существенны только совпадения и различия имен, а также связи между предикатами, устанавливаемые с помощью конъюнкций и импликаций. Однако в Прологе существуют предопределенные имена (встроенные предикаты), которые позволяют выполнить арифметические операции, сравнения, графические построения, ввод-вывод и другие полезные операции как побочный продукт выполнения программы. Встроенные предикаты Arity- Prolog описаны в справке по системе программирования, вызываемой нажатием клавиши F1. Аналогичный набор встроенных предикатов имеется в других версиях языка Пролог. Существует целый класс задач, в которых отношения между объектами можно определить только пользуясь самими определяемыми соотношениями. Получающиеся при этом правила называются рекурсивными. В системах логического программирования рекурсия служит также для описания циклов, повторений и является важнейшим методом программирования. В общем виде рекурсия на Прологе выглядит так: Р(1, . . .) . P(nf...) I~ Q1, , Qn, Р (п_1, .. .),R1, . ..Rm. Правило Р обращается само к себе, при этом происходит углубление рекурсии. Предикаты Q1, ..., Qn выполняются на прямом ходе рекурсии, a R1,..., Rm — на обратном; п — это некоторый условный параметр, входящий в условие продолжения рекурсии, а Р(1,...) — факт, завершающий процесс рекурсии. Особенно простым случаем рекурсии является простое циклическое повторение. Один из способов организации повторения связан с наличием в базе знаний процедуры вида repeat. repeat repeat. Использование repeat в качестве подцели некоторого правила приводит к многократному повторению остальных подцелей этого правила. Управление процессом просмотра предложений является важным аспектом программирования на Прологе. Это осуществляется с помощью специальной встроенной функции «резать», обозначаемой символом «!». Данная встроенная функция может быть использована ддя достижения следующих трех целей: 1) исключения бесконечной петли при выполнении программы; 2) программирования взаимоисключающих утверждений; 3) блокирования просмотра целей. На практике часто встречаются задачи, связанные с перечислением объектов. В некоторых случаях при решении задач важно сохранять информацию об уже сде- данных шагах решения, чтобы их не повторять. Для решения таких задач в языке Пролог предусмотрены списки. . Список можно задать перечислением элементов. Например, имена учеников класса: [саша,петя,дима,ксюша,лена]. Элементами списка могут быть не только атомы, но и функции и вообще любые элементы, даже списки. Заранее дайна списка не задается, и в ходе выполнения программы она может меняться. Альтернативный способ задания списка использует понятия головы и хвоста списка. Например, в списке [х | Y] х — это голова списка, a Y — его хвост. Хвост списка по определению также является списком. Теперь список может быть определен рекурсивно: 1) пустой список [] —список; 2) [х i y] — список, если y — список. Определение списка через его голову и хвост в сочетании с рекурсией лежит в основе большого количества программ, оперирующих списками. Эти программы состоят: 1) из факта, ограничивающего рекурсию и описывающего операцию для пустого списка; 2) из рекурсивного правила, определяющего операцию над списком, состоящим из головы и хвоста (в голове правила), через операцию над хвостом (в подцели). Арифметические операторы. Арифметическое выражение состоит из функтора и его аргументов. Функтор — арифметическая операция; аргументы — целые или переменные, они являются операндами для функтора. Например: + (х, 1). Пролог позволяет использовать инфиксную нотацию. Например: х+1. Можно использовать арифметические выражения вида: x+Y, x-y, x*y, x/y (обычное деление, результат — действительное число), X//Y (целое деление, результат — целое число), xay (возведение в степень); - х; X/ \y (конъюнкция; только int) (and), х\ /y (дизъюнкция; int) (or), \ (X) - NOT (ТОЛЬКО int), xy — смещение x вправо (int), [X] — оценить (приблизительное вычисление) х, х mod y — выдает остаток от деления х на Y, abs (X) — абсолютное значение (х), acos (X) — arccos (X) asin (X) — arcsin (X) atan(X) — arctg(X), cos (X), exp(X), ln (X), log(X), sin (X), sqrt(X) , tg(X), round (x, ■ N) — округление x до N символов после запятой, (NЕ2 проверяет, больше ли значение El значения Е2; аналогично: еКе2, Е1>=е2, еК=е2; х is El — El вычисляется и сопоставляется с х; Е1=: =Е2 — вычисляются El и Е2 и проверяются на эквивалентность; Е1=\=Е2 — вычисляются El и Е2 и проверяются на неравенство; randomise (tSeed) — переустановка генератора случайных чисел (аргумент Seed — целый); inc (+х, - Y) — увеличение целого х и возврат в y; dec (+x,-Y) — уменьшение целого х и возврат в Y.