假设我有一组文字(例如表示为列表)和一个动态指定的谓词,我想要的是产生一组文字,其中包含除了可以扣除的文字以外的所有文字。将谓词应用于集合。
一个例子,定义了谓词
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)]
).
最有效和最通用的方法是什么?我一直在想类似的事情:
是不是有更好的方法?
UPDATE 这个解决方案,由CapelliC更好地定义,使用元编程无法处理对象标识下的集合中的变量。对此有何解决方法?
答案 0 :(得分: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。