2

假设我有一组文字(例如表示为一个列表)和一个动态指定的谓词,我想要的是生成一组文字,其中包含所有以前的文字以及可以通过应用谓词扣除的文字到集合。

一个例子,已经定义了谓词

pred(A, B) :- base(A, B).
pred(A, C) :- base(A, B), pred(B, C).

并假设谓词有这样的签名

deduce_set(+Set, +Pred, ?DeducedSet)

以下陈述成立(为真):

deduce_set([base(a,b), base(a,c), base(b,d), base(d, e)],
           pred/2,
           [base(a,b), base(a,c), base(b,d), base(d,e), pred(a,d), pred(a,e), pred(b,e)]
          ).

最有效和最通用的方法是什么?我一直在考虑类似的事情:

  • 断言 Set 中的所有文字
  • 调用 Pred
  • 如果它成功断言它的头
  • 收集结果集中所有断言的事实并放入列表中

没有更好的方法吗?

更新这个解决方案,由 CapelliC 更好地定义,通过使用元编程不能处理对象标识下集合中的变量。有什么解决方法吗?

4

1 回答 1

2

您可以使用 findall/3(或更好的findall /4),避免在重试演绎步骤之前区分(例如)您需要删除哪些 pred/2 实例的问题。

deduce_set(Base, Pred/Arity, Res) :-
    functor(P, Pred, Arity),

    % how to 'undo' this without a description?
    % retractall(base(_,_)),

    setof(F-A, M^(member(M, Base), functor(M, F, A)), Desc),
    maplist(retractdesc, Desc),

    maplist(assertz, Base),

    findall(P, P, All),
    append(Base, All, Res).

retractdesc(F-A) :-
    functor(P, F, A),
    retractall(P).

我还会添加对 Base 元素的描述,以了解在运行之前要清除的内容(当然可以使用 获得setof(F-A,M^(member(M,Base),functor(M,F,A)),Desc)

pred(A, B) :- base(A, B).
pred(A, C) :- base(A, B), pred(B, C).

test :-
    deduce_set([base(a,b), base(a,c), base(b,d), base(d, e)], pred/2, R),
    R = [base(a,b), base(a,c), base(b,d), base(d,e), pred(a,d), pred(a,e), pred(b,e)].

请注意 test/0 将失败,因为返回集与预期列表不匹配。

?- test.
base(a,b)
base(a,c)
base(b,d)
base(d,e)
pred(a,b)
pred(a,c)
pred(b,d)
pred(d,e)
pred(a,d)
pred(a,e)
pred(b,e)
false.

一般来说,我建议您使用 Datalog 来完成您的任务,因为非正式的描述似乎非常相似。有关“免费使用”且功能丰富的系统,请参见DES 。

于 2013-02-13T10:15:36.063 回答