3
votes

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.

1
Where's a link to this code? I'm confused by what's meant by maplist(same_length(Rows, Rows), Rows). The rest of it does not seem insane to me at first blush.Daniel Lyons
I added it to the descriptionascawath
I copied and pasted the code off the site myself and it works. In your last edit, you removed the typo I pointed out in my earlier comment; I suggest that you need to try copy-pasting the code again and run the query per the linked page and it will work for you.Daniel Lyons
I use swi Prolog and copied it 1 to 1 in sudoku.pl and consulted this file. But i Still get the errorascawath
funny enough. No it works. But i changed not a bitascawath

1 Answers

6
votes

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:

Facts vs. directives

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.

Convenience definitions

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.