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.
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.
Related
So basically i have this afirmations and rules and somehow the compiler is saying that the clauses are not in the source file and i dont get why, like the program is well written i think?
Program:
forne(f001,zé_dos_parafusos,fabricante,carregado).
forne(f002,branquinho,fabricante,lisboa).
forne(f003,lar_ideal,fabricante,lisboa).
tipo_prod(p001,parafuso).
tipo_prod(p002,broca).
tipo_prod(p003,lavatório).
tipo_prod(p004,sabonete).
tipo_prod(p005,detergente).
og_prod(f001,p001,30000).
og_prod(f001,p002,500).
og_prod(f002,p003,25).
og_prod(f002,p004,50000).
og_prod(f002,p005,50000).
og_prod(f003,p001,1000).
og_prod(f003,p002,50).
og_prod(f003,p003,5).
og_prod(f003,p005,500).
tipo_prod(X, _) :- og_prod(X, _, _).
og_prod(X, Y, _) :- tipo_prod(Y, _), forne(X, _, _, _).
Warnings:
Clauses of tipo_prod/2 are not together in the source-file
Clauses of og_prod/3 are not together in the source-file
Earlier definition at ex1 cap7.pl:11
Current predicate: tipo_prod/2
Use :- discontiguous og_prod/3. to suppress this message
If someone could explain to me whats wrong in this program i would appreciate it a lot.
Prolog doesn't care whether the clauses are facts or rules -- they're all just clauses (facts simply don't have a ":- ..." part; but you can also think of them as having :- true).
You have rules for tipo_prod/2 and og_prod/3 separate from the facts for those predicates. So, you're getting a warning, as that's often the indication of a typo.
BTW, your code probably won't do what you think it's doing. My guess is that you want to use different names for the rules tipo_prod/2 and og_prod/3 that's different from the names for the facts.
anyone of you could tell me how to turn off "Redefined static procedure" warnings?
I red online documentation of swi-prolog and i found this predicate no_style_check(ultimate) that in principle should turn off these warnings, but when i execute this predicate
main:-
no_style_check(singleton),
no_style_check(discontiguous),
no_style_check(multiple),
require,
test_all.
i received this error
ERROR: Domain error: style_name' expected, foundmultiple'
Anyone knows an alternative way to do this or could tell me why i receive this error ?
Thanks in advance!
Prolog is a pretty loosey-goosey language, so by default it warns you when you do certain things that are not wrong per se, but tend to be a good indication that you've made a typo.
Now, suppose you write something like this:
myfoo(3, 3).
myfoo(N, M) :- M is N*4+1.
Then from the prompt you write this:
?- asserta(myfoo(7,9)).
ERROR: asserta/1: No permission to modify static procedure `myfoo/2'
ERROR: Defined at user://1:9
What's happening here is that you haven't told Prolog that it's OK for you to modify myfoo/2 so it is stopping you. The trick is to add a declaration:
:- dynamic myfoo/2.
myfoo(3, 3).
myfoo(N, M) :- M is N*4+1.
Now it will let you modify it just fine:
?- asserta(myfoo(7,9)).
true.
Now suppose you have three modules and they each advertise themselves by defining some predicate. For instance, you might have three files.
foo.pl
can_haz(foo).
bar.pl
can_haz(bar).
When you load them both you're going to get a warning:
?- [foo].
true.
?- [bar].
Warning: /home/fox/HOME/Projects/bar.pl:1:
Redefined static procedure can_haz/1
Previously defined at /home/fox/HOME/Projects/foo.pl:1
true.
And notice this:
?- can_haz(X).
X = bar.
The foo solution is gone.
The trick here is to tell Prolog that clauses of this predicate may be defined in different files. The trick is multifile:
foo.pl
:- multifile can_haz/1.
can_haz(foo).
bar.pl
:- multifile can_haz/1.
can_haz(bar).
In use:
?- [foo].
true.
?- [bar].
true.
?- can_haz(X).
X = foo ;
X = bar.
:- discontiguous does the same thing as multifile except in a single file; so you define clauses of the same predicate in different places in one file.
Again, singleton warnings are a completely different beast and I would absolutely not modify the warnings on them, they're too useful in debugging.
I've been struggling trying to edit Eliza chatbot in Prolog. every time I try to edit something, a new error show up. Is it protected to any sort of editing?
I edited using SWI-prolog editor. The problem is that I'm trying to minimize the code without fully understanding it. I'm trying to do a simple short version of it. So, I might removed something essential perhaps! like "my_char_type" for example. The error I got is " retract/1: No permission to modify static procedure `rules/1'"
Is there any code for a smaller chatbot that I can understand?
Please help :'(
Prolog has a static store and a dynamic store. If you open up a file, say program.pl and you put some lines in it like this:
foo(tabitha).
foo(darlene).
those facts wind up in the static store. They're not a mutable part of your program (by default).
The asserta/1, assertz/1 and retract/1 and retractall/1 procedures form the basis of the dynamic store. If you are just sitting at the console you could just add some facts to the dynamic store and remove them by doing something like this:
?- asserta(baz(tabitha)).
true.
?- baz(X).
X = tabitha.
?- retract(baz(tabitha)).
true.
?- baz(X).
false.
However, if you are sitting at the prompt after loading program.pl and you try to retract foo(tabitha) you're going to get the static procedure message:
?- retract(foo(tabitha)).
ERROR: retract/1: No permission to modify static procedure `foo/1'
ERROR: Defined at /Users/fusion/program.pl:1
The reason is because the foo/1 facts were placed in the static store rather than the dynamic store, because you didn't put them there with asserta/1 or assertz/1 or declare the predicate as dynamic, like this:
:- dynamic foo/1.
So there are two ways forward:
Edit the program source directly and reload it.
Declare the rules/1 predicate dynamic as above.
Incidentally, reloading in SWI-Prolog is best done by running make. from the prompt.
I would recommend option #1 since otherwise it will be difficult to reconstruct your working program's state when you like what it is doing.
SWISH has the simplest Eliza ever, I have the old code below, used to test my Prolog interpreter.
here is an example session
1 ?- eliza.
? i am hungry
how long have you been hungry ?
? very long
please go on
? bye
Goodbye. I hope I have helped you
true.
SWI-Prolog tested version, ported from below ELIZA.IL (alas, SWISH is apparently missing IO primitive like read_line_from_codes, so it's simpler to paste the full code)
eliza :-
write('? '), read_word_list(Input), eliza(Input), !.
eliza([bye]) :-
write('Goodbye. I hope I have helped you'), nl.
eliza(Input) :-
pattern(Stimulus, Response),
match(Stimulus, Dictionary, Input),
match(Response, Dictionary, Output),
reply(Output),
!, eliza.
match([N|Pattern], Dictionary, Target) :-
integer(N), lookup(N, Dictionary, LeftTarget),
append(LeftTarget, RightTarget, Target),
match(Pattern, Dictionary, RightTarget).
match([Word | Pattern], Dictionary, [Word | Target]) :-
atom(Word), match(Pattern, Dictionary, Target).
match([], _Dictionary, []).
pattern([i,am,1],[how,long,have,you,been,1,'?']).
pattern([1,you,2,me],[what,makes,you,think,i,2,you,'?']).
pattern([i,like,1],[does,anyone,else,in,your,family,like,1,'?']).
pattern([i,feel,1],[do,you,often,feel,that,way,'?']).
pattern([1,X,2],[can,you,tell,me,more,about,your,X,'?']) :- important(X).
pattern([1],[please,go,on]).
important(father).
important(mother).
important(son).
important(sister).
important(brother).
important(daughter).
reply([Head | Tail]) :-
write(Head), write(' '), reply(Tail).
reply([]) :- nl.
lookup(Key, [(Key, Value) | _Dict], Value).
lookup(Key, [(Key1, _Val1) | Dictionary], Value) :-
Key \= Key1, lookup(Key, Dictionary, Value).
read_word_list(Ws) :-
read_line_to_codes(user_input, Cs),
atom_codes(A, Cs),
tokenize_atom(A, Ws).
Older code: eliza and rwl
I was testing my new version of SWI prolog and keep coming across the error :singleton variable.
Example:
member(X,[X|T]).
member(X,[X|T]) :- member(X,T).
finds the member of a list such as :
member(yolands,[yolanda,tim])
X = yes
but instead I get a singleton variables error for X and T
if I do the following:
member(X,[X|_]).
member(X,[_|T]) :- member(X,T).
It works but looks ugly!
Can anyone explain why single variables ar enot allowed and if this ANSI standard?
Singleton variables are useless in Prolog, and are easily introduced by editing typos.
The warning is welcome to me, as it allows to easily spot such frequent cause of error.
Being a warning, you can run code containing singletons, but any value these eventually will assume will be lost.
I don't think that ISO standard (never heard about ANSI) forbids such variables.
You could rewrite your example in this way
member(X, [Y|T]) :- X = Y ; member(X, T).
and then forget about the singleton.
You have a bug here:
member(X,[X|T]) :- member(X,T).
What you're actually saying (as opposed to what you think you're saying) is that member/2 holds if X is at the head of the list and present in the tail of the list. This predicate will only ever be true for the first N copies of the same thing at the beginning of a list, so it's a very strange thing to say!
?- member(X, [a,a,c]).
X = a ;
X = a ;
false.
?- member(X, [b,a,a]).
X = b ;
false.
Now, you could correct the bug and still have a singleton warning by doing something like this:
member(X, [Y|T]) :- member(X, T).
But this is neither as good as the conventional definition with two heads or #CapelliC's version (+1) with an explicit OR. I think you should wait until you understand Prolog a little better before putting much stock in your sense of Prolog code aesthetics. If you stick with it for a while you'll come to appreciate this warning as well as the use of anonymous variables.
What makes singleton variables useless in Prolog is that they're named but nothing is known about them and they have no effect on the rest of the computation. The underscore highlights that absolutely anything could go in there without affecting the meaning. What makes
member(X, [X|T]).
true is that the X is position 1 is the same as the X at the head of the list in position 2. Lists must either be empty or have a head and a tail, but what's in the tail is not relevant here, what matters is that X is also the head. The T could be the rest of the list, or it could be an improper list, or it could be a breadbox or lightning or the smell of the air on a spring day. It has no bearing on the truth of member(X, [X|T]).
The singleton warning tells you "you've reserved a name for something here, but you never call anything by that name." The first thing I do when I get this message and it isn't an obvious typo is replace the name with _ and see if my code still makes sense. If it doesn't, I have a logic error. If it does, it was probably unnecessary.
You can read about it on the official page of SWI-Prolog FAQ
The most common cases this warning appears are:
Spelling mistakes in variables
Forget to use/bind a variable
SWI suggest some ways to ignore it:
Use anonymous variable named _ for this purpose.
Use your variable starting with _ (like _T, _X), to avoid warning and document what you ignore.
If you are aware of what you are doing, you can use :- style_check(-singleton). and all warnings should go away.
I am trying to implement a meta-program in ECLiPSe Prolog, and here's the code that i have written -
:- dynamic go/1.
sol(true):- !.
sol((A,B)):- !, sol(A), sol(B).
sol(A):- clause(A, Body), sol(Body).
go(X):- X is 5.
Now when I query with sol(go(X)). , I get the error accessing a procedure defined in another module in clause(X is 5, _292) and it aborts. I tried clearing all toplevel modules and reopening ECLiPSe and then running, but still the same error.
What could be the reason?
Thanks!
Predicate p/1 is using the built-in predicate (is)/2. Note that X is 5 is a syntactically more convenient way of writing is(X,5). But your meta-interpreter is only expecting user defined predicates and the control constructs (',')/2 and true/0. If you want to handle (is)/2 you have to introduce a separate clause for it.
sol(X is Y) :- !, X is Y.
Within ISO Prolog, the goal predicate_property(Goal,built_in) can be used to test if Goal is a built-in predicate. This works in many systems like B, GNU, SICStus, SWI, XSB, YAP. So you can write:
sol(Bip) :- predicate_property(Bip, built_in), !, Bip.
In ECLiPSe this built-in is not directly available. You have to load a library. The index of the manual suggests to use library swi or quintus. For some (unclear) reason it is not part of the ECLiPSe library iso, yet it is ISO. So state
:- use_module(library(swi)).
in your file (or at the toplevel) first.
If you want a meta-interpreter to cover the full Prolog language you will have to handle all control constructs explicitly. Here they are - as defined in the standard (7.8 Control constructs).
true/0
fail/0
call/1
!/0
(',')/2
(;)/2 - disjunction
(->)/2
(;)/2 - if-then-else
catch/3
throw/1
Please be aware that only a few of them can be handled by directly calling the goal. Most of them must be handled explicitly!