Use of =.. predicate to perform symbolic manipulation of furmulas in Prolog - prolog

I am learning Prolog for an universitary university exam using SWI Prolog and I have some doubts about how it work this exercise that use the univ =.. =.. predicate to perform symbolic manipulation of furmulas formulas where a frequent operation is to substituite substitute some subexpression by another expression.
It is perform defining the following relation:
substituite(SubTerm, Term, SubTerm1, Term1)
that it is TRUE if Term1 rappresent represents Term expression in which all the occurrences of SubTerm are substituited by SubTerm1.
For example if I have:
substituite(sin(x), 2*(sin(x)), t, F).
Then: F = 2*t*f(t) because all the sin(x) occurrences are substituited by t
This is the solution (founbd on Bratko book) but I am not so sure about my interpretation:
% substitute( Subterm, Term, Subterm1, Term1)
% Term1 is Term with all occurrences (by matching)
% of Subterm are replaced by Subterm1.
% Test: ?- substitute( b, f(a,b,c), e, F).
% Test: ?- substitute( b, f(a,X,c), e, F).
% Test: ?- substitute( b, f(a,X,Y), e, F).
% Test: ?- substitute( a+b, f( a, A+B), v, F).
% Test: ?- substitute(b,B,e,F).
% Test: ?- substitute(b,b,e,F).
% Test: ?- substitute(b,a,e,F).
% Logic, there are three cases:
% If Subterm = Term then Term1 = Subterm1
% otherwise if Term is 'atomic' (not a structure)
% then Term1 = Term (nothing to be substituted)
% otherwise the substitution is to be carried
% out on the arguments of Term.
/* Case 1: SubTerm = Term --> SubTerm1 = Term1 */
substitute(Term, Term, Term1, Term1) :- !.
% Case 2: Se Term è atomico non c'è niente da sostituire
substitute( _, Term, _, Term) :- atomic(Term), !.
/* Case 3:
substitute(Sub, Term, Sub1, Term1) :-
Term =.. [F|Args], % Term è composto da: F è il FUNTORE PRINCIPALE ed Args è la lista dei suoi argomenti
substlist(Sub, Args, Sub1, Args1), % Sostituisce Sub1 al posto di Sub nella lista degli argomenti Args generando Args1
Term1 =.. [F|Args1]. % Term1 è dato dal FUNTORE PRINCIPALE F e dalla nuova lista degli argomenti Args1
/* sublist: sostituisce all'interno della lista degli argomenti: */
substlist(_, [], _, []).
substlist(Sub, [Term|Terms], Sub1, [Term1|Terms1]) :-
/* L'elemento in testa Term1 corrisponde all'eventuale sostituzione */
substitute(Sub, Term, Sub1, Term1),
/* Il problema è già risolto per le sottoliste e Terms1 rappresenta la sottolista Terms in cui tutte le occorrenze di Sub
sono già state sostituite con Sub1:
*/
substlist(Sub, Terms, Sub1, Terms1).
The first rule rappresent represents the particular case in which SubTerm = Term so the final Term1=SubTerm1 (because I substituite substitute whole term)
The second rule rappresent represents the particular case in which Term is an atom so, regardless of the values ​​of SubTerm and SubTerm1, I do not perform any substitution
I think that up to here it is simple and my reasoning it is correct...next to it begin the more difficult part and I am not so sure...
The rule:
substitute(Sub, Term, Sub1, Term1) :-
Term =.. [F|Args],
substlist(Sub, Args, Sub1, Args1),
Term1 =.. [F|Args1].
rappresent represents a generic case in which I have an expression rappresented represented by Term, its possible subexpression rappresented represented by Sub, a new subexpression Sub1 that eventually should be substituted when you meet an occurrence of Sub and the expression Term1 that rappresent Term expression in which all the occurrences of SubTerm are substituited by SubTerm1.
So I can read it declaratively in this whay way:
It is TRUE that Term1 rappresent represents Term expression in which all the occurrences of SubTerm are substituited by SubTerm1 if there are TRUE the following facts:
1) The original expression Term can be decomposed in a list that have in the head its main functor F (the first operator executed in the expression evalutation) and later a sublist Args that rappresent the arguments of this functor F (I think that, in some case, Args can contain also other functor that, in this computational step, don't are the main functor...so in these case there are still some subproblem to solve)
2) It is true that substlist(Sub, Args, Sub1, Args1) that means that this is true that Args1 rappresent Args in which all the argument equals to Sub subexpression are replaced by Sub1 subexpression.
3) Finally it must be true that the new Term1 is the result of the univ =.. predicate beetwen the main functor F and the new arguments list Args1 (I think that =.. recombine the main functor F with the new arguments list
To perfrom the substitution in the arguments list it is used the substlist relation that it is divided into:
A BASE CASE:
substlist(_, [], _, []).
that simply say: if there is nothing in the arguments list, there is nothing to replace
A GENERAL CASE:
substlist(Sub, [Term|Terms], Sub1, [Term1|Terms1]) :-
/* L'elemento in testa Term1 corrisponde all'eventuale sostituzione */
substitute(Sub, Term, Sub1, Term1),
/* Il problema è già risolto per le sottoliste e Terms1 rappresenta la sottolista Terms in cui tutte le occorrenze di Sub
sono già state sostituite con Sub1:
*/
substlist(Sub, Terms, Sub1, Terms1).
And this is the more difficult part to understand for me, I see it in the following way, declarative reading:
It is TRUE that [Term1|Terms1] rappresent the list of arguments [Term|Terms] in which all the Sub term are replaced by Sub1 if it is true that:
1) substitute(Sub, Term, Sub1, Term1): that means that it is TRUE that Term1 (the head of the new arguments list it is Term (the head of the old arguments list) in which if Term == Sub ---> Term1 == Sub1
2)substlist(Sub, Terms, Sub1, Terms1) that means all the subproblem are solved, I think that this is an important point because the argument list Term is the argument list of a current main functor F but can contain other sub functors inside it and each of these rappresent a subproblem that have to be solved befor perform the Sub-->Sub1 replacements in this step.
But I am not so sure about this last thing...
someone can help me to deeply understand it
Tnx
Andrea

