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
Пролог можно использовать для синтаксического разбора. Грамматика для языка может быть описана в виде набора фактов.
предложение-->группа_существительного,группа_глагола.
группа_существительного-->артикль,существительное.
группа_глагола-->глагол,группа_существительного;глагол.
артикль-->[the].
существительное-->[apple];[man].
глагол-->[eats];[sings].
разбор(P,L,R):-(P-->G),разбор(G,L,R).
разбор((X,Y),L,R):-разбор(X,L,Q),разбор(Y,Q,R).
разбор((X;Y),L,R):-разбор(X,L,R);разбор(Y,L,R).
разбор([X|T],[X|L],R):-разбор(T,L,R).
разбор([],R,R).
?-разбор(предложение,[the,man,eats,the,apple],[]).
yes
Использование дополнительных аргументов у нетерминальных символов позволяет получать дерево синтаксического разбора и определять более широкий класс грамматик, чем контекстно-свободные, а именно DC-грамматики. DC-грамматики легко преобразовать в предложения Пролога, добавив аргументы для входной и выходной последовательности. Для этого можно использовать встроенный предикат expand_term/2.
Упражнения
1. Молочник принес на продажу два полных бидона с молоком по 10 литров. Две женщины пришли купить по 2 литра молока. У одной кувшин на 4 литра, у другой на 5 литров. Нужно налить в каждый кувшин по 2 литра молока.
2. К берегу реки подошел крестьянин с волком, козой и капустой. У берега оказалась двухместная лодка. Крестьянин не может оставить без присмотра волка с козой или козу с капустой. Требуется переправиться на другой берег.
3. В одном старой гостинице вместо пожарной лестницы была следующая система для спасения при пожаре. К блоку над окном подвешивались две корзины, соединенные веревкой. Для спуска вниз нужно было сесть в корзину и "пожарная" система достаточно мягко спустит вниз. При этом разница груза в корзинах не должна превышать 30 фунтов.
Однажды в гостинице случился пожар и обычная лестница оказалась в огне. Найти способ спуститься вниз постояльцу (вес 90 фунтов), его жене (210 фунтов), собаке (60 фунтов) и младенцу (30 фунтов). При этом следует учесть, что собака и младенец не могут выбраться из корзины самостоятельно без помощи взрослых. В корзину можно помещать несколько человек или животных.
4. "Я много думала о Мартовском Зайце, Болванщике и Соне", – сказала Алиса. – "Болванщика называют сумасшедшим Болванщиком, но разве он и в самом деле безумен? А Мартовский Заяц и Соня?"
"Видишь ли, милочка", – ответила Герцогиня, – "Болванщик как-то раз упомянул о том, что Мартовский Заяц думает, что не все трое участников безумного чаепития в своем уме. Кроме того. Соня считает, что Мартовский Заяц в здравом рассудке."
В своем ли уме Мартовский Заяц, Болванщик и Соня?
5. В Лесу Забывчивости живут Траляля и Труляля. Один из них лгал по понедельникам, вторникам и средам и говорил правду во все остальные дни недели. Другой лгал по четвергам, пятницам и субботам, но во все остальные дни недели говорил правду. Алиса не знает, кто из них как себя ведет. К тому же братья были так похожи друг на друга, что Алиса даже не могла различить их.
Однажды Алиса встретила обоих братцев вместе. Они высказали следующие утверждения.
Первый. Если я Траляля, то он Труляля.
Второй. Если он Труляля, то я Траляля.
Можно определить, кто из братцев Траляля и кто Труляля? Можно ли определить, что это был за день недели?
6. Алиса нашла погремушку и отправилась в Лес Забывчивости чтобы вернуть её владельцу. Траляля и Труляля сидели под деревом и ухмылялись. Алиса направилась к тому, кто был поближе, и спросила: "Чья это погремушка?". Тот ответил: "Это погремушка Труляля". Алиса немного подумала и спросила второго братца: "Вы кто?" "Труляля", — ответил тот. Алиса не помнила точно, в какой день недели происходил этот разговор, но была уверена, что не в воскресенье. Кому Алиса должна отдать погремушку?
loading