Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Язык программирования SWI-Prolog. Учебно-методическое пособие

.pdf
Скачиваний:
0
Добавлен:
15.08.2026
Размер:
830 Кб
Скачать

МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ

ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ «САМАРСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

К а ф е д р а «Прикладная математика и информатика»

Г.Н. ГУТМАН М.Н. САУШКИН

ЯЗЫК ПРОГРАММИРОВАНИЯ SWI-Prolog

Учебно-методическое пособие с практическими заданиями

Самара Самарский государственный технический университет

2020

Печатается по решению ученого совета СамГТУ(протокол №8 от

28.03.2019 г.).

УДК 004.43(075.8) ББК 32.97я73 Г 971

Гутман Г.Н.

Язык программирования SWI-Prolog: учебно-методическое пособие / Г.Н. Гутман, М.Н. Саушкин. – Самара: Самар. гос. техн. ун-т, 2020. – 110 с.

Изложены основы языка программирования SWI-Prolog, приведены примеры решения задач, иллюстрирующих основные возможности языка. Содержит большое количество заданий для самостоятельного решения. Эти же задания можно использовать для проведения лабораторных работ в рамках дисциплины «Функционально-логические языки программирования».

Предназначено для студентов, обучающихся по направлению подготовки 01.04.02 «Прикладная математика и информатика» (квалификация «магистр»).

Р е ц е н з е н т : канд. физ.-мат. наук, доцент В.Н. Маклаков

УДК 004.43(075.8) ББК 32.97я73 Г 971

©Г.Н. Гутман, М.Н. Саушкин, 2020

©Самарский государственный технический университет, 2020

ВВЕДЕНИЕ

Среди множества языков программирования особняком стоит язык логического программирования Пролог(англ. Prolog). Пролог получил своё название от английских словPROgramming in LOGic. Данный язык программирования был создан в 1972 году и нашел применение при разработке баз знаний и экспертных систем, систем искусственного интеллекта, а также при решении логических задач. В настоящее время существует целый ряд коммерческих и свободных реализаций языка. Наиболее удобным для начального знакомства с языком авторы считают вариант языка SWI-Prolog.

По языку Пролог существует целый ряд книг, в которых излагаются как общие принципы логического программирования, так и методика и примеры решения различных задач на этом языке [1–9].

Язык SWI-Prolog имеет хорошо структурированную документацию (на английском языке), размещённую в свободном доступе на официальном сайте [10] в сети Интернет.

Разработка, отладка и выполнение программ на языкеSWI-Prolog возможна как в интегрированной среде разработки на локальном компьютере,

так и в режимеonline на сайте https://swish.swi-prolog.org [11]. В настоя-

щем пособии авторы ориентировались именно на работу в online-режиме. Заметим, что как сам язык SWI-Prolog, так и указанный веб-интерфейс

являются свободным программным обеспечением и распространяются в соответствии с Simplified BSD license (упрощенной Berkeley Software Distribution лицензией), также известной как BSD-2 лицензия.

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

Вторая часть работы представляет собой сборник задач для самостоятельного решения. Задания разбиты на темы: задачи на вычисление, работа со списками, структуры данных, числовые ребусы, базы данных, решение логических задач, игры и головоломки. Задания частично взяты из печатных изданий [12–14], частично найдены в сети Интернет, некоторые задачи придуманы авторами.

Вприложении приводится описание технологии разработки программ

сиспользование веб-интерфейса и приводится пример такой разработки.

3

1.ТЕОРЕТИЧЕСКАЯ ЧАСТЬ

1.1.Общие сведения о языке Prolog

Теоретической основой Prolog является раздел символьной логики, называемый исчислением предикатов. Предикат – это логическая функция от нескольких аргументов, которая принимает значение «истина» или «ложь».

Пример. Предложение «вещественное число Х> 0» является предикатом, так как принимает значение«истина» только для положительных вещественных чисел. При подстановке вместо Х конкретного значения предикат превращается в высказывание, т. е. в предложение, содержание которого можно однозначно определить как истинное или ложное.

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

механизм вывода с поиском и возвратом (откат);

встроенный механизм сопоставления с образцом (унификация).

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

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

4

1.2. Объекты и синтаксис языка Prolog

1.2.1. Алфавит и ключевые слова языка

В алфавит языка включены буквы латиницы и кириллицы, цифры и ряд специальных символов, в частности, символ подчеркивания. Ключевые слова в том понимании, в котором они используются в процедурных языках, в языке отсутствуют. Их заменяют встроенные предикаты– аналог функций в процедурных языках программирования.

