How to get a listing of a specific knowledge base? - prolog

Suppose that the file foobar.pl in the current working
directory contains the following minimal knowledgebase:
foo(bar).
foo(baz).
frobozz.
If I start swi-prolog (by running swipl at the command), and immediately run
?- [foobar].
% foobar compiled 0.00 sec, 4 clauses
true.
?- listing.
...the contents of foobar are lost in a sea of >100 lines of unrelated output.
How can I limit listing's output to foobar?
Alternatively, how can I limit it to contents of those knowledgebases I have explicitly consulted?
I did look at the docs for listing/1 and listing/0, but I could not find anything helpful:
listing/1
List predicates specified by Pred. Pred may be a predicate name (atom), which lists all predicates with this name, regardless of their arity. It can also be a predicate indicator (/ or //), possibly qualified with a module. For example: ?- listing(lists:member/2)..
A listing is produced by enumerating the clauses of the predicate using clause/2 and printing each clause using portray_clause/1. This implies that the variable names are generated (A, B, ... ) and the layout is defined by rules in portray_clause/1.
listing/0
List all predicates from the calling module using listing/1. For example, ?- listing. lists clauses in the default user module and ?- lists:listing. lists the clauses in the module lists.
Of course, I did try the following useless idea:
?- foobar:listing.
true.

in SWI-Prolog, you can limit the scope of the loaded clauses with the module/2 directive. I.e. your file foobar.pl should become (for instance)
:- module(foobar, [foo/1]).
foo(bar).
foo(baz).
frobozz.

You can load the contents of a plain Prolog file into a module easily. For example:
?- fb:consult(foobar).
true
And then call:
?- fb:listing.
foo(bar).
foo(baz).
frobozz.
true.
Or list just a specific predicate:
?- fb:listing(foo/1).
foo(bar).
foo(baz).
true.

Related

Representing truth regarding beliefs in prolog

How to make this (or something similar) work in Prolog:
belief(john,red(apple)).
belief(peter,red(apple)).
X :- belief(john,X), belief(peter,X).
And get true. for the following query (while consulting above):-
?- red(apple).
First, it's useful to define a little helper to capture when all (relevant) persons believe something:
all_believe(Belief) :-
belief(john, Belief),
belief(peter, Belief).
Then you can define, for example:
red(Object) :-
all_believe(red(Object)).
green(Object) :-
all_believe(green(Object)).
And with your given set of beliefs you get:
?- red(apple).
true.
?- green(apple).
false.
This works. It requires you to define similar rules for any term that you want to use as a belief.
You can make this a bit shorter with macro definitions using term_expansion:
term_expansion(declare_belief(Belief),
Belief :- all_believe(Belief)).
This means that every top-level definition in your source code of the form declare_belief(Belief) should be treated as if you had written Belief :- all_believe(Belief) instead (with the variable Belief substituted appropriately).
So now you can just write this:
declare_belief(red(_)).
declare_belief(green(_)).
and it will be treated exactly like the longer definitions for red(Object) and red(Object) above. You will still have to write this kind of declaration for any term that you want to use as a possible belief.
Prolog does not allow the head of a rule to be just a variable. The head must be a nonvar term, whose functor (i.e., name and arity) identifies the predicate being defined. So, a possible solution would be something like this:
true_belief(X) :-
belief(john, X),
belief(peter, X).
belief(john, red(apple)).
belief(peter, red(apple)).
Examples:
?- true_belief(red(apple)).
true.
?- true_belief(X).
X = red(apple).

Listing/1 with char codes displayed as characters and not codes?

Using SWI-Prolog
Version:
?- current_prolog_flag(windows,Value).
Value = true.
?- current_prolog_flag(version,Value).
Value = 80000.
For a simple DCG
constant_value --> "ID".
listing/1 outputs
?- listing(constant_value).
constant_value([73, 68|A], A).
However in my notes I have it as
?- listing(constant_value).
constant_value(['I', 'D'|A], A).
but I don't know what I did to have the character codes appear as characters.
I tried the SWI-Prolog flag double_quotes with various values (chars, codes, string) but can't reproduce the desired output.
How are listing/1 of a DCG created where the character codes are displayed as characters?
I think that you probably had double_quotes flag in codes when constant_value was compiled. The value of this flag won't affect clauses already stored in the database.
constant_value1 --> "ID".
:-set_prolog_flag(double_quotes, chars).
constant_value2 --> "ID".
?- listing(constant_value1).
constant_value1([73, 68|A], A).
?- listing(constant_value2).
constant_value2(['I', 'D'|A], A).
Edit by Guy Coder
Since I use the Q&A at SO as a personal notebook with my own Q&A, I tend to look at the accepted answer for the details; I am adding them here for everyone's benefit.
As this answer correctly states, the problem was caused by the fact that originally in the source code, which was a module stored as a file, I had the statement
:- set_prolog_flag(double_quotes,chars).
before the code
constant_value --> "ID".
then in the REPL
?- consult('C:/dcg_examples.pl').
?- listing(constant_value).
constant_value(['I', 'D'|A], A).
true.
and to use this
?- phrase(constant_value,"ID").
true.
Latter in the source code I changed the value for double_quotes
:- set_prolog_flag(double_quotes,codes).
notice the change from chars to codes
Restarting the REPL and doing the same
?- consult('C:/dcg_examples.pl').
?- listing(constant_value).
constant_value([73, 68|A], A).
true.
?- phrase(constant_value,"ID").
true.
gave the different result for listing/1.
However in the REPL using
set_prolog_flag(double_quotes,<VALUE>).
had no effect on the result of listing/1.
<VALUE> can be one of string, chars, codes, traditional, or atom.
The key point to note here is that listing/1 uses consulted/compiled/stored code. So the value of double_quotes at the time of consulting/compiling/storing is what listing/1 uses. Any changes to double_quotes after that in the REPL will not change the consulted/compiled/stored code and thus the result of listing/1.
To effect a change you have to add
:- set_prolog_flag(double_quotes,<VALUE>).
in your source code before the predicate then consult/1 to load it and then listing/1.
The meaning of consulted/compiled/stored does not imply that these are three separate actions performed in a sequence, here they define when the source code is put into the database for use by listing/1.

turning off Redefined static procedure in prolog

anyone of you could tell me how to turn off "Redefined static procedure" warnings?
I red online documentation of swi-prolog and i found this predicate no_style_check(ultimate) that in principle should turn off these warnings, but when i execute this predicate
main:-
no_style_check(singleton),
no_style_check(discontiguous),
no_style_check(multiple),
require,
test_all.
i received this error
ERROR: Domain error: style_name' expected, foundmultiple'
Anyone knows an alternative way to do this or could tell me why i receive this error ?
Thanks in advance!
Prolog is a pretty loosey-goosey language, so by default it warns you when you do certain things that are not wrong per se, but tend to be a good indication that you've made a typo.
Now, suppose you write something like this:
myfoo(3, 3).
myfoo(N, M) :- M is N*4+1.
Then from the prompt you write this:
?- asserta(myfoo(7,9)).
ERROR: asserta/1: No permission to modify static procedure `myfoo/2'
ERROR: Defined at user://1:9
What's happening here is that you haven't told Prolog that it's OK for you to modify myfoo/2 so it is stopping you. The trick is to add a declaration:
:- dynamic myfoo/2.
myfoo(3, 3).
myfoo(N, M) :- M is N*4+1.
Now it will let you modify it just fine:
?- asserta(myfoo(7,9)).
true.
Now suppose you have three modules and they each advertise themselves by defining some predicate. For instance, you might have three files.
foo.pl
can_haz(foo).
bar.pl
can_haz(bar).
When you load them both you're going to get a warning:
?- [foo].
true.
?- [bar].
Warning: /home/fox/HOME/Projects/bar.pl:1:
Redefined static procedure can_haz/1
Previously defined at /home/fox/HOME/Projects/foo.pl:1
true.
And notice this:
?- can_haz(X).
X = bar.
The foo solution is gone.
The trick here is to tell Prolog that clauses of this predicate may be defined in different files. The trick is multifile:
foo.pl
:- multifile can_haz/1.
can_haz(foo).
bar.pl
:- multifile can_haz/1.
can_haz(bar).
In use:
?- [foo].
true.
?- [bar].
true.
?- can_haz(X).
X = foo ;
X = bar.
:- discontiguous does the same thing as multifile except in a single file; so you define clauses of the same predicate in different places in one file.
Again, singleton warnings are a completely different beast and I would absolutely not modify the warnings on them, they're too useful in debugging.

Converting Terms to Atoms preserving variable names in YAP prolog

Is there a way to configure YAP (and/or SWI prolog) so they will preserve variable names in any call to term_to_atom/2 ?.
For example, when I execute this:
term_to_atom(member(X, [1,2]), A).
I obtain this answer:
A = 'member(_131405,[1,2])'
Where X has been replaced by its internal representation.
However, I would like to get this answer instead:
A = 'member(X,[1,2])'
Thanks for any help!
There are two issues involved. How to get the variable name X into the system, and how to get a term with such a variable into the atom.
The X you type in is read by the top level which converts it to a regular variable which does not have a name associated. Let's see that in YAP:
?- read(Term).
|: X+3*Y+X.
Term = _A+3*_B+_A
The |: is YAP's prompt for input. And we have entered X+3*Y+X. However, the variable Term contains _A and _B (names chosen by the top level) in place of X and Y. So the information is lost and cannot be restored once it is read by read/1.
You have to access that information differently with the more general built-in for reading read_term/2,3 and the option variable_names/1.
?- read_term(T,[variable_names(Eqs)]).
|: X+3*Y+X.
Eqs = ['X'=_A,'Y'=_B],
T = _A+3*_B+_A
So the read option variable_names/1 gives you the information to restore the variable names. For each named variable read by read_term/2 there is a structure Name = Variable where Name is an atom representing the variable name. Above, 'X' is the name capital X.
Anonymous variables, that is variables whose name is _, do not occur in the list of variable names. They can be rapidly extracted like so:
?- read_term(T,[variable_names(Eqs)]),
term_variables(Eqs, Named),
term_variables(Named+T, Vars),
append(Named, Anons, Vars).
So much for the reading.
Now for the writing. We cannot write the term directly but have to accompany it with the list Eqs. Let's call the new predicate term_to_atom(Term, Eqs, Atom). In both YAP and SWI there is with_output_to(Output, Goal) which writes the output of Goal to different destinations like atom(A). So you can now use write_term/2 to write the term as you please. An example:
?- with_output_to(atom(A),write_term('a b'+X,[quoted(true)])).
A = '\'a b\'+_131284'.
The variable _131284 looks very ugly. To get variables associated with their names for printing we can implement term_to_atom/3 as follows:
term_to_atom(T, Eqs, A) :-
with_output_to(atom(A), write_term(T,[variable_names(Eqs),quoted(true)]) ).
And use it like so:
?- read_term(T,[variable_names(Eqs)]), term_to_atom(T, Eqs, Atom).
|: X+3*Y+X.
Atom = 'X+3*Y+X',
Eqs = ['X'=_A,'Y'=_B],
T = _A+3*_B+_A
variable_names/1 exists as a write option in ISO, Minerva, Jekejeke, GNU, B, SWI, YAP, and SICStus.
In SICStus, the originator of writing terms to lists, one writes:
:- use_module(library(codesio)).
term_to_atom(T, Eqs, Atom) :-
write_term_to_codes(T, Codes, [variable_names(Eqs),quoted(true)]),
atom_codes(Atom, Codes).
The following was an ISO incompatible work around for YAP prior to 6.3.4. It is no longer necessary. As for the differences to a separate write option: term_to_atom/3 as defined below interferes with constraints and does not correctly render '$VAR'/1.
But for the moment we can only approximate the ideal option
variable_names/1. To print terms with our own variable names,
variables have to be substituted in YAP by '$VAR'(Codes) where
Codes is a list of character codes. This does not do exactly the
same, but it is very close. This goes into a file:
:- use_module(library(apply)).
:- use_module(library(lambda)).
write_eqs_term(T, Eqs) :-
\+ \+ (
maplist(\Eq^( Eq = (N='$VAR'(Chs)), atom_codes(N,Chs)), Eqs),
write_term(T,[numbervars(true),quoted(true)])
).
term_to_atom(T, Eqs, A) :-
with_output_to(atom(A), write_eqs_term(T, Eqs) ).
For SWI, you would have to replace atom_codes(N,Chs) by N = Ch.
and install library(lambda) first. It's pre-installed in YAP.

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