Prolog - Unification of complex terms - prolog

I am currently studying for an AI exam and my final thing to revise is Prolog.
Below you can see the question I have to solve:
If possible, unify uncle(brother(W), Q) with uncle(john, mother(S))
I am completely lost as on a high level, it doesn't unify, but I guess my knowledge of Prolog is a bit outdated.
Could someone help me understand how to unify them if possible? I don't understand how I would unify functors to atoms.
Thank you!

I find that when learning syntactic unification that it works better if you first decompose the terms into abstract syntax trees then do the unification. Doing the decomposition really helps with nested list. So after decomposition you have brother(W) trying to unify with john which will fail. Once you have a failure you can skip the rest of the unification process.
While these are not abstract syntax trees, the predicates =.. and write_term help in converting complex terms to ASTs.
Using =../2
?- uncle(brother(W),Q) =.. List.
List = [uncle, brother(W), Q].
?- uncle(john,mother(S)) =.. List.
List = [uncle, john, mother(S)].
and then trying to unify the individual terms
?- brother(W) = john.
false.
For Prolog list use write_term/2 with option dotlists(true)
?- write_term([a],[dotlists(true)]).
.(a,[])
true.
?- write_term([a,b],[dotlists(true)]).
.(a,.(b,[]))
true.
?- write_term([a,B],[dotlists(true)]).
.(a,.(_15276,[]))
true.
?- write_term([a,[b]],[dotlists(true)]).
.(a,.(.(b,[]),[]))
true.
?- write_term([a,b,[c],[d,[e,[f],g]],h],[dotlists(true)]).
.(a,.(b,.(.(c,[]),.(.(d,.(.(e,.(.(f,[]),.(g,[]))),[])),.(h,[])))))
true.
In this post are some actual ASTs for learning syntactic unification.
Do to limitation of Discourse I could not get the images to line up with the actual Prolog terms as I wanted but it is better than not having them.

Related

How does unify predicate (=)/2 differ from first order equality?

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.

Prolog Unification with not()

I am just learning prolog and there is a thing I can't get my head over.
Suppose I have the following program
value(v).
a(X) :- not(value(X)).
So a(v). gives me false, as value(v) can be proved correct.
a(w) gives me true, as there is no fact value(w), therefore, even when trying, it can't be proved correct.
In my understanding, requesting a(X). should give me the first possible value that makes value(X) unproveable. There should be an infinite amount of possibilities, as only value(v) is correct.
But why does Prolog keep answering false?
First of all, please use the ISO predicate (\+)/1 instead of not/1.
Second, please don't use (\+)/1 to denote disequality of terms: (\+)/1 is incomplete in Prolog, and thus not logically sound. It is not logical negation, but rather denotes "not provable".
In your case: ?- value(X). succeeds, so it is provable, so ?- \+ value(X). fails although there are instantiations that make the query succeed.
In particular, ?- \+ value(a). succeeds.
So we have:
?- \+ value(V).
false.
But a more specific query succeeds:
?- V = a, \+ value(V).
V = a.
This obviously runs counter to logical properties we expect from pure relations. See logical-purity.
To denote disequality of terms, use dif/2. If your Prolog system does not support dif/2, ask for its inclusion, or use iso_dif/2 as a safe approximation that is logically sound. See prolog-dif for more information.
Prolog operates under "closed world assumption" – it only knows what we told it about. In particular, we've told it nothing about no w, u, or any other stuff, so how could it produce them to us? And why should w come before u, and not vice versa?
The only thing sensible could be to produce (X, dif(X,v)), but it would be the answer to a different question, namely, "how to make a(X) provable?", not the one Prolog is actually answering, namely "is a(X) provable?".
To ease up your cognitive burden, rename the Prolog prompt's replies in your head from true to Yes, and from false to No.
Yes would mean Prolog telling us "yes, I could prove it!", and No – "no, I couldn't prove it."
Also rename "not" to read \+ as not_provable, mentally.

Prolog programming language and proof trees

