Logical OR in Prolog - prolog

I´m new in Prolog learning and tried out a logical OR-operator for that context:
%a.
b.
foo:- a ; b.
I have commented a. to try out the logical OR-Operator but it does not work. If you query with ?-foo. you get an exception. Prolog only checks the first term but not the second. Can anyone help me please?
Best regards.

You get the exception as a/0 is undefined. In order to check the or-operator you could explicitely define a as being false.
a:-false.
b.
foo:- a ; b.
Now ?- foo. gives the answer true.
Prolog makes a 'closed world' assumption. It can only evaluate the trueness or falseness of a predicate that is defined. That means that you need at least one clause that has the predicate on its left hand side (or a fact, as this will be interpreted as a clausel with no condition thus without a right hand side).

This is essentially equivalent to:
foo :- a.
foo :- b.
The first clause tries to assess whether foo is true or not, by evaluating whether a is true or not. a doesn't even exist in the database, therefore you get an error.

Related

Prolog single-variable query returns an error. Why?

I've created a simple Prolog program (using GNU Prolog v1.4.4) with a single fact:
sunny.
When I run the following query:
sunny.
I get:
yes
As I'd expect. When I run this query:
X.
I get:
uncaught exception: error(instantiation_error,top_level/0)
when I expected to get:
X = sunny
Anyone know why?
Prolog is based on first-order logic but X is a second order logic query (the variable stands for a rule head / fact, not only a term): you ask "which predicates can be derived?" or in other words "which formulas are true?". Second order logic is so expressive that we lose many nice properties of first-order logic (*). That's why a second order variable must be sufficiently instantiated to know which rule to try at the time it is called (that's what the error message means). For instance the queries
?- X=member(A,[1,2,3]), X.
and
?- member(A,[1,2,3]).
still allow Prolog to try the definition of the member predicate (in fact the two definitions are equivalent) but
?- X, X=member(A,[1,2,3]).
will throw an exception because at the time X should be derived, we don't know that it's supposed to become the predicate member(A,[1,2,3]).
Your case is much simpler though: you can wrap sunny as a term into a predicate such that Prolog knows which rules to try. The facts
weather(sunny).
weather(rainy).
define the predicate weather such that now we only have a first-order variable as argument in our query:
?- weather(X).
X = sunny ;
X = rainy.
Now that we are talking about the term level, everything works as you expected.
(*) Although the problem of finding out if a formula is valid is undecidable in both cases, in first order logic at least all true formulas can be eventually derived but if a formula is false, the search might not terminate (i.e. first-order logic is semi-decidable). For second order logic there are formulas that can neither be proved not disproved. What is worse is that we cannot even tell if a second-order formula belongs to this category.

logic in prolog language

I have a question in prolog here is the code:
sound(time1).
sound(time2).
sun(time3).
relax(X):-
not(sound(X)),
!,
sun(X).
relax(_):-
sun(_).
now I an running - relax(T). I get true when I run relax(F) I get true also. Why does it happen?
and one more question, why relax(time4). also gets false? I think I am missing something.
thanks a lot!
The fact that relax(T) and relax(F) both give the same result, is normal: uppercase identifiers are variables. So the two queries are semantically the same: you query with an ungrounded variable.
Now why do we get true.? If you query relax(T), Prolog will first call the first clause of relax(X).
The first clause has a body that starts with not(sound(X)). So we actually query not(sound(T)). Not is satisfied by the negation as finite failure principle: Prolog will aim to "prove" sound(T), and if that fails (it cannot find a way to satisfy that query).
So now Prolog queries sound(T), and this query is satisfied: indeed, sound(time1) satisfies this query, since Prolog reasons that now T = time1. As a result not(sound(T)) is false, and thus Prolog backtracks.
Now Prolog will try the next clause: relax(_) :- sun(_). The _ is a "wildcard" or "don't care" variable. Furthermore if you use multiple _s in the same clause, those are not related. So you basically say: everything is relax/1, given there is at least one sun/1. So now Prolog will query for a sun(_). This query succeeds: sun(time3) is a valid candidate, since _ = time3. So that means that relax(_) succeeds. We did not alter the variable T (or F), so Prolog can only say that the query is true.
Now if we query relax(time4), that's a different story. Again Prolog will first try to satisfy the first clause of relax/1. This is again done by calling not(sound(time4)). But note that time4 is a constant. And in Prolog all constants are different: so time1 and time4 cannot unify.
So now Prolog first aims to unify sound(time1) (first clause for sound/1) with sound(time4), but since time1 and time4 are different, that fails. Next it aims to unify sound(time2) (second clause of sound/1) with sound(time4), but again no luck. Now there are no clauses of sound/1 anymore. So Prolog gives up and considers not(sound(time4)) to be true.
That means that Prolog will continu in the body of the first clause of relax/1. The next statement is a !, that is a "cut" in Prolog. It means that Prolog should, for this branching point - no longer consider the remaining clauses. So it will from now on, ignore the second clause of relax/1. Next it encounters sun(X). So now Prolog will call sun(time4) and aim to satisfy this. It will aim to unify with the first (and only) clause of sun/1: sun(time3). But as said before, time3 and time4 do not unify. So as a result, that fails. Since Prolog cannot take the second clause of relax/1 (due to the cut (!)), it thus has exhausted all the options, and decides that the query relax(time4) is false.

Commutativity of disjunction in Prolog