Let me start by saying that it would be nice if you kept questions short and to the point. The whole idea of Stackoverflow is that questions and answers will be later useful to others, and writing good questions is a big part of this.
Moving on: All programming languages have some right to the claim that the actual source code of a program is the most clear, complete, and exhaustive explanation (to a human) of what the program does. Prolog definitely has a right to that claim. It takes a bit of getting used to, but soon a well-written predicate does tell more about the program logic than an often futile attempt to give a precise specification / definition in an inherently ambiguous natural language, be it English, Italian, or even German.
Now to your question...
What does =../2 do? We may look here, but, in a few words, we have f(a,b, ..., x) on the left side, and [f, a, b, ..., x] on the right side of it.
Assuming recursion, lists, matching and unification don't need to be explained here, the program you have extensively studied, commented in Italian, and thoroughly explained to us in English, does one simple thing: all occurrences of Subterm in Term are substituted by Subterm1 in Term1.
This is done:
by directly replacing simple terms (atoms) by matching
by breaking down complex terms (of the form f(Args)) into a list (using =..), and then applying the algorithm recursively on the simpler terms in that list (the elements of Args). Afterwords, the list is reassembled, using =.. again.
So if you have a nested term, you still get:
?- substitute(x, f( g( h(x,y,z), h(k,l,m) ), g(x,z) ), q, T).
T = f(g(h(q, y, z), h(k, l, m)), g(q, z)) ;
false.
The only slight difficulty one might encounter here is that substitute and substlist are mutually recursive. If this is giving you that much difficulty, one thing you can try and do is to remove all comments from the predicate definitions, fit the whole program on the screen at once (or print it out), and look at it and think about it until it makes sense. It works!

Related

Prolog Array Pipe Meaning

