Different results in swi-prolog and yap - prolog

The sample program enumerates and counts the number of 8-queen solutions. (sorry if the code is hard to read; this is machine-generated from an S-expression. The original code is https://www.cpp.edu/~jrfisher/www/prolog_tutorial/2_11.html)
rules:
[user].
(perm([X|Y],Z) :- (perm(Y,W),takeout(X,Z,W))).
perm([],[]).
takeout(X,[X|R],R).
(takeout(X,[F|R],[F|S]) :- (takeout(X,R,S))).
(solve(P) :- (perm([1,2,3,4,5,6,7,8],P),combine([1,2,3,4,5,6,7,8],P,S,D),alldiff(S),alldiff(D))).
(combine([X1|X],[Y1|Y],[S1|S],[D1|D]) :- (is(S1,+(X1,Y1)),is(D1,-(X1,Y1)),combine(X,Y,S,D))).
combine([],[],[],[]).
(alldiff([X|Y]) :- (\+ member(X,Y),alldiff(Y))).
alldiff([X]).
end_of_file.
query:
(setof(P,solve(P),Set),length(Set,L),write(L),write('\n'),fail).
swipl returns 92; while yap returns 40320.
Also, when I query solve(P), swipl only returns two solutions (which also contradicts 92); yap returns much more (possibly 40320 of them). So why the difference? Is there such a serious compatibility issue?
Versions:
YAP 6.2.2 (x86_64-linux): Sat Sep 17 13:59:03 UTC 2016
SWI-Prolog version 7.2.3 for amd64

In older versions of YAP, a query for an undefined predicate simply failed. In the case above, it is member/2 which is not defined in YAP. And for this reason your test alldif/1 always succeeds - thus the large number you get.
The behavior for this is governed by the Prolog flag unknown whose default value should be error. In YAP 6.2 the default was (incorrectly) fail. This was corrected in 6.3. Say
:- set_prolog_flag(unknown, error).
to get a clean error for undefined predicates. Then, you would need to define member/2.

Related

How to use assert and retract in SWI-Prolog

In SWI-Prolog, if I use assert and retract at the prompt, I get
?- assert(at(1)).
true.
?- retract(at(1)).
true.
However, if I put these statements into a program file called "test" as
assert(at(1)).
retract(at(1)).
and run SWI-Prolog as
> swipl
?- [test].
I get
ERROR: /....../test:2:
No permission to modify static procedure `retract/1'
true.
What does this mean and how should I deal with it?
Put statements within a predicate, e.g.:
:- dynamic at/1.
test_assert :-
assert(at(1)).
test_retract :-
retract(at(1)).
Load the program, and then run:
?- test_assert.
true.
?- at(X).
X = 1.
?- test_retract.
true.
?- at(X).
false.
The prompt and source code files are different environments with slightly different behaviours. It's like the difference between calling Python len(x) in the repl and writing function len(x): in Python source code - you would be overriding the builtin len() with your own one. Python lets you do that, SWI Prolog also does but not easily.
When you type them at the prompt, you call the existing predicate assert/1 and actually do insert the fact at(1). into the database. When you type retract/1 you actually do retract the fact at(1) from the database.
In a fresh prompt, try ?- listing(at). and get an error, then ?- assert(at(1)). then do the listing again and see the fact, then retract it and try the listing and see only the remains of the dynamic declaration and the fact is gone.
When you put them in a source code file, you would be trying to override the existing builtin predicates with your new ones. Your new ones say "assert/1 is a predicate which succeeds when its arugment unifies with at(1)" and "retract/1 is a predicate which succeeds when its arugment unifies with at(1)".
That is, they don't do any asserting or retracting or database changes.
In your test file, put this:
:- redefine_system_predicate(assert(_)).
:- redefine_system_predicate(retract(_)).
assert(at(1)) :- true.
retract(at(1)) :- true.
Then save and consult it:
?- [testing].
true.
?- listing(at). % <-- your code ran, but did not insert `at(1)`.
ERROR: procedure `at' does not exist (DWIM could not correct goal)
^ Exception: (13) setup_call_catcher_cleanup(system:true, prolog_listing:listing_(user:at, []), _19450, prolog_listing:close_sources) ? abort
% Execution Aborted
?- assert(P). % <-- it's now behaving
P = at(1). % <-- like any other predicate.

Prolog what's the difference between \+ and \=

What is the difference \= and \+?
because
?- 15\=14.
?- \+ 15=14.<--- this gives an error while the above does not.
Why?Aren't they the same?
Edit: here's the error:
Compiling the file:
D:\Program Files\Strawberry Prolog Beta\Games\WarCraft.pro
Warning 4: The string \+ is not an operator. (line 1, before the first clause)
Error 16: Instead of the integer 15 what is expected here is something like an infix operator or a full stop. (line 1, before the first clause)
1 error, 1 warning.
Also I'm using Strawberry prolog I also tried it on SWI prolog still the same.
I think you are putting queries into Prolog source files. That is not where they should go:
predicate definitions go into Prolog source files
queries are typed into the interactive Prolog toplevel
Try running the SWI-Prolog program without an input file. You should get a window with some informational messages about the SWI-Prolog version and then a prompt ?-. That is the toplevel. Try typing your query there. All queries should go there.
I don't know about Strawberry Prolog, but I suspect it's the same there.

How to run prolog queries from within the prolog file in swi-prolog?

If I have a prolog file defining the rules, and open it in a prolog terminal in windows, it loads the facts. However, then it shows the ?- prompt for me to manually type something. How can I add code to the file, so that it will actually evaluate those specific statements as if I typed them in?
something like this
dog.pl
dog(john).
dog(ben).
% execute this and output this right away when I open it in the console
dog(X).
Does anyone know how to do this?
Thanks
There is an ISO directive on this purpose (and more): initialization
If you have a file, say dog.pl in a folder, with this content
dog(john).
dog(ben).
:- initialization forall(dog(X), writeln(X)).
when you consult the file you get
?- [dog].
john
ben
true.
Note that just asserting dog(X). doesn't call dog(X) as a query, but rather attempts to assert is as a fact or rule, which it will do and warn about a singleton variable.
Here's a way to cause the execution the way you're describing (this works for SWI Prolog, but not GNU Prolog):
foo.pl contents:
dog(john).
dog(ben).
% execute this and output this right away when I open it in the console
% This will write each successful query for dog(X)
:- forall(dog(X), (write(X), nl)).
What this does is write out the result of the dog(X) query, and then force a backtrack, via the false call, back to dog(X) which will find the next solution. This continues until there are no more dog(X) solutions which ultimately fails. The ; true ensures that true is called when dog(X) finally fails so that the entire expression succeeds after writing out all of the successful queries to dog(X).
?- [foo].
john
ben
true.
You could also encapsulate it in a predicate:
start_up :-
forall(dog(X), (write(X), nl)).
% execute this and output this right away when I open it in the console
:- start_up.
If you want to run the query and then exit, you can remove the :- start_up. from the file and run it from the command line:
$ swipl -l foo.pl -t start_up
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.2.3)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.
For help, use ?- help(Topic). or ?- apropos(Word).
john
ben
% halt
$
dog.pl:
dog(john).
dog(ben).
run :- dog(X), write(X).
% OR:
% :- dog(X), write(X).
% To print only the first option automatically after consulting.
Then:
$ swipl
1 ?- [dog].
% dog compiled 0.00 sec, 4 clauses
true.
2 ?- run.
john
true ; # ';' is pressed by the user
ben
true.
3 ?-

