Turbo Prolog's 'save' analogue in SWI-Prolog - prolog

Is there any SWI's analogue for Turbo's save function, which saves into a file facts, previously loaded via consult and then appended via assert?

I've not found any save-like functions in manual. May be try the following replacement:
% Save whole DB into file
save(FileName) :-
open(FileName, update, F),
with_output_to(S, listing),
close(F).
Or even shorter:
save(FileName) :-
tell(FileName), listing, told.

Related

print_term writing to a file in PROLOG

In this mcve]
test :-
tell('junk.txt'),
print_term(
examples([this,is,a,really,long,example,list],
[made,of,lists,atoms,and,including,terms(involving,parentheses,like,this)]),
[]),
told.
SWI-PROLOG does print the term to the screen neatly in the print_term way, but won't print it to the file. How do I redirect the output?
You may use current_output/1 to get the current Stream and then pass it to print_term/2 in its Options parameter:
test :-
tell('junk.txt'),
current_output(Stream),
print_term(
examples([this,is,a,really,long,example,list],
[made,of,lists,atoms,and,including,terms(involving,parentheses,like,this)]),
[output(Stream)]),
told.
I believe all those Edinburgh style predicates that deal with files are in maintenance mode and you now may prefer to use ISO stream predicates.

Prolog solve Sudoku

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.

Open .pl file and close current one in SWI - Prolog

I have created two different .pl files in SWI-Prolog for a text adventure game. They are two different missions.
Is there any way at the end of the first mission to open the second mission (the second .pl file) and close the first one?
Also, what would be better: To create N .pl files for my N missions or one big .pl file?
I agree with your initial impulse in thinking that using a number of module files would be best. I imagine that one reason for using different files would be to provide different name spaces for facts and rules which would be best expressed using the same predicates. So that, for instance, Description would be different for room(1, Description) in mission 1 than in mission 2.
One way of achieving this would be by accessing private, non-exported predicates in each of the different mission-modules. (Aside: I read Jan Wielemaker caution against this practice somewhere, but I'm not sure why, nor am I sure that I did read this.)
Here's a possible pattern I threw together:
Given a main file, 'game.pl', with the following program,
:- use_module([mission1, mission2]).
start :-
playing(mission1).
playing(CurrentMission) :-
read(Command),
command(CurrentMission, Command),
playing(CurrentMission).
command(_, quit) :- write('Good bye.'), halt.
command(CurrentMission, Command) :-
( current_predicate(CurrentMission:Command/_) % Makes sure Command is defined in the module.
-> CurrentMission:Command % Call Command in the current mission-module
; write('You can\'t do that.'), % In case Command isn't defined in the mission.
).
and these mission modules,
In file 'mission1.pl':
:- module(mission1, []).
turn_left :-
write('You see a left-over turnip').
eat_turnip :-
write('You are transported to mission2'),
playing(mission2). % Return to the prompt in `game` module, but with the next module.
In file 'mission2.pl':
:- module(mission2, []).
turn_left :-
write('You see a left-leaning turncoat.').
Then we can play this shitty game:
?- start.
|: turn_left.
You see a left-over turnip
|: eat_turnip.
You are transported to mission2
|: turn_left.
You see a left-leaning turncoat.
|: quit
|: .
Good bye.
The specifics of this program are problematic for a number of reasons. For instance, I expect we might rather have a single predicate that handles navigating through places, and that we'd rather describe places and object that react to different commands in our missions, rather than account for every possible command. But the general principle of using the different files would still work.
Another approach would be to use consult/1 and unload_file/1 to load and unload modules, in which case you should be able to use their public, exported predicates instead of calling them by module. Documentation for those and related predicates can be found in the manual in the section "Loading Prolog Source Files".

Defining predicates in SICStus Prolog / SWI-Prolog REPL

I am reading http://cs.union.edu/~striegnk/learn-prolog-now/html/node3.html#subsec.l1.kb1,
but I am having trouble running the following predicate:
SICStus 4.0.1 (x86-win32-nt-4): Tue May 15 21:17:49 WEST 2007
| ?- woman(mia).
! Existence error in user:woman/1
! procedure user:woman/1 does not exist
! goal: user:woman(mia)
| ?-
If, on the other hand, I write it to a file and run consult the file, it seems to work fine...
Am I only allowed to define predicates in a file having later to consult them? Can't I just do it in the editor itself?
It's a little annoying to make predicates in the repl. You could do
| ?- ['user'].
woman(mia).
^D
ie consult user input, or
| ?- assertz(woman(mia)).
assert it. Both awkward IMO -- there might be a better way, though, I just don't know it. In general it is easier to use a script.
You should enter woman(mia). into a file to assert it as a fact. If you write it into the interpreter, it's taken as a query, not a fact.
From the SWI Prolog FAQ:
Terms that you enter at the toplevel are processes as queries, while
terms that appear in a file that is loaded into Prolog is processed as
a set of rules and facts. If a text reads as below, this is a rule.
carnivore(X) :- animal(X), eats_meat(X).
Trying to enter this at the toplevel results in the error below. Why?
Because a rule is a term :-(Head, Body), and because the toplevel
interprets terms as queries. There is no predicate with the name :-
and two arguments.
?- carnivore(X) :- animal(X), eats_meat(X). ERROR: Undefined
procedure: (:-)/2 ERROR: Rules must be loaded from a file ERROR:
See FAQ at http://www.swi-prolog.org/FAQ/ToplevelMode.txt
Isn't this stupid? Well, no. Suppose we have a term
eats_meat(rataplan). If this appears in a file, it states the fact
that rataplan eats meat. If it appears at the toplevel, it asks Prolog
to try proving whether rataplan eats meat.
If a text reads
:- use_module(library(clpfd)).
This is a directive. Directives are similar to queries, but instead of
asking the toplevel to do something, they ask the compiler to do
something. Like rules and facts, such terms belong in files.
Instead of writing to a file you can also use assert in the toplevel (as explained later in the FAQ as well).

How to define a predicate in prolog

I am new to Prolog and I have so far learned how to define a predicate in a file and the run the interpreter to use it. But I would like to know if there is a way to define the predicate at the ?- prompt so that I don't have to switch back and forth.
the way I am doing it now is like this
file defs.pl:
adjacent(1,2).
adjacent(1,3).
in the prolog interpreter:
?- consult('defs.pl').
% defs.pl compiled 0.00 sec, 122 bytes
true.
?- adjacent(1,2).
true.
EDIT
maybe I meant how to define 'facts' I'm not sure.
You can use the assert/1 predicate:
?- assert(adjacent(1,4)).
true
EDIT:
By the way, this will not work if you try to combine it with predicates defined in a file.
So either define all adjacent/2 predicates in your file, are define them all with assert in the command line.
If you do want to define some of the predicates in the file, and others with assert, then declare in your file that the predicate is dynamic:
% file contents
:- dynamic(adjacent/2).
adjacent(1,2).
adjacent(1,3).
You can do
?- consult(user).
or
?- [user].
and enter the clauses after that, then terminate the input with the end of file character (Ctrl-D in Linux, could be Ctrl-Z in MS-Windows). This is equivalent to reading a file, see the documentation of consult/1.
assert/1 and retract/1 are intended for predicates that are changed dynamically by the code (i.e. for storing global data), not for normal programming.

Resources