accessing program listing in prolog - prolog

I'm having some strange (or not so strange) problems defining variables in SWI-Prolog. Example:
I'd like to do something like below:
:- initialization(main).
main :-
X = listing(main),
write(X).
but it's simply printing "listing(main)"

maybe, using another casual predicate instead of main/0...
?- with_output_to(atom(X), listing(pattern)), write(X).
gram:pattern(A, B, C) :-
dig(A, B, C).
gram:pattern(A+C, B, E) :-
ten(A, B, D),
dig(C, D, E).
...

What you are doing with X = listing(...) is creating a term, which later you are printing with write.
It seems you want to access the code of main. The thing you are looking for is clause/2:
clause(:Head, ?Body)
True if Head can be unified with a clause head and Body with the corresponding clause body. Gives alternative clauses on backtracking. For facts, Body is unified with the atom true.
Example:
main :- clause(main, X), write(X).
?- main.
clause(main,_G2381),write(_G2381)
true.

Related

Is there a non-unifying alternative to member/2 in SWI-Prolog?

In prolog, the difference between A = B and A == B is that = tries to unify A with B, while == will only succeed if A and B are already unified.
member/2 does seem to perform unification.
Example session:
?- A = B.
A = B.
?- A == B.
false.
?- member(A, [B]).
A = B.
I have been looking but I can't find a non-unifying alternative to member/2, but not found anything. Is there something built in or do I have to invent my own thing? As I'm rather new to Prolog I don't trust myself with writing a performant version of this.
EDIT:
I came up with the following, though I don't know if the cut is correct. Without it, it seems to deliver two answers for that branch of the code (true, followed by false) though. I'd also still like to know if there is a standard library function for this.
member_eq(_, []) :-
false.
member_eq(X, [H|_]) :-
X == H,
!.
member_eq(X, [_|T]) :-
member_eq(X, T).
You may slightly modify builtin predicate member/2 to use ==/2 instead of unification:
member_not_bind(X, [H|T]) :-
member_not_bind_(T, X, H).
member_not_bind_(_, X, Y):- X==Y.
member_not_bind_([H|T], X, _) :-
member_not_bind_(T, X, H).
Sample run:
?- L=[a,b,c(E)], member_not_bind(A, L).
false.
?- A=c(E),L=[a,b,c(E)], member_not_bind(A, L).
A = c(E),
L = [a, b, c(E)].
I leave this here as it solves a related question (checking if X may unify with any item in L without actually performing the bindings)
You can use double negation like this:
member_not_bind(X, L):- \+(\+(member(X, L))).
Sample runs:
?- A=c(e),L=[a,b,c(E)], member_not_bind(A, L).
A = c(e),
L = [a, b, c(E)].
?- A=d(E),L=[a,b,c(E)], member_not_bind(A, L).
false.

Prolog reasoning about predicates

Assume someone wrote the following huge list of clauses:
loves(me, wife).
loves(me, dog).
loves(wife, dog).
hates(me, enemy).
attracts(iron, magnet).
...
Now I want to automatically generate reciprocal clauses given some higher-order predicate and rule similar to:
reciprocal([loves, hates, attracts, ...]).
some_conclusion :- some_premises.
so that I have the following expected result:
?- loves(wife, me).
true.
To keep things simple, I ignored the list argument and instead defined the simple clause reciprocal(loves). with some complex rule using reciprocal(X), but I can't seem to assert a rule with success.
I've tried different variations and orderings of
assert(
Y :- (reciprocal(P), Y =.. [P, B, A], X =.. [P, A, B], call(X))
).
or (to add the deduced clauses themselves)
assert(Y), reciprocal(P), Y =.. [P, B, A], X =.. [P, A, B], call(X)
but I've only got false or errors like Arguments are not sufficiently instantiated using SWI-Prolog.
My question is (obviously): how can I make this rule work? I don't care whether the rule is part of the database or just a preprocessor to add the actual clauses to the database (although the former would be preferable), I just want to learn how to reason about predicates (i.e. how to use higher-order predicates).
Note: I've learned logic programming since a month only, and I want to try out some ideas from Notation3 and N-triples etc.
EDIT:
The missing part, the absolute cherry on the cake, is some dynamic solution using a rule similar to
Y :- (reciprocal(P), call(P, A, B), Y =.. [P, B, A]).
If anyone has some solution for this one, please post it!
I found the way to add clauses one by one to the database as such (MVP):
?- [user].
|: loves(me, wife).
|: loves(me, dog).
|: loves(wife, dog).
|: reciprocal(loves).
|: (Ctrl-Z)
?- dynamic loves/2 %! seems necessary for next clause...
true.
?- reciprocal(P), X =.. [P, A, B], Y =.. [P, B, A], assert(X :- (Y, !)).
P = loves,
X = loves(A, B),
Y = loves(B, A).
?- loves(wife, me).
true.
It seems I didn't arrange the 'rule' in this way which is procedurally sound.
Now I'll focus on findall to avoid requiring user input (the ; after each solution for P).
EDIT:
I completed all but one feature... Given a file db.pl containing
loves(me, wife).
loves(me, dog).
loves(wife, dog).
attracts(iron, magnets).
and a file rules.pl containing
reciprocal([
loves,
attracts
]).
parse_reciprocal([]).
parse_reciprocal([H|T]) :-
X =.. [H, A, B], Y =.. [H, B, A], dynamic(H/2), assert(X :- (Y, !)),
parse_reciprocal(T).
:- initialization reciprocal(L), parse_reciprocal(L).
I succeed at my first goal
?- [db].
true.
?- [rules].
true.
?- loves(dog, wife).
true.
?- attracts(magnets, iron).
true.
The missing part, the absolute cherry on the cake, is some dynamic solution using a rule similar to
Y :- (reciprocal(P), call(P, A, B), Y =.. [P, B, A]).

