2

So I'm stuck on an exercise that I've been working on. I have the following facts:

sd(appleseed0, appleseed1).

sd(appleseed0, apple1).
sd(appleseed1, apple1).
sd(appleseed2, apple1).

sd(appleseed0, apple2).
sd(appleseed1, apple2).
sd(appleseed2, apple2).

What this means is that appleseed1 came from appleseed0, apple1 came from appleseed0, etc. The problem I'm having is that I need it to print out false if the values are switched around. Meaning, I want the query to result in "true" when the query is seed(appleseed0, apple1) and then "false" when the query is in opposite order like seed(apple1, appleseed0).

Right now, my predicate looks like this:

seed(A,B) :- sd(A,B) ; sd(B,A).

I understand that this is why my queries are returning true, no matter the order, but my only other idea is:

seed(A,B) :- sd(A,B). 

but I cannot write it like that because that would make it an infinite loop with no false. How can I make it so that the query will result in "true" when shown with something like seed(appleseed2, apple2) and "false" when shown with something like seed(apple2, appleseed2)?

Joffrey Baratheon
  • 494
  • 1
  • 5
  • 19
  • If "apple1 came from appleseed0", why does also apple1 come from appleseed1? It is by no means clear what sd/2 now means. – false Jan 28 '15 at 13:48

1 Answers1

1

Hoping that I am reading your question correctly:

You don't need an extra predicate. Indeed, what you are looking for is the query:

?- sd(A, B).

This will succeed or fail just like you describe. The predicate

seed(A, B) :-
    (   sd(A, B)
    ;   sd(B, A)
    ).

(just like yours, just formatted to be easier to follow) reads: "seed(A, B) is true when sd(A, B) is true. It is also true when sd(B, A) is true" (like you have noticed). An interesting side effect is that if you had these two facts in your database:

sd(foo, bar).
sd(bar, foo).

Then the query:

?- seed(foo, bar).

will succeed twice (!), just like the query

?- seed(bar, foo).

or the equivalent top level query

?- sd(bar, foo) ; sd(foo, bar).

That last query makes it most obvious why the query will succeed twice.

What confuses me: Why do you think that

seed(A, B) :-
    sd(A, B).

will lead to an infinite loop? Is there some part of the program that you are not showing? As it stands, defining a predicate like this is equivalent to just giving sd/2 an alias, seed/2. This definition reads: "seed(A, B) is true when sd(A, B) is true."

  • Ah, this makes sense. I was confusing myself with (1) seed(A,B) :- seed(A,B) and I didn't consider (2) seed(A,B) :- sd(A,B). I assumed that since (1) would produce an "infinite loop" where nothing would be false, then (2) would do the same thing because it seems to be doing the same thing that (1) is doing. Logically speaking, (2) makes sense. You explantation cleared up my confusion. Thank you! I am new to Prolog so this was valuable to my learning! – Joffrey Baratheon Jan 28 '15 at 07:48