Prolog: How to check if a predicate exists? - prolog

How can I check if a predicate exists in a Prolog program? That would be an exists/1, like:
?- exists(some_predicate).
false.
?- assert(some_predicate).
true.
?- exists(some_predicate).
true.

You can use current_predicate/1, current_predicate/2 or predicate_property/2 (for the last you will probably need functor/3):
?- current_predicate(a/1).
false.
?- functor(A,a,1),predicate_property(A,visible).
false.
?- functor(A,a,1),current_predicate(_,A).
false.
?- assert(a(42)).
true.
?- current_predicate(a/1).
true.
?- functor(A,a,1),predicate_property(A,visible).
A = a(_G136).
?- functor(A,a,1),current_predicate(_,A).
A = a(_G122).
current_predicate/2 and predicate_property/2 (with visible) succeeds if the predicate can be autoloaded while currrent_predicate/1 fails

the 'old fashioned way', but accepted in ISO, is clause/2. You could encounter it while reusing/browsing some of the older examples.
example:
?- [user].
|: app([], Y, Y).
|: app([X|Xs], Y, [X|Zs]) :- app(Xs, Y, Zs).
|: % user://1 compiled 0,15 sec, 17 clauses
true.
?- clause(app(X,Y,Z),Body).
X = [],
Y = Z,
Body = true ;
X = [_G338|_G339],
Z = [_G338|_G342],
Body = app(_G339, Y, _G342).

Related

Constraint Handling Rules in SWI Prolog: The `neq` constraint doesn't work

I am learning Constraint Handling Rules (CHR) in swi-prolog.
I started with the tutorial from Tom Schrijvers' Constraint Handling Rules A Tutorial for (Prolog) Programmers.
In p.286, the author gave an example to implement Inequality constraint.
:- use_module(library(chr)).
:- chr_constraint neq/2.
neq(X,X) <=> fail.
neq(X,Y) <=> X \= Y | true.
But it does not work as expected in swi-prolog.
For example, in swi-prolog
?- neq(A,B).
true.
?- neq(A,B), A = B.
A = $VAR(B).
but it should be
?- neq(A,B).
neq(A,B).
?- neq(A,B), A = B.
false.
How can I get the same result as in the slide?
My swi-prolog version (threaded, 64 bits, version 8.2.4) on windows.
Thanks.
You may use ?=/2 for your second clause:
:- use_module(library(chr)).
:- chr_constraint neq/2.
neq(X,X) <=> fail.
neq(X,Y) <=> ?=(X,Y) | true.
Sample runs:
?- neq(a,a).
false.
?- neq(a,b).
true.
?- neq(A,B).
neq(A, B).
?- neq(A,B), A = f(C), B = f(D).
A = f(C),
B = f(D),
neq(f(C), f(D)).
?- neq(A,B), A = [1,X], B=[].
A = [1, X],
B = [].
Here is a temporary workaround for neq:
:- use_module(library(chr)).
:- chr_constraint neq/2.
neq(X,X) <=> fail.
neq(X,Y) <=> ground(X), ground(Y) | true.
It can pass all the tests in the slide:
?- neq(a,a).
false.
?- neq(a,b).
true.
?- neq(A,B).
neq($VAR(A),$VAR(B)).
?- neq(A,B), A = B.
false.
?- neq(A,B), A = a, B = a.
false.
?- neq(A,B), A = a, B = b.
A = a,
B = b.
?- neq(A,B), A = f(C), B = f(D).
A = f($VAR(C)),
B = f($VAR(D)),
neq(f($VAR(C)),f($VAR(D))).
%% And some other tests which not in the slide.
?- neq([1,2,3], [1,2,X]).
neq([1,2,3],[1,2,$VAR(X)]).
?- neq([1,2,3], [1,2,X]), X=3.
false.
?- neq([1,2,3], [1,2,X]), X=4.
X = 4.
?- neq([1,2,3], X).
neq([1,2,3],$VAR(X)).
?- neq([1,2,3], X), X=[1,2,3].
false.
?- neq([1,2,3], X), X=[1,2,Y].
X = [1,2,$VAR(Y)],
neq([1,2,3],[1,2,$VAR(Y)]).
It seems that the current CHR implementation inhibits binding variables that appear at the head in guards (see Check guard bindings yourself), even if these bindings could roll back via \+. Note that X \= Y equivalents to \+ X = Y. Also, the unification predicate = in guards seems only comparing with variables' identifier instead of unifying them.
The drawback of this workaround is that, for example,
?- neq(A,B), A = [1,X], B=[].
A = [1,$VAR(X)],
B = [],
neq([1,$VAR(X)],[]).
Since A is not ground, the second rule doesn't fire, but we know that A and B cannot be equal, i.e. neq([1,$VAR(X)],[]) should have been removed.
Anyway, it's just a temporary workaround. If someone has a better solution or explanation, I could delete this answer.

