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]
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.
I have a problem using prolog on a Mac, I figured out how to run it using SWI-Prolog but when I run it, it gives an error and does not give the expected output
Expected output: homer, bart
male(homer).
male(bart).
female(marge).
female(lisa).
female(maggie).
parent(homer, bart).
parent(homer, lisa).
parent(homer, maggie).
parent(marge, bart).
parent(marge, lisa).
parent(marge, maggie).
mother(X, Y) :- parent(X, Y), female(X).
father(X, Y) :- parent(X, Y), male(X).
son(X, Y) :- parent(Y, X), male(X).
daughter(X, Y) :- parent(Y, X), female(X).
?- male(X).
Here is the error I was speaking about earlier
Warning: /Users/[username]/Desktop/simpsons.pl:19:
Warning: Singleton variables: [X]
true.
And instead of outputting homer, bart it outputs true
When programming in Prolog, you put definitions and queries in different places. Definitions go into source files. Queries do not go into source files. You enter them while interacting with the Prolog system in something called the "toplevel" or "prompt" or "shell" or maybe "REPL" (read-eval-print loop).
For example, these are definitions:
male(homer).
male(bart).
female(marge).
female(lisa).
female(maggie).
You have put them in a source file called simpsons.pl. This is correct.
This is not a definition but a query:
?- male(X).
This does not go in a source file. Do not put it in simpsons.pl. Rather, you:
start your Prolog system
load the simpsons.pl file somehow
enter the query male(X). and observe answers
This video: https://www.youtube.com/watch?v=t6L7O7KiE-Q shows these steps with SWI-Prolog on a Mac.
If you are comfortable using a command line, you might also be able to do this simpler. For example, on my (Linux) machine, I can start SWI-Prolog with a command line argument naming a file to be loaded:
$ swipl simpsons.pl
Welcome to SWI-Prolog (threaded, 64 bits, version 7.6.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?-
See that ?-? That is the prompt meaning that the toplevel is now waiting for your input. Here is where you enter your male(X) query. You can use ; or Space to cycle through the various answers:
?- male(X).
X = homer ;
X = bart.
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 ?-
I'm trying to write output from make_tests to a file, but nothing I've tried seems to insert the correct information in the output file.
I've looked at SWI documentaion at http://www.complang.tuwien.ac.at/SWI-Prolog/Manual/IO.html and have tried a whole bunch of those predicates but none have worked.
Here's what I'm trying to do:
:- use_module(library(test_wizard)).
init_test_file(FILE) :-
set_prolog_flag(log_query_file, FILE).
gen_test_in(FILE) :-
make_tests(lists, FILE, current_output).
So running this (in console) for example:
init_test_file('mytest.pro').
member(a, [a,b]).
gen_test_in('mytest.pro').
I get the following output (in console):
true.
6 ?- gen_test_in('r.pro').
:- begin_tests(lists).
test(member, [nondet]) :-
member(a, [a, b]).
:- end_tests(lists).
true.
How do I get this same output (starting at begin_tests and ending at end_tests in a text file?
I tried doing things like modifying gen_test_in to:
gen_test_in(FILE) :-
open(FILE, write, Out),
make_tests(lists, FILE, Out),
close(Out).
But I just get an empty text file.
You are messing up the arguments here. The library you are using, library(test_wizard), is meant for generating tests from queries. In the predicate you are using, make_tests/3, you have the following three arguments:
The module
The file from which the queries are read
The stream to which the generated tests are written
In the examples you use, you either set your output stream to be current_output (so standard output if you are on the top level), or, in the last example you give, you are opening the file you want to read for writing, and then pass the file and its handle to make_tests/3. Instead, if you have a file called queries.pl:
$ cat queries.pl
member(a, [a,b]).
member(X, [a,b]).
Then:
$ swipl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.16-36-g42820df)
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).
?- use_module(library(test_wizard)).
true.
?- setup_call_cleanup(open('lists.plt', write, Out),
make_tests(lists, 'queries.pl', Out),
close(Out)).
Out = <stream>(0xe59ef0).
?- halt.
$ cat lists.plt
:- begin_tests(lists).
test(member, [nondet]) :-
member(a, [a, b]).
test(member, [all(A==[a, b])]) :-
member(A, [a, b]).
:- end_tests(lists).
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.