1.2.2. Переменные

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

Имя переменной должно начинаться с прописной буквы или символа подчеркивания, например, A, Петя, _tmp и даже _1 – это имена переменных. Если имя переменной состоит из единственного символа подчеркивания, то это анонимная переменная. Анонимную переменную нельзя конкретизировать, поэтому её можно многократно использовать в одном и том же выражении. Анонимная переменная в большинстве случаев ставится на место аргумента, значение которого нужно проигнорировать.

Значение переменной может быть числом, атомом или более сложной структурой. Рассмотрим подробнее все эти случаи.

1.2.3. Числа и сопоставление значений

Числа (тип number) могут быть целыми и вещественными, последние можно задать как в виде числа с целой и дробной частью(разделитель – точка), так и в показательном виде.

Пример.

?- A = 12, B = 7.45, C = 1e20.

5

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

Пример.

?- 12 = A, 7.45 = B, 1e20 = C.

Этот вариант тоже работает! Дело в том, что Пролог рассматривает это выражение как некий предикат и подбирает такие значения дляA, B и C, чтобы этот предикат стал истинным – это и есть унификация (сопоставление). Результат зависит от того, является ли переменная, участвующая в выражении, свободной (т. е. не имеющей значения) или конкретизированной (т. е. уже получившей значение). Например, если в выражении X = 17 переменная X является свободной, то она будет конкретизирована значением 17. Если же переменная X уже имеет значение, то выражение X = 17 рассматривается как операция сравнения!

При этом если «переменная» X получила определённое значение, то значение этого объекта в рамках запроса изменить нельзя! То есть и выражение X = X+5, и выражение X is X+5 будут ложными, так как Пролог будет сравнивать в первом случае термы17 и 17+5, а во втором – значения 17 и 22. Если же X есть свободная переменная, то выражение X+5 лишено смысла, так как X не имеет значения.

Запятая, соединяющая отдельные выражения, обозначает логическую операцию И, а точка с запятой – логическую операцию ИЛИ.

Пример. Запрос A = 12, A = 7 эквивалентен предикату (A = 12) И (A = 7), поэтому он вернёт в качестве результата значениеfalse. С другой стороны, если использовать в предыдущем примере логическую операцию ИЛИ, то запрос A = 12; A = 7 вернёт два значения:

A = 12

A = 7,

так как он эквивалентен предикату(A = 12) ИЛИ (A = 7), истинному при двух значениях A.

1.2.4. Арифметические операции и математические функции

Хотя Prolog и не предназначен для вычислений, в нём есть все арифметические операции, операторы сравнения и ряд математических функций. Однако из-за особого характера оператора= для вычисления числовых значений используется оператор is.

6

Пример.

?- A = 1 + 3, B is 1 + 3, C is sin(pi/4).

Результат:

A = 1+3,

B = 4,

C = 0.7071067811865475

Заметим, что оператор is также не является оператором присваивания.

Он так же, как и оператор =, выполняет сопоставление левой и правой ча-

сти с той лишь разницей, что вычисляет значения выражения в правой ча-

сти. В левой части может стоять число (тогда is похож на оператор сравне-

ния) или имя значения (тогда is похож на оператор присваивания).

 

Примеры.

 

 

 

 

 

 

 

 

Запрос1.0 is sin(pi/2) вернёт true.

 

 

 

 

Запросsin(pi/2) is 1.0 также вернёт true.

 

 

 

Запрос1

is sin(pi/2) вернёт false, так

как не

совпадают

типы

левой

и

правой

частей. В

то

же

время

оператор

сравнения

1 =:= sin(pi/2) вернёт true.

 

 

 

 

 

При выводе можно использовать форматирование. Например, запрос

C is sin(pi/4), format('C = ~4f',C)

выведет значение C с четырьмя знаками после запятой:

C = 0.7071

Арифметические операции:

+ и – (минус) – операции сложения и вычитания. Несколько подряд идущих операций выполняются слева направо.

* и / – операции умножения и деления. Несколько подряд идущих операций выполняются слева направо.

^ – возведение в степень. В отличие от предыдущих случаев несколько подряд идущих операций выполняются справа налево!

Пример.

Запрос A is 4^3^2, B is (4^3)^2, C is 4^(3^2).

Результат:

A = C, C = 262144,

B = 4096

7