Can anybody explain the following code? I know it returns true if X is left of Y but I do not understand the stuff with the pipe, underscore and R. Does it mean all other elements of the array except X and Y?
left(X,Y,[X,Y|_]).
left(X,Y,[_|R]) :- left(X,Y,R).
If you are ever unsure about what a term "actually" denotes, you can use write_canonical/1 to obtain its canonical representation.
For example:
| ?- write_canonical([X,Y|_]).
'.'(_16,'.'(_17,_18))
and also:
| ?- write_canonical([a,b|c]).
'.'(a,'.'(b,c))
and in particular:
| ?- write_canonical([a|b]).
'.'(a,b)
This shows you that [a|b] is the term '.'(a,b), i.e., a term with functor . and two arguments.
To reinforce this point:
| ?- [a|b] == '.'(a,b).
yes
#mat answered the original question posted quite precisely and completely. However, it seems you have a bigger question, asked in the comment, about "What does the predicate definition mean?"
Your predicate, left(X, Y, L), defines a relation between two values, X and Y, and a list, L. This predicate is true (a query succeeds) if X is immediately left of Y in the list L.
There are two ways this can be true. One is that the first two elements in the list are X and Y. Thus, your first clause reads:
left(X, Y, [X,Y|_]).
This says that X is immediately left of Y in the list [X,Y|_]. Note that we do not care what the tail of the list is, as it's irrelevant in this case, so we use _. You could use R here (or any other variable name) and write it as left(X, Y, [X,Y|R]). and it would function properly. However, you would get a singleton variable warning because you used R only once without any other references to it. The warning appears since, in some cases, this might mean you have done this by mistake. Also note that [X,Y|_] is a list of at least two elements, so you can't just leave out _ and write [X,Y] which is a list of exactly two elements.
The above clause is not the only case for X to be immediately left of Y in the list. What if they are not the first two elements in the list? You can include another rule which says that X is immediately left of Y in a list if X is immediately left of Y in the tail of the list. This, along with the base case above, will cover all the possibilities and gives a complete recursive definition of left/3:
left(X, Y, [_|R]) :- left(X, Y, R).
Here, the list is [_|R] and the tail of the list is R.
This is about the pattern matching and about the execution mechanism of Prolog, which is built around the pattern matching.
Consider this:
1 ?- [user].
|: prove(T):- T = left(X,Y,[X,Y|_]).
|: prove(T):- T = left(X,Y,[_|R]), prove( left(X,Y,R) ).
|:
|: ^Z
true.
Here prove/1 emulates the Prolog workings proving a query T about your left/3 predicate.
A query is proven by matching it against a head of a rule, and proving that rule's body under the resulting substitution.
An empty body is considered proven right away, naturally.
prove(T):- T = left(X,Y,[X,Y|_]). encodes, "match the first rule's head. There's no body, so if the matching has succeeded, we're done."
prove(T):- T = left(X,Y,[_|R]), prove( left(X,Y,R) ). encodes, "match the second rule's head, and if successful, prove its body under the resulting substitution (which is implicit)".
Prolog's unification, =, performs the pattern matching whilst instantiating any logical variables found inside the terms being matched, according to what's being matched.
Thus we observe,
2 ?- prove( left( a,b,[x,a,b,c])).
true ;
false.
3 ?- prove( left( a,b,[x,a,j,b,c])).
false.
4 ?- prove( left( a,b,[x,a,b,a,b,c])).
true ;
true ;
false.
5 ?- prove( left( a,B,[x,a,b,a,b,c])).
B = b ;
B = b ;
false.
6 ?- prove( left( b,C,[x,a,b,a,b,c])).
C = a ;
C = c ;
false.
The ; is the key that we press to request the next solution from Prolog (while the Prolog pauses, awaiting our command).

Arithmetic expression in prolog solving

