printЛогическое программирование

printПримеры программ на языке Пролог

Рассмотрим несколько программ, демонстрирующих возможности Пролога для решения различных типов задач. Наиболее используемым алгоритмом является поиск в пространстве состояний. Если пространство поиска ограничено, то можно использовать простой перебор в глубину. Этот метод можно применить для решения известной головоломки о миссионерах и каннибалах, которая формулируется так: "К берегу реки подошли 3 миссионера и 3 каннибала. Как им всем безопасно переправиться на другой берег, используя двухместную лодку, если каннибалы могут съесть миссионеров, оказавшись в большинстве". Текущее состояние будем представлять в виде структуры s(ML,KL,B,MR,KR), где ML – число миссионеров на левом берегу, KL – число каннибалов на левом берегу, B – положение лодки, MR и KR – число миссионеров и каннибалов на правом берегу. Начальное состояние описывается структурой s(3,3,л,0,0).
решить:-старт(S),решить(S,[S],R),reverse(R,P),write(P).
решить(S,R,R):-цель(S),!.
решить(S,P,R):-ход(S,Z),\+ member(Z,P),решить(Z,[Z|P],R).
старт(s(3,3,л,0,0)).
цель(s(_,_,_,3,3)).
лодка(0,1).
лодка(0,2).
лодка(1,1).
лодка(2,0).
лодка(1,0).
безопасно(M,K):-M=:=0; M>=K.
ход(s(ML1,KL1,л,MR1,KR1), s(ML2,KL2,п,MR2,KR2)):-
    лодка(M,K), ML1>=M, KL1>=K,
    ML2 is ML1-M, KL2 is KL1-K, безопасно(ML2,KL2),
    MR2 is MR1+M, KR2 is KR1+K, безопасно(MR2,KR2).
ход(s(ML1,KL1,п,MR1,KR1), s(ML2,KL2,л,MR2,KR2)):-
    ход(s(MR1,KR1,л,ML1,KL1), s(MR2,KR2,п,ML2,KL2)).
В Прологе легко выполнять различные символические вычисления. Например, написание программы для дифференцирования выражений сводится просто к переводу правил дифференцирования на язык Пролог.
% d(+Выражение,+Переменная,-Результат).
d(X,X,1):-!. 
d(C,X,0):-atomic(C). 
d(-U,X,-A):-d(U,X,A). % (-u)’=-u’
d(U+V,X,A+B):-d(U,X,A),d(V,X,B). % (u+v)’=u’+v’.
d(U-V,X,A-B):-d(U,X,A),d(V,X,B). 
d(C*U,X,C*A):-atomic(C),C\=X,d(U,X,A),!.
d(U*V,X,U*B+A*V):-d(U,X,A),d(V,X,B). % (uv)’=uv’+u’v
d(U/V,X,(A*V-U*B)/V?2):-d(U,X,A),d(V,X,B).
d(U?C,X,C*A*U?(C-1)):-d(U,X,A).
d(log(U),X,A/U):-d(U,X,A).
?-d(x*x-2,x,R).
R=x*1+1*x-0
Полученный результат нужно упростить с помощью специальной программы.
упростить(E,E):-atomic(E),!.
упростить(E,R):-E=..[Op,A],упростить(A,X),s(Op,X,R).
упростить(E,R):-E=..[Op,A,B],
   упростить(A,X),упростить(B,Y),s(Op,X,Y,R).
% таблица упрощений
s(-,X,R):-number(X),R is -X.
s(-,X,-X).
s(+,X,0,X).
s(+,0,X,X).
s(+,X,Y,R):-number(X),number(Y),R is X+Y.
s(+,X*Z,Y*Z,R*Z):-number(X),number(Y),R is X+Y.
. . . % чем больше будет рассмотрено случаев, тем лучше упрощение
s(+,X,Y,X+Y). % ловушка для +
s(*,0,_,0).
s(*,_,0,0).
s(*,X,1,X).
s(*,1,X,X).
. . . % другие правила упрощения
s(*,X,Y,X*Y). % ловушка для *
. . . % правила для – и /
Некоторые задачи можно легко решить с помощью перебора всех возможных состояний объектов и проверки соотношений, заданных в задаче. В одной из глав книги Р. Смаллиана "Алиса в Стране Смекалки" рассказывается о сказочном королевстве, в котором все персонажи либо в своем уме, либо не в своем. Те, кто в своем уме, делают верные умозаключения, а те, кто не в своем, – ложные. Одна из головоломок звучит так: "Король думает, что королева думает, что она не в своем уме". Требуется определить состояние ума всех участников головоломки.
участник('в своем уме').
участник('не в своем уме').
думает('в своем уме',Z):-Z.
думает('не в своем уме',Z):- \+ Z.
?-участник(Король),участник(Королева),
   думает(Король,думает(Королева,Королева=’не в своем уме’)).
Король=’не в своем уме’, Королева=’в своем уме’;
Король=’не в своем уме’, Королева=’не в своем уме’;
no

Решение более сложной головоломки:
  1. Five colored houses in a row, each with an owner, a pet, cigarettes, and a drink.
  2. The English lives in the red house.
  3. The Spanish has a dog.
  4. They drink coffee in the green house.
  5. The Ukrainian drinks tea.
  6. The green house is next to the white house.
  7. The Winston smoker has a serpent.
  8. In the yellow house they smoke Kool.
  9. In the middle house they drink milk.
  10. The Norwegian lives in the first house from the left.
  11. The Chesterfield smoker lives near the man with the fox.
  12. In the house near the house with the horse they smoke Kool.
  13. The Lucky Strike smoker drinks juice.
  14. The Japanese smokes Kent.
  15. The Norwegian lives near the blue house.