Заметим, что для возведения в степень можно(но не рекомендуется!) использовать оператор **, так как он не допускает нескольких подряд идущих операций.

N // K – целочисленное деление;

N div K – другой способ целочисленного деления, не эквивалентный N // K. Отличия появляются, если одно из значений N или K отрицательно;

N mod K – вычисление остатка от деления N на K;

N rem K – другой способ вычисления остатка, не эквивалентный N mod K. Отличия появляются, если одно из значений N или K отрицательно.

Операторы сравнения: = (равно), \= (не равно), < (меньше), =< (равно или меньше – в SWI-Prolog именно так!), > (больше), >= (больше или равно).

Для сравнения числовых значений двух выражений вместо знаков = (равно) и \= (не равно) нужно использовать операторы =:= и =\=.

Примеры.

Запрос 9 = 5+4 вернёт false, в то время как запрос 9 =:= 5+4 вернёт true. Запрос 9 \= 5+4 вернёт true, в то время как запрос 9 =\= 5+4 вернёт false.

Основные математические функции в языке SWI-Prolog: abs(X) – модуль (абсолютная величина) числа;

sqrt(X) – квадратный корень; exp(X) – экспонента;

sin(X), cos(X), tan(X) – тригонометрические функции; log(X) – натуральный логарифм;

log10(X) – десятичный логарифм; sign(X) – знак числа X;

random(X) – случайное целое число в полуинтервале [0; X) и другие.

1.2.5. Атомы и термы

Атом – это отдельный объект, считающийся элементарным. В Прологе атом представляется последовательностью букв нижнего и верхнего регистра, цифр и символа подчеркивания'_', начинающейся со строчной буквы. Кроме того, любой набор допустимых символов, заключенный в апострофы, также является атомом.

Примеры атомов: s_55, one, хоккей, 'Михаил'.

8

Термом в Прологе является любой объект данных– значения, переменные, атомы и составные термы. Фактически составной терм соответствует структуре в других языках программирования, причём имя структуры играет роль типа структуры.

Примеры.

vector(1,2,3) – именованная структура, содержащая три целых числа; (‘Сергей’, 1990) – неименованная структура, содержащая атом и число.

1.2.6. Списки

Основной структурой для хранения данных в Прологе являются списки. Список является составным объектом, который представляет собой набор произвольных термов (чисел, атомов, списков). Список в Прологе заключается в квадратные скобки, и элементы списка разделяются запятыми. Список, который не содержит ни одного элемента, называется пустым списком.

Примеры списков: [] – пустой список;

[1, 2, 3] – список, элементами которого являются целые числа; [A, B, C] – список, элементами которого являются переменные; [(‘Сергей’, 1990), (‘Ирина’, 2004)] – список структур;

[A, 12, [1,2,3], B, 18, [4,5,6]] – список произвольных термов.

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

Пример. Найти сумму элементов числового списка.

Решение. Составим предикат listsum с двумя параметрами: первый параметр – это список чисел, второй параметр – сумма элементов этого списка.

9

Предикат состоит из двух правил. Первое правило: сумма элементов пустого списка равна нулю.

listsum([], 0) :- !.

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

Второе правило: сумма элементов непустого списка равна значению головы списка плюс сумма элементов хвоста списка:

listsum(L,S) :-

 

L

=[

H|T

],

% представляем список в виде голова|хвост

listsum(T,W), % находим сумму элементов хвоста

S

is

W +

H.

% к найденной сумме прибавляем значение

 

 

 

 

%

головы списка

Заметим, что SWI-Prolog содержит встроенный предикат sum_list(список, сумма), который как раз и находит сумму элементов списка.

Пример. Получить список L из N случайных чисел в диапазоне от 0 до

K-1.

Решение. В предикате randList(N, K, L) рассмотрим три случая.

1) N < 0. В этом случае нужно завершить процесс решения и сообщить об ошибке – для этого используем встроенный предикатfail (он выведет false).

randList(N,_,_):-

N < 0, !, writeln('Ошибка: параметр меньше нуля'), fail.

2) N = 0. В этом случае нужно получить пустой список и закончить работу.

randList(0,_,[]):-!.

3) N > 0. В этом случае список L нужно представить в виде [H|T], где H – голова списка, а T – хвост списка. Затем записать в H случайное число и рекурсивно вызвать тот же предикат для хвоста списка T:

randList(N, K, L):-

L = [H|T], N1 is N-1, H is random(K), randList(N1, T).

10

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