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

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.

Related

Prolog Dynamic Predicates Basic Usage

with this knowledge base using https://swish.swi-prolog.org
:- dynamic happy/1.
go:-
assert(happy(mia)),
write(happy(mia)).
if I run go. I get
happy(mia)
true
If I just have
:- dynamic happy/1.
assert(happy(mia)).
and run happy(mia), I get false.
What fundamental concept am I missing please?
When you write:
assert(happy(mia)).
you are (re)defining the predicate assert/1, not calling it as in your definition of the go/0 predicate. Thus, happy(mia) is never added to the database. The query fails as the predicate happy/1 is know by the system (thanks to the dynamic/1 directive) but have no clauses.
Most Prolog systems prevent the redefinition of standard built-in predicates. But assert/1 is a legacy/deprecated predicate. That explains why SWI-Prolog doesn't complain about the redefinition. Always use the standard assertz/1 predicate instead of assert/1.

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.

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.

How can I provide Prolog asks questions to me

Assume that we have prolog knowledge base like this:
guilty(X) :-
commits(X,Y),
crime(Y).
crime(murder).
crime(theft)
When I ask this question:
?- guilty(john)
I want that Prolog asks me a question like that:
is commits(john, murder) ?
and I answer no then
is commits(john, theft) ?
if I answer yes Prolog says
**yes**
How can I make something like this?
Thanks..
You need a modified proof engine, that when encounters an unknown fact query the user about.
Doing it with some generality can be an interesting task, Google for metainterpreter Prolog, if you are interested in this argument, the first link provides you the valuable page A Couple of Meta-interpreters in Prolog by Markus Triska, where you can learn more.
For your question, would suffice a rule
commits(Person, Crime) :-
crime(Crime),
format('is ~w ?', [commits(Person, Crime)]),
read(yes).
test:
?- guilty(john).
is commits(john,murder) ?no.
is commits(john,theft) ?yes.
true.
note that read/1 requires a dot to terminate the input.
You want an 'interactive shell' for your little reasoner. Building one is not difficult, but beyond the scope of a stackoverflow question. This tutorial builds one in the 2nd or 3rd lesson and generally answers this question. It calls facts like your user answers 'working storage'.
http://www.amzi.com/ExpertSystemsInProlog/
Prolog "executes" things from left to right. Try:
guilty(X) :-
crime(Y),
commits(X,Y).
crime(murder).
crime(theft)
So then guilty(X) depends on commits(X,murder) and/or commits(X,theft)

Resources