Reputation: 59
I'm rather new at Prolog and found this example on swi-prolog.org to solve a sudoku. But I can't run it. I looked up same_length and there is only same_length/2
not same_length/1
. Also all_distinct/2
and not all_distinct/0
. http://www.swi-prolog.org/pldoc/man?section=clpfd-sudoku
Here are my errors:
ERROR: d:/.../prolog/sudoku.pl:5:10: Syntax error: Operator expected
% d:/.../prolog/sudoku compiled 0.00 sec, 0 clauses
Warning: The predicates below are not defined. If these are defined
Warning: at runtime using assert/1, use :- dynamic Name/Arity.
Warning:
Warning: all_distinct/1, which is referenced by
Warning: d:/.../prolog/sudoku.pl:16:8: 2-nd clause of blocks/3
And here is the code of SWI-Prolog example:
use_module(library(clpfd)).
sudoku(Rows) :-
length(Rows, 9), maplist(same_length(Rows), Rows),
append(Rows, Vs),
Vs in 1..9,
maplist(all_distinct, Rows),
transpose(Rows, Columns),
maplist(all_distinct, Columns),
Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is],
blocks(As, Bs, Cs),
blocks(Ds, Es, Fs),
blocks(Gs, Hs, Is).
blocks([], [], []).
blocks([N1,N2,N3|Ns1], [N4,N5,N6|Ns2], [N7,N8,N9|Ns3]) :-
all_distinct([N1,N2,N3,N4,N5,N6,N7,N8,N9]),
blocks(Ns1, Ns2, Ns3).
problem(1, [[_,_,_,_,_,_,_,_,_],
[_,_,_,_,_,3,_,8,5],
[_,_,1,_,2,_,_,_,_],
[_,_,_,5,_,7,_,_,_],
[_,_,4,_,_,_,1,_,_],
[_,9,_,_,_,_,_,_,_],
[5,_,_,_,_,_,_,7,3],
[_,_,2,_,1,_,_,_,_],
[_,_,_,_,4,_,_,_,9]]).
I hope you can help me to find my mistake.
Upvotes: 4
Views: 2398
Reputation: 40768
As far as I can tell, it now already works for you. However, I would still like to take the opportunity to show a few hints that may be useful for you:
First, why doesn't the code that you post in your answer work?
The Prolog message already gives a pretty good indication:
Warning: The predicates below are not defined. ... ... all_distinct/1, which is referenced by
This shows that you are in fact using all_distinct/1
(not all_distinct/2
!) in your code somewhere, and it is not available.
Why? Because all_distinct/1
is available in library(clpfd)
, and you are not importing that library!
This is a pretty common error among beginners. Take a look at the following line in your program:
use_module(library(clpfd)).
Contrary to what you may believe, this does not import the library! Why? Because, as it stands, this is simply a Prolog fact of the form use_module/1
, similar to the fact:
name(bob).
which, likewise, does not name bob
, but simply states that name(bob)
holds.
What you want instead is to use a directive to import a library.
Directives are terms of the form :-(D)
, which can also be written as :- D
since (:-)/1
is a prefix operator.
Hence, what you meant to write is:
:- use_module(library(clpfd)).
This is a term of the form :-(T)
, and will be processed as a directive when the file is loaded.
Personally, I often write small Prolog programs, and most of them use CLP(FD) constraints. At some point, I got tired of adding :- use_module(library(clpfd)).
to all my programs, so I added the following definition to my ~/.emacs
:
(global-set-key "\C-cl" (lambda () (interactive) (insert ":- use_module(library()).") (forward-char -3)))
When you now press C-c l
, the following snippet is inserted at point:
:- use_module(library()).
and point is placed within the ()
so that you only have to type the actual name of the library instead of the whose :- use_module...etc.
directive.
So, to use library(clpfd)
, I would simply type:
C-c l clpfd
After a while, I got tired of that as well, and simply added :- use_module(library(clpfd)).
to my ~/.swiplrc
configuration file, because almost all programs I write perform integer arithmetic, and so it makes sense for me to make CLP(FD) constraints available in all Prolog programs I write. This is also already the case in systems like GNU Prolog and B-Prolog, for example.
However, I still have kept the .emacs
definition, because sometimes I need to import other libraries, and I find typing the whole :- use_module...
directive too cumbersome and error-prone.
Upvotes: 6