What is the best way to express a total order relation in Prolog ?
For example, say I have a set of facts
person(tim)
person(ana)
person(jack)
...
and I want to express the following truth about a person's fortune: for each two persons X and Y, if not(X==Y), either X is richer than Y or Y is richer than X.
So my problem is that the richer clause should be capable of instantiating its variables and also to ensure that it is never the case that richer(X, Y) and richer(Y, X) at the same time.
Here is a better example to see what I mean:
person(tim).
person(john).
happier(tim, john).
hates(X, Y) :- person(X), person(Y), richer(Y, X).
hates(X, Y) :- person(X), person(Y), richer(X, Y), happier(Y, X).
Now the answer to the query hates(john, tim) should return true, because if richer satisfies the mentioned property, one of those two hates clauses must be true. In a resolution based inference engine I could assert the fact (richer(X, Y) V richer(Y, X)) and the predicate hates(john, tim) could be proved to be true.
I don't expect to be able to express this the same way in Prolog with the same effect. However, how can I implement this condition so the given example will work ?
Note also that I don't know who is richer: tim or john. I just now that one is richer than the other.
Thank you.
you cannot write in pure Prolog that a predicate should be a total order: that would require higher order logic since you want to declare a property about a predicate.
this is a predicate that checks if a relationship is total order on a finite set:
is_total_order(Foo,Set):-
forall(
(member(X,Set),
member(Y,Set)),
(
XY =.. [Foo,X,Y],
YX =.. [Foo,Y,X],
(call(XY);call(YX)), %checking if the relationship is total
\+ (call(XY),call(YX), X\=Y) %checking if it's an order
)
).
the operator =../2 (univ operator) creates a predicate from a list (ie: X =.. [foo,4,2]. -> X = foo(4,2)) and the predicate call/1 calls another predicate.
As you can see we use meta-predicates that operate on other predicates.
For an total order on infinite sets things get more complicated since we cannot check every single pair as we did before. I dont even think that it can be written since proving that a relationship is a total order isn't something trivial.
Still, this doesnt declare that a predicate is a total order; it just checks if it is.
So I believe your question is the best way to represent the relation between these 3 people. If you don't actually care about their wealth #'s, just their relative order, you could add predicates like this -
is_richer(tim, anna).
is_richer(anna, jack).
and then a predicate to find all people who X is richer than -
richer(X, Z) :-
is_richer(X, Z).
richer(X, Z) :-
is_richer(X, Y),
richer(Y, Z).
If your is_richer predicate contains cycles though (in this example, if you added is_richer(jack, tim)), this could explode. You need to track where you have visited in this tree.
An example run of richer would be:
?- richer(X, Y).
X=tim
Y=anna ;
X=anna
Y=jack ;
X=tim
y=jack ;
no
Related
I am working through Seven Languages in Seven Weeks, but there is something I don't understand about prolog. I have the following program (based on their wallace and grommit program):
/* teams.pl */
onTeam(a, aTeam).
onTeam(b, aTeam).
onTeam(b, superTeam).
onTeam(c, superTeam).
teamMate(X, Y) :- \+(X = Y), onTeam(X, Z), onTeam(Y, Z).
and load it like this
?- ['teams.pl'].
true.
but it doesn't give me any solutions to the following
?- teamMate(a, X).
false.
it can solve simpler stuff (which is shown in the book):
?- onTeam(b, X).
X = aTeam ;
X = superTeam.
and there are solutions:
?- teamMate(a, b).
true ;
false.
What am I missing? I have tried with both gnu prolog and swipl.
...AND THERE IS MORE...
when you move the "can't be your own teammate" restriction to then end:
/* teams.pl */
onTeam(a, aTeam).
onTeam(b, aTeam).
onTeam(b, superTeam).
onTeam(c, superTeam).
teamMate(X, Y) :- onTeam(X, Z), onTeam(Y, Z), \+(X = Y).
it gives me the solutions I would expect:
?- ['teams.pl'].
true.
?- teamMate(a, X).
X = b.
?- teamMate(b, X).
X = a ;
X = c.
What gives?
You have made a very good observation! In fact, the situation is even worse, because even the most general query fails:
?- teamMate(X, Y).
false.
Declaratively, this means "there are no solutions whatsoever", which is obviously wrong and not how we expect relations to behave: If there are solutions, then more general queries must not fail.
The reason you get this strange and logically incorrect behaviour is that (\+)/1 is only sound if its arguments are sufficiently instantiated.
To express disequality of terms in a more general way, which works correctly no matter if the arguments are instantiated or not, use dif/2, or, if your Prolog system does not provide it, the safe approximation iso_dif/2 which you can find in the prolog-dif tag.
For example, in your case (note_that_I_am_using_underscores_for_readability instead of tuckingTheNamesTogetherWhichMakesThemHarderToRead):
team_mate(X, Y) :- dif(X, Y), on_team(X, Z), on_team(Y, Z).
Your query now works exactly as expected:
?- team_mate(a, X).
X = b.
The most general query of course also works correctly:
?- team_mate(X, Y).
X = a,
Y = b ;
X = b,
Y = a ;
X = b,
Y = c ;
etc.
Thus, using dif/2 to express disequality preserves logical-purity of your relations: The system now no longer simply says false even though there are solutions. Instead, you get the answer you expect! Note that, in contrast to before, this also works no matter where you place the call!
The answer by mat gives you some high-level considerations and a solution. My answer is a more about the underlying reasons, which might or might not be interesting to you.
(By the way, while learning Prolog, I asked pretty much the same question and got a very similar answer by the same user. Great.)
The proof tree
You have a question:
Are two players team mates?
To get an answer from Prolog, you formulate a query:
?- team_mate(X, Y).
where both X and Y can be free variables or bound.
Based on your database of predicates (facts and rules), Prolog tries to find a proof and gives you solutions. Prolog searches for a proof by doing a depth-first traversal of a proof tree.
In your first implementation, \+ (X = Y) comes before anything else, so it at the root node of the tree, and will be evaluated before the following goals. And if either X or Y is a free variable, X = Y must succeed, which means that \+ (X = Y) must fail. So the query must fail.
On the other hand, if either X or Y is a free variable, dif(X, Y) will succeed, but a later attempt to unify them with each other must fail. At that point, Prolog will have to look for a proof down another branch of the proof tree, if there are any left.
(With the proof tree in mind, try to figure out a way of implementing dif/2: do you think it is possible without either a) adding some kind of state to the arguments of dif/2 or b) changing the resolution strategy?)
And finally, if you put \+ (X = Y) at the very end, and take care that both X and Y are ground by the time it is evaluated, then the unification becomes more like a simple comparison, and it can fail, so that the negation can succeed.
So I just started Prolog and I was wondering two things:
1) Is there built in functions (or are they all called predicates?) for simple things like max of 2 numbers, or sine of a number, etc... If so, how do I access them?
2) How can I call a predicate from another one? I wrote two predicates called car and cdr. car returns the head of a list and cdr returns the list without the head. But now I want to call car on the cdr. Here are some examples for clarification:
car([3,4,5,5], H). would return H = 3
cdr([3,4,5,5],L). would return L = [4,5,5]
and what I am asking is how can I do this:
car(cdr[3,4,5,5]))
??
As others have pointed out, the predicates in Prolog are called that for a reason: they really aren't functions. Many newcomers to Prolog start out by trying to map the functionality they know in other languages over to Prolog and it generally fails. Prolog is a very different programming tool than most other languages. So it's a bit like using a variety of hammers for a long time, then having someone hand you a wrench, and you wonder why it doesn't make a good hammer.
In Prolog, predicates are a means of declaring relations between entities. If you say foo(a, b) it means there's a relationship between a and b called foo. You've probably seen the examples: knows(joe, jim). and knows(jim, sally). And you can define a relation, like:
remotely_acquainted(X, Y) :- knows(X, Z), knows(Z, Y), \+ knows(X, Y).
Or something like that.
A predicate does not return a value. It either succeeds or it fails. If you have a sequence of predicates separated by commas (an "and" relationship) and Prolog encounters a predicate that fails, it backs up (backtracks) to the nearest prior predicate which it can make succeed again with different instantiation of its arguments and moves forward again.
Just to add a little to the confusion, there are some predicates in Prolog designed specifically for the evaluation of arithmetic expressions. These act like functions, but they are special case. For example:
X is Y / gcd(Z, 4).
Here, gcd of Z and 4 is computed an its value returned, and then Y is divided by that value and the result is instantiated into X. There are a variety of other functions as well, such as max/2, sin/1, etc. You can look them up in the documentation.
Arithmetic comparative operators function this way as well (using =:=/2, >/2, </2, etc with numeric expressions). So if you say:
X < Y + Z
The Prolog will consider numerical evaluation of these arguments and then compare them.
So having said all that, Prolog does allow embedding of term structures. You could have something like:
car(cdr([1,2,3]))
as a term. Prolog will not interpret it. Interpretation is left up to the programmer. I could then create a predicate which defines an evaluation of such terms:
car([H|_], H).
cdr([_|T], T).
proc_list(car(X), Result) :-
proc_list(X, R1),
car(R1, Result), !.
proc_list(cdr(X), Result) :-
proc_list(X, R1),
cdr(R1, Result), !.
proc_list(X, X).
The cut in the above clauses prevents backtracking to proc_list(X, X) when I don't want it.
Then:
| ?- proc_list(car(cdr([1,2,3])), R).
R = 2
yes
| ?- proc_list(car(cdr(cdr([1,2,3]))), R).
R = 3
yes
| ?-
Note this is a simple case and I may not have captured all of the subtleties of doing a proper sequence of car and cdr. It can also be made more general using =.. and call, etc, instead of discrete terms car and cdr in the parameters. For example, a slightly more general proc_list might be:
proc_list(Term, Result) :-
Term =.. [Proc, X], % Assumes terms have just one argument
member(Proc, [car, cdr]), % True only on recognized terms
proc_list(X, R1), % Recursively process embedded term
ProcCall =.. [Proc, R1, Result], % Construct a calling term with Result
call(ProcCall), !.
proc_list(X, X).
This technique of processing a term does step away from relational behavior which Prolog is best at, and leans into functional behavior, but with an understand of how Prolog works.
Prolog has a really different attitude to computing...
You don't define functions, but relations among arguments. The most similar and well known language I'm aware of is SQL. Think of predicates as tables (or stored procedures, when some computation not predefined by database engine is required).
car([H|_],H).
cdr([_|T],T).
car_of_cdr(L, Car) :- cdr(L, Cdr), car(Cdr, Car).
but since lists' syntax is a core part of the language, a better definition could be
car_of_cdr([_,X|_], X).
Anyway, I think you should spend some time on some Prolog tutorial. SO info page has much more information...
:- use_module(support).
This means the module will use predicates written in other modules.
<module_name>:<predicate_name>(<atoms / Variables>).
This way you can call a predicate in another module.
How do I define a binary operation on a list in prolog and then check its properties such as closure , associative, transitive , identity etc. ? I am new to prolog.. I don't know whether it is the place to ask but I tried and I didn't come across anything somewhere.
In Prolog you define predicates, i.e. relations among a symbol (called functor) and its arguments.
A predicate doesn't have a 'return value', just a 'truth value', depending of whether it can be evaluated WRT its arguments. Then your question it's not easy to answer.
Associativity, transitivity, identity, are of little help when it come down to speaking about predicates. The first and most common property we wish to evaluate is termination, because Prolog control flow it's a bit unusual and can easily lead to infinite recursion.
Anyway, the simpler binary relation on a list is member/2, that holds when its first argument it's an element of the second argument (the list).
member(X, [X|_]).
member(X, [_|T]) :- member(X,T).
I can't see any benefit in assessing that it's not associative, neither transitive (its arguments are of different types !).
Common operations like intersection, union, etc typically needs 3 arguments, where the last is the result of the operation performed between 2 lists.
Identity in Prolog (that is an implementation of first order logic) deserves a special role. Indeed, the usual programming symbol = used to assess identity, really performs a (potentially) complex operation, called unification. You can see from the (succint) documentation page that it's 'just' a matching between arbitrary terms.
You could do something like this:
% Define sets I want to try
set7([0,1,2,3,4,5,6]).
% Define operations
% Sum modulo 7
sum7(X, Y, R) :-
R is (X+Y) mod 7.
% Normal sum
nsum(X, Y, R) :-
R is X + Y.
% A given set is closed if there is not a single case which
% indicates that it is not closed
closed(S, Operator) :-
\+ n_closed(S, Operator, _), !.
% This predicate will succeed if it finds one pair of elements
% from S which, when operated upon, will give a result R which
% is outside of the set
n_closed(S, Operator, R) :-
member(X, S),
member(Y, S),
Operation =.. [Operator, X, Y, R],
Operation,
\+ member(R, S).
When you execute it, you get these results:
| ?- set7(S), closed(S, sum7).
(1 ms) yes
| ?- set7(S), closed(S, nsum).
no
I'm not convinced my closure check is optimal, but it gives some ideas for how to play with it.
How to implement rule1 that succeeds iff rule2 returns two or more results?
rule1(X) :-
rule2(X, _).
How can I count the results, and then set a minimum for when to succeed?
How can I count the results, and then set a minimum for when it's true?
It is not clear what you mean by results. So I will make some guesses. A result might be:
A solution. For example, the goal member(X,[1,2,1]) has two solutions. Not three. In this case consider using either setof/3 or a similar predicate. In any case, you should first understand setof/3 before addressing the problem you have.
An answer. The goal member(X,[1,2,1]) has three answers. The goal member(X,[Y,Z]) has two answers, but infinitely many solutions.
So if you want to ensure that there are at least a certain number of answers, define:
at_least(Goal, N) :-
\+ \+ call_nth(Goal, N).
with call_nth/2 defined in another SO-answer.
Note that the other SO-answers are not correct: They either do not terminate or produce unexpected instantiations.
you can use library(aggregate) to count solutions
:- use_module(library(aggregate)).
% it's useful to declare this for modularization
:- meta_predicate at_least(0, +).
at_least(Predicate, Minimum) :-
aggregate_all(count, Predicate, N),
N >= Minimum.
example:
?- at_least(member(_,[1,2,3]),3).
true.
?- at_least(member(_,[1,2,3]),4).
false.
edit here is a more efficient way, using SWI-Prolog facilities for global variables
at_least(P, N) :-
nb_setval(at_least, 0),
P,
nb_getval(at_least, C),
S is C + 1,
( S >= N, ! ; nb_setval(at_least, S), fail ).
with this definition, P is called just N times. (I introduce a service predicate m/2 that displays what it returns)
m(X, L) :- member(X, L), writeln(x:X).
?- at_least(m(X,[1,2,3]),2).
x:1
x:2
X = 2.
edit accounting for #false comment, I tried
?- call_nth(m(X,[1,2,3]),2).
x:1
x:2
X = 2 ;
x:3
false.
with call_nth from here.
From the practical point of view, I think nb_setval (vs nb_setarg) suffers the usual tradeoffs between global and local variables. I.e. for some task could be handly to know what's the limit hit to accept the condition. If this is not required, nb_setarg it's more clean.
Bottom line: the better way to do would clearly be using call_nth, with the 'trick' of double negation solving the undue variable instantiation.
(This is NOT a coursework question. Just my own personal learning.)
I'm trying to do an exercise in Prolog to delete elements from a list. Here's my code :
deleteall([],X,[]).
deleteall([H|T],X,Result) :-
H==X,
deleteall(T,X,Result).
deleteall([H|T],X,[H|Result]) :- deleteall(T,X,Result).
When I test it, I first get a good answer (ie. with all the Xs removed.) But then the backtracking offers me all the other variants of the list with some or none of the instances of X removed.
Why should this be? Why do cases where H==X ever fall through to the last clause?
When you are using (==)/2 for comparison you would need the opposite in the third rule, i.e. (\==)/2. On the other hand, such a definition is no longer a pure relation. To see this, consider deleteall([X],Y,Zs), X = Y.
For a pure relation we need (=)/2 and dif/2. Many Prologs like SWI, YAP, B, SICStus offer dif/2.
deleteall([],X,[]).
deleteall([H|T],X,Result) :-
H=X,
deleteall(T,X,Result).
deleteall([H|T],X,[H|Result]) :-
dif(H,X),
deleteall(T,X,Result).
Look at the answers for deleteall([X,Y],Z,Xs)!
Edit (after four years):
More efficiently, but in the same pure vein, this can be written using if_/3 and (=)/3:
deleteall([], _X, []).
deleteall([E|Es], X, Ys0) :-
if_( E = X, Ys0 = Ys, Ys0 = [E|Ys] ),
deleteall(Es, X, Ys).
The last clause says that when removing X from a list, the head element may stay (independently of its value). Prolog may use this clause at any time it sees fit, independently of whether the condition in the preceding clause is true or not backtrack into this clause if another clause fails, or if you direct it to do so (e.g. by issuing ; in the top-level to get the next solution). If you add a condition that the head element may not equal X, it should work.
Edit: Removed the incorrect assertion I originally opened with.