Open vs Consult in SWI Prolog - prolog

I'm new to Prolog, please just don't blast me.
Whenever i had to consult a prolog database i used the predicate consult/1 :
consult(:File)
Now, i noticed that there exist also the predicate open
open(+SrcDest, +Mode, --Stream, +Options)
that allows to read a database.
Apart the possibility to modify the database, not allowed by consult, which are the differences between consult and open (maybe in the extensions of the files that each predicate can open, or maybe because consult reads fact and rules, while with open we can read terms) ?

Using consult/1 seems to be quite similar to use ?- [filename]. Using consult/1 in your program, you can have access to all the facts and predicates written into the file. So for instance if you have a file data.pl like this:
fact(a).
fact(b).
fact(c).
hello:-
writeln('hello').
You can create a file, test.pl and use all the facts and predicate of data.pl:
run:-
consult(prova),
findall(A,fact(A),L),
hello,
writeln(L).
?- run.
hello
[a,b,c]
true.
Moreover, consult seems to accept only .pl file with a dictionary sructure. On the other hand, with open/3, you can access each type of file and read also char by char, but you cannot access the predicates and facts written into the file:
run:-
open('prova.pl',read,Str),
findall(A,fact(A),L),
hello,
writeln(L).
?- run.
ERROR: Undefined procedure: fact/1
Obviously, with open/3 or open/4 you can create, write into files and so on.

Related

Dealing with dynamic predicates that cause compilation failures

I am attempting to run an example GNU Prolog program used as an example during my course work. The code is pulled directly from https://www.cpp.edu/~jrfisher/www/prolog_tutorial/2_17pl.txt and was shown working at one point by my professor.
However, when I run the provided example code, I get the following compilation warning:
| ?- consult('C:/Users/Chase/Desktop/Prolog files/newAnimal.pro').
compiling C:/Users/Chase/Desktop/Prolog files/newAnimal.pro for byte code...
C:/Users/Chase/Desktop/Prolog files/newAnimal.pro:74:12: syntax error: . or operator expected after expression
1 error(s)
compilation failed
The line that is keeping the program from compiling correctly is:
:- dynamic yes/1,no/1.
Which I read up on here: https://www.swi-prolog.org/pldoc/man?predicate=dynamic/1
However, despite attempting to rewrite and reformat the section, I could still not get it to compile.
Any help on why the provided code may not be running?
I am using a Windows GUI GNU Prolog console V1.4.5
The ISO Prolog standard doesn't require dynamic(or multifile or discontiguous) to be declared as an operator. A few systems do it (e.g. SWI-Prolog like you mentioned) but not GNU Prolog. Thus, to ensure code portability, avoid using dynamic as an operator. Write instead:
:- dynamic(yes/1).
:- dynamic(no/1).
Or:
:- dynamic((yes/1, no/1)).
Or:
:- dynamic([yes/1, no/1]).
These are the standard conforming alternatives for declaring multiple predicates as dynamic.
Also, GNU Prolog have a fine manual (part of its installation) which you should refer to when using GNU Prolog.

How to call facts and rules from another file