Prolog : Evaluating logical expression w/o backtracking with AND/OR op/2?

I'm trying to implement logical expressions evaluation w/o backtracking behavior.
After some experimentation I got it working, here goes :
:- op(80, xfy, and).
:- op(80, xfy, or).
%check/evaluate logical expressions
check(true) :- !.
check(Cond and Conds) :- !, (check(Cond) , check(Conds)).
check(Cond or Conds) :- !, (check(Cond) ; check(Conds)), !. %% <- weird
check(Cond) :- !, call(Cond).
?- check(true and true).
true.
?- check(true and false).
false.
?- check(true or false).
true.
?- check(true or (false and true)).
true.
?- check((true or false) and (false and true)).
false.
?- X = 1 , Y = 2 , check((X = 1) and (Y > 1)).
X = 1,
Y = 2.
So the code works.
My question is why it works, especially the need of two cuts! in the OR expression.
Does this look like a proper Prolog implementation ?
How would you have done it yourself ?

Prolog Successor Arithmetic

I have a knowledge base with the following:
numeral(0).
numeral(s(X)) :- numeral(X).
numeral(X+Y) :- numeral(X), numeral(Y).
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
add2(W+X,Y+Z,R) :- add(W,X,A),add(Y,Z,T),add2(A,T,R).
add2(X+Y,Z,R) :- add(X,Y,A),add2(A,Z,R).
add2(X,Y+Z,R) :- add(Y,Z,A),add2(X,A,R).
add2(X,Y,R) :- add(X,Y,R).
which evaluates correctly queries such as:
?- add2(s(0)+s(s(0)), s(s(0)), Z).
Z = s(s(s(s(s(0)))))
?- add2(0, s(0)+s(s(0)), Z).
Z = s(s(s(0)))
?- add2(s(s(0)), s(0)+s(s(0)), Z).
Z = s(s(s(s(s(0)))))
However the following query is evaluated to:
?- add2(s(0)+s(0), s(0+s(s(0))), Z).
Z = s(s(s(0+s(s(0))))) .
But the required output is:
?- add2(s(0)+s(0), s(0+s(s(0))), Z).
Z = s(s(s(s(s(0)))))
I know the issue is with the line:
add2(W+X,Y+Z,R) :- add(W,X,A),add(Y,Z,T),add2(A,T,R).
But i just can't figure it out. Any help would be appreciated!
I think you make the problem more complex by handling the cases with an add2/3 predicate. You first need to resolve the structure of the first two arguments to something of the shape s(s(...s(0)...)).
In order to do this, we can make an resolve/2 function that looks for (+)/2 terms and recursively works with add/3:
resolve(0,0).
resolve(s(X),s(Y)) :-
resolve(X,Y).
resolve(X+Y,Z) :-
resolve(X,RX),
resolve(Y,RY),
add(RX,RY,Z).
So now for a grammar:
E -> 0
E -> s(E)
E -> E + E
resolve/2 will convert this to a grammar with:
E -> 0
E -> s(E)
For example:
?- resolve(s(0)+s(0),X).
X = s(s(0)).
?- resolve(s(0+s(s(0))),X).
X = s(s(s(0))).
And now our add2/3 predicate will first resolve/2 the operands, and then add these together:
add2(A,B,C) :-
resolve(A,RA),
resolve(B,RB),
add(RA,RB,C).
The sample queries you then write resolve to:
?- add2(s(0)+s(s(0)), s(s(0)), Z).
Z = s(s(s(s(s(0))))).
?- add2(0, s(0)+s(s(0)), Z).
Z = s(s(s(0))).
?- add2(s(s(0)), s(0)+s(s(0)), Z).
Z = s(s(s(s(s(0))))).
?- add2(s(0)+s(0), s(0+s(s(0))), Z).
Z = s(s(s(s(s(0))))).

