How to define a predicate in prolog - 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.

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).

How to get a listing of a specific knowledge base?

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.

Prolog print statement does not work as expected

I was trying to define a functor and print each individual items of list in Prolog, but Prolog is not printing in correct format.
rint(L):-
write(H).
the output is like
rint([a, s,v ,c]).
_L139
true.
This is what I expect to achieve by calling the functor, any help or thought is appreciated, I'm new to Prolog and learning it.
?- rint([a,b,c,d]).
.(a, .(b, .(c, .(d, []))))
I think it should be
rint(L) :- write(L).
Also if you want .(a, .(b, .(c, .(d, [])))) and not [a, b, c, d] in output, use display:
rint(L) :- display(L).
The problem is an error in your rule for rint.
Your definition says that rint(L) succeeds if write(H) succeeds. At that point, the interpreter knows nothing about H. So it writes a value it doesn't know, which is why you see the _L139, the internal representation of an uninitialised variable.
Having done that, write(H) has succeed, is true, so rint(L) is true. The interpreter tells you that: true.
To define your own rint/1 without relying on built-ins such as display/1, you would need to do something like
rint([]) :-
write([]).
rint([H|T]) :-
write('.('),
write(H),
write(', '),
rint(T),
write(')').
If you're trying to display an empty list, just write it. If you're trying to display any other list, write the opening period and parenthesis, write the Head, write the following comma and space, then call itself for the Tail of the list, then write the closing parenthesis.

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 can I insert an additional argument after the last argument in a prolog procedure?

I am new to learning prolog, and I want to know, if we have some procedure like
father("Nic","Adam").
and I want to write a function that it will add new value to this
father("Nic","Adam","something"..)
how can I do this? Using list? Or what?
Quick answer: You don't want to do that.
Longer answer: The father/2 predicate has a certain meaning, namely that for father(X,Y) X is the father of Y. A father/3 predicate is a different thing altogether. What do you want to achieve with that third argument? Normally, you use additional rules, which derive things from the father/2 predicate, or even resolve it to a father/3 argument.
The main question remains: what's the purpose of the third argument? If you want your resolution to work for certain specific 3rd arguments based on the existance of a corresponding father/2 predicate for example, you could do father(X, Y, 'something') :- father(X,Y) which will succeed if you have a corresponding father/2 fact.
PS: Do learn your terminology. In Prolog we don't speak of procedures and we don't write functions. Instead we have predicates, facts, rules, ...
PPS: I am not sure which Prolog implementation you are using, but you might want to use 'something' instead of "something". The latter usually creates a list of character codes, not a string:
?- X = 'some'.
X = some.
?- X = "some".
X = [115, 111, 109, 101].
Simply writing
father(nic, adam).
As a predicate already defines it. It is like stating a fact: you declare that father(nic, adam) is true, then you can execute the following with these expected results :
?- father(nic, adam).
Yes
?- father(nic, X).
X = adam

Resources