I was reading a code piece in Prolog and I saw the below code :
r(a).
q(b).
p(X) :- not r(X)
Questions :
?-q(X), p(X) // Result: b
?-p(X), q(X) // Result: no
So, why for ?-q(X), p(X) we get "b" and for ?-p(X), q(X) which is exactly the same as ?-q(X), p(X) we get "no" ?
?-q(X), p(X) // Result: b
q(X) eventually unifies with q(b), which then calls p(b), which calls not r(b), which is true.
?-p(X), q(X) // Result: no
p(X) calls not r(X), which causes X to unify with a, which causes the preceding clause to evaluate to not r(a), which is false, and the conjuction operator short circuits to no.
In fact the two queries are not exactly the same because Prolog "conjunction" operator (the comma) is usually not commutative:
the execution is from left to right and so the order in which the variables are instantiated is different in those queries
if you only use pure logical predicates, that is predicates that are defined not using extra-logical predicates (like not/1 or if-then-else constructs), nor predicates having side-effects (like I/O ones), nor predicates that require some of its arguments to be instantiated beforehand (like is/2), the change in instantiation order does not affect commutativity
but as one of your predicates uses not/1 and it behaves differently when its argument is r(_) or r(b) as explained in C.B. answer, commutativity does not hold.
As you may know not/1 does not implement pure logical negation: it implements so-called negation as failure meaning that it succeeds if the execution of its argument fails and otherwise fails (if the argument is a free variable you get an instantiation error). As the execution is from left to right you cannot expect that its behaviour is affected by some instantiation made after its call.
Related
The tag logical purity mentions (=)/2 as pure. Is it
"intrinsically" pure or "operational" pure? To the
best of my knowledge it can be defined by this Horn clause:
∀x(=(x, x))
Which is this Prolog fact, if were not already a built-in:
X = X.
This means (=)/2 would be "intrinsically" pure, as SWI-Prolog already remarks. So what is
then the difference to first order equality (FOL=), if there
are any differences?
The "intrinsinc" definition of (=)/2 I guess does assure that the unify predicate is reflexive, symmetric and transitive. Requirements that are also satisfied by FOL=. But FOL= also requires congruence, which is this axiom schema:
/* Predicate Congruence in FOL= */
∀x1..∀xn∀yj(=(xj, yj) & p(x1, .., xn) -> p(x1, .., xj-1, yj, xj+1, .., xn))
Which is not represented by the only Horn clause for the unify predicate. And since the unify predicate is a built-in, the missing Horn clauses can also not be added. So what can go wrong? Can we make an example that would go wrong?
The classical example is this fact:
p(morning_star).
Obviously this query succeeds in Prolog:
?- p(morning_star).
true
But this query fails in Prolog, whereas in FOL= it would succeed:
?- morning_star = evening_star, p(evening_star).
false
The situation is different in so called unification modulo theories, where the unification and also the unify predicate might change their meaning.
I have the followings:
mother(grimalde).
daughter(biancaneve, grimalde).
love(X, Y) :- mother(X), daughter(Y, X).
\+(kill(X, Y)) :- mother(X), daughter(Y, X), love(X, Y).
when I run consult('ex.pl'). I get:
?- consult('ex.pl').
ERROR: /home/antonio/Scrivania/ex.pl:4:
No permission to modify static procedure `(\+)/1'
Defined at /usr/lib/swi-prolog/boot/init.pl:242
% ex.pl compiled 0.00 sec, 0 clauses
And I don't understand why...
In Prolog you cannot use negation in a clause head.
Definite clauses
Remember that Prolog clauses are definite clauses, i.e. conjunctions of literals of which exactly one is positive. This positive literal is called the head of the clause and is the part preceding the ":-".
Abstracting a bit, your clause looks like this:
\+H :- B1, B2, B3
which corresponds to the following clause:
\+H, \+B1, \+B2, \+B3
which is not definite.
Negation as failure
Also remember that Prolog negation is not logical negation but negation as failure. In that sense \+(kill(X,Y)) should be read "In this Prolog program it cannot be derived that X kills Y."
Permission error
So why do you get a permission error? Since \+/1 is not interpreted negating the clause head (since the Prolog language does not allow this), it seems like you are redefining \+/1. Since \+/1 is the outer functor of the clause head, it looks as if you are defining it. But redefining this predicate is not allowed.
So I just started Prolog and I was wondering two things:
1) Is there built in functions (or are they all called predicates?) for simple things like max of 2 numbers, or sine of a number, etc... If so, how do I access them?
2) How can I call a predicate from another one? I wrote two predicates called car and cdr. car returns the head of a list and cdr returns the list without the head. But now I want to call car on the cdr. Here are some examples for clarification:
car([3,4,5,5], H). would return H = 3
cdr([3,4,5,5],L). would return L = [4,5,5]
and what I am asking is how can I do this:
car(cdr[3,4,5,5]))
??
As others have pointed out, the predicates in Prolog are called that for a reason: they really aren't functions. Many newcomers to Prolog start out by trying to map the functionality they know in other languages over to Prolog and it generally fails. Prolog is a very different programming tool than most other languages. So it's a bit like using a variety of hammers for a long time, then having someone hand you a wrench, and you wonder why it doesn't make a good hammer.
In Prolog, predicates are a means of declaring relations between entities. If you say foo(a, b) it means there's a relationship between a and b called foo. You've probably seen the examples: knows(joe, jim). and knows(jim, sally). And you can define a relation, like:
remotely_acquainted(X, Y) :- knows(X, Z), knows(Z, Y), \+ knows(X, Y).
Or something like that.
A predicate does not return a value. It either succeeds or it fails. If you have a sequence of predicates separated by commas (an "and" relationship) and Prolog encounters a predicate that fails, it backs up (backtracks) to the nearest prior predicate which it can make succeed again with different instantiation of its arguments and moves forward again.
Just to add a little to the confusion, there are some predicates in Prolog designed specifically for the evaluation of arithmetic expressions. These act like functions, but they are special case. For example:
X is Y / gcd(Z, 4).
Here, gcd of Z and 4 is computed an its value returned, and then Y is divided by that value and the result is instantiated into X. There are a variety of other functions as well, such as max/2, sin/1, etc. You can look them up in the documentation.
Arithmetic comparative operators function this way as well (using =:=/2, >/2, </2, etc with numeric expressions). So if you say:
X < Y + Z
The Prolog will consider numerical evaluation of these arguments and then compare them.
So having said all that, Prolog does allow embedding of term structures. You could have something like:
car(cdr([1,2,3]))
as a term. Prolog will not interpret it. Interpretation is left up to the programmer. I could then create a predicate which defines an evaluation of such terms:
car([H|_], H).
cdr([_|T], T).
proc_list(car(X), Result) :-
proc_list(X, R1),
car(R1, Result), !.
proc_list(cdr(X), Result) :-
proc_list(X, R1),
cdr(R1, Result), !.
proc_list(X, X).
The cut in the above clauses prevents backtracking to proc_list(X, X) when I don't want it.
Then:
| ?- proc_list(car(cdr([1,2,3])), R).
R = 2
yes
| ?- proc_list(car(cdr(cdr([1,2,3]))), R).
R = 3
yes
| ?-
Note this is a simple case and I may not have captured all of the subtleties of doing a proper sequence of car and cdr. It can also be made more general using =.. and call, etc, instead of discrete terms car and cdr in the parameters. For example, a slightly more general proc_list might be:
proc_list(Term, Result) :-
Term =.. [Proc, X], % Assumes terms have just one argument
member(Proc, [car, cdr]), % True only on recognized terms
proc_list(X, R1), % Recursively process embedded term
ProcCall =.. [Proc, R1, Result], % Construct a calling term with Result
call(ProcCall), !.
proc_list(X, X).
This technique of processing a term does step away from relational behavior which Prolog is best at, and leans into functional behavior, but with an understand of how Prolog works.
Prolog has a really different attitude to computing...
You don't define functions, but relations among arguments. The most similar and well known language I'm aware of is SQL. Think of predicates as tables (or stored procedures, when some computation not predefined by database engine is required).
car([H|_],H).
cdr([_|T],T).
car_of_cdr(L, Car) :- cdr(L, Cdr), car(Cdr, Car).
but since lists' syntax is a core part of the language, a better definition could be
car_of_cdr([_,X|_], X).
Anyway, I think you should spend some time on some Prolog tutorial. SO info page has much more information...
:- use_module(support).
This means the module will use predicates written in other modules.
<module_name>:<predicate_name>(<atoms / Variables>).
This way you can call a predicate in another module.
Because Prolog uses chronological backtracking(from the Prolog Wikipedia page) even after an answer is found(in this example where there can only be one solution), would this justify Prolog as using eager evaluation?
mother_child(trude, sally).
father_child(tom, sally).
father_child(tom, erica).
father_child(mike, tom).
sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).
parent_child(X, Y) :- father_child(X, Y).
parent_child(X, Y) :- mother_child(X, Y).
With the following output:
?- sibling(sally, erica).
true ;
false.
To summarize the discussion with #WillNess below, yes, Prolog is strict. However, Prolog's execution model and semantics are substantially different from the languages that are usually labelled strict or non-strict. For more about this, see below.
I'm not sure the question really applies to Prolog, because it doesn't really have the kind of implicit evaluation ordering that other languages have. Where this really comes into play in a language like Haskell, you might have an expression like:
f (g x) (h y)
In a strict language like ML, there is a defined evaluation order: g x will be evaluated, then h y, and f (g x) (h y) last. In a language like Haskell, g x and h y will only be evaluated as required ("non-strict" is more accurate than "lazy"). But in Prolog,
f(g(X), h(Y))
does not have the same meaning, because it isn't using a function notation. The query would be broken down into three parts, g(X, A), h(Y, B), and f(A,B,C), and those constituents can be placed in any order. The evaluation strategy is strict in the sense that what comes earlier in a sequence will be evaluated before what comes next, but it is non-strict in the sense that there is no requirement that variables be instantiated to ground terms before evaluation can proceed. Unification is perfectly content to complete without having given you values for every variable. I am bringing this up because you have to break down a complex, nested expression in another language into several expressions in Prolog.
Backtracking has nothing to do with it, as far as I can tell. I don't think backtracking to the nearest choice point and resuming from there precludes a non-strict evaluation method, it just happens that Prolog's is strict.
That Prolog pauses after giving each of the several correct answers to a problem has nothing to do with laziness; it is a part of its user interaction protocol. Each answer is calculated eagerly.
Sometimes there will be only one answer but Prolog doesn't know that in advance, so it waits for us to press ; to continue search, in hopes of finding another solution. Sometimes it is able to deduce it in advance and will just stop right away, but only sometimes.
update:
Prolog does no evaluation on its own. All terms are unevaluated, as if "quoted" in Lisp.
Prolog will unfold your predicate definitions as written and is perfectly happy to keep your data structures full of unevaluated uninstantiated holes, if so entailed by your predicate definitions.
Haskell does not need any values, a user does, when requesting an output.
Similarly, Prolog produces solutions one-by-one, as per the user requests.
Prolog can even be seen to be lazier than Haskell where all arithmetic is strict, i.e. immediate, whereas in Prolog you have to explicitly request the arithmetic evaluation, with is/2.
So perhaps the question is ill-posed. Prolog's operations model is just too different. There are no "results" nor "functions", for one; but viewed from another angle, everything is a result, and predicates are "multi"-functions.
As it stands, the question is not correct in what it states. Chronological backtracking does not mean that Prolog will necessarily backtrack "in an example where there can be only one solution".
Consider this:
foo(a, 1).
foo(b, 2).
foo(c, 3).
?- foo(b, X).
X = 2.
?- foo(X, 2).
X = b.
So this is an example that does have only one solution and Prolog recognizes that, and does not attempt to backtrack. There are cases in which you can implement a solution to a problem in a way that Prolog will not recognize that there is only one logical solution, but this is due to the implementation and is not inherent to Prolog's execution model.
You should read up on Prolog's execution model. From the Wikipedia article which you seem to cite, "Operationally, Prolog's execution strategy can be thought of as a generalization of function calls in other languages, one difference being that multiple clause heads can match a given call. In that case, [emphasis mine] the system creates a choice-point, unifies the goal with the clause head of the first alternative, and continues with the goals of that first alternative." Read Sterling and Shapiro's "The Art of Prolog" for a far more complete discussion of the subject.
from Wikipedia I got
In eager evaluation, an expression is evaluated as soon as it is bound to a variable.
Then I think there are 2 levels - at user level (our predicates) Prolog is not eager.
But it is at 'system' level, because variables are implemented as efficiently as possible.
Indeed, attributed variables are implemented to be lazy, and are rather 'orthogonal' to 'logic' Prolog variables.
Is there any difference between input and output parameters in Prolog predicate definitions? How does this this compare with other languages such as Scheme and C?
I hope I understand your question. You should look into how unification is implemented in Prolog, as it will make things clearer. Anyway:
Briefly, there is no built-in way to declare an argument to a Prolog predicate as input, output, or input/output.
In C, you could say:
void foo(int const *a, int *b)
{
*b += *a;
}
and you could argue that in the context of foo, a is an input argument, while b is an output argument. In Prolog, you can use this notation when describing predicates, but there is no way to declare in the head of the predicate definition that an argument must be bound or a free variable when the predicate is called. And anyway, most predicates in pure Prolog have arguments that can be input, output, or input/output, depending how the predicate is used. Look at the list library of SWI-Prolog for many examples.
You can of course demand that an argument is instantiated, or a free variable, but this is done in the body of the predicate definition:
add_2(A, B) :- integer(A), var(B), B is A+2.
Compare this to:
plus_2(A, B) :- integer(A), integer(B), B =:= A+2.
which checks whether B=A+2 holds true, instead of adding 2 to A and unifying the result with B. integer/1, var/1, and the other predicates that verify the type of a term cannot be implemented in pure Prolog.
In my very limited experience with Prolog, I have noticed that one will try to define predicates that work as long as enough arguments are instantiated to either:
Instantiate the other variables according to the logic of the predicate
Infer whether the relationship between the arguments described by the predicate holds true.
For example, length(List, Integer) can tell you how long a list is, make a list of uninstantiated variables of the given length, or check whether the list is that long.
What you can do, however, is have a ground term in the head of the predicate definition, for example foo(1). This sort of predicates are called facts. A clause with a ground term in the head is the usual way for defining the end-of-recursion for recursive predicates.
Is there any difference between the input/output parameters in Prolog definitions?
No, and in fact a parameter can be either one depending on how it is used. Boris's length example is a good one, because you can calculate length:
?- length([1,2,3], X).
X = 3.
Or test an answer:
?- length([1,2,3], 3).
true.
Or generate a list of specified length:
?- length(X, 3).
X = [_G273, _G276, _G279].
Or even generate lists and lengths:
?- length(X, Y).
X = [],
Y = 0 ;
X = [_G15],
Y = 1 ;
X = [_G15, _G18],
Y = 2 ;
...
So you see either argument of length/2 can be instantiated or not and you'll still get meaningful answers. Not every predicate in Prolog is this flexible, but many are.
How does this this compare with other languages such as scheme and C ?
This is the principal difference between Prolog and other languages. There is no other, better-known language which behaves analogously to help you grok it. It means that, among other differences, there is no implicit "return value," you must have a parameter to pass results back in, but you're not limited to just one result parameter. In the case where both arguments to length/2 were uninstantiated, they were both acting as return values.
By convention, you will want to write your predicates so that input parameters go before output parameters for the common cases (or at least, in a sensible way for the name you've chosen).