#prolog
#prolog
Вопрос:
Используя Prolog, я сначала создал два факта, называемых grade и food: первый факт — это grade (X, Y), где X — ученик (Роб или Мэтт), а Y — уровень оценки (первокурсник или второкурсник). Второй факт — это еда (X, Y), где X — ученик (Роб или Мэтт), а Y — еда (пицца, бургер, паста, обертка).
Я создал правило с именем preference(X, Y), где X — это студент (Роб или Мэтт), а Y — предпочтения студентов.
Я хочу войти preference(rob,X).
в GNU Prolog и вернуть его:
второкурсник, пицца, бургер.
Тем не менее, оно продолжает возвращаться: второкурсник, пицца, пицца.
Как мне решить эту проблему? Я потратил часы на изучение этого. Спасибо
Это код, который у меня есть:
grade(rob, sophomore).
grade(matt, freshman).
food(rob, pizza).
food(rob, burger).
food(matt, pasta).
food(matt, wrap).
preference(X,Y):-
grade(X,A),
food(X,B),
food(X,C),
Y = (A, B, C).
Комментарии:
1. Просто хочу убедиться, что я понял вопрос: почему вы хотите
Y
, чтобы в нем были и еда, и оценкаpreference
?2. Я хотел бы сначала вернуть уровень оценки, а затем оба продукта, потому что Роб любит пиццу и бургер. Я не могу заставить его возвращать только пиццу.
Ответ №1:
То, как вы определили свои факты, приятно. Способ запроса не является обычным. Вот как я бы это сделал. Правило «предпочтений» проще:
grade(rob, sophomore).
grade(matt, freshman).
food(rob, pizza).
food(rob, burger).
food(matt, pasta).
food(matt, wrap).
preference(X, A, Y):-
grade(X, A),
food(X, Y).
Вы обычно запрашиваете базу данных и получаете все решения с обратным отслеживанием:
?- preference(rob, Grade, Food).
Grade = sophomore,
Food = pizza ;
Grade = sophomore,
Food = burger.
Если вы хотите собрать продукты, вы можете использовать bagof / setof, например:
?- bagof(Food, preference(rob, Grade, Food), Foods).
Grade = sophomore,
Foods = [pizza, burger].
Что, если вы хотите запросить всех первокурсников?
?- bagof(Food, preference(Person, freshman, Food), Foods).
Person = matt,
Foods = [pasta, wrap].
Ответ №2:
Вам нужно указать, что значение B
и C
различны; для простоты я использую несколько способов ==/2
(документация):
preference(X,Y):-
grade(X,A),
food(X,B),
food(X,C),
B==C,
Y = (A, B, C).
Выдает вывод
| ?- preference(X,Y).
X = rob
Y = (sophomore,pizza,burger) ? ;
X = rob
Y = (sophomore,burger,pizza) ? ;
X = matt
Y = (freshman,pasta,wrap) ? ;
X = matt
Y = (freshman,wrap,pasta) ? ;
no
Если вы не хотите, чтобы записи в основном были удвоены, вы можете использовать (в данном случае лексическое) «меньше» @</2
:
preference(X,Y):-
grade(X,A),
food(X,B),
food(X,C),
B @< C,
Y = (A, B, C).
| ?- preference(X,Y).
X = rob
Y = (sophomore,burger,pizza) ? ;
X = matt
Y = (freshman,pasta,wrap) ? ;
no
Ответ №3:
Возможно, я ошибаюсь, но я подозреваю, что это может быть неправильным пониманием prolog в целом в дополнение к неинтуитивному REPL. На самом деле Prolog не «возвращает» значение, он просто пытается сопоставить переменные со значениями, которые делают ваши предикаты истинными, и я был бы готов поспорить, что вы нажмете enter после того, как увидите первый результат.
Способ preference
в настоящее время написан B
и C
будет соответствовать любым двум продуктам, с которыми rob
он связан. Это может быть pizza, pizza
или pizza, burger
или burger, pizza
, или так далее. Он не проверяет, равны ли B
и C
. Когда я запускаю preference(rob,X).
prolog, он не только выдает мне первый результат, ЕСЛИ я не нажму enter.
| ?- preference(rob,X).
X = (sophomore,pizza,pizza) ? ?
Action (; for next solution, a for all solutions, RET to stop) ?
Если вы нажмете a
(или отправите спам ;
несколько раз), prolog выдаст вам остальные результаты.
| ?- preference(rob,X).
X = (sophomore,pizza,pizza) ? a
X = (sophomore,pizza,burger)
X = (sophomore,burger,pizza)
X = (sophomore,burger,burger)
yes
| ?-
Я думаю, что все, что вам действительно нужно, чтобы получить все предпочтения пользователя, — это только food
если они вам конкретно не нужны в кортеже или списке, что потребует немного более сложной логики (дайте мне знать в комментарии, если это то, что вы ищете)
| ?- food(rob, X).
X = pizza ? a
X = burger
yes
| ?-