如何在prolog中计算prolog(不使用列表)中父母的子女数量?

时间:2011-09-22 16:49:48

标签: prolog

我有以下问题。我有一定数量的事实,例如: 父(简,迪克)。 父(迈克尔,迪克)。 我希望有一个谓词如: numberofchildren(迈克尔,X) 所以,如果我这样称呼它显示X = 1。

我在网上搜索过,每个人都把孩子放到列表中,有没有办法不使用列表?

2 个答案:

答案 0 :(得分:2)

计算解决方案的数量需要一些额外的逻辑工具(它本质上是非单调的)。这是一个可能的解决方案:


:- 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 :(得分:1)

我只能看到两种方法来解决这个问题。

第一个,似乎更容易,是将所有解决方案都列入清单并计算。我不确定你为什么不喜欢这个选项。你担心效率还是什么?或者只是一项任务?

问题在于,如果不使用像setof/3这样的元逻辑谓词,您将不得不允许Prolog以通常的方式绑定值。如果你让Prolog这样做,那么循环的唯一方法就是失败,就像这样:

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

这不会起作用;首先,你将获得arguments not sufficiently instantiated。然后你要解决这个问题并得到类似的东西:

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

原因是你需要Prolog回溯它是否会逐一查看事实,并且每次回溯时,它都会解除自上一个选择点以来绑定的任何内容。我知道在这个障碍中传递数据的唯一方法是使用动态存储:

:- 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(_).

我没有对此进行过测试,因为我觉得它相当恶心,但如果不这样做,它可能会起作用。 :)

无论如何,我强烈建议你尽可能采用列表选项。