Что происходит в вашей программе? Это зацикливается навсегда или требуется только некоторое время, так как вы не обновляли свое оборудование в последние десятилетия? Мы не можем сказать. (На самом деле, мы могли бы сказать, глядя на вашу программу, но на данный момент она слишком сложна).
Что мы можем сделать с легкостью, так это сузить источник этих дорогостоящих усилий. И это, без глубокого понимания вашей программы. Начнем с запроса:
| ?- multiple(X, s(s(s(s(s(s(0))))))).
X = s(0) ? ;
X = s(s(0)) ? ;
X = s(s(s(0))) ? ;
X = s(s(s(s(s(s(0)))))) ? ;
** LOOPS or takes too long ***
Нет ли более простого способа сделать это? Весь этот ввод с запятой. Вместо этого просто добавьте false
в свой запрос. Таким образом, найденные решения больше не отображаются, и мы можем сосредоточиться на этом раздражающем зацикливании. И, если мы готовы, вы также можете добавить в свою программу цели false
! По таким целям количество выводов может уменьшиться (или остаться прежним). И если результирующий фрагмент (называемый failure-slice) зацикливается, то это причина, почему ваша исходная программа зацикливается:
multiple(_X,0) :- false.
multiple(X,Y) :- lt(0,X), false, lt(0,Y), diff(Y,X,D), multiple(X,D).
natNum(0) :- false.
natNum(s(X)) :- natNum(X), false.
lt(0,s(X)) :- natNum(X), false.
lt(s(X),s(Y)) :- false, lt(X,Y).
?- multiple(X, s(s(s(s(s(s(0))))))), false.
** LOOPS ***
Узнаете ли вы свою программу? Остались только те части, которые нужны для петли. И, собственно, в этом случае мы имеем бесконечный цикл.
Чтобы это исправить, нам нужно что-то изменить в оставшейся, видимой части. Я бы выбрал lt/2
, первое предложение которого можно обобщить до lt(0, s(_))
.
Но ждать! Почему можно обобщить требование, чтобы у нас было натуральное число? Посмотрите на факт multiple(X,0).
, который вы написали. Вы также не требовали, чтобы X
было натуральным числом. Такого рода чрезмерные обобщения часто встречаются в программах на Прологе. Они улучшают свойства завершения при относительно низкой цене: иногда они слишком общие, но все термины, которые дополнительно вписываются в обобщение, не являются натуральными числами. Это такие термины, как any
или [a,b,c]
, поэтому, если они появляются где-то, вы знаете, что они не относятся к решениям.
Итак, идея заключалась в том, чтобы поместить в вашу программу false
целей, чтобы результирующая программа (отказ-срез) по-прежнему зацикливалась. В худшем случае вы поместите false
не в то место, и программа завершится. Путем проб и ошибок вы получаете минимальный процент неудач. Все те вещи, которые сейчас перечеркнуты, не имеют значения! В частности diff/3
. Так что не нужно это понимать (на данный момент). Достаточно посмотреть на оставшуюся программу.
person
false
schedule
20.04.2019
trace.
? - person Willem Van Onsem   schedule 20.04.2019?- multiple(X, s(s(s(s(s(s(0))))))).
где s(0) равно 1, s(s(0)) равно 2 и т. д. Он дает все желаемые ответы для X, но после последнего ответа он застревает. Я предполагаю, что в бесконечном рекурсивном цикле? @WillemVanOnsem - person Huzo   schedule 20.04.2019lt/2
иdiff/3
. Как мы можем сказать, если мы не видим их! - person false   schedule 20.04.2019X = s(_)
вместоlt(0,X)
(дважды) - person false   schedule 20.04.2019Y = s(_)
вместоlt(0,Y)
, верно? - person Huzo   schedule 20.04.2019