Как посчитать количество детей родителей в прологе (без использования списков) в прологе? - PullRequest
1 голос
/ 22 сентября 2011

У меня следующая проблема.У меня есть определенное количество фактов, таких как: родитель (Джейн, Дик).родитель (майкл, член).И я хочу иметь предикат, такой как: numberofchildren (michael, X), чтобы, если я назову его так, он показывает X = 1.

Я искал в Интернете, и все помещали детей в списки,Есть ли способ не использовать списки?

Ответы [ 2 ]

2 голосов
/ 22 сентября 2011

Для подсчета количества решений требуется какой-то дополнительный логический инструмент (по сути, он не монотонный).Вот возможное решение:


:- dynamic count_solutions_store/1.

count_solutions(Goal, N) :-
    assert(count_solutions_store(0)),
    repeat,
    (   call(Goal),
        retract(count_solutions_store(SoFar)),
        Updated is SoFar + 1,
        assert(count_solutions_store(Updated)),
        fail
    ;   retract(count_solutions_store(T))
    ),
    !, N = T.

1 голос
/ 22 сентября 2011

Я вижу только два пути решения этой проблемы.

Первый, который кажется более простым, состоит в том, чтобы собрать все решения в списке и сосчитать его.Я не уверен, почему вам не нравится этот вариант.Вы беспокоитесь об эффективности или что-то?Или просто присваивание?

Проблема в том, что без использования мета-логического предиката, подобного setof/3, вам придется позволить Прологу связывать значения обычным способом.Единственный способ зацикливаться, если вы позволяете Прологу делать это, - это сбои, как в следующем:

numberofchildren(Person, N) :- parent(Person, _), N is N+1.

Это не сработает;сначала вы получите arguments not sufficiently instantiated.Затем вы исправите это и получите что-то вроде этого:

?- numberofchildren(michael, N)
N = 1 ;
N = 1 ;
N = 1 ;
no.

Причина в том, что вам нужен Пролог, чтобы отследить, если он собирается пройтись по фактам один за другим, и каждый раз, когда он возвращается,он связывает все, что связывал с момента последнего выбора.Единственный известный мне способ передачи данных через этот барьер - это динамическое хранилище:

:- dynamic(numberofchildrensofar/1).

numberofchildren(Person, N) :- 
  asserta(numberofchildrensofar(0)), 
  numberofchildren1(Person), 
  numberofchildrensofar(N), !.

numberofchildren1(Person) :-
  parent(Person, _),
  retract(numberofchildrensofar(N)),
  N1 is N + 1,
  asserta(numberofchildrensofar(N1),
  !, fail.
numberofchildren1(_).

Я не проверял это, потому что я думаю, что это довольно отвратительно, но, вероятно, его можно заставить работать, еслиэто не так.:)

В любом случае, я настоятельно рекомендую вам воспользоваться списком, если это возможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...