Case: I have a file, solution.pl, where I want to use the rules of another file (this is the definition of the program, not up to me, but I think it's somewhat common).
So I'm using Ciao Prolog and the syntax seems to be ensure_loaded('c:/Path').
but when I try to use the rules of the other file, it tells me he doesn't know what rule I'm trying to use.
On the other hand, if I write on the console that same lane, and then query again, it does work.
So I was wondering maybe the syntax for doing it on the console and on a file are different??
Could someone tell me a step by step so I can figure it out if I'm missing something? What I'm doing right now is loading the program as I would do with smaller programs, then try to query rules of the file included in the ensure_loaded command. And as I said, it does seem to work if write the command outside of the program.
in solution.pl, try
:- ensure_loaded('c:/Path').
or, if the source in c:/Path has a module directive - that is, it begins with :- module(name, [exported/arity, ...]).
:- use_module('c:/Path').

Persistence of facts in Prolog

I'm kinda new in Prolog and I'm using SWI-Prolog v6.6 to storage asserts in a *.pl file.
:- dynamic fact/2.
assert(fact(fact1,fact2)).
With the code above I can make asserts and it works fine, but the problem is when I close SWI-Prolog and I open the *.pl file again, the asserts I've made are gone...
Is there a way to make asserts and those get stored even if I exit the Prolog process?
Sorry about my bad english and Thanks! (:
Saving state has certain limitations, also see the recent discussion on the SWI-Prolog mailing list.
I think the easiest way to persistently store facts on SWI-Prolog is to use the persistency library. For that I would rewrite your code in the following way:
:- use_module(library(persistency)).
:- persistent fact(fact1:any, fact2:any).
:- initialization(init).
init:-
absolute_file_name('fact.db', File, [access(write)]),
db_attach(File, []).
You can now add/remove facts using assert_fact/2, retract_fact/2, and retractall_fact/2.
Upon exiting Prolog the asserted facts are automatically saved to fact.db.
Example usage:
$ swipl my_facts.pl
?- assert_fact(some(fact), some(other,fact)).
true.
?- halt.
$ swipl my_facts.pl
?- fact(X, Y).
X = some(fact),
Y = some(other, fact).
If what you're after is just to get a list of certain facts asserted with a predicate, then mbratch's suggestion will work fine. But you may also want to save the state of your program in general, in which case you can use qsave_program/2. According to the swi docs, qsave_program(+File, +Options)
Saves the current state of the program to the file File. The result is a resource archive containing a saved state that expresses all Prolog data from the running program and all user-defined resources.
Documentation here http://www.swi-prolog.org/pldoc/man?section=runtime

How can I change a Prolog Database to be dynamic?

I have the following Database which connects streets via switches:
For Example
switch(r2,w52=s).
switch(w52=s,w53=d).
How can it be determined algorithmically, not through explicit deposit in a data base.??
Any suggestions?
You have several options to create and consult dynamically-generated facts in Prolog.
The basic one is to use meta-predicates such as assert and retract. There predicates add and remove facts from the program. E.g., assert(switch(w52=s,w53=d)) will add a switch clause to your program. You have to declare :- dynamic switch/2. in advance. The downside of using assert is that it does not backtrack. That is, if you asserted some fact in some predicate and it backtracked, the fact is not automatically cleaned up.
Another option is to accumulate these facts inside a list, and then use member/2 or memberchk/2 to check if a given fact is in that list, instead of querying the program. E.g.:
L = [switch(w52=s,w53=d), switch(w53=d,w54=d), ...]
member(switch(w53=A, w54=B), L) % Unifies A=d, B=d
Unlike using assertions, this method will work like any other Prolog predicate.
Finally, you can run a two-phase program. During the first phase, print to a file the terms you calculated and want to serve as facts. That's easy because Prolog supports writing complete terms, no need to format them yourself. Afterwards just consult the file. If you read the facts more often than generate them, this is the most efficient method, since Prolog will compile your file.

Saving GProlog database

In my program I have a dynamic clauses, they works fine, but when I closing my program, they are disappears.
I've tryed that
saveState :-
write_pl_state_file('backup.dat').
loadState :-
file_exists('backup.dat'),
read_pl_state_file('backup.dat'); !.
but this is not works.
Is there a way to save this databse to a file?
The predicates write_pl_state_file/1 and read_pl_state_file/1 are connected with the information/state that affects parsing of terms, i.e. operator definitions, character conversion Prolog flags, etc.
So that is part of your solution (perhaps), but more fundamentally you wish to save the dynamic clause definitions, probably in a form that allows you to reinstate them by consulting a file.
The predicate listing/0 does something like this, but it displays the dynamic clauses to the "console", not to a file. Probably you want to use the underlying predicate portray_clause/2, which does allow redirecting output to a file (stream).
The author Daniel Diaz noted a slight change (adding a newline to end of output) for portray_clause/2 in recent release notes for version 1.4.0, so you may want to make sure you've got the latest version for the sake of legibility.
Added:
It appears that starting with version 1.3.2 GNU Prolog supports sending listing/0 output to the current stream (rather than just to the console as in 1.3.1 and earlier).
Here's a test case:
| ?- assertz(whoami(i)).
| ?- assertz(whoami(me)).
| ?- assertz(whoami(myself)).
which creates three clauses (facts) for a dynamic predicate whoami/1.
I then created a file myClauses.pl with the following query:
| ?- open('myClauses.pl',write,S), set_output(S), listing, close(S).
Once the stream S is closed, current output is reset to the console.
You will find that the file myClauses.pl contains a blank line followed by the three clauses, so that the source code is in proper form to be consulted. However I'm having a problem with the consult/1 predicate (and its File -> Consult... menu equivalent) in my newly installed GNU Prolog 1.4.0 under Windows. The compilation works from the command line and produces a byte-code file that load/1 can correctly handle in the console, so there's some small problem in how things are set up. I'll post a further note when I get that squared away, having sent in a bug report. I've not tried it yet under Linux.
You can use current_predicate/1 or predicate_property/2 to access predicates, and clause/2 to access the clauses for a predicate.
Then you can write a save utility by using that information.

Resources