Recall this proof meta-circular
solve(true, true).
solve([], []).
solve([A|B],[ProofA|ProofB]) :-
solve(A,ProofA),
solve(B, ProofB).
solve(A, node(A,Proof)) :-
rule(A,B),
solve(B,Proof).
Assume that the third rule of the interpreter is altered, while the other rules of the interpreter are unchanged, as follows:
% Signature: solve(Exp, Proof)/2 solve(true, true).
solve([], []).
solve([A|B], [ProofA|ProofB]) :-
solve(B, ProofB), %3
solve(A, ProofA).
solve(A, node(A, Proof)) :-
rule(A, B),
solve(B, Proof).
Consider the proof tree that will be created for some query in both versions. Can any variable substitution be achieved in one version only? Explain. Can any true leaf move to the other side of the most left infinite branch? Explain. In both questions give an example if the answer is positive. How will this influence on the proof?
please help me ! tx
(I have a lot of reservations against your meta-interpreter. But first I will answer the question you had)
In this meta-interpreter you are reifying (~ implementing) conjunction. And you implement it with Prolog's conjunction. Now you have two different versions how you interpret a conjunction. Once you say prove A first, then B. Then you say the opposite.
Think of
p :- p, false.
and
p :- false, p.
The second version will produce a finite failure branch, whereas the first will produce an infinite failure branch. So that will be the effect of using one or the other meta-interpreter. Note that this "error" might again be mitigated by interpreting the meta-interpreter itself!
See also this answer which might clarify the notions a bit.
There are also other ways to implement conjunction (via binarization) ; such that the next level of meta-interpreter will no longer able to compensate.
Finally a comment on the style of your meta-interpreter: You are mixing lists and other terms. In fact [true|true] will be true. Avoid such a representation by all means. Either stick with the traditional "vanilla" representation which operates on the syntax tree of Prolog rules. That is, conjunction is represented as (',')/2. Or stick to lists. But do not mix lists and other representations.

How to call a predicate from another predicate in Prolog?

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.

Semantic knowledge representation predicate in Prolog

I am studying DCG grammars and parse trees in Prolog using Ivan Bratko's Programming for Artificial Intelligence. In a program that uses a DCG grammar to extrapolate the meaning of a sentence, I find these two predicates that, I think, represent a kind of semantic knowledge:
properName(john) --> [john].
properName(mary) --> [mary].
How should I read these predicates? I am thinking that they mean: it is true that an element of a list represented by the string "john" is a proper name and this proper name is John (same thing for Mary).
Is it my reading correct or are there some other implications?
properName(X) is just an unary rule (in the context of DCG; it is a ternary predicate in Prolog - check it out with ?- listing(properName) ). you could've called it "socks", or "jam", it's totally up to you. So the semantic knowledge about it representing proper name "john" or "mary" is nowhere to be found in the code (it uses naming as self-documenting feature, but documentation is not code).
The predicate allows for an atom john or mary to be present in the input stream, and nothing else; and demands that X unified with that atom.
You could've defined it thus:
name(X) --> [X], { member(X, [john, mary]) }.
then,
4 ?- phrase( name(X), [john,jack], Z).
X = john,
Z = [jack] ;
false.
5 ?- phrase( name(X), [jack,john], Z).
false.
8 ?- phrase( name(X), [john,mary], Z).
X = john,
Z = [mary] ;
false.
9 ?- phrase( name(X), [mary,john,jack], Z).
X = mary,
Z = [john, jack].
11 ?- phrase( name(jack), [jack,mary,john], Z).
false.
This is a trivial predicate that does not lend itself to interpretation outside of the context in which it is used.
In other words, it can only be used to demand that a proper name is used in a certain way, by a DCG rule that uses it on its right-hand side. The way you have shown it, in isolation, it means nothing more than:
'john' is a proper name, and so is 'mary'.
EDIT
I might be wrong here, but you are still abusing the English language to describe things that are best described using a formal language. Prolog is a formal language, with a defined syntax and semantics. It can be used to formally describe logical relationships, or computation. Trying to faithfully translate it into English is bound to be clumsy and unnecessary. Something as trivial as the predicate in your question turns into something that is silly, difficult to understand, and difficult to work with.
P.S. The correct spelling of the word you like so much is representation.

Resources