Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Some problems asserting a new rule in SWI-Prolog

Tags:

prolog

I am studying on Ivan Bratko book: "Programming for Artificial Intelligence" for an universitary exame and using SWI Prolog and I have some doubts about an example show on this book regarding the assert and retract predicates.

It simply present the following code that declare some facts as dynamic:

:-dynamic fast(ann).
:-dynamic slow(tom).
:-dynamic slow(pat).

Then in the Prolog shell use the assert rule to define a new rule into the database:

[debug] 59 ?- assert((faster(X,Y) :- fast(X), slow(Y))).
true.

Ok, so the new rule seems to be added to my database.

Now I try to perform this query and it fail:

[debug] 64 ?- faster(X,Y).
false.

On the book say that the output should be this one:

A = ann
B = tom

and it sound good and rational because I have consult the previous program where say that specify who is fast and who is slow and later I have add the faster rule asserting it...

Why don't work? maybe it depends by the Prolog implementation (SWI-Prolog)?

like image 247
AndreaNobili Avatar asked Oct 15 '25 03:10

AndreaNobili


1 Answers

The dynamic directive in Prolog is useful in compiled programs (and normally used within a source file to be compiled). If you use assert or an equivalent mechanism to create facts (or rules) in the interactive shell, then SWI-Prolog will already assume those predicates are dynamic.

However the dynamic directive is beneficial in a case where you want to refer to a predicate through a clause in a rule before defining any facts for that predicate. That is, suppose we first do this:

?- assert((faster(X,Y) :- fast(X), slow(Y))).
true.

and then try a query:

?- faster(X,Y).

You might expect this to simply fail, because no facts exist (yet) for fast/1 or slow/1. But actually SWI-Prolog will (by design) throw an error exception:

ERROR: faster/2: Undefined procedure: fast/1

To prevent this we should add the dynamic directives in user entry mode:

?- [user].
|: :-dynamic fast/1, slow/1.
|: (type Ctrl-z to exit user entry mode)
% user://1 compiled 0.00 sec, 1 clauses

Now we will get the expected fail behavior (assuming the previously asserted rule):

?- faster(X,Y).
false.

and you can use the same mode to create your facts:

?- [user].
|: fast(ann).
|: slow(tom).
|: slow(pat).
|: (type Ctrl-z to exit user entry mode)
% user://2 compiled 0.00 sec, 4 clauses
true.

Now the faster query succeeds in two different ways:

?- faster(X,Y).
X = ann,
Y = tom ;
X = ann,
Y = pat.
like image 170
hardmath Avatar answered Oct 17 '25 13:10

hardmath



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!