Representing truth regarding beliefs in prolog - 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).

Related

Is there a way to tell Prolog that the argument X of a specific predicate f(X) is always true if the predicate is true?

Apologies if this is a silly question, but I haven't been able to find an answer.
Suppose I have some predicate, proven_true(X), where X is some sort of factual statement like person(bob). Is there any way to tell Prolog that if proven_true(X) is true, then X itself is also true? Say I define proven_true(X) as
proven_true(X) :- condition_1(X), condition_2(X) ... condition_n(X).
and in my facts, all of the above conditions are true for X = person(bob). Then I not only want proven_true(person(bob)) to be true, but also person(bob) to be true.
Obviously for a specific X this would be doable, but I couldn't get it to work for variable X. My first try was something along the lines of
X :- f(x).
but that didn't work because I was treating the head of the rule itself as a variable.
Thanks in advance for any assistance!
Edit:
To clear up some confusion, suppose my code was:
proven_true(X) :- condition_1(X), condition_2(X).
condition_1(dog(fido)).
condition_2(dog(fido)).
Then I could query proven_true(dog(X)) and get fido, but if I queried dog(X), I wouldn't get a result. So if I then wanted to use the fact that fido is a dog as a condition for another rule, I'd have to wrap it in the proven_true() predicate, e.g.:
barks(X) :- proven_true(dog(X)).
What I would like is some way to have X always be true if proven_true(X) is also true. That way, I could write the above rule as
barks(X) :- dog(X).
For a specific term like dog(X), I could achieve this using
dog(X) :- proven_true(dog(X)).
but I'd like to be able to achieve it for all terms. Something like
X :- proven_true(X).
(although this doesn't work). Hopefully that clears up confusion.
You want asserta/1 or assertz/1. It will modify the Prolog database during run-time.
proven_true(X) :- condition_1(X), condition_2(X), assertz(X).
condition_1(dog(fido)).
condition_2(dog(fido)).
assertz adds the assertion at the end of the database.

Want PROLOG to require == matches on already matched variables, = for others

I have this code:
contradicts(at(X,_),location(X)).
mustContradict(A, B) :- contradicts(A, B).
contradicts/2 is meant to say: if X is at somewhere, then X can't itself be a location.
mustContradict/2 is meant to say: succeed if A and B are contradictory.
When I run it to detect that if you're at a location, you can't be a location (mustContradict(at(Thing,Location),location(Thing)).) -- it succeeds, as it should. On this one, however:
mustContradict(at(Thing,Location),location(Location)).
it also succeeds, with variable assignment Thing=Location.
I could probably mangle a way to make it ensure all variables are identical when trying to match, something like:
A=at(Thing,Location),B=location(Location),
contradicts(A,AsContradiction),
B==AsContradiction.
but then it would fail on the first test, trying to verify that a Thing that is "at" something can't be a location.
What I think I want is to be able to distinguish variables that are already assigned to other variables from those that are so far not matched to anything.
You shouldn't check your predicates with variables (starting with uppercase), but with terms (starting with lowercase).
mustContradict(at(thing,location),location(location)). fails as it should since thing doesn't equal location. In your example you use variables that can be assigned anything.
I have no idea why you are reassigning mustContradict(A, B) :- contradicts(A, B).
you can change contradicts definition to contradicts(at(X,Y),location(X)) :- not(X == Y).
I wonder if this is not what you wanted to achieve:
at(thing, location).
at(thingLocation, location).
location(location).
location(thingLocation).
contradicts(X) :- at(X,_), location(X).
now contradicts(X). succeeds with X = thingLocation
Looks like the solution was to convert all variables to atoms. Only converting those that were shared or repeated meant that the others could bind to inappropriate things (as in the first example), so the behavior didn't change.
Binding them to atoms, as in this code:
contradicts(at(X,_),location(X)).
mustContradict(X,Y) :-
replaceVariablesWithAtoms(X,NewX), replaceVariablesWithAtoms(Y,NewY),
contradicts(NewX,NewY).
replaceVariablesWithAtoms(Term,NewTerm) :-
Term =.. TermAsList,
terms_to_atoms(TermAsList,NewTermAsList),
NewTerm =..NewTermAsList.
terms_to_atoms([],[]).
terms_to_atoms([H|T],[NewH|NewT]) :-
terms_to_atoms(T,NewT),
term_to_atom(H,NewH).
gives the right answer to both queries.
?- mustContradict(at(Thing,Location),location(Thing)).
true.
?- mustContradict(at(Thing,Location),location(Location)).
false.
Wouldn't it be easier just to write it as you have defined the problem statement:
I have this code:
contradicts(at(X,_),location(X)).
mustContradict(A, B) :- contradicts(A, B).
contradicts/2 is meant to say: "if X is at somewhere, then X can't itself be a location."
mustContradict/2 is meant to say: "succeed if A and B are contradictory."
Assuming that your at/2 and location/1 are facts/predicates in your prolog program . . . why not something like this:
contradiction(X) :- at(X,_), location(X) .

Transform in meta-predicate at prolog

I have been reading and noticed that predicates like call are called meta-predicates and they can return other predicates as a result (Don't know if return is a good use of the word here) for example here:
assert(call(goal, X,Y)).
Edit: lurker called me to reason, this doesn't work.
I understand that it's not supposed to call predicates functions but is there a way of making assert over a predicate that will be unknown until runtime?
I want to use the same insertion predicate for more than one fact , so assert(fact(X)) does not suit my needs. I can retrieve the fact's name on runtime but how could i use assert without unifying a fact directly?
You should explicitly use assertz/1 or asserta/1. assert/1 is an alias for assertz/1 but only in some Prolog systems.
The call:
assertz(call(goal, X, Y)).
will attempt to assert a fact with functor call. This is what it tries to assert in the database:
call(goal, _, _).
Since call is a functor already defined in Prolog as a predicate, it will generate an error. If you were to assert, say, the following:
assertz(foo(goal, X, Y)).
It would be successful, but what you'd get in the database is something like this:
foo(goal, _, _).
Which doesn't seem very useful. In other words, the assert is just doing what you asked it: asserting a term that you just described whose functor is call or foo in the above cases.
If you want to assert an actual predicate, you just need to use the fact that a predicate is a term whose functor is :-. The general predicate term would be something like Head :- Body or, in canonical form, ':-'(Head, Body). This kind of term can be asserted, as long as at least Head is instantiated before the assertz call.
assertz(':-'(Head, Body)).
Or equivalently (since :- is an operator):
assertz((Head :- Body)).
If I do this:
Head = goal, assertz((Head :- Body)).
I get (using listing/0):
:- listing.
goal :-
call(_).
Not very useful. So Body really should be instantiated before making this assertz/1 call. Here then is another example:
Head = double(X, Y), Body = (Y is X * 2), assertz((Head :- Body)).
Which now results in the following:
:- listing.
double(A, B) :-
B is A * 2.

Convert list into functor parameter

I got stuck to implement a logic. At some instance in my program I have a list say named as List.
The length of this List is variable and I don't know in advance. Now I have to pass this list in a functor to create a fact and I am unable to implement it. For eg:
if List is [first] then it should add the fact functor(first).
if List is [first,second] then it should add the fact functor(first,second).
if List is [first,second,third] then it should add the fact functor(first,second,third).
and so on...
I was trying by =.. but here I am unable to map that variable length constraint. For fixed length I am able to perform but I don't know in advance that how many elements will be there in list.
Any suggestions to implement this logic. Thanks.
I don't quite understand your problem with =.. but this worked for me:
assert_list(List) :-
Term =.. [my_functor|List],
assert(Term).
Note that I use my_functor instead of simply functor because functor/3 is a built-in predicate so you cannot assert ternary functor facts (functor(first, second, third)).
Calling it:
?- assert_list([first,second,third]).
true.
Checking that it works:
?- listing(my_functor).
:- dynamic user:my_functor/3.
user:my_functor(first, second, third).
true.
Note that technically, the different n-ary my_functor/n predicates are not the same predicates. You must use different queries in your program for each n. To circumvent this, you could simply assert the list as one and only argument of my_functor:
?- List = [first, second, third],
assert(my_functor(List)).
true.
?- listing(my_functor).
:- dynamic user:my_functor/3.
user:my_functor([first, second, third]).
true.
My SWI-Prolog version is 5.7.5.

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