查找符合条件的项目

时间:2013-11-14 09:37:49

标签: prolog

我有一个类似于:

的数据库
item(coin, [gold, metal, round]).
....
item(ball, [sphere, bouncy, -red]).  % notice the negated property

我的目标是找到与给定财产匹配的项目。

问题的一个例子:

?- findall(I, (item(I, P), properties_true(P, [gold], [], match)), Items).
Items = [coin, ball]

findall/3正在返回所有项目。在这种情况下,目标是仅检索黄金项目。

我怀疑是因为item/2实际上正在返回所有项目,因此将其添加到Items。我的假设是properties_true/4ball来说是假的,因此它不会被添加到Items

有人能够指出我正确的方向吗?

以下是我正在使用的规则:

%% properties_true(Prop, True, False, SearchType)
%
%  Prop = the items to search
%  True = List of properties that must be in Prop
%  False = List of items that mustn't be in Prop
%  SearchType = match|solve
%    * solve = Return true if item has all of True and none of False
%    * match = Return true if item has 0 or more of true and none of False  
% 
% 
properties_true([-Property|Rest], True, False, SearchType) :-
    !, property_true(-Property, True, False, SearchType),
    properties_true(Rest, True, [Property|False], SearchType), !.
properties_true([Property|Rest], True, False, SearchType) :-
    property_true(Property, True, False, SearchType),
    properties_true(Rest, [Property|True], False, SearchType), !.

%% property_true/4
%
properties_true([], _, _, _) :- !.
property_true(-Property, _, False, solve) :-
    !, member(Property, False).
property_true(-Property, True, _, match) :-
    !, not(member(Property, True)).
property_true(Property, True, _, solve) :-
    !, member(Property, True).
property_true(Property, _, False, _) :-
    !, not(member(Property, False)).
property_true(_ , [], [], solve) :- !. % dont think i really need this

使用示例:

?- properties_true([sphere, bouncy, -red], [], [], match).
true.

?- properties_true([sphere, bouncy, -red], [], [], solve). % solve needs to match all     properties
false.

?- properties_true([sphere, bouncy, -red], [sphere, bouncy], [red], solve).
true.

1 个答案:

答案 0 :(得分:2)

首先建议:规范化您的数据。而不是:

item(coin, [gold,metal,round]).
item(ball, [sphere, bouncy, -red]).

说:

item(coin).
item(ball).
item(chair).
item(keyboard).

item_property(coin, gold).
item_property(coin, metal).
item_property(coin, red).
item_property(ball, sphere).
item_property(ball, bouncy).
item_property(ball, -red).
item_property(chair, black).
item_property(chair, -bouncy).
item_property(keyboard, black).
item_property(keyboard, plastic).

编写match_property/2谓词现在要容易得多:

match_property(Property, Item) :-
    (   Property = -NegP
    ->  match_neg_property(NegP, Item)
    ;   item_property(Item, Property)
    ).

match_neg_property(NegP, Item) :-
    item(Item),
    once(neg_property(Item, NegP)).

neg_property(Item, NegP) :-
    item_property(Item, -NegP).
% whether you actually want this clause depends on how you model your world!
neg_property(Item, NegP) :-
    \+ item_property(Item, NegP).

match_property_list(PList, Item) :-
    foreach(
        member(P, PList),
        match_property(P, Item)
    ).

请注意,您不必为正面和负面属性设置两种“模式”。我不确定这是如何适合你的一般想法(Prolog说“如果它不是真的它一定是假的”;明确的负面属性是不一样的,但你的初始代码暗示你仍然希望“否定为失败”)

但是有了这些基本构建模块,您现在可以轻松地说:

?- match_property(-red, Item).
Item = ball ;
Item = chair ;
Item = keyboard.

?- match_property_list([-red, -plastic], Item).
Item = ball ;
Item = chair ;
false.

?- match_property_list([black, -bouncy], Item).
Item = chair ;
Item = keyboard.

我不确定这是否能回答你的问题,但这似乎是一种有效的方法。