given an expression:
(x*0+6)*(x-x+3+y*y) and value of y:2 the Predicate should give only one
solution (x*0+6)*(x-x+3+4).
when 6*(3+x*x) and x:2 is given then it should give the output 42 .
I have been coding for hours and i could manage to get only the second part of it .my code is posted below .can some one help me with solution .
partial_eval(Expr0, Var,Val, Expr) :-
evaluate(Expr0,[Var:Val],Expr).
evaluate(Exp, LstVars, Val) :-
analyse(LstVars, Exp, NewExp),
Val is NewExp.
analyse(LstVars, Term,R) :-
functor(Term, Term, 0), !,
( member(Term : V, LstVars)
-> R = V
; R = Term ).
analyse(LstVars, Term, V) :-
functor(Term, Name, _),
Term =.. [Name | Lst],
maplist(analyse(LstVars), Lst, LstV),
V =.. [Name|LstV].
This problem can be broken down into two: One is substituting in values for variables. The other is recursively evaluating arithmetic subexpressions. Prolog is nondeterministic but both of these operations are deterministic, so that's something to keep in mind while implementing them.
You seem to have a good generic recursion structure (using =..) for the substitution part. For the arithmetic evaluation part you may find it easier to use + and * terms in the recursion. Hope that helps you get started, ask if you get stuck and need more advice.

Prolog program to return atoms in a proposition formula

I am a newbie to prolog and am trying to write a program which returns the atoms in a well formed propositional formula. For instance the query ats(and(q, imp(or(p, q), neg(p))), As). should return [p,q] for As. Below is my code which returns the formula as As. I dont know what to do to split the single F in ats in the F1 and F2 in wff so wff/2 never gets called. Please I need help to proceed from here. Thanks.
CODE
logical_atom( A ) :-
atom( A ),
atom_codes( A, [AH|_] ),
AH >= 97,
AH =< 122.
wff(A):- ground(A),
logical_atom(A).
wff(neg(A)) :- ground(A),wff(A).
wff(or(F1,F2)) :-
wff(F1),
wff(F2).
wff(and(F1,F2)) :-
wff(F1),
wff(F2).
wff(imp(F1,F2)) :-
wff(F1),
wff(F2).
ats(F, As):- wff(F), setof(F, logical_atom(F), As).
First, consider using a cleaner representation: Currently, you cannot distinguish atoms by a common functor. So, wrap them for example in a(Atom).
Second, use a DCG to describe the relation between a well-formed formula and the list of its atoms, like in:
wff_atoms(a(A)) --> [A].
wff_atoms(neg(F)) --> wff_atoms(F).
wff_atoms(or(F1,F2)) --> wff_atoms(F1), wff_atoms(F2).
wff_atoms(and(F1,F2)) --> wff_atoms(F1), wff_atoms(F2).
wff_atoms(imp(F1,F2)) --> wff_atoms(F1), wff_atoms(F2).
Example query and its result:
?- phrase(wff_atoms(and(a(q), imp(or(a(p), a(q)), neg(a(p))))), As).
As = [q, p, q, p].
This should do what you want. It extracts the unique set of atoms found in any arbitrary prolog term.
I'll leave it up to you, though, to determine what constitutes a "well formed propositional formula", as you put it in your problem statement (You might want to take a look at DCG's for parsing and validation).
The bulk of the work is done by this "worker predicate". It simply extracts, one at a time via backtracking, any atoms found in the parse tree and discards anything else:
expression_atom( [T|_] , T ) :- % Case #1: head of list is an ordinary atom
atom(T) , % - verify that the head of the list is an atom.
T \= [] % - and not an empty list
. %
expression_atom( [T|_] , A ) :- % Case #2: head of listl is a compound term
compound(T) , % - verify that the head of the list is a compound term
T =.. [_|Ts] , % - decompose it, discarding the functor and keeping the arguments
expression_atom(Ts,A) % - recurse down on the term's arguments
. %
expression_atom( [_|Ts] , A ) :- % Finally, on backtracking,
expression_atom(Ts,A) % - we simply discard the head and recurse down on the tail
. %
Then, at the top level, we have this simple predicate that accepts any [compound] prolog term and extracts the unique set of atoms found within by the worker predicate via setof/3:
expression_atoms( T , As ) :- % To get the set of unique atoms in an arbitrary term,
compound(T) , % - ensure that's its a compound term,
T =.. [_|Ts] , % - decompose it, discarding the functor and keeping the arguments
setof(A,expression_atom(Ts,A),As) % - invoke the worker predicate via setof/3
. % Easy!
I'd approach this problem using the "univ" operator =../2 and explicit recursion. Note that this solution will not generate and is not "logically correct" in that it will not process a structure with holes generously, so it will produce different results if conditions are reordered. Please see #mat's comments below.
I'm using cuts instead of if statements for personal aesthetics; you would certainly find better performance with a large explicit conditional tree. I'm not sure you'd want a predicate such as this to generate in the first place.
Univ is handy because it lets you treat Prolog terms similarly to how you would treat a complex s-expression in Lisp: it converts terms to lists of atoms. This lets you traverse Prolog terms as lists, which is handy if you aren't sure exactly what you'll be processing. It saves me from having to look for your boolean operators explicitly.
atoms_of_prop(Prop, Atoms) :-
% discard the head of the term ('and', 'imp', etc.)
Prop =.. [_|PropItems],
collect_atoms(PropItems, AtomsUnsorted),
% sorting makes the list unique in Prolog
sort(AtomsUnsorted, Atoms).
The helper predicate collect_atoms/2 processes lists of terms (univ only dismantles the outermost layer) and is mutually recursive with atoms_of_prop/2 when it finds terms. If it finds atoms, it just adds them to the result.
% base case
collect_atoms([], []).
% handle atoms
collect_atoms([A|Ps], [A|Rest]) :-
% you could replace the next test with logical_atom/1
atom(A), !,
collect_atoms(Ps, Rest).
% handle terms
collect_atoms([P|Ps], Rest) :-
compound(P), !, % compound/1 tests for terms
atoms_of_prop(P, PAtoms),
collect_atoms(Ps, PsAtoms),
append(PAtoms, PsAtoms, Rest).
% ignore everything else
collect_atoms([_|Ps], Rest) :- atoms_of_prop(Ps, Rest).
This works for your example as-is:
?- atoms_of_prop(ats(and(q, imp(or(p, q), neg(p))), As), Atoms).
Atoms = [p, q].

