我有一个类似于:
的数据库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/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.
答案 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.
我不确定这是否能回答你的问题,但这似乎是一种有效的方法。