2
votes

Hi guys :) I have encountered problem during programming in prolog. I have partial order defined as facts, and I have defined maximal and greatest element as predicates. We can think of partial order like greater or equal, so le(6,7) is something like 6 <= 7.

le(6,7).
le(4,4).
le(6,6).
le(5,6).
le(5,5).
le(4,5).
le(4,4).

maximal(X) :-
    not((le(X,Z) , X\=Z)).
greatest(X) :-
    not(le(X,_)).
minimal(X) :-
    not((le(Z,X) , X\=Z)).
smallest(X) :-
    not(le(_,X)).

When I have typed query like maximal(7) the prolog output is true, and when I ask prolog to find the solution like maximal(X) it gives mi fail. I am beginner prolog programmer, so sorry if the question is too trivial, but I couldn't find the solution on my own.

1
You should try avoid using not so much, if possible. Prolog can't "generate" a solution often times when there's negation involved unless it knows what the "universe of choices" is. For example, if you had a trivial predicate, is_seven(X) :- X = 7, you could query is_seven(X) and get X = 7. However, if you have is_not_seven(X) :- X \= 7. (or is_not_seven(X) :- not(X = 7).)` A query like is_not_seven(X) fails because Prolog doesn't know what possible values of X to consider. - lurker
Although maximal(7) succeeds, so does maximal(8). So that's a problem, right? Also part of the "universe of choices" issues. - lurker
Can just add le(X,_) or ( le(X,_) ; le(_,X) ) outside the negation, to get the numbers. - Tomas By
thank you :) i have worked out your advices and now everything is clear - bring112

1 Answers

2
votes

Prologs uses pre-defined steps to find the answer and negation is always tricky.

To make a long story short, to make the code easier to reason about most logic should be positive and negation applied to expressions where values of all variables are known.

Here is how you could make the code work.

le(6,7).
le(4,4).
le(6,6).
le(5,6).
le(5,5).
le(4,5).
le(4,4).

is_my_number(X) :- le(X, _).
is_my_number(X) :- le(_, X).

equal_or_not_le(X, Y) :- X = Y.
equal_or_not_le(X, Y) :- not(le(X, Y)).

maximal(X) :- is_my_number(X), forall(is_my_number(Y), equal_or_not_le(X, Y)).

Then query:

?- maximal(X).
X = 7 .

Good luck!