Листинг 14.4, Решение числового ребуса в системе CLP(FD)
% Программа решения числового ребуса DONALD+GERALD=ROBERT средствами CLP(FD)
solve С [D, О,H,A, L,D] , [G, E,R,A,L,D] , [R, 0, В, E, R, Г] ) :-
Vars = ,0,N,A,L,G,E,R,B,T] , % Переменные, необходимые для решения задачи
domain [ Vars, 0, 9) , all_dif ferent I Vars), 1000C0*D + 10000*0 + 100D00*G + 10000*E + 100000*R + 10000*0 + labeling £ [], Vars). |
% % |
Все эти переменные обозначают- десятичные цифры Все эти переменные - разные
1000*N + 100*A + 10*L + D + 1000*R + 100*A + 10*L + D # = 1000*B + 1D0*E + 10*R + T,
В листинге 14.5 приведена программа CLP(FD) для решения знакомой задачи с восемью ферзями. В качестве указания по составлению подобных программ следует отметить, что обе программы (и для решения числовых ребусов, и для решения задачи с восемью ферзями) имеют следующую основную структуру: вначале задаются области определения переменных, затем налагаются определенные ограничения и в конечном итоге предикат разметки находит конкретные решения. Это — обычная структура программ CLP(FD),
Часть II.Применение языка Prolog в области искусственного интеллекта
Листинг 14,5. Программа CLP(FO)для задачи с восемью ферзями
% Программа решения задачи с восемью ферзями средствами CLP(FD)
solution С Ys) ;- % Ys - список координат Y ферзей
Ys = [_,_,_,_, _г _,_,_] , * Количество ферзей равно 8
domain ( Ys, 1, В) , % Все координаты имеют область определения 1. .8
alldif ferent ! Ys), % Все координаты - разные, что позволяет
% предотвратить взаимные нападения по горизонтали
safe! Ys), % Ограничение, с помощью которого предотвращаются
% нападения по диагонали
labeling! [J, Ys). I Найти конкретные значения для Ys
safe С П) ■
safe! [Y | Ys]) :-
no attack ( Y, Ys, 1), 4 1 - расстояние по горизонтали между ферзем Y
% и ферзями из списка Ys
safet Ys) .
% no_attack( Y, Ys, D):
% ферзь, который определен переменной Y, не нападает ни на одного из ферзей
h в списке Ys;
I D - расстояние по горизонтали между первым ферзем и остальными ферзями
no_attack( Y, [],_).
no_attack( Yl, [Y2 | Ys] , D) :-D #\= Y1-Y2, D #\=Y2-Yl, Dl is D+l, no_attack( Yl, Ys, Dl) .
Наконец, рассмотрим процедуру решения с помощью системы CLP(FD) задач оптимизации, таких как минимизация времени завершения при составлении расписаний. Для решения задач оптимизации удобно применять следующие встроенные предикаты CLP(FD): minimize! Goal, X) и maximize; Goal, X)
Эти предикаты находят такое решение Goal, которое минимизирует (максимизирует) значение X. Как правило, Goal - это цель предиката indomain или предиката разметки, например, как показано ниже.
?- х in 1..20, V # = X*(20-Х), maximize ( indomain (X) , V), X = 1 0 , V = 100
Простую задачу планирования (см. рис. 14.1) можно решить с помощью следующего запроса:
?.- StartTimes = [Та, ТЬ, Тс, Td,Tf ] , % Tf - время завершения domain< StartTimes, 0, 20), Та #>= 0,
Та + 2#=<ТЬ, % Задание а предшествует заданию Ь
Та + 2#=<Тс, % Задание а предшествует заданию с
ТЬ + 3 #=< Td, % Задание b предшествуетзаданию d
Тс + 5#=<Tf, % Задание с завершается ко времени завершения Tf
Td + 4 #=< Tf,
minimize! labeling([ ] , StartTiraes], Tf) .
StartTimes = [0,2,2,5,9]
В данном случае вырабатывается только одно оптимальное решение.
Глава 14. Логическое программирование в ограничениях