
- •Глава 1. Введение в пролог
- •1. Декларативные и процедурные языки программирования
- •2. Пролог и логика предикатов. Внешние цели
- •3. Управление программой. Подцели. Механизм сопоставления
- •4. Внутренние подпрограммы унификации
- •Глава 2. Внутренние цели. Механизм возврата
- •1. Структура пролог-программы
- •2. Использование внутренних целей
- •3. Встроенный предикат fail
- •4. Сокращенные варианты внутренних запросов
- •5. Использование в запросах анонимных переменных
- •6. Механизм возврата
- •Глава 3. Типы данных и арифметика Turbo Prolog
- •1. Стандартные типы данных
- •2. Структуры, простые и составные
- •3. Структурные диаграммы
- •4. Использование в запросах анонимных переменных
- •5. Использование альтернативных доменов
- •6. Арифметика в Turbo Prolog
- •Глава 4. Предикат отсечения (!). Программирование альтернатив. Правила повтора
- •1. Повторения и возвраты
- •2. Отсечение (!)
- •3. Программирование альтернатив
- •4. Правило повтора
- •Глава 5. Методы организации рекурсии
- •1. Простая рекурсия
- •2. Метод обобщенного правила рекурсии
- •3. Граничное условие рекурсии. Нисходящая и восходящая рекурсии
- •4. Программа о подсчете числа точек
- •Глава 6. Списки
- •1. Основные понятия
- •2. Списки и турбо-пролог
- •3. Атрибуты списка
- •4. Внутреннее представление списков
- •5. Применение списков в программе
- •6. Метод разделения списка на голову и хвост
- •7. Поиск элемента в списке
- •8. Присоединение списка
- •9. Добавление и удаление элемента
- •10. Подсписок
- •11. Перестановки списка
- •Глава 7. Сортировка списков
- •1. Разделение списка на два
- •2. Сортировка списков методом вставки
- •3. Быстрая сортировка
- •4. Быстрая сортировка_1
- •5. Компоновка данных в список
- •Глава 8. Программирование алгоритмов с возвратом. Представление графов в turbo prolog
- •1. Задача о весах
- •2. Представление графов в turbo prolog
- •3. Поиск пути на неориентированном графе
- •4. Поиск гамильтоновых циклов
- •5. Поиск пути минимальной стоимости
- •Глава 9. Динамическая база данных
- •1. Турбо-пролог и реляционные базы данных
- •2. Описание предикатов динамических бд
- •3. Встроенные предикаты asserta, assertz, retract, retractall, save, consult
- •4. Создание динамической базы данных
- •5. Обсуждение проекта базы данных
- •6. Создание базы данных
- •7. Написание программных модулей
- •Глава 10. Глобальные переменные в turbo prolog
- •1. Модификация базы данных
- •2. Накопление результатов с помощью вынуждаемого возврата
- •3. Подсчет членов парторганизации
- •4. Поиск пути минимальной стоимости от a до z
- •Библиографический список
- •Оглавление
4. Поиск пути минимальной стоимости от a до z
Вспомним задачу из главы 8 о поиске пути минимальной стоимости. Пути мы получали за счет возвратов, а глобальной переменной, чтобы запоминать текущий минимум, у нас не было.
Для хранения текущего минимального пути заведем предикат динамической БД min_way, первым аргументом которого будет текущий минимальный путь, вторым — его стоимость.
database
dmin_way(list,integer)
При генерации очередного пути воспользуемся следующим методом: прежде, чем добавлять к пути новое ребро, проверим, не станет ли его стоимость больше либо равна стоимости текущего минимального пути. Если да, то этот путь не нужно генерировать до конца (он уже не будет меньше текущего минимума), а следует переходить к генерации следующего пути.
Поэтому рекурсивное правило процедуры way1 изменится:
way1(Z, [X|Was],SW, Sol,S):-
sosed1(X,Y,St),
not(member(Y,Was)),
SW1=SW+St,
dmin_way(_,Stoim),
% сравнеие с минимумом после добавления ребра
Stoim>Sw1,
way1(Z,[Y,X|Was],SW1,Sol,S).
Если проверка Stoim>Sw1 не проходит, то происходит возврат к sosed1, которая находит следующую вершину — соседку для продолжения пути.
Перед началом генерации путей запишем в базу начальное значение минимума:
assert(dmin_way([],1000))
Процедура поиска минимального пути будет иметь следующий вид:
find_min(Z, A):-
% перебор всех путей
way1(Z, [A], 0, Sol, MinS),
% изменение текущего min пути
change_base(Sol,MinS),
fail.
find_min(_, _):-
dmin_way(Sol,St),
% печать окончательного минимума
write(Sol),nl,
write(St),nl.
Все правила изменения текущего минимума спрятаны на уровень ниже, в процедуре change_base:
change_base(Sol,MinS):-
dmin_way(_,St),
St > MinS,
retract(dmin_way(_,_)),
assert(dmin_way(Sol,MinS)),!.
В процедуру передается очередной путь Sol и его стоимость MinS, затем стоимость MinS сравнивается с текущим минимумом St, и, в случае успеха проверки, предикат dmin_way переписывается.
/* Программа 10.1 «Поиск пути от A до Z */
/* минимальной стоимости». Назначение: */
/* демонстрация работы с динамической БД */
domains
uzl=integer
list=uzl*
list1=integer*
database
dmin_way(list,integer)
predicates
graph1(list,list1)
show_min
find_min(uzl,uzl)
way1(uzl,list,integer,list,integer)
change_base(list,integer)
sosed1(uzl,uzl,integer)
member1(uzl,list,list1,integer)
member(uzl,list)
goal
show_min. % показать минимальный путь
clauses
% 1-й список — список соседок,
% 2-й список — стоимостей соответствующих ребер.
graph1([1,2,3,4],[3,0,2]).
graph1([2,1,3,5],[3,4,5]).
graph1([3,1,2,4],[0,4,0]).
graph1([4,1,3,5],[2,0,1]).
graph1([5,2,4],[5,1]).
show_min:-
write("Начало пути "), readint(A),
write("Конец пути "), readint(Z),
assert(dmin_way([],1000)),
find_min(Z,A),
save("minway.dba").
find_min(Z, A):-
% перебор всех путей
way1(Z, [A], 0, Sol, MinS),
% изменение текущего min пути
change_base(Sol,MinS),
fail.
find_min(_, _):-
dmin_way(Sol,St),
% печать минимума
write(Sol),nl,
write(St),nl.
way1(Z, [Z|Was],S, [Z|Was],S).
way1(Z, [X|Was],SW, Sol,S):-
sosed1(X,Y,St),
not(member(Y,Was)),
SW1=SW+St,
dmin_way(_,Stoim),
Stoim>Sw1,
way1(Z, [Y,X|Was],SW1, Sol,S).
change_base(Sol,MinS):-
dmin_way(_,St),
St > MinS,
retract(dmin_way(_,_)),
assert(dmin_way(Sol,MinS)),!.
sosed1(X, Y, St):-
graph1([X|T], LS),
member1(Y, T, LS, St).
member1(H,[H|_],[S|_],S).
member1(X,[_|T],[_|ST],S):-
member1(X,T,ST,S).
member(H,[H|_]):-!.
member(X,[_|T]):-
member(X,T).
/* конец программы */
Упражнение 10.2.
Найти на нагруженном графе гамильтонов цикл минимальной стоимости с использованием глобальных переменных.