我有以下问题。我有一定数量的事实,例如: 父(简,迪克)。 父(迈克尔,迪克)。 我希望有一个谓词如: numberofchildren(迈克尔,X) 所以,如果我这样称呼它显示X = 1。
我在网上搜索过,每个人都把孩子放到列表中,有没有办法不使用列表?
答案 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(_).
我没有对此进行过测试,因为我觉得它相当恶心,但如果不这样做,它可能会起作用。 :)
无论如何,我强烈建议你尽可能采用列表选项。