2012-01-15 3 views
1

У меня есть база данных, полные факты, такие как:Пролога - Помощь пониманию правила

checkpoint(checkpoint1,checkpoint2,2). 
checkpoint(checkpoint2,checkpoint3,3). 
checkpoint(checkpoint3,checkpoint4,4). 
checkpoint(checkpoint4,checkpoint5,2). 
checkpoint(checkpoint5,checkpoint6,2). 

контрольной точка (например, firstcheckpoint secondcheckpoint, ВремяВМинуты).

Тогда следующие тесты правило, если поездка возможна между двумя контрольно-пропускными пунктами в гонке:

journey(X,Y):- checkpoint(X,_,_), checkpoint(_,Y,_),!; checkpoint(Y,_,_), checkpoint(_,X,_),!. 

journey(X,Y):- checkpoint(X,Z,_), journey(Z,Y). 
journey(X,Y):- checkpoint(Z2,Y,_), journey(X,Z2). 

Обратите внимание, что вы не можете пропустить пункты пропуска, вы можете получить только в checkpoint4 сначала собираюсь 1,2 затем- Вы можете, однако, вернуться назад, например, перейти от контрольной точки 4 до 3.

Я понимаю, что этот код проверяет, возможно ли путешествие между двумя контрольно-пропускными пунктами, если между X и Y имеется промежуточная контрольная точка, которая в этом случае Z. Однако я не совсем понимаю, что делает Z2. Я предполагаю, что его просто используют в качестве другого промежуточного элемента, например Z, однако почему он называется другой переменной? Не может ли Z2 быть изменен на Z, и он все равно будет работать?

ответ

1

Z2 можно окончательно переименовать в Z в последнем правиле, и логика правила не изменится. Причина, по которой автор не решался использовать Z, вероятно, потому, что эта переменная не обозначает «среднюю точку», как это делает Z в первом правиле.

Лично я бы с более описательными именами переменных - From и To звучат как хорошие кандидаты:

journey(From,To):- checkpoint(From,Mid,_), journey(Mid,To). 
journey(From,To):- checkpoint(Someplace,To,_), journey(From,Someplace). 
1

Вы можете переименовать переменный без изменения смысла правило, если переименовать все в вхождения одинаковы.

Но первое правило путешествия выглядит неправильно для меня: какой эффект вы ожидаете от сокращений? Дизъюнкция не имеет возможности работать, вызывать первый разрез.

Оставьте только первое правило, то попробуйте ?- findall((X,Y),journey(X,Y),L). Вы увидите единственный ответ L = [ (checkpoint1, checkpoint2)].

Итак, ответ от @dasblinklight (+1) предполагает более глубокое исправление друг от друга переменных переименования: просто перенесите первое правило путешествия ...

EDIT

Эта процедура (без сокращений) расширяет оригинальной спецификации, что позволяет перечислить все возможные поездки, и может соответствовать первоначальному определению:

journey(X, Y):- 
    journey([], X, Y). 
journey(Visited, X, Y) :- 
    (checkpoint(X, I, _) ; checkpoint(I, X, _)), 
    \+ memberchk(I, Visited), 
    (I = Y ; journey([X|Visited], I, Y)). 
+0

Хм хорошо, если я вообще не включаю разрезы, я, кажется, попадаю в бесконечный цикл, где после того, как я получу истинное положение, я могу продолжать настаивать; и пролог будет продолжать возвращаться. Я предположил, что после добавления сокращений это просто сработало, но я попробую, что вы сказали в комментарии. – Arun22

+0

После нескольких тестов кажется, что разрезы прекрасно подходят? Я протестировал исходный код, полностью удалив строку после дизъюнкции, а затем проверил обратное путешествие на контрольную точку, которая вернулась как ожидалось. Однако, с дизъюнкцией и разрезами, если я тестирую обратное путешествие, он возвращает true, предлагая, что он работает отлично? – Arun22

+0

Вы правы, удаление первого правила запрещает любое решение. Я отредактирую ответ ... – CapelliC

Смежные вопросы