I'm just trying to figure out constraint programming in SWI-Prolog, looking at this tutorial : http://en.wikibooks.org/wiki/Prolog/Constraint_Logic_Programming
However I seem to be falling at the first hurdle.
?- use_module(library(clpfd)).
true.
?- X #> Y, X in 1..3, Y=2.
ERROR: Syntax error: Operator expected
ERROR: X
ERROR: ** here **
ERROR: #> Y, X in 1..3, Y=2 .
?-
What's going wrong here? I seem to have included the library, but the first example line from the tutorial throws a syntax error.
All the tutorials I can find seem to use operators like #=, #< etc. But my SWI-Prolog baulks at them. Are they an extra syntax which comes with that constraint library? (And am I failing to load it?)
Or am I misreading the tutorial examples?
Update : Trying to understand things from Horsh's reply below. I can get this to work if I use the library and run the line in the interactive terminal. But if I try to import the library and use these operators in a source file, then it throws the error again. What am I not understanding?
Update 2 :
OK. If, in my source file, I invoke the library and then write a rule which contains a #>. Then I try to consult it from the command-line. It will throw an error and the #> syntax is un-recognised. If import the library to the command line before trying to consult the program, it works. Can this be right?
Building on Horsh's answer, you should be importing the library in your source code, remembering to put ?- at the beginning of the line like so:
?- use_module(library(clpfd)).
The ?- tells SWI-Prolog to execute the line as if it were typed into the interpreter directly, instead of trying to declare it as a predicate in your program.
Don't be concerned about SWI-Prolog importing the library more than once, it knows to check if the library was modified and only reloads it if the library was changed since the last time it was loaded.
For anyone else that finds this in the future, if you want to import a library in an SWI-Prolog source file, the following will also work:
:- use_module(library(clpfd)).
Note the :- and not ?-.
The is all in the manual here and there.
?- [library(clpfd)].
% library(error) compiled into error 0.00 sec, 10,128 bytes
% library(apply) compiled into apply 0.00 sec, 16,840 bytes
% library(assoc) compiled into assoc 0.00 sec, 13,132 bytes
% library(lists) compiled into lists 0.00 sec, 14,332 bytes
% library(pairs) compiled into pairs 0.00 sec, 5,372 bytes
% library(clpfd) compiled into clpfd 0.05 sec, 392,604 bytes
true.
?- X #> Y, X in 1..3, Y=2.
X = 3,
Y = 2.
Related
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.
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.
I'm Prolog beginner, and now I'm stuck, because Prolog doesn't show me any result. I'm reading a few tutorials, and all they has an example code like this:
main.
human(ann).
human(george).
human(mike).
?- bagof(H, human(H), Humans).
% Expected result:
% Humans = [ann, george, mike].
?- human(Who).
% Expected result:
%
% Who = ann;
% Who = george;
% Who = mike.
But all output I get is:
Warning: /Users/admin/prolog/test.pl:105:
Singleton variables: [Who]
% test.pl compiled 0.00 sec, 34 clauses
true.
Or:
Warning: /Users/admin/prolog/test.pl:105:
Singleton variables: [Humans]
% test.pl compiled 0.02 sec, 1,409 clauses
true.
What am I doing wrong? I really read everything I could, but all manuals say that such code must return result. But it doesn't for me.
SWI-Prolog version: 6.6.5 for x86_64-darwin13.1.0
OS: MAC OS X 10.9.2 Maverix
If you go back to the tutorials you've been looking at, they should be making clear (as #PauloMoura points out) that there's a difference between consulting a file in Prolog and interacting with Prolog at it's interactive prompt.
If you simply run Prolog without consulting a file, you can manually enter facts and rules, then press ctrl-D to finish. For example:
? - [user].
|: human(ann).
|: human(george).
|: human(mike).
|: % user://1 compiled 0.00 sec, 2 clauses
true.
Then you can query by typing (at the shown prompt):
?- human(Who).
Who = ann ;
Who = george ;
Who = mike.
?- bagof(H, human(H), Humans).
Humans = [ann, george, mike].
?-
If you want to put things in a file, you can put your facts in a file, say, humans.pl:
human(ann).
human(george).
human(mike).
Then consult the file from the Prolog prompt:
?- [humans].
% humans compiled 0.00 sec, 5 clauses
true.
And then do my queries (again, manually in this case) shown above with the same results:
?- human(Who).
Who = ann ;
Who = george ;
Who = mike.
?- bagof(H, human(H), Humans).
Humans = [ann, george, mike].
These outputs are provided courtesy of the interactive prompt. If you want to have everything in the file, you need to have a predicate in the file which would use I/O functions to output the information you want.
So we can make humans.pl look like this:
human(ann).
human(george).
human(mike).
?- human(Who), write(Who), nl, fail.
?- bagof(H, human(H), Humans), write(Humans), nl.
And then you'd get:
?- [humans].
ann
george
mike
Warning: /home/mark/src/prolog/_play_/humans.pl:5:
Goal (directive) failed: user: (human(_G606),write(_G606),nl,fail)
[ann,george,mike]
% humans compiled 0.00 sec, 5 clauses
true.
?-
The warning comes because the first query fails (used to do the backtrack for more results). you can get rid of that failure just by adding an alternative true path to that query:
?- human(H), write(H), nl, fail ; true.
Or, you can introduce a single predicate to output all the humans:
human(ann).
human(george).
human(mike).
show_humans :-
human(H),
write(H), nl,
fail.
show_humans.
?- show_humans.
?- bagof(H, human(H), Humans), write(Humans), nl.
Which results in:
?- [humans].
ann
george
mike
[ann,george,mike]
% humans compiled 0.00 sec, 7 clauses
true.
It seems that you're writing your queries in the file itself instead of trying them at the Prolog top-level interpreter. Queries in a file such as ?- human(Who). are (usually) executed silently. The queries in your file are also the reason you're getting the singleton variable warnings. If you want a query embed in a source file to output anything you need to explicitly add the necessary calls to output the results.
If you want to use Prolog in batch mode, not in interactive mode, you can write the code in human.pl.
:- initialization main.
human(ann).
human(george).
human(mike).
main :-
bagof(X, human(X), L),
write(L),
halt.
To run it with swipl human.pl (I use swi prolog). Then, the results will be:
% human.pl compiled 0.00 sec, 6 clauses
[ann,george,mike]
I'm brand new to Prolog. I am simply trying to get some output from Prolog on Windows Vista.
I have downloaded and installed Prolog 5.1; I chose the .pro file extension when installing (not to confuse with Perl files).
I created a file called test.pro.
Inside this file I put the following:
inside(tom).
?-inside(tom).
I double clicked the file and a command line interface popped up. On this interface (after a bunch of generic Prolog version/copyright info) the only output is:
1 ?-
OK, for starters, I did not expect it to ask a question; I expected it to answer a question (something along the line of 'yes').
Anyway, I tried to respond to the query with the following:
In the command line I re-inserted 'inside(tom).', so the whole line looks like:
1 ?- inside(tom).
I pressed Enter and got an error message:
ERROR: toplevel: Undefined procedure: inside/1 (DWIM could not correct goal)
Prolog doesn't answer questions if you haven't told it facts. (Except for some built-in facts such as member(1, [1,2,3]).)
You can tell it who is inside by (comment follow a %):
1 ?- [user]. % get facts and rules from user input
|: inside(mary). % Mary and John are explicitly inside
|: inside(john).
|: inside(X) :- location(X, house). % rule: anyone in the house is inside
|: inside(X) :- location(X, office). % (variables start with a capital letter)
|:
|: location(tom, house).
|: location(bernard, house).
|: location(anne, office).
|: % type Ctrl+D
% user://1 compiled 0.00 sec, 1,220 bytes
true.
2 ?- inside(tom). % Prolog deduces that Tom is inside
true .
If you want to learn Prolog, Learn Prolog Now is a good, free tutorial.
You need to compile this first (also called "consult" in prolog). If I knew which version of prolog you have I could find out the exact key entry for this command (Ctrl-L may work). By the way, welcome to the wonderful world of prolog- I love it :) As soon as you're over this hurdle, it gets a lot better. :)
Quick and dirty. What was missing was 'compiling' the file, known as consult
and the syntax is as follows, all characters in the line are relevant.
?- [filename].
then you can ask questions and do other things with what the database.(the source code in prolog)
http://www.swi-prolog.org/pldoc/man?section=quickstart
I am experimenting with prolog, reading "Programming in prolog using the ISO standard, fith edition". I have installed yap (yet another prolog) on my ubuntu 10.10 Maverick RC system, installed using synaptic. I am running prolog from within emacs23 using prolog-mode.
The following code (from chapter five of book) does not give results as in book:
/* FILE history_base.pl */
use_module(library(lists)) /* to use member/2 */
event(1505,['Euclid',translated,into,'Latin']).
event(1510,['Reuchlin-Pfefferkorn',controversy]).
event(1523,['Christian','II',flies,from,'Denmark']).
mywhen(X,Y):-event(Y,Z),member(X,Z).
% Restoring file /usr/lib/Yap/startup
YAP version Yap-5.1.3
< reading the above file into yap>
?- mywhen("Denmark",D).
no
which is not what the book gives!
Now adding to the file above the line (from the book):
hello1(Event):- read(Date), event(Date,Event).
Gives this error when reading the file into yap
(using "consult buffer" in the prolog menu in emacs):
?- % reconsulting /tmp/prolcomp14814QRf.pl...
SYNTAX ERROR at /tmp/prolcomp14814QRf.pl, near line 3:
use_module( library( lists ) )
< ==== HERE ====>
event( 1505 , [ Euclid , translated , into
, Latin ] ).
% reconsulted /tmp/prolcomp14814QRf.pl in module user, 0 msec 752 bytes
yes
?-
¿Any comments?
Perhaps you should terminate the use_module(library(lists)) statement with a . and declare it as a directive, i.e.:
:- use_module(library(lists)).
You have to write Denmark between single quotes instead of double quotes, i.e.:
?- mywhen('Denmark', D).
When you put Denmark between double quotes, the prolog interprets it as a list of character codes instead of an atom, but in the definition of event it is written as an atom (between single quotes).