How to export dynamically created predicate?

Consider the following code:
:- module(my_export, [create/2]).
create(Predicate, Id) :-
assertz(Predicate),
export(Id).
Assuming that the predicated and the identifier match, I'd expect the newly asserted predicate to be available outside the module. However, I get this output:
?- create(c(A,B) :- A > B, c/2).
true.
?- c(1,2).
Correct to: "my_export:c(1,2)"?
How come the predicate isn't exported? What is the correct way to do this?
You have to import module by using use_module/1.
For example, if this is sample_module.pl:
:- module(my_export, [create/2]).
create(Predicate, Id) :-
assertz(Predicate),
export(Id).
Then this input and output is true (observe closely what's going on):
?- create(tmp(A,B) :- A > B, tmp/2).
ERROR: toplevel: Undefined procedure: create/2 (DWIM could not correct goal)
?- consult('c:\\Prolog\\pl\\bin\\sample_module.pl').
% c:\Prolog\pl\bin\sample_module.pl compiled into my_export 0.00 sec, 2 clauses
true.
?- create(tmp(A,B) :- A > B, tmp/2).
true.
?- tmp(1,2).
Correct to: "my_export:tmp(1,2)"? yes
false.
?- use_module('c:\\Prolog\\pl\\bin\\sample_module.pl').
true.
?- tmp(1,2).
false.
?- tmp(5,4).
true.
Now, when you "compile buffer" in SWI-Prolog what really happens is consult/1. You need to import your module manually.
Your code work as-is, as long as the module is initially imported, as Grzegorz explained. For example:
?- [user].
:- module(my_export, [create/2]).
|:
|: create(Predicate, Id) :-
|: assertz(Predicate),
|: export(Id).
|: % user://1 compiled into my_export 0.00 sec, 2 clauses
true.
?- module_property(my_export, P).
P = class(user) ;
P = file('user://1') ;
P = line_count(10) ;
P = exports([create/2]) ;
false.
?- my_export:create(c(A,B) :- A > B, c/2).
true.
?- module_property(my_export, P).
P = class(user) ;
P = file('user://1') ;
P = line_count(10) ;
P = exports([c/2, create/2]) ;
false.
?- create(tmp(A,B) :- A > B, tmp/2).
true.
?- module_property(my_export, P).
P = class(user) ;
P = file('user://1') ;
P = line_count(10) ;
P = exports([tmp/2, c/2, create/2]) ;
false.
Note, however, that export/1 is usually a directive, not a predicate. There might be portability issues to other Prolog dialects supporting a module system.

SWI Prolog Database

is there a way I can query a SWI Prolog database to check if it doesn't contain an element?
I have tried using "not" but doesn't seem to work with this version of Prolog.
maybe you're looking for clause/2. A dummy session sample
1 ?- [user].
|: a(1).
|: a(2).
|: a(X) :- b(X).
|: b(3).
|: b(4).
% user://1 compiled 0.03 sec, 6 clauses
true.
2 ?- clause(a(X),Body).
X = 1,
Body = true ;
X = 2,
Body = true ;
Body = b(X).
3 ?- clause(b(X),Body).
X = 3,
Body = true ;
X = 4,
Body = true.
4 ?- clause(c(X),Body).
false.
you can see that c/1 is not defined...
Anyway, SWi-Prolog database is a complex beast, and it offers much more control about its contents.

Resources