Persistence of facts in Prolog - 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

Related

How to assert multiple facts or rules in one assert/1 statement?

If I'm at the repl I can do
?- assert(foo(a)),assert(foo(b)),assert(foo(c)).
and that works, but not
?- assert((bar(a),bar(b),bar(c))).
or similar. Is there a way to only need to type "assert" once and pass in multiple facts? Same question for rules.
thanks!
I tried several variations of what I mentioned above to accomplish this but can't figure out how to do it. Also looked at the doc for assert/1 but it doesn't show how.
Maybe you can instead consult from user?
?- [user].
:- dynamic(foo/1).
foo(a).
foo(b).
foo(c).
Press Ctrl-D to end consulting. If you just want to add clauses the database, you may not need to type the dynamic/1 directive.
P.S. assert/1 is a deprecated/legacy predicate. Use instead assrta/1 or assertz/1 if you must.

Open vs Consult in SWI 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.

Prolog term_expansion not working

I am trying to perform the following term_expansion with swipl:
a(asda).
a(astronaut).
term_expansion(a(X),b(X)).
But it does not work, i.e. there is no b/1 consulted. I have tried a few variations:
term_expansion(a(X),[b(X)]).
user:term_expansion(a(X),b(X)).
user:term_expansion(a(X),[b(X)]).
user:term_expansion(user:a(X),[user:b(X)]).
None of which works. What is the problem?
As explained by #mat, you need to define the term_expansion/2 predicate before the clauses you want to expand are loaded. Also, the term_expansion/2 predicate is a multifile and dynamic predicate defined for the user pseudo-module. Thus, you should write:
:- multifile user:term_expansion/2.
:- dynamic user:term_expansion/2.
user:term_expansion(a(X), b(X)).
This will ensure that your expansion code will work if you move it into a module.
If portability to other Prolog systems with a term-expansion mechanism (which, btw, is far from standard), than consider moving the term-expansion code to its own file, loaded before the source files you want to expand.

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