查找匹配谓词的所有事实

时间:2016-04-15 17:18:22

标签: prolog prolog-setof

我有一个充满interacts关系的事实库:

% Drug, Drug, Interaction Effect
interacts(terbinafine,tramadol,muscle_spasm).
interacts(terbinafine,triazolam,amnesia).
interacts(terbinafine,warfarin,arterial_pressure_nos_decreased).
interacts(terbinafine,warfarin,bradycardia).
interacts(terbinafine,rosiglitazone,hyperglycaemia).
interacts(terbinafine,allopurinol,arterial_pressure_nos_decreased).

确定两种药物是否相互作用的功能:

interacts_with(D1, D2) :-
  interacts(D1, D2, _) ; interacts(D2, D1, _).

我试图列出两种给定药物的所有相互作用效果。鉴于两种药物相互作用(interacts_with()返回true),我将如何收集这两种药物相互作用的副作用?

例如:

interacts_with(terbinafine, warfarin).

应该返回:

[arterial_pressure_nos_decreased, bradycardia]

我一直在尝试使用findall/3,但我只会在包含更多匹配项的列表中返回我传入的内容:

?- findall([terbinafine, warfarin], interacts_with(D1, D2), Foo).
Foo = [[terbinafine, warfarin], [terbinafine, warfarin], [terbinafine, warfarin], [terbinafine, warfarin], [terbinafine, warfarin], [terbinafine, warfarin], [terbinafine, warfarin], [terbinafine|...], [...|...]|...].

修改

我试图实现@false建议的内容:

    interacts_with(D1, D2) :-
        interacts(D1, D2, _) ; interacts(D2, D1, _).

    print_effects(D1, D2) :-
        ( interacts_with(D1,D2)
            -> findall([D1, D2], interacts_with(D1, D2), [])
            ; write(D1), write(" does not interact with "), write(D2)
        ).

现在我得到了:

?- print_effects(terbinafine, warfarin).
false.

setoffindall都返回false而不是传递的药物列表

1 个答案:

答案 0 :(得分:3)

首先,您的知识库包括事实相互作用/ 3:两种药物及其相互作用。然后定义一个谓词interacts_with / 2,它只有两个药物作为参数。交互隐藏在规则的主体中,因此无法从规则的头部访问,而规则的主要部分就是它的接口。再次查看interacts / 3,您可以交互式查询两种药物的效果:

   ?- interacts(terbinafine,warfarin,I).
I = arterial_pressure_nos_decreased ? ;
I = bradycardia

请注意,查询的结果是作为变量保留的谓词参数(I)之一。然后Prolog将这个变量与所有与两种药物相匹配的相互作用统一起来。这就是我在上面写的从头部可以访问时的意思......本质上是它的接口。您可以使用findall / 3或setof / 3一次性获取上述查询的所有解决方案:

   ?- findall(I,interacts(terbinafine,warfarin,I),AI).
AI = [arterial_pressure_nos_decreased,bradycardia]

   ?- setof(I,interacts(terbinafine,warfarin,I),AI).
AI = [arterial_pressure_nos_decreased,bradycardia]

如果有的话,后者会从列表中删除重复项。