Unable to use user-defined operator in Prolog

I've been stuck for quite some time on this issue, my Prolog program has the following line within its operator definitions:
:- op(100, xfx, [has,gives,'does not',eats,lays,isa]).
and then this fact:
fact :: X isa animal :-
member(X, [cheetah,tiger,giraffe,zebra,ostrich,penguin, albatross]).
When I try to use the operator It says it is undefined and I just do not understand why.
?- peter isa tiger.
ERROR: [Thread pdt_console_client_0_Default Process] toplevel: Undefined
procedure: (isa)/2 (DWIM could not correct goal)
Sorry if its something silly (which it probably is) but I am new to Prolog. Any help is much appreciated.
It is working. See for yourself:
stefan#stefan-Lenovo-G510 ~ $ swipl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.12)
% ...
?- op(100, xfx, [has,gives,'does not',eats,lays,isa]).
true.
?- Term = (peter isa tiger).
Term = peter isa tiger.
The error message that you got ...
procedure: (isa)/2 (DWIM could not correct goal)
... says that too!
Is it clearer now?

Prolog, getting right answer in terminal, but wrong answer when running a program

Typing "prolog" in terminal gets:
GNU Prolog 1.3.0
By Daniel Diaz
Copyright (C) 1999-2007 Daniel Diaz
| ?-
Typing:
| ?- member(2, [1,2,3]).
Gets:
true ?
Then pressing enter gets:
yes
Typing:
| ?- member(4, [1,2,3]).
gets:
no
When i write a file; test.pl consisting of this:
:- member(4, [1,2,3]), nl, halt.
And then write in the terminal:
| ?- [test2].
I get:
compiling /path/test.pl for byte code...
/path/test.pl:1: warning: unknown directive (',')/2 - maybe use initialization/1 - directive ignored
/path/test.pl compiled, 1 lines read - 139 bytes written, 11 ms
yes
Shouldnt the answer here be no? What am i doing wrong. Also, how would you do this in prolog:
if (testInPrologTerminal(member(4, [1,2,3])) { do this; }
I.e, i want to send queries to the prolog top level, and get an answer
When you type the query member(2, [1,2,3]), GNU Prolog prompts you for a possible additional solution (hence the true ? prompt) as only by backtracking (and looking to the last element in the list, 3) it could check for it. When you press enter, you're telling the top-level interpreter that you are satisfied with the current solution (the element 2 in the list second position). The second query, member(4, [1,2,3]), have no solutions so you get a no.
To execute a query when a file is loaded, the standard and portable way of doing it, is to use the standard initialization/1 directive. In this case, you would write:
:- initialization((member(4, [1,2,3]), nl, halt)).
Note the ()'s surrounding the query, otherwise you may get a warning about an unknown initialization/3 standard, built-in, control construct. If you have more complex queries to be executed when a file is loaded, then define a predicate that makes the queries a call this predicate from the initialization/1 directive. For example:
main :-
( member(4, [1,2,3]) ->
write('Query succeeded!'), nl
; write('Query failed!'), nl
).
:- initialization(main).
Writing arbitrary queries as directives in a source file is legacy practice and thus accepted by several Prolog implementations but using the initialization/1 directive is the more clean, standard, and portable alternative.

Resources