Who owns the zebra and who drinks water?
% соседи
adjacent(A, B, Ls) :- append(_, [A,B|_], Ls);append(_, [B,A|_], Ls).

?-length(Hs, 5),                                          %  1
member(h(english,_,_,_,red), Hs),                         %  2
member(h(spanish,dog,_,_,_), Hs),                         %  3
member(h(_,_,_,coffee,green), Hs),                        %  4
member(h(ukrainian,_,_,tea,_), Hs),                       %  5
adjacent(h(_,_,_,_,green), h(_,_,_,_,white), Hs),         %  6
member(h(_,snake,winston,_,_), Hs),                       %  7
member(h(_,_,kool,_,yellow), Hs),                         %  8
Hs = [_,_,h(_,_,_,milk,_),_,_],                           %  9
Hs = [h(norwegian,_,_,_,_)|_],                            % 10
adjacent(h(_,fox,_,_,_), h(_,_,chesterfield,_,_), Hs),    % 11
adjacent(h(_,_,kool,_,_), h(_,horse,_,_,_), Hs),          % 12
member(h(_,_,lucky,juice,_), Hs),                         % 13
member(h(japanese,_,kent,_,_), Hs),                       % 14
adjacent(h(norwegian,_,_,_,_), h(_,_,_,_,blue), Hs),      % 15
member(h(Drinker,_,_,water,_), Hs),
member(h(Owner,zebra,_,_,_), Hs).


Пролог можно использовать для синтаксического разбора. Грамматика для языка может быть описана в виде набора фактов.
предложение-->группа_существительного, группа_глагола.
группа_существительного-->артикль, существительное.
группа_глагола-->глагол, группа_существительного; глагол.
артикль-->[the].
существительное-->[apple];[man].
глагол-->[eats];[sings].
Для проверки соответствия последовательности слов (лексем) грамматике языка нужно сделать запрос:
?-предложение([the,man,eats,the,apple],[]).
yes
Пролог позволяет определять более широкий класс грамматик, чем контекстно-свободные, а именно DC-грамматики. В GNU Prolog правила грамматики преобразуются в предложения Пролога, при этом добавляются аргументы для входной и выходной последовательности. Кроме того, можно добавить собственные аргументы для получения результатов разбора и действия в {} для их формирования.
% проверка, что далее операция или конец входной цепочки
isop([],_).
isop([X|_],_):-member(X,[+,-,*,/]).
% перевод выражения в обратной польской записи в обычную инфиксную форму
выр(_,[],_):-!,fail.
выр(X)-->[X],{member(X,[+,-,*,/]),!,fail;true}; % число или идентификатор
         выр(X1),(isop,{!,fail};выр(X2), [Op], {member(Op,[+,-,*,/]),X=..[Op,X1,X2]}).
?-выр(R,[a,1,+,2,*],[]).
R=(a+1)*2

Упражнения
1. Молочник принес на продажу два полных бидона с молоком по 10 литров. Две женщины пришли купить по 2 литра молока. У одной кувшин на 4 литра, у другой на 5 литров. Нужно налить в каждый кувшин по 2 литра молока.
2. К берегу реки подошел крестьянин с волком, козой и капустой. У берега оказалась двухместная лодка. Крестьянин не может оставить без присмотра волка с козой или козу с капустой. Требуется переправиться на другой берег.
3. В одном старой гостинице вместо пожарной лестницы была следующая система для спасения при пожаре. К блоку над окном подвешивались две корзины, соединенные веревкой. Для спуска вниз нужно было сесть в корзину и "пожарная" система достаточно мягко спустит вниз. При этом разница груза в корзинах не должна превышать 30 фунтов.
Однажды в гостинице случился пожар и обычная лестница оказалась в огне. Найти способ спуститься вниз постояльцу (вес 90 фунтов), его жене (210 фунтов), собаке (60 фунтов) и младенцу (30 фунтов). При этом следует учесть, что собака и младенец не могут выбраться из корзины самостоятельно без помощи взрослых. В корзину можно помещать несколько человек или животных.
4. "Я много думала о Мартовском Зайце, Болванщике и Соне", – сказала Алиса. – "Болванщика называют сумасшедшим Болванщиком, но разве он и в самом деле безумен? А Мартовский Заяц и Соня?"
"Видишь ли, милочка", – ответила Герцогиня, – "Болванщик как-то раз упомянул о том, что Мартовский Заяц думает, что не все трое участников безумного чаепития в своем уме. Кроме того. Соня считает, что Мартовский Заяц в здравом рассудке."
В своем ли уме Мартовский Заяц, Болванщик и Соня?
5. В Лесу Забывчивости живут Траляля и Труляля. Один из них лгал по понедельникам, вторникам и средам и говорил правду во все остальные дни недели. Другой лгал по четвергам, пятницам и субботам, но во все остальные дни недели говорил правду. Алиса не знает, кто из них как себя ведет. К тому же братья были так похожи друг на друга, что Алиса даже не могла различить их.
Однажды Алиса встретила обоих братцев вместе. Они высказали следующие утверждения.
Первый. Если я Траляля, то он Труляля.
Второй. Если он Труляля, то я Траляля.
Можно определить, кто из братцев Траляля и кто Труляля? Можно ли определить, что это был за день недели?
6. Алиса нашла погремушку и отправилась в Лес Забывчивости чтобы вернуть её владельцу. Траляля и Труляля сидели под деревом и ухмылялись. Алиса направилась к тому, кто был поближе, и спросила: "Чья это погремушка?". Тот ответил: "Это погремушка Труляля". Алиса немного подумала и спросила второго братца: "Вы кто?" "Труляля", — ответил тот. Алиса не помнила точно, в какой день недели происходил этот разговор, но была уверена, что не в воскресенье. Кому Алиса должна отдать погремушку?
loading