Как предотвратить удаление пустых значений правилом Datalog?

У меня есть следующие факты и правила:

% frequents(D,P) % D=drinker, P=pub
% serves(P,B) % B=beer
% likes(D,B)

frequents(janus, godthaab).
frequents(janus, goldenekrone).
frequents(yanai, goldenekrone).
frequents(dimi,  schlosskeller).

serves(godthaab, tuborg).
serves(godthaab, carlsberg).
serves(goldenekrone, pfungstaedter).
serves(schlosskeller, fix).

likes(janus, tuborg).
likes(janus, carlsberg).

count_good_beers_for_at(D,P,F) :- group_by((frequents(D,P), serves(P,B), likes(D,B)),[D,P],(F = count)).
possible_beers_served_for_at(D,P,B) :- lj(serves(P,B), frequents(D,R), P=R).

Теперь я хотел бы построить правило, которое должно работать как предикат, возвращающий «истина», когда количество доступных «понравившихся» сортов пива в каждом пабе, который «пьющий» «часто» больше, чем 0.

Я бы считал предикат истинным, если правило не возвращает кортежей. Если предикат ложный, я планировал заставить его возвращать бары, в которых не было ни одного «понравившегося» пива.

Как видите, у меня уже есть правило подсчета хорошего пива для данного пьющего в данном пабе. У меня также есть правило, определяющее количество порций пива.

DES> count_good_beers_for_at(A,B,C)

{                                           
  count_good_beers_for_at(janus,godthaab,2)
}
Info: 1 tuple computed.          

Как видите, счетчик не показывает посещаемые пабы, но в которых нет понравившихся сортов пива. Я планировал обойти это, используя левое внешнее соединение.

DES> is_happy_at(D,P,Z) :- lj(serves(P,B), count_good_beers_for_at(D,Y,Z), (Y=P))

Info: Processing:
  is_happy_at(D,P,Z) :-
    lj(serves(P,B),count_good_beers_for_at(D,Y,Z),Y = P).
{                                           
  is_happy_at(janus,godthaab,2),
  is_happy_at(null,goldenekrone,null),
  is_happy_at(null,schlosskeller,null)
}
Info: 3 tuples computed.

Это почти правильно, за исключением того, что я также не посещаю пабы. Я пытаюсь добавить дополнительное условие:

DES> is_happy_at(D,P,Z) :- lj(serves(P,B), count_good_beers_for_at(D,Y,Z), (Y=P)), frequents(D,P)

Info: Processing:
  is_happy_at(D,P,Z) :-
    lj(serves(P,B),count_good_beers_for_at(D,Y,Z),Y = P),
    frequents(D,P).
{                                           
  is_happy_at(janus,godthaab,2)
}
Info: 1 tuple computed.

Теперь я каким-то образом отфильтровал все, что содержит нули! Я подозреваю, что это связано с логикой нулевого значения в DES.

Я понимаю, что, возможно, неправильно подхожу ко всей этой проблеме. Любая помощь приветствуется.

РЕДАКТИРОВАТЬ: Назначение: «very_happy(D) ist wahr, genau dann wenn jede Bar, die Trinker D besucht, wenigstens ein Bier ausschenkt, das er mag». что переводится как «very_happy(D) верно, если и только если каждый посетитель бара D, который посещает бар, предлагает по крайней мере 1 пиво, которое ему нравится». Поскольку это задание касается журнала данных, я думаю, что его определенно можно решить без использования Пролога.


person Janus Troelsen    schedule 04.06.2012    source источник
comment
понятия не имею, но я думаю, что если кто-то заботится о теге журнала данных, они с большей вероятностью помогут, чем люди, которые заботятся о кортежах...   -  person andrew cooke    schedule 06.06.2012
comment
@andrewcooke: посмотреть историю редактирования. у меня был тег журнала данных по этому вопросу со вчерашнего дня до сегодняшнего дня, когда я попробовал новую партию тегов. к сожалению, ни у одного из соответствующих тегов нет большого количества подписчиков.   -  person Janus Troelsen    schedule 06.06.2012
comment
а, ладно, извини. давно им не пользовался, ничем помочь не могу...   -  person andrew cooke    schedule 07.06.2012


Ответы (2)


Я думаю, что для вашего задания вам следует использовать базовый Даталог, не злоупотребляя агрегатами. Суть вопроса в том, как выразить универсальные количественные условия. Я погуглил «журнал данных универсального количественного анализа» и на первом месте нашел deductnotes.pdf, в котором утверждается:

Универсально квантифицируемое условие может быть выражено только эквивалентным условием с экзистенциальной квантификацией и отрицанием.

В этом PDF вы также найдете полезный пример (стр. 9 и 10).

Таким образом, мы должны перефразировать наш вопрос. Я закончил с этим кодом:

not_happy(D) :-
  frequents(D, P),
  likes(D, B),
  not(serves(P, B)).

very_happy(D) :-
  likes(D, _),
  not(not_happy(D)).

это кажется то, что требуется:

DES> very_happy(D)

{                                           
}
Info: 0 tuple computed.          

Обратите внимание на likes(D, _), который требуется, чтобы янай и дими не попали в список очень_счастливых, без явного утверждения того, что им нравится (OT, извините, мой английский действительно отстой...)

EDIT: извините, но приведенное выше решение не работает. Я переписал это так:

likes_pub(D, P) :-
  likes(D, B),
  serves(P, B).

unhappy(D) :-
  frequents(D, P),
  not(likes_pub(D, P)).

very_happy(D) :-
  likes(D, _),
  not(unhappy(D)).

контрольная работа:

DES> unhappy(D)

{                                           
  unhappy(dimi),
  unhappy(janus),
  unhappy(yanai)
}
Info: 3 tuples computed.          

DES> very_happy(D)

{                                           
}
Info: 0 tuples computed.          

Теперь добавим факт:

serves(goldenekrone, tuborg).

и мы можем увидеть исправленный результат кода:

DES> unhappy(D)

{                                           
  unhappy(dimi),
  unhappy(yanai)
}
Info: 2 tuples computed.          

DES> very_happy(D)

{                                           
  very_happy(janus)
}
Info: 1 tuple computed.          
person CapelliC    schedule 07.06.2012
comment
ОП запросил доступное любимое пиво в каждом пабе, который часто посещает пьющий, больше 0. Больше 0 означает только экзистенциальное, универсальное означало бы, что счет равен всем сортам пива или чему-то в этом роде. Я не думаю, что ОП требует универсальности. - person Mostowski Collapse; 08.06.2012
comment
Как должно быть ясно из моего ответа, агрегация не имеет ничего общего с поставленной проблемой. Я думаю, что is_happy_at/2 это просто союз. Даже когда у нас есть счетчики, мы все равно должны решить универсальную количественную оценку, введенную each - person CapelliC; 08.06.2012
comment
Да. Двойное отрицание в forall играет ту же роль, что и два отрицания, необходимые для универсальной количественной оценки. В Datalog у нас нет других инструментов... - person CapelliC; 08.06.2012
comment
Хорошо, теперь я понимаю, что вы имеете в виду. Согласен, проблема связана с forall. Проблема здесь в ограниченности ареала, откуда вы берете набор особей? Ваша проекция лайк/2 является законной. - person Mostowski Collapse; 08.06.2012
comment
эти 2 предыдущих комментария меняются местами. Хронологически это Cookie Monster 8 июня в 18:47 затем chac в 18:46 (неточность времени для разных мест?) - person CapelliC; 08.11.2012

Возможно, это не тот ответ, который вы ожидаете. Но вы можете использовать обычный Пролог и легко выполнять групповые запросы со встроенными предикатами bagof/3 или setof/3.

?- bagof(B,(frequents(D,P), serves(P,B), likes(D,B)),L), length(L,N).
D = janus,
P = godthaab,
L = [tuborg,carlsberg],
N = 2

Семантика bagof/3 такова, что она не вычисляет внешнее соединение для данного запроса. Запрос обычно выполняется Прологом. Результаты сначала накапливаются и сортируются по ключам. Наконец, результаты затем возвращаются путем возврата. Если ваш журнал данных не может обойтись без нулей, тогда да, вам нужно фильтровать.

Но вам не нужно вдаваться в агрегаты, когда вы хотите знать только о существовании понравившегося пива. Вы можете сделать это напрямую через запрос без каких-либо агрегатов:

is_happy_at(D,P) :- frequents(D,P), once((serves(P,B), likes(D,B))).
?- is_happy_at(D,P).
D = janus,
P = godthaab ;
Nein

Once/1 предотвращает ненужный возврат. Datalog может либо автоматически не выполнять ненужного возврата, когда видит проекцию в is_happy_at/2, т. е. B проецируется прочь. Или вам может потребоваться явно использовать то, что соответствует SQL DISTINCT. Или, в конце концов, ваш журнал данных предоставит вам что-то, что соответствует SQL EXISTS, что наиболее точно соответствует разу/1.

Пока

person Mostowski Collapse    schedule 07.06.2012