Справочная информация
Пролог может искать более одного решения вашего запроса.
Рассмотрим эту программу:
human(alice).
human(bob).
Когда вы запрашиваете ?- human(X).
, Пролог будет искать назначения для X
, которые соответствуют вашей программе. Он покажет вам решение X = alice
. После этого вы можете остановить поиск, нажав .
, или продолжить поиск, нажав ;
. Если вы продолжите, Пролог найдет X = bob
. После этого он остановится, поскольку исчерпал все возможные решения:
?- human(X).
X = alice .
?- human(X).
X = alice ;
X = bob.
Вы можете управлять процессом поиска, используя предикат сокращения !
. Предикат cut обрезает альтернативные пути в текущем слое. Поэтому, если вы расширите вышеупомянутую программу с помощью этого правила:
find_first_human(X) :- human(X), !.
Выполнение запроса ?- find_first_human(X).
будет только выводить X = alice.
без поиска дальнейших ответов. Пролог знает, что human(X)
может быть разрешен несколькими способами, но затем !
говорит Прологу игнорировать эти альтернативы.
Применение этого к вашей программе
Основная проблема заключается в том, что ваш последний предикат triangle
не требует CONT > 0
. Поэтому, когда вы запрашиваете ?- triangle(3).
, Пролог в конечном итоге достигает triangular(3,3,0).
, что соответствует вашему правилу write
. Как видите, ваша программа выдает 3
, как и ожидалось. Однако Пролог видит, что есть альтернативные решения для triangular(3,3,0)
, поэтому он предлагает вам продолжить поиск. Вы можете остановиться, нажав .
, или продолжить, нажав ;
. Если вы продолжите, Пролог попробует последнее правило для triangular
, с разрешением CONT
до 0
. Таким образом, NCONT
становится -1
. Затем это go превратится в бесконечное l oop, где последнее triangular
правило применяется неоднократно, уменьшая CONT
без конца.
Это можно проверить с помощью trace.
(можно снова отключить с помощью notrace.
):
?- trace.
?- triangular(3).
Call: (8) triangular(3) ? creep
Call: (9) triangular(3, 0) ? creep
Call: (10) triangular(3, 0, 3) ? creep
...
Call: (13) triangular(3, 3, 0) ? creep
Call: (14) write(3) ? creep
3
Exit: (14) write(3) ? creep
Exit: (13) triangular(3, 3, 0) ? creep
...
true ;
Redo: (13) triangular(3, 3, 0) ? creep
Call: (14) _2076 is 0+ -1 ? creep
Exit: (14) -1 is 0+ -1 ? creep
...
Вы можете остановить это, изменив последнее правило на:
triangular(N,AC,CONT) :- CONT > 0,
NCONT is CONT - 1,
NAC is AC + NCONT,
triangular(N,NAC,NCONT).
Это запрещает Прологу применять правило для triangular(3,3,0)
. Когда вы запускаете запрос ?- triangular(3).
с измененной программой, Prolog должен выписать 3
, как и раньше, при достижении triangular(3,3,0)
. После этого он обнаруживает, что могут быть альтернативные решения. Если вы нажмете ;
, то обнаружит, что последнее правило не может быть применено, поскольку ограничение CONT > 0
не выполняется. Затем поиск прекращается:
?- triangular(3).
3
true ;
false.
Мы можем еще больше упростить это с помощью предиката сокращения !
, показанного в предыдущем разделе, изменив правило write
на:
triangular(N,AC,0) :- write(AC), !.
Это говорит Прологу не искать альтернативные решения для triangular(3,3,0)
. Когда вы запускаете запрос ?- triangular(3).
, Пролог должен выписать 3
, как и прежде, и затем выйти без дальнейшего поиска:
?- triangular(3).
3
true.