Пролог Отрицание - PullRequest
       25

Пролог Отрицание

5 голосов
/ 29 марта 2011

Я пытаюсь решить простой запрос в Прологе, который использует отрицание, но я не могу взломать его. Запрос «Найти категории, которые никогда не были проданы».

База знаний выглядит следующим образом:

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).

Ответы [ 5 ]

3 голосов
/ 29 марта 2011

Ответ Сэма Сегерса верен, хотя он даст вам список категорий не проданных.Если вам не нужна агрегация, а скорее предикат, который будет возвращать все категории, у которых нет проданных товаров, вы напишите что-то вроде этого:

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 ?
 ).

Этот предикат при возврате даствсе категории, по которым нет товаров, где продаются.

2 голосов
/ 29 марта 2011

Известно ли вам о предикате Пролога отрицание как отказ (контроль), \ + / 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).
2 голосов
/ 29 марта 2011

Может быть, не самый эффективный способ.

not_sold(Cats)  :-
    findall(Y,(sale(_,_,X,_),item(X,Y,_,_)),Sold),
    findall(C,(category(C,_,_,_,_),not(member(C,Sold))),Cats).

Но я думаю, что это должно сработать.

0 голосов
/ 29 марта 2011
not_sold(Cats) :-
    findall(C, (
        category(C, _, _, _, _),
        \+ (    
            item(I, C, _, _),
            sale(_, _, I, _)
        )
    ), Cats).

Использование:

?- not_sold(Cats).
Cats = [books].
0 голосов
/ 29 марта 2011

Как сказал Сэм Сегерс, вы можете поместить not () в выражение.

Вы также можете использовать оператор \ + для логического отрицания предиката:

removeItem([Head|Tail], Head, Tail).
removeItem([Head|Tail], Item, [Head|Tail2]) :-
  \+(Head = Item),
  removeItem(Tail, Item, Tail2).
...