I have the following prolog code:
equiAngularTriangle(T) :-
equiLateralTriangle(T).
equiLateralTriangle(T) :-
equiAngularTriangle(T).
Is there a way to keep the interpreter from asking the same question twice? For instance, if I ask equiAngularTriangle(t), then it's going to ask equiLateralTriangle(t), then ask equiLateralTriangle(t), but it should know not to pursue that last one again, because the same question is on the "query stack".
Is there an option or some special syntax that lets Prolog behave the way I want it to?
If the prolog implementation supports tabling or you are using XSB then you could use it and get the desired behaviour.
You could also add a state argument:
%State = [Checked_for_equiAngular, Checked_for_equiLateral]
equiAngularTriangle(T, [_,false]) :-
equiLateralTriangle(T, [true,true]).
equiLateralTriangle(T, [false,_]) :-
equiAngularTriangle(T, [true,true]).
of course you will need to modify the rest of the clauses.
The last (and best imo) option is to rewrite your predicates. I guess that your code will be similar to this example:
ang(T):-
foo(T).
ang(T):-
lat(T).
lat(T):-
bar(T).
lat(T):-
ang(T).
so you could simply write:
ang(T):-
foo(T).
ang(T):-
bar(T).
lat(T):-
ang(T).
normally you will use some wrapper predicates if instead of foo(T) you had foo1(T),foo2(T) etc
Try XSB Prolog. It implements tabling which will short-circuit evaluation like in your case. You need to tell it which predicates should be tabled, though.
Related
I'm writing a software using SWI-Prolog where i have to find all the groundings of a predicate. In particular all the subtitutions that grounds the head and relative body supposing i can access independently head and body. Here an example of the behaviour i would like to obtain:
student(a).
student(b).
student(c).
play.
study(A):-
play,
student(A).
ground(Head,Body,Result):-
% some code
...
?- ground([study(A)],[play, student(A)],R).
R = [
[study(a):- play, student(a)],
[study(b):- play, student(b)],
[study(c):- play, student(c)]
]
And maybe generalize to:
dog(d).
dog(e).
study(A,B):-
play,
dog(B),
student(A).
?- ground([study(A,B)],[play, dog(B),student(A)],R).
R = [[study(a):- play, dog(d), student(a)] ... ]
So, for the body, find all non ground variables, ground them and then ground the head variables. Basically find all the combinations. The problem is to manage the body...
Maybe i can use for instance =../2, functor/3 and call/1 but i don't know how to takle the body (see this question/answer).
Thanks!
I am not sure why in the examples you provide the goal is inside a list and you also provide the body.
The procedure in this answer takes a goal, gets a matching clause and then gets all the solutions (binding the variables on the way). It may leave some variable unbound if they are not grounded by the goal. Upon backtracking it may take other clauses that match the initial goal.
ground(Goal, Body, LGroundClauses):-
clause(Goal, Body),
findall((Goal:-Body), call(Body), LGroundClauses).
sample run:
?- ground(study(A), Body, LClauses).
Body = (play, student(A)),
LClauses = [
(study(a):-play, student(a)),
(study(b):-play, student(b)),
(study(c):-play, student(c))
]
Note on the question and accepted solution that's a bit too long for a comment.
#gusbro writes (emphasis mine): "I am not sure why in the examples you provide the goal is inside a list and you also provide the body." I would also like to see a clarification on this point.
The ISO Prolog Core standard allows the clause/2 predicate to retrieve clauses for public predicates. But most Prolog systems, with a notably exception being SWI-Prolog, only allow using clause/2 to access clauses of dynamic predicates. Moreover, SWI-Prolog protect_static_code flag can be set to true to disable using clause/2 on static predicates. This makes the solution non-portable (and possibly undesirable in a deployment scenario) unless the predicates are declared dynamic. A possible alternative, assuming that indeed the Body argument is bound in a ground(Head,Body,Result) goal, would be to construct the clause body using the list of goals. Something like:
ground(Goal, BodyGoals, LGroundClauses):-
list_to_conjunction(BodyGoals, Body),
findall(Goal:-Body, call(Body), LGroundClauses).
This would remove the requirement of calling clause/2 and possibly making the predicates dynamic for portability. But does it make sense in your case?
I am using SWI Prolog and am surprised to find no obvious way to do this in Prolog. What I'm after is something similar to clause/2 but allows uninstantiated first argument (and is specific to the clauses in a given file, ie I don't want the entire Prolog library!). Here is what I wrote to find all the clauses
clauseX(H,B) :-
current_predicate(P/Arity),
functor(H,P,Arity),
absolute_file_name('filname.pl', AbsFileName),
predicate_property(H, file(AbsFileName)),
clause(H,B).
Is there a more concise way of doing this?
OK, so I've been able to shorten it somewhat, the first two literals aren't required, this will return clauses in the file filename.pl
clauseX(H,B) :-
absolute_file_name('filname.pl', AbsFileName),
predicate_property(H, file(AbsFileName)),
clause(H,B).
However I am still concerned about the efficiency of this and whether it has to consult the file every time clauseX is called
What I have now checks that X(Y) is not an accepted fact in my small DB. Since X(Y) returns false it will attempt to assert it. (I realize this presents problems when X is a rule and not a fact)
ifNotAdd(X,Y):-
not(call(X,Y)),
!,
assert(X(Y)).
For example, let's say that this fact is in the DB
mammal(dolphin).
I ask
ifNotAdd(mammal, elephant).
I want it to see that ? mammal(elephant). is false and then assert mammal(elephant).
Obviously the "assert(X(Y))." line is wrong but what do I replace it with? I'm trawling prolog documentation and forums for the answer but no luck so far. I'm also trying to write something that will do this on my own.
EDIT
I need to edit the DB in order to have a dynamic database the user can interact with. I'm building an argument machine and I need to allow the user to tell the system that they "know the fact for sure" so that the system can deal with knowledge outside of it's domain.
In the vein of http://en.wikipedia.org/wiki/Reason_maintenance
Cheers,
You can use the univ operator =../2 to construct the term before asserting it (note that the predicate in question has to be declared dynamic for it to work) :
ifNotAdd(X,Y):-
not(call(X,Y)),
!,
Term =.. [X, Y],
assert(Term).
BTW if you want ifNotAdd/2 not to fail when it doesn't need to add the fact to the db, you should wrap that in a if structure, plus, not/1 is deprecated, (\+)/1 is preferred :
:- dynamic(mammal/1).
mammal(dolphin).
ifNotAdd(X, Y):-
( \+ call(X, Y)
-> Term =.. [X, Y],
assert(Term)
; true).
But I'm not sure what you're trying to do is right there. Quite often when a beginner in prolog wants to manipulate the database it's because a particular prolog mechanism isn't properly understood. Then again you might not be a beginner and my remark could be dumb, in which case, just forget it ! But if you do are a beginner, you may want to precise what you're trying to achieve here so that we can confirm that those manipulations are needed !
I'm stuck on a simple problem in prolog.
Let's consider the program
worker(bill).
worker(smitt).
worker(fred).
worker(dany).
worker(john).
car(bmw).
car(mazda).
car(audi).
owner(fred,mazda).
owner(dany,bmw).
owner(john,audi).
I need to add one more predicate no_car(X),that will be true if the worker X has no cars,i.e,if we input a query
?:- no_car(X).
the prolog should answer
X=smitt,
X=bill,
yes
What i have done is
hascar(X):-owner(X,_).
nocar(X):- worker(X),not hascar(X).
But this approach does not work because anonimous variables are avaliable only for queries.
So,i'm really stuck on this.
I know there are "NOT EXISTS" words in SQL which allow to express this logic in a query,but is there something similar to them in prolog?
The following works for me and provides the expected result:
no_car(W):-
worker(W),
\+ owner(W, _).
Now this is close to what you have. For one thing, you can of course use _ in predicates; it is not restricted to queries. I usually use \* for negation, and not gives me a syntax error here!?
EDIT:
Ah! In my, albeit dated, version of Prolog you have to use not(hascar(X)) to make it work, so not/1 needs to be used as a term, not an operator. But the manual also says not is deprecated in favor of \+.
I'm working on a college assignment where I must verify if a certain clause (as a fact or as a rule) exists in the current clause database.
The idea is to use a rule whose head is verify(+name, +arguments). This rule should be true if in the database exists another rule whose head is name(arguments)
Any help would be greatly appreciated...
Using call/1 is not a good idea because call/1 actually calls the goal, but you just want to find out if the fact/rule exists, and you don't want to wait after a long calculation that the call might trigger, and you don't want to have something printed on the screen if the called rule in turn calls e.g. writeln/1. In addition, you would want verify/2 to succeed even if the call failed (but the fact/rule is otherwise there).
As a solution, SWI-Prolog offers callable/1
callable(+Term)
True if Term is bound to an atom or a compound term,
so it can be handed without type-error to call/1, functor/3 and =../2.
Here are two version of verify/2, one using call/1 and the other using callable/1.
verify1(Name, Arguments) :-
Term =.. [Name | Arguments],
call(Term).
verify2(Name, Arguments) :-
Term =.. [Name | Arguments],
callable(Term).
father(abraham, isaac) :-
writeln('hello').
father(abraham, adam) :-
fail.
Are you familiar with the concept of unification? What you have to do is: just call a predicate that looks like the one you're trying to find.
So, say in your database is:
father(abraham,isaac).
Now you want to call something like:
verify(father,[abraham,isaac]).
Your predicate body will then have to contain a mechanism of calling father(abraham,isaac). which should then return true. Calling father(abraham,adam) should fail.
You will need two predicates for this: =../2 and call/2. If you are using SWI-Prolog, call help(=..). and help(call) from the interpreter's command line to access the documentation.
I hope I didn't spoil the assignment for you. You still have to find out what to do with partially instantiated predicates (so, say something like verify(father,[abraham,X]). on your own, but it shouldn't be hard from here.
Good luck.