我试图在Prolog中解决一个使用否定的简单查询,但我无法破解它。查询是“查找从未销售过的类别”。
知识库如下:
category(stationery, 30, 200, 10, 2).
category(books, 10, 30, 3, 2).
category(consumables, 50, 300, 15, 3).
item(pen, stationery, 10, 150).
item(colgate_small, consumables, 20, 65).
item(colgate_medium, consumables, 45, 70).
item(colgate_big, consumables, 70, 34).
item(juice_small, consumables, 45, 23).
item(juice_medium, consumables, 60, 23).
item(juice_big, consumables, 80, 12).
item(book, stationery, 5, 65).
item(pencil, stationery, 7, 56).
item(newspaper, books, 50, 400).
sale(tom, 1/1/07, pen, 3).
sale(peter, 1/1/07, book, 85).
sale(peter, 1/1/07, juice_small,1).
sale(alice, 7/1/07, pen, 10).
sale(alice, 7/1/07, book, 5).
sale(patrick, 12/1/07, pen, 7).
答案 0 :(得分:3)
not_sold(Cat):-
category(Cat,_,_,_,_), % Get one category at a time
\+ ( % Applies negation
item(Item, Cat,_,_), % Check for items in this category
sale(_,_,Item,_) % Has the item been sold ?
).
这个谓词在回溯时会产生所有没有卖出物品的类别。
答案 1 :(得分:2)
可能不是最有效的方式。
not_sold(Cats) :-
findall(Y,(sale(_,_,X,_),item(X,Y,_,_)),Sold),
findall(C,(category(C,_,_,_,_),not(member(C,Sold))),Cats).
但我认为它应该有用。
答案 2 :(得分:2)
您是否了解Prolog的negation-as-failure(对照)谓词,\+/1?如果目标无法证明,则为true
。
使用谓词,任务减少到找到已售出的类别,即
is_category(C) :- category(C, _, _, _, _).
sold_category(C) :-
is_category(C),
item(I, C, _, _),
sale(_, _, I, _).
和
unsold_category(C) :- is_category(C), \+ sold_category(C).
如果您想要所有这些类别的列表,只需使用findall谓词。
findall(C, unsold_category(C), L).
答案 3 :(得分:0)
正如Sam Segers所提到的,你可以在表达式周围添加一个not()。
您还可以使用\ +运算符逻辑否定谓词:
removeItem([Head|Tail], Head, Tail).
removeItem([Head|Tail], Item, [Head|Tail2]) :-
\+(Head = Item),
removeItem(Tail, Item, Tail2).
答案 4 :(得分:0)
not_sold(Cats) :-
findall(C, (
category(C, _, _, _, _),
\+ (
item(I, C, _, _),
sale(_, _, I, _)
)
), Cats).
用法:
?- not_sold(Cats).
Cats = [books].