First steps to a CAS

I tried to run this code:
eq(mul(a,b),mul(c,b)).
eq(X,Y) :- eq(mul(X,Z),mul(Y,Z))
with the query: eq (X, Y)
I expected the results:
X=mul(a,b),Y=(mul(c,b)) and X=a,Y=c
But I just got the first one.
I think you want:
eq(mul(a, b), mul(c, b)).
equal(X,Y) :-
eq(mul(X, Z), mul(Y, Z)).
Note that I have used different predicate names, to prevent a common mistake of infinite recursion/looping if a predicate (e.g. "eq") is calling itself.
Result in swi-prolog:
?- equal(X, Y).
X = a,
Y = c.
This rule would be wrong:
eq(X,Y) :- eq(mul(X,Z),mul(Y,Z)).
because X cannot be simultaneously mul(something) and part of the same something inside the mul(). Also, it falls into the trap of infinite recursion/looping.

PROLOG - clause returns true for constants, but won't find solution for variable?

After many years of abstinence of the PROLOG programming language, I'm trying to get into it again.
And promptly there, something confused me.
(I am using SWI prolog 6.4.1. on windows)
Consider the following defined:
father(jack, clara).
father(jack, sophie).
mother(angela,clara).
mother(angela,sophie).
parent(A, B) :- father(A, B).
parent(A, B) :- mother(A, B).
sibling( A, B ) :-
A \= B,
parent(P, A),
parent(P, B).
Now, if I "ask" the interpreter:
sibling(clara, sophie).
true is the answer.
But if I try to get the siblings of e.g. clara:
sibling(clara, X).
The answer is just false.
Just as
findall( X, sibling(clara, X ), L ).
returns an empty list.
Why?
To prove sibling(clara, X), you first need to prove clara \= x. But that doesn't work because it reduces to \+ clara = X, were \+ is the infamous negation as failure: Prolog tries to prove clara = X, which succeeds, and concludes that clara \= X must therefore be false.
You should either reorder your program to do the \= check last instead of first, or use dif(clara, X).

Prolog difference routine

I need some help with a routine that I am trying to create. I need to make a routine that will look something like this:
difference([(a,b),(a,c),(b,c),(d,e)],[(a,_)],X).
X = [(b,c),(d,e)].
I really need help on this one..
I have written a method so far that can remove the first occurrence that it finds.. however I need it to remove all occurrences. Here is what I have so far...
memberOf(A, [A|_]).
memberOf(A, [_|B]) :-
memberOf(A, B).
mapdiff([], _, []) :- !.
mapdiff([A|C], B, D) :-
memberOf(A, B), !,
mapdiff(C, B, D).
mapdiff([A|B], C, [A|D]) :-
mapdiff(B, C, D).
I have taken this code from listing(subtract).
I don't fully understand what it does, however I know it's almost what I want. I didn't use subtract because my final code has to be compatible with WIN-Prolog... I am testing it on SWI Prolog.
Tricky one! humble coffee has the right idea. Here's a fancy solution using double negation:
difference([], _, []).
difference([E|Es], DL, Res) :-
\+ \+ member(E, DL), !,
difference(Es, DL, Res).
difference([E|Es], DL, [E|Res]) :-
difference(Es, DL, Res).
Works on SWI-PROLOG. Explanation:
Clause 1: Base case. Nothing to diff against!
Clause 2: If E is in the difference list DL, the member/2 subgoal evaluates to true, but we don't want to accept the bindings that member/2 makes between variables present in terms in either list, as we'd like, for example, the variable in the term (a,_) to be reusable across other terms, and not bound to the first solution. So, the 1st \+ removes the variable bindings created by a successful evaluation of member/2, and the second \+ reverses the evaluation state to true, as required. The cut occurs after the check, excluding the 3rd clause, and throwing away the unifiable element.
Clause 3: Keep any element not unifiable across both lists.
I am not sure, but something like this could work. You can use findall to find all elements which can't be unified with the pattern:
?- findall(X, (member(X, [(a,b),(b,c),(a,c)]), X \= (a,_)), Res).
gets the reply
Res = [ (b, c) ]
So
removeAll(Pattern, List, Result) :-
findall(ZZ109, (member(ZZ109, List), ZZ109 \= Pattern), Result).
should work, assuming ZZ109 isn't a variable in Pattern (I don't know a way to get a fresh variable for this, unfortunately. There may be a non-portable one in WIN-Prolog). And then difference can be defined recursively:
difference(List, [], List).
difference(List, [Pattern|Patterns], Result) :-
removeAll(Pattern, List, Result1),
difference(Result1, Patterns, Result).
Your code can be easily modified to work by making it so that the memberOF predicate just checks to see that there is an element in the list that can be unified without actually unifying it. In SWI Prolog this can be done this way:
memberOf(A, [B|_]) :- unifiable(A,B,_).
But I'm not familiar with WIN-PRolog so don't know whether it has a predicate or operator which only tests whether arguments can be unified.

Resources