studying for prolog/haskell programming exam

I starting to study for my upcoming exam and I'm stuck on a trivial prolog practice question which is not a good sign lol.
It should be really easy, but for some reason I cant figure it out right now.
The task is to simply count the number of odd numbers in a list of Int in prolog.
I did it easily in haskell, but my prolog is terrible. Could someone show me an easy way to do this, and briefly explain what you did?
So far I have:
odd(X):- 1 is X mod 2.
countOdds([],0).
countOdds(X|Xs],Y):-
?????
Your definition of odd/1 is fine.
The fact for the empty list is also fine.
IN the recursive clause you need to distinguish between odd numbers and even numbers. If the number is odd, the counter should be increased:
countOdds([X|Xs],Y1) :- odd(X), countOdds(Xs,Y), Y1 is Y+1.
If the number is not odd (=even) the counter should not be increased.
countOdds([X|Xs],Y) :- \+ odd(X), countOdds(Xs,Y).
where \+ denotes negation as failure.
Alternatively, you can use ! in the first recursive clause and drop the condition in the second one:
countOdds([X|Xs],Y1) :- odd(X), !, countOdds(Xs,Y), Y1 is Y+1.
countOdds([X|Xs],Y) :- countOdds(Xs,Y).
In Prolog you use recursion to inspect elements of recursive data structs, as lists are.
Pattern matching allows selecting the right rule to apply.
The trivial way to do your task:
You have a list = [X|Xs], for each each element X, if is odd(X) return countOdds(Xs)+1 else return countOdds(Xs).
countOdds([], 0).
countOdds([X|Xs], C) :-
odd(X),
!, % this cut is required, as rightly evidenced by Alexander Serebrenik
countOdds(Xs, Cs),
C is Cs + 1.
countOdds([_|Xs], Cs) :-
countOdds(Xs, Cs).
Note the if, is handled with a different rule with same pattern: when Prolog find a non odd element, it backtracks to the last rule.
ISO Prolog has syntax sugar for If Then Else, with that you can write
countOdds([], 0).
countOdds([X|Xs], C) :-
countOdds(Xs, Cs),
( odd(X)
-> C is Cs + 1
; C is Cs
).
In the first version, the recursive call follows the test odd(X), to avoid an useless visit of list'tail that should be repeated on backtracking.
edit Without the cut, we get multiple execution path, and so possibly incorrect results under 'all solution' predicates (findall, setof, etc...)
This last version put in evidence that the procedure isn't tail recursive. To get a tail recursive procedure add an accumulator:
countOdds(L, C) :- countOdds(L, 0, C).
countOdds([], A, A).
countOdds([X|Xs], A, Cs) :-
( odd(X)
-> A1 is A + 1
; A1 is A
),
countOdds(Xs, A1, Cs).