I've just started learning Prolog and I encountered a problem that I don't understand.
When I ask:
?- fail; true.
Prolog answers:
true
Which is something I expected. But, if I ask:
?- true; fail.
Prolog answers:
true ;
false.
..and I don't understand why. The disjunction operator should be commutative. Why are these two Prolog answers different?
Also note that the Prolog disjunction operator, (;)/2, is not commutative in general. For example:
?- !; write(else).
true.
?- write(then); !.
then
true ;
true.
The right branch of the disjunction is only tried on backtracking if the implicit choice point is not cut when executing the left branch. Note that a clause such as:
foo :- (!; write(else)).
is equivalent to:
foo :- !.
foo :- write(else).
Thus, cuts and (other) side-effects result in (;)/2 not behaving as logical disjunction.
it's just a detail of top level interaction, then you could observe a different behaviour depending on Prolog interpreter you're using.
SWI-Prolog, in introductory documentation, gives some information:
2.1.2 Executing a query
After loading a program, one can ask Prolog queries about the program. The query below asks Prolog what food `sam' likes. The system responds with X = if it can prove the goal for a certain X. The user can type the semi-colon (;) or spacebar6 if (s)he wants another solution. Use the return key if you do not want to see the more answers. Prolog completes the output with a full stop (.) if the user uses the return key or Prolog knows there are no more answers. If Prolog cannot find (more) answers, it writes false.
The confusion regards how prolog displays results. When you make a query in prolog, it will attempt to find all possible answers. That means it will start at the first fact or clause, go through them sequentially and, when it can finally make the query true, displays the answer. If there was a choice point in the process of finding the last solution, prolog prompts the user to seek more possible successful solutions.
In the case of:
?- false ; true.
This query starts by looking at the clause false, which fails and then, since there's a disjunction ;, checks the clause after the ; which is true. This succeeds, and prolog displays:
true
Note that when it found this solution, there were no more choices, so there's no prompt for further solutions.
Now let's look at the second example:
?- true ; false.
Prolog looks at the first clause, true, and succeeds and tells the user:
true
But in this case, it hasn't exhausted all of the possible solutions since there's a disjunction ; that created another choice. So when you enter the ; at the prompt:
true ;
You tell prolog to find more solutions. Prolog goes back and checks the clause after the disjunction and encounters false. This fails and there are no other solutions. Therefore, your request for further solutions fails and prolog outputs false:
true ;
false
The first true means it succeeded. The false means it found no more solutions and failed on the second attempt.
Prolog's behavior is to seek solutions sequentially through the appropriate clauses and present them as long as you ask for them until it fails. When it finally fails, you get false. Some prologs output no. The behavior above is not a commutativity issue.

Declarative interpretation of list inversion in Prolog

I have some problem to join declarative reasoning...so I am here to ask you if my reasoning is correct or if there is something wrong or if I am missing something...
I have the following problem: Write a Prolog program that invert the element of a list
for example if I call something like:
myreverse([a,b,c,d,e],X). I have to obtain that X=[e,d,c,b,a]
I have the following solution:
naiverev([],[]).
naiverev([H|T],R):- naiverev(T,RevT),
append(RevT,[H],R).
This is my interpretation:
I have a fact that say that the inverse of an empty list is an empty list.
If the first list it is not empty, the fact it is not true and the fact it is not match so move on to the next rule.
The rule say that: the program that prove that the list R is the inverse of the list [H|T]
I can read the logic implication from right to left in the following way:
IF it is TRUE that naivrev(T, RevT) AND append(RevT, [H], R) ---> naivrev([H|T],R) it is TRUE
So (in the body of the rule) I am assuming that the "function" naivrev(T,RevT) respond TRUE if RevT is the inverse of T, FALSE otherwise.
At the same time I am assuming* that **append(RevT,[H],R) respond TRUE if R is [H|RevT], FALSE otherwise.
Then, if both the parts of the rule body are TRUE, the program can infer that the HEAD is TRUE (in this case that R is the inverse of [H|T])
Is this reasoning good or I am missing something?
Like the last two times, you have again intermixed Prolog's engine of computation with the purely declarative reading. Whenever you say, procedurally "the rule is not matched so move on" or anything like that, you're invoking Prolog's algorithm to explain what's going on, not logic. But you're getting better, because the rest of your stuff is much closer than before.
Rule 1: the reverse of the empty list is the empty list. (Same as you have.)
Rule 2: the reverse of [H|T] is the reverse of T, called RevT, appended to the list [H].
What makes this work, of course, is that Prolog will try rule 1, when it doesn't match, it will try rule 2, and recursively build up the result (in a tremendously inefficient way, as you probably realize). But this "making it go" of checking rules and choosing between them and how that process is performed, is what Prolog adds to a declarative or logical statement.
Your reading of the logical implication is correct: If naiverev(T, RevT) is true and append(RevT, [H], R) is true, then naiverev([H|T], R) is true. This is just as #false explained in your previous question, so I would say you're definitely starting to get it. Your remarks about the body being true leading to the head being true are spot on.
So good job, it looks like you're getting it. :)

Prolog not returning expected values

I'm trying to get comfortable with Prolog (SWI Prolog specifically).
I have this very simple listing:
animal(bear).
animal(mouse).
animal(bird).
Now whenever I ask for all atoms that fulfill (what is the correct expression?) the predicate
animal I always get only the first one.
?- animal(X).
X = bear .
Though all three atoms evaluate to 'true' for animal.
?- animal(mouse).
true.
?- animal(bird).
true.
What am I doing wrong? Is this behavior controllable via some setting?
There is nothing wrong in your code. Prolog is a reasoning machine. So it tries to find the first solution that will satisfy all the variables.
Once the solution is found it prints it out.
Now if you need additional solution there should be some combination that you should enter so that prolog will continue searching.
If I remember correctly it might be a semicolon...
Hope this helps

Resources