Как суммировать в Clingo?

У меня есть следующий набор данных:

food_a(bagel, 245).
food_a(sandwich, 200).
food_a(salad,300).
food(bagel).
food(sandwich).
food(salad).

Я хочу удовлетворить следующее ограничение: учитывая общее количество калорий, я хочу вернуть продукты, которые ему соответствуют. Например, общее количество калорий = 500, программа должна вернуть «бублик + бутерброд» в качестве решения. Я закодировал его следующим кодом clingo:

food_a(bagel, 245).
food_a(sandwich, 200).
food_a(salad,300).
food(bagel).
food(sandwich).
food(salad).
has(bagel, wheat).
has(sandwich, bread).
has(sandwich, tomatoes).
has(sandwich, onion).
has(sandwich, cheese).
%calories(food,amount):-food_a(food,amount).
%food(F):-food_a(F,C).
%limits(calories,200).

%sol(F) :- food_a(F,C1),food_a(F,C2), C1+C2<500.
%:- {food(F,C) : food_a(F,C1),food_a(F,C2)} , C1+C2 >500.

%food_diet(F) :- food(F,C), C<250.
%:- food(F1) ,food_a(F2,C2), C1+C2=445.

totals(P, S) :- S = #sum{ I : food_a(P,I)}, food(P), S<500.

Результат, который я получаю, представлен на снимке экрана:  введите описание изображения здесь

Судя по всему, программа возвращает только отдельные продукты, не учитывая комбинации из 2 или 3 из них за раз. Может ли кто-нибудь предложить изменения или шаги, которые я должен выполнить, чтобы добиться того же.


person tortuga    schedule 01.04.2017    source источник


Ответы (1)


В настоящее время вы рассчитываете сумму для каждого продукта питания отдельно. Если у вас было несколько значений для одной и той же еды, например food_a(bagel, 100) и food_a(bagel, 200), тогда результат будет total(bagel, 300). По сути, поскольку у вас есть только один food_a/2 для каждого продукта питания, ваше totals/2 определение эквивалентно

totals(P, S) :- food_a(P, S), food(P), S<500.

Вы хотите что-то вроде

food_a(bagel, 245).
food_a(sandwich, 200).
food_a(salad,300).
food(bagel).
food(sandwich).
food(salad).

% allow any combination of foods to be selected
{ selected(P) } :- food(P).
% sum calories on selected foods
total(S) :- S = #sum{ I : food_a(P,I), selected(P) }.
% limit total calories
:- total(S), S>=500.

#show selected/1.
#show total/1.

Который дает

> clingo how-to-sum-clingo.asp 0
clingo version 4.5.4
Reading from how-to-sum-clingo.asp
Solving...
Answer: 1
total(0)
Answer: 2
selected(sandwich) total(200)
Answer: 3
selected(bagel) total(245)
Answer: 4
selected(bagel) selected(sandwich) total(445)
Answer: 5
selected(salad) total(300)
SATISFIABLE

Models       : 5
Calls        : 1
Time         : 0.002s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time     : 0.000s
person vukk    schedule 02.04.2017