How do you translate DCGs into normal definite clauses in PROLOG?

How would you translate the following DCGs into normal definite clauses of PROLOG?
expr_regular --> cor_ini,numero,guion,numero,cor_fin.
cor_ini --> ['['].
numero --> ['0'];['1'];['2'];['3'];['4'];['5'];['6'];['7'];['8'];['9'].
cor_fin --> [']'].
guion --> ['-'].
EDIT: I want to translate the DCG into normal PROLOG clauses cause I can't use both DCGs and normal clauses in the same code(in my case). I have this two pieces of code:
Piece1:
traducir(Xs, Ys) :- maplist(traduccion, Xs, Ys).
traduccion('^',comeza_por).
traduccion('[',inicio_rango).
traduccion('0',cero).
traduccion('-',a).
traduccion('9',nove).
traduccion(']',fin_rango).
An example of how to use it would be:
?- traducir(['[','0','-','9',']'],[]).
true .
And Piece2:
traducir--> cor_ini,numero,guion,numero,cor_fin.
cor_ini --> ['['].
numero --> ['0'];['1'];['2'];['3'];['4'];['5'];['6'];['7'];['8'];['9'].
cor_fin --> [']'].
guion --> ['-'].
An example of how to use it would be:
traducir(['^','[','0','-','9',']'],X).
X = [comeza_por, inicio_rango, cero, a, nove, fin_rango].
I want to join both codes into one to test if traducir is well written (if it follows the DCG) and to translate what you enter into text ,so the final program should able to do the following:
?- traducir(['^','[','0','-','9',']'],X).
X = [comeza_por, inicio_rango, cero, a, nove, fin_rango].
?- traducir(['[','0','-','9',']'],[]).
true .
In SWI-Prolog you can use listing/1 directly on the prolog-toplevel:
?- forall(member(NT,[expr_regular//0,cor_ini//0,numero//0,cor_fin//0,guion//0]),
listing(NT)).
expr_regular(A, F) :-
cor_ini(A, B),
numero(B, C),
guion(C, D),
numero(D, E),
cor_fin(E, F).
cor_ini(['['|A], A).
numero(A, B) :-
( A=['0'|B]
; A=['1'|B]
; A=['2'|B]
; A=['3'|B]
; A=['4'|B]
; A=['5'|B]
; A=['6'|B]
; A=['7'|B]
; A=['8'|B]
; A=['9'|B]
).
cor_fin([']'|A], A).
guion([-|A], A).
true.
That's it! You may profit from looking at the answers of the related question "Is there a way or an algorithm to convert DCG into normal definite clauses in Prolog?".
Your grammar it's exceptionally simple: just terminals. So we can translate to a very specific pattern (beware: no generalization allowed).
expr_regular(S, G) :-
S = [0'[, N1, 0'-, N2, 0']|G], numero(N1), numero(N2).
numero(N) :-
memberchk(N, "0123456789").
The only think worth to note it's ISO standard character notation...
Well I don't really get your question. Anyway, if you don't want to use the nice DCGs syntax for some reason you can still go with things like wildcard_match/2, or reinvent the wheel and use difference lists yourself to re-implement DCGs, or append. For the wildcard_match/2 part:
expr_regular(R) :- wildcard_match('[[][0-9]-[0-9]]', R).

Resources