0

我有一个类似于的数据库:

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实际上是返回所有项目,因此将其添加到项目中。我的假设是这properties_true/4将是错误的ball,因此它不会被添加到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.
4

1 回答 1

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.

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

于 2013-11-14T10:56:08.970 回答