Prolog: Replace fact using fact - prolog

I am trying to implement a predicate replace(+OldFact,+NewFact)
which succeed only if the OldFact existed. If this succeeds then the
NewFact must be added to the set of clauses and the OldFact must be
deleted.
How do I do this?
I am not able to figure out clearly that how to achieve this
replacement using facts as well as how to use those assert and retract
database manipulation commands.
Thanks.

If I take the request at face value, you only need to use the predicates I mentioned in my comment. Your predicate would look something like this:
replace_existing_fact(OldFact, NewFact) :-
( call(OldFact)
-> retract(OldFact),
assertz(NewFact)
; true
).
I'm assuming that if the OldFact is not found, then you want the predicate simply to succeed. If failure of the predicate is acceptable if the old fact doesn't exist, this would be written simply:
replace_existing_fact(OldFact, NewFact) :-
call(OldFact),
retract(OldFact),
assertz(NewFact).
Note that if you have more than one same OldFact in the database, this predicate will backtrack for each one, replacing one occurrence on each backtrack. If you only want to replace one of them, you could use a cut:
replace_existing_fact(OldFact, NewFact) :-
call(OldFact), !, % Don't backtrack to find multiple instances of old fact
retract(OldFact),
assertz(NewFact).
Alternatively, if you want to replace each one without being prompted for backtracking:
replace_each_existing_fact(OldFact, NewFact) :-
forall(replace_existing_fact(OldFact, NewFact), true).

Related

Prolog Cut operator

I defined my knowledge base as:
edge(mammal,isa,animal).
edge(human,isa,mammal).
edge(simba,isa,human).
edge(animal,swim,bybirth).
edge(human,swim,mustlearn).
path(X,Y) :- edge(X,isa,Y).
path(X,Y) :- edge(X,isa,Z), path(Z,Y).
swim(X,Y) :- edge(X,swim,Y).
swim(X,Y) :- path(X,Z), swim(Z,Y).
Now, to use the above knowledge base, I use the following:
?- swim(simba,bybirth).
?- swim(simba,mustlearn).
And for both the queries, Prolog returns true. I want Prolog to check for the property swim locally first, then look at the direct parent, and so on in a hierarchical fashion. And it should stop searching as soon as we know that Simba "mustlearn" to swim, and shouldn't look any further. Thus, it should return false for the first query and true for the second.
I know it has to be done by limiting backtracking. I tried using the cut and not operators, but couldn't succeed. Is there a way to achieve this?
I tried it and ran into a problem too. I thought this might work:
swim(X,Y) :- once((edge(X,swim,Y); path(X,Z), swim(Z,Y))).
It doesn't work, because if Y is already instantiated on the way in, the first step will fail to unify and it will try the second route going through the human intermediate. So even though the query only produces one result, it can be fooled into producing swim(simba, bybirth). The solution is to force Prolog to commit to a binding on another variable and then check that binding after the commitment:
swim(X,Y) :-
once((edge(X,swim,Method); path(X,Z), swim(Z,Method))),
Method = Y.
This tells Prolog, there is only one way to get to this method, so find that method, and then it must be Y. If you find the wrong method, it won't go on a search, it will just fail. Try it!

Using OR operator with different / non existent facts in Prolog

I have a fact:
loves(romeo, juliet).
then i have an 'or' rule:
dances(juliet) :- loves(romeo, juliet).
dances(juliet) :- dancer(juliet).
As you can see dancer fact does not exist but this should be no problem and dances(juliet) should return me true. Instead it returns me true and then throws an exsitence exception about dancer fact. Is there a way to write rules for non existent facts or rules? Do I need to check if the fact exists?
To achieve "failure if not existant", you can declare your predicate dynamic using the directive dynamic/1.
For example:
:- dynamic dancer/1.
If you add this directive to your program, you get:
?- dances(X).
X = juliet .
and no errors.
As far as I know there is not a way to use a nonexistant predicate. You could either check if the rule exists using the methods described in this question or you could just have some sort of placeholder to make sure that it does exist. A rule doesn't seem very useful if it is always false, so just write a couple of the true cases before you use it.
dancer(someone). %% To make sure that fact exists
loves(romeo, juliet).
dances(juliet) :- loves(romeo, juliet).
dances(juliet) :- exists(dancer), dancer(juliet).
Technically, you could do something like this:
dances(juliet) :- catch(dancer(juliet),
error(existence_error(procedure, dancer/1), _),
false
).
Which will run dancer(juliet) if the predicate exists, fail if it doesn't, and error otherwise.
I wouldn't say this is a very advisable thing to do though.

prolog expanding predicate to iterate for multiple results, combining / resolving result sets

I have a predicate "lookupOptions" which returns one by one some lists (Menus).
I'm trying to get it to satisfy the case of multiple inputs. I can return a single set of options as follows, by reading the head of the "list_places" list.
find_options(Restaurant,Town,Menu) :- lookupOptions(Restaurant,H,Menu), list_places(Town,[H|T])
But, I'm not able to get it to iterate.
I have tried a lot of things, these were my best efforts so far.
a) standard enough iteration, but it wont resolve ...
doStuff(X,[],_).
doStuff(Restaurant,[H|T],_):- lookupOptions(Resturant,H,_), doStuff(Restaurant,T,_).
find_options(Restaurant,Town,Menu) :- doStuff(Restaurant,[H|T],Menu), list_places(Town,[H|T]).
b) expanding the goal predicate ...
find_options(_,Town,[H|T],_)
find_options(Restaurant,Town,Menu) :- find_options(Restaurant,Town,[],Menu).
find_options(Restaurant,Town,X,Menu) :- list_places(Town,X).
find_options(Restaurant,Town,[H|T],Menu) :- lookupOptions(Restaurant,[H],Menu), find_options(Restaurant,Town,T,Menu).
Would either of these work ? if the pattern was written correctly. Or if there was an appropriate cut put in place?
Any help most appreciated ...
It's no clear on what you want iterate. Prolog uses backtracking to examine all alternatives, then you should start backtracking if you are after some alternative, or use the all solutions family.
Now I think you want simply declare there could be more find_options(Restaurant,Town,Menu). Then try replacing the head match [H|T] with this:
find_options(Restaurant,Town,Menu) :-
lookupOptions(Restaurant,H,Menu),
list_places(Town, Places),
member(H, Places).
BTW T is a singleton in your original rule. This could be a hint for the need of generalize it.

how can I print all database facts in prolog

I have a database in prolog, all I want to do is enuamrate through its element and print one by one. How can this be done?
fact(is(mike,asthmatic)).
fact(has(andy,highPressure)).
fact(is(mike,smoker)).
I have written this, which works ok but it removes elements from the database, so I want to access them without removing.
print:-
retract(factA(P)),
write(factA(P)),nl,
fail.
print.
You might also consider using forall/2 predicate:
print:-
forall(fact(P), writeln(P)).
Well, you were almost there :
print :-
fact(A),
writeln(A),
First, we get a fact and print it.
fail;true.
Then, we backtrack (through fail) until no solution is left. To avoid returning false, we add the disjunction with true.
Note that you can proceed differently, like :
print2 :-
findall(Fact, fact(Fact), Facts),
maplist(writeln, Facts).
But if you go that road, prefer #gusbro solution, it's better !

How to verify if a rule exists in a prolog file clause database

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.

Resources