- •Предисловие
- •Лабораторная работа 1
- •Темы для предварительной проработки
- •1.1. Порядок выполнения работы
- •1.2. Содержание отчета
- •1.3. Индивидуальные задания
- •1.4. Пример решения задачи
- •Контрольные вопросы
- •Приложение 1а
- •Приложение 1б
- •Приложение 1в
- •Приложение 1г
- •Лабораторная работа 2
- •Темы для предварительной проработки
- •2.1. Порядок выполнения работы
- •2.2. Содержание отчета
- •2.3. Индивидуальные задания
- •2.4. Пример решения задачи
- •Контрольные вопросы
- •Приложение 2а
- •Приложение 2б
- •Лабораторная работа 3
- •1.4. Пример решения задачи
- •Контрольные вопросы
- •Приложение 3а
- •Приложение 3б
- •Приложение 3в
- •Приложение 3г
- •Лабораторная работа 4
- •4.4. Пример решения задачи
- •Контрольные вопросы
- •Лабораторная работа 5
- •Темы для предварительной проработки
- •5.1. Порядок выполнения работы
- •5.2. Содержание отчета
- •5.3. Индивидуальные задания
- •5.4. Пример решения задачи
- •Контрольные вопросы
- •Приложение 5а
- •Лабораторная работа 6
- •Темы для предварительной проработки
- •6.1. Порядок выполнения работы
- •6.2. Содержание отчета
- •6.3. Индивидуальные задания
- •6.4. Пример решения задачи
- •Контрольные вопросы
- •Приложение 6а
- •Приложение 6б
- •Константы типа драйвера
- •Константы режимов драйвера
- •Константы цветов
- •Константы стиля и толщины линий (для предикатов GetLineStyle, SetLineStyle)
- •Константы типа шрифта (задаются в предикате settextstyle(Font,Direction,Charsize))
- •Лабораторная работа 7
- •Темы для предварительной проработки
- •7.1. Порядок выполнения работы
- •7.2. Содержание отчета
- •7.3. Индивидуальные задания
- •7.4. Пример решения задачи
- •Контрольные вопросы
- •Приложение 7а
- •Приложение б
- •Редактор о.І. Шпільова
- •61002 Харків, вул. Фрунзе, 21
7.4. Пример решения задачи
Тема: работа с графами и деревьями в среде Turbo Prolog.
Цель работы: ознакомление с возможностями обработки графов и деревьев в среде Turbo Prolog 2.0 и приобретение практических навыков создания и использования структур данных для представления и обработки деревьев и графов.
Индивидуальное задание: построить неориентированный граф с заданными стоимостями ребер, определить все возможные пути от одной заданной вершины к другой и стоимости этих путей.
Разработка метода решения задачи.
Для решения поставленной задачи предлагается представить граф, элементами которого являются факты, содержащие сведения о связи двух вершин между собой и о стоимости такой связи. Такой факт (прил. 7Б) представляется в виде d(вершина1,вершина2,стоимость). Факты целесообразно хранить во внешнем текстовом файле der8_db.pro.
После загрузки фактов, описывающих граф, целесообразно составить отсортированный список вершин, входящих в граф. Эта функция возлагается на предикат р.
У пользователя спросить имена исходной и целевой вершин и проверить, входят ли они в граф. Эти действия выполняет предикат v3(вершина, список_вершин). Если вершина не входит в граф, на экран выводится соответствующее сообщение и работа программы завершается. Если вершины входят в граф, инициируется поиск всех возможных путей между ними (предикат v), подсчет стоимостей путей и вывод на экран результата.
Собственно поиск путей выполняет предикат р1(вершина, путь, стоимость).
Описание предикатов, разработанных для реализации метода решения задачи на языке Turbo Prolog.
Предикаты файла der8.pro
Предикаты |
Назначение |
b(ii) |
База данных найденных путей и их стоимостей |
d(i,i,i) |
База данных, описывающая граф: d(вершина1,вершина2,стоимость) |
p(ii) |
Составление упорядоченного списка вершин графа |
p1(i,ii,i) |
Предикат поиска пути: р1(вершина, путь, стоимость) |
v1(i,i,i) |
Проверка наличия связи между двумя вершинами: v1(вершина1, вершина2, флаг_наличия_связи) |
v2(i,ii) |
Проверка вхождения вершины в найденный список вершин (путь): v2(вершина, путь) |
v3(i,ii) |
Проверка вхождения вершины в граф: v3(вершина, список_вершин) |
v |
Инициация поиска пути |
Предикаты файла sort.pro:
Предикаты |
Назначение |
men(i,ii,ii,ii) |
Деление списка на два результирующих списка относительно значения первого элемента: men(элемент,исходный_список,рез_список1,рез_список2) |
sort_quick(ii,ii) |
Выполнение «быстрой сортировки» списка: sort_quick(исх_список, отсортированный_список) |
konk(ii,ii,ii) |
Конкатенация двух списков: konk(список1, список2, объединенный_список) |
ud(ii,ii) |
Удаление из списка одинаковых элементов: ud(исх_список, результирующий_список) |
Стандартные предикаты, используемые для решения задачи:
Стандартные предикаты для работы с оперативной базой данных взяты из Приложения 2Б.
Текст программы.
%Выполняет поиск всех существующих путей на графе
include "sort.pro" % Подключение файла sort.pro
database
b(ii) % База данных найденных путей и их стоимостей
d(i,i,i) %База данных - граф
% d(вершина1,вершина2,стоимость)
predicates
p(ii) %Составление упорядоченного списка вершин графа
p1(i,ii,i) %Поиск пути
v1(i,i,i) %Проверка наличия связи между двумя вершинами
v2(i,ii) %Проверка вхождения вершины в найденный список
% вершин (путь)
v3(i,ii) %Проверка вхождения вершины в граф
v %Инициализация поиска пути
clauses
%Составление упорядоченного списка вершин графа
p(P):-
findall(X,d(X,_,_),P1), % Составление списка "левых" вершин
findall(Y,d(_,Y,_),P2), % Составление списка "правых" вершин
konk(P1,P2,P3), % Конкатенация списков (см. файл sort.pro)
sort_quick(P3,P4), % Сортировка списка (см. файл sort.pro)
ud(P4,P). % Удаление из списка одинаковых элементов
% (см. файл sort.pro)
Продолжение программы
%Поиск пути
p1(X,[X|P],S):- % Завершение рекурсии, если голова списка
% равна исходной вершине (первый аргумент)
PP=[X|P], %Список вершин пути записывается в переменную РР
write(PP," S=",S), % Вывод на экран пути и его стоимости
nl.
p1(X,[Z|P],S):- % Вершина Z присоединяется к пути после
% выполнения следующих далее проверок
v1(Y,Z,S1), % Проверка наличия связи между вершинами Х и Y
v2(Y,P), % Проверка вхождения вершины Х в путь
S2=S+S1, % Добавление веса ребра к стоимости пути
p1(X,[Y,Z|P],S2). % Рекурсивный вызов
%Проверка наличия связи между вершинами Х и Y
v1(X,Y,S1):- % Определение веса ребра
d(X,Y,S1). % по найденному факту связи вершин
v1(X,Y,S1):-
d(Y,X,S1).
%Проверка вхождения вершины в найденный список вершин (путь)
v2(_,[]). % Если список-путь пуст, то вершина
% в него не входит
v2(X,[Y|P]):- % Проверка вхождения вершины в список
X<>Y, % Если вершина не равна голове списка,
v2(X,P). % то продолжать поиск
%Проверка вхождения вершины в граф
v3(X,[X|_]):-!. % Если вершина равна голове списка,
% то она входит в граф
v3(X,[_|P]):- % Рекурсивное правило
v3(X,P). % (вторая формулировка)
v3(X,[]):- % Во всех остальных случаях вершина
% не входит в граф.
nl,write("Вершина ",X," не входит в граф!"),
nl,write("Путей нет!"),
readint(_),fail.
%Инициация поиска путей
v:-
b(P),write("Список вершин:"),nl,
write(P),nl,
write("Исходная вершина:"),nl,
readint(X),
v3(X,P), %Проверка вхождения исходной вершины в граф
write("Целевая вершина:"),nl,
readint(Y),
v3(Y,P), %Проверка вхождения целевой вершины в граф
write("Найденные пути и их стоимости:"),nl,
p1(X,[Y],0), %Поиск путей
fail.
Продолжение программы
v.
goal
clearwindow, %Очистка экрана
retractall(d(_,_,_)), % Очиска оперативной памяти
retractall(b(_)),
consult("der8_db.pro"),% Загрузка базы данных
p(P), % Составление списка вершин графа
asserta(b(P)), % Добавление списка вершин в опер. память
v,nl, % Инициация поиска путей
write("*****"). % Конец работы
К основной программе подключается файл sort.pro, содержащий вспомогательные предикаты для выполнения конкатенации и сортировки списков и удаления одинаковых элементов из списка:
domains i=integer ii=i*
predicates
men(i,ii,ii,ii) % Делит список на два списка относительно значения
% первого элемента
sort_quick(ii,ii) % Выполнение «быстрой сортировки» списка
konk(ii,ii,ii) % Конкатенация двух списков
ud(ii,ii) % Удаление из списка одинаковых элементов
clauses
men(_,[],[],[]). % Условие завершения рекурсии:
% когда второй параметр-список пуст, третий и четвертый
% параметры – тоже пустые списки.
men(A,[B|X],[B|L1],L2):- %Если голова В списка-второго параметра
B<A,men(A,X,L1,L2). % меньше, чем первый параметр предиката,
% то эта голова сцепляется
% со списком-третьим параметром предиката,
% а четвертый параметр-список остается
% без изменений.
men(A,[B|X],L1,[B|L2]):- %Во всех остальных случаях голова В
men(A,X,L1,L2). % списка-второго параметра сцепляется
% со списком четвертым параметром предиката,
% а третий параметр-список остается
% без изменений.
sort_quick([],[]). % Когда первый список пуст, второй тоже пуст
sort_quick([A|X],R):- % Выделяется голова первого списка
men(A,X,L1,L2), % Вызов предиката men, который
% возвращает два списка –
% L1 (его элементы меньше элемента А), и
% L2 (его элементы больше элемента А).
sort_quick(L1,M1), % Вызов сортировки списка L1. Возвращается
Продолжение программы
% отсортированный список М1
sort_quick(L2,M2), % Вызов сортировки списка L2. Возвращается
% отсортированный список М2
konk(M1,[A|M2],R). % Конкатенация списков М1, М2 и головы А
%Конкатенация списков
konk([],Z,Z). %Когда первый список пуст,
% третий список равен второму
konk([X|Y],Z,[X|R]):- % Голова первого списка присоединяется
% в начало третьего списка
konk(Y,Z,R). % Рекурсивный вызов
%Удаление из списка одинаковых элементов
ud([X],[X]). %Когда первый список состоит из одного элемента,
% второй список состоит из этого же одного элемента.
ud([A|X],P):- % В первом списке выделяется голова А и хвост Х
ud(X,[Y|P1]), % Выполняется рекурсивный вызов и сцепление
% головы Y и хвоста Р1 во втором списке
A<Y, % Если А меньше Y, то
P=[A,Y|P1]. % список Р представляет собой сцепление элементов
% А, Y и хвоста Р1.
ud([_|X],P):- %Рекурсивное правило для перебора всех элементов
% первого списка.
ud(X,P).
База данных, представляющая дерево, хранится в файле der8_db.pro в следующем виде:
d(1,2,2).
d(2,4,1).
d(1,3,3).
d(2,5,5).
d(5,6,1).
d(3,6,2).
d(1,7,1).
d(7,8,3).
d(8,6,2).
Выводы
При выполнении лабораторной работы были изучены особенности представления графов и деревьев в Прологе с помощью структур. Для реализации индивидуального задания были разработаны рекурсивные предикаты. Программа реализована по модульному принципу.
