How can I provide Prolog asks questions to me - prolog

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)

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.

Prolog existence_error for predicate in generated prolog file

I'm having a problem with a program that I'm writing. The program takes an input and generates a prolog program based on it. It generates something like this:
test(A):-condA(A),condB(A).
condA(val).
condB(val).
My problem is that sometimes, there is no condB(val), or condB anywhere in the program, except in the above definition of test. In that case, I got existence_error for condB, when I try to ask test(val), for example. Is there a way to add something to the prolog program that would define condB as false for all values of it's argument?
I'm sorry if this is stupid question, as I'm new to prolog.
You can tell the prolog processor that condB/1 is dynamic:
:-dynamic condB/1.
Answer to your question is simple.
condB(_):-fail.
the symbol '_' is free variable.

Is it acceptable for a prolog procedure to work only one way?

I have a prolog program:
link(liverpool,preston).
link(liverpool,manchester).
link(preston,lancaster).
link(preston,manchester).
link(lancaster,carlisle).
link(lancaster,leeds).
link(carlisle,leeds).
link(manchester,leeds).
%checks to see if X is in the supplied list
inlist( X, [X|_]).
inlist( X, [_|Ys]) :- inlist( X, Ys).
merge([],L,L).
merge([H|T],BList,CList):-
inlist(H,BList),
merge(T,BList,CList).
merge([H|T],BList,[H|CList]):-
merge(T,BList,CList),
not(inlist(H,BList)).
Merge works if I call it like this:
merge([a,b,c],[d,e,f],Result). --> [a,b,c,d,e,f]
or more importantly, what it was designed to solve:
merge([a,b,c],[a,d,e,f],Result). --> [a,b,c,d,e,f]
but if I call merge like this:
merge(X,[d,e,f],[a,b,c,d,e,f]).
There is a stack overflow. Is this generally acceptable behavior for a function that is designed to work one way? Or is there some convention that functions should work in both ways?
Edit: merge works if you call it like this:
merge([a,b,c],X,[a,b,c,d,e,f]). --> [d,e,f]
First, you should not call these "functions". "Predicates" is the correct term.
It's generally desirable for Prolog predicates to work "both ways". But it's not always possible or worth the effort in a particular situation.
To inform about ways a predicate is intended to be used mode-declarations can be used. These declarations conventions are different from system to system. These declarations are mostly serve as a documentation for programmers and rarely used by compilers, but can be used by testing frameworks and other helper tools.
Examples of conventions for mode declarations:
SWI-Prolog: http://www.swi-prolog.org/pldoc/man?section=modes
ECLiPSe CLP: http://eclipseclp.org/doc/applications/tutorial003.html#toc10 (scroll to 2.7.3 Mode declaration)
Also there is a convention (described in "The Craft of Prolog", for example) that input parameters of a predicate come first, output parameters come last.

what does" readin" predicate in prolog mean?

I have a question and I hope to help me:
what does" readin" predicate in prolog do?
I have searched in google but I have nothing
could you explain it to me with an example?
Regards.
I think you must be seeing readln not readin. The library predicate readln/1 reads tokens from an input line in the interactive SWI-Prolog console and makes a list of them. Most Prolog term reading predicates require a period to terminate input, but this predicate would include any terminating period in the list.
See here for a bit of documenation.

adding a search Path in SWI prolog

In many Prolog systems it is easy to add a new search path for consulting file.
In Yap for example, the predicate I know it is add_to_path(NewPath).
Is there a way to do the same in SWI Prolog ?. My question is specifically about adding one path to the already existing paths, I am aware of the file_search_path/2 predicate for declaring directories, and the cd/1 predicate for changing the current directory, but I would like to know if there is an alternative method, like the one I found in Yap.
thanks in advance !
There are several mechanisms to this. The first one I met was in C-Prolog, which indeed used clauses for library_directory/1. The current SWI-Prolog mechanism is derived from Quintus and also used in SICStus. It generalises from the library_directory/1 approach
be treating expressions of the form <alias>(Path) as a search over the path-alias <alias>.
Paths for an alias are defined using the predicate file_search_path/2. Now, library is just an alias. Normally, libraries are added using a clause file_search_path(library, Dir).
This mechanism has proven to be pretty flexible. Of course, it would be nice if Prolog systems get more compatible here. I think todays YAP also supports the file_search_path system. (2016 Edit: It does indeed, see YAP Prolog User's Manual: Changing the Compiler’s Behavior)
In your .plrc/.yaprc/.sicstusrc/.swiplrc:
:- multifile(library_directory/1).
library_directory('/home/ulrich/lftp/Prolog-inedit').

Resources