1
votes

Using Prolog, I first created two facts called grade and food: The first fact is grade(X,Y) where X is the student (rob or matt) and Y is the grade level (freshman or sophomore). The second fact is food(X,Y) where X is the student (rob or matt) and Y is the food (pizza, burger, pasta, wrap).

I created a rule called preference(X,Y), where X is the student (rob or matt) and Y is the students' preference.

I want to enter preference(rob,X). in the GNU Prolog and have it return:

sophomore, pizza, burger.

However, it keeps returning: sophomore, pizza, pizza.

How do I fix this problem? I've spent hours looking into this. Thanks

This is the code I have:

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).
3
Just making sure I understand the question, why do you want Y to have both food and a grade in preference?qfwfq
I would like to first return the grade level and then both of the foods because rob likes pizza and burger. I can't have it only return pizza.Will

3 Answers

2
votes

The way you have defined your facts is nice. The way you query it is not conventional. Here is how I would do it. The "preference" rule is simpler:

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

You conventionally query the database and get all solutions with backtracking:

?- preference(rob, Grade, Food).
Grade = sophomore,
Food = pizza ;
Grade = sophomore,
Food = burger.

If you want to collect the foods, you can use bagof/setof, like this:

?- bagof(Food, preference(rob, Grade, Food), Foods).
Grade = sophomore,
Foods = [pizza, burger].

What if you want to query all freshmen?

?- bagof(Food, preference(Person, freshman, Food), Foods).
Person = matt,
Foods = [pasta, wrap].
1
votes

You need to state that the value of B and C are different; there are multiple ways to do that, for the simplicity I go with \==/2 (documentation):

preference(X,Y):-
   grade(X,A),
   food(X,B),
   food(X,C),
   B\==C,
   Y = (A, B, C).

Gives the output

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

If you don't want to have the basically doubled entries you can go with the (in this case lexical) "less than" @</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
0
votes

I may be wrong, but I suspect this may be a misunderstanding of prolog in general in addition to a non-intuitive REPL. Prolog doesn't really "return" a value, it just tries to match the variables to values that make your predicates true, and I would be willing to bet you're hitting enter after you see the first result.

The way preference is currently written B and C will match any two foods that rob is associated with. This could be pizza, pizza or pizza, burger or burger, pizza, or so on. It does not check whether B and C are equal. When I run preference(rob,X). prolog does not only give me the first result UNLESS I hit enter.

| ?- preference(rob,X).

X = (sophomore,pizza,pizza) ? ?
Action (; for next solution, a for all solutions, RET to stop) ?

If you hit a (or spam ; a few times) prolog will give you the rest of the results.

| ?- preference(rob,X).

X = (sophomore,pizza,pizza) ? a

X = (sophomore,pizza,burger)

X = (sophomore,burger,pizza)

X = (sophomore,burger,burger)

yes
| ?-

I think that all you really need to get all of a person's preferences is just food unless you specifically need them in a tuple or list which will take some slightly more complicated logic (let me know in a comment if that's what you're looking for)

| ?- food(rob, X).

X = pizza ? a

X = burger

yes
| ?-