Проверка, является ли число треугольным - PullRequest
1 голос
/ 18 апреля 2020

Итак, у меня есть этот предикат tri angular (N), в котором N является числом, и этот предикат возвращает true, если число является числом tri angular.

Моя проблема заключается в том, что по какой-то причине мой предикат делает бесконечное l oop вместо простого суммирования чисел до N.

Пример:

? - tri angular (3). 3 true

и оно не заканчивается.

Так что, в основном, это вывод числа до 3, но я делаю что-то, чего я не понимаю.

Программа:

triangular(N) :- triangular(N,0).

triangular(N,AC) :- triangular(N,AC,N).

triangular(N,AC,0) :-  write(AC).

triangular(N,AC,CONT) :- NCONT is CONT - 1,
                         NAC is AC + NCONT,
                         triangular(N,NAC,NCONT).

1 Ответ

0 голосов
/ 18 апреля 2020

Справочная информация

Пролог может искать более одного решения вашего запроса.

Рассмотрим эту программу:

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.
...