1

I understand that the \+ symbol in Prolog stands for "not provable", which evaluates to false if some clause is provable.

This got me thinking about the reversibility of a Rule's logic, is there a way to reverse a rules logic that uses similar syntax to the \+ symbol given above? i.e. that doesn't require you changing the clause itself.

By reverse I mean the rule's logic is inverted. For example, if the rule is X > Y, then the reverse returns the outcome X < Y.

For a more complex example, imagine, instead, I had the clause:

passed(X, Y) :- mark(X, Y, Z), Z >= 40.
mark(john, maths, 50).
mark(paul, maths, 10).
mark(harry, maths, 78).

Could I reverse the following statement:

?- passed(X, maths).
X = john
X = harry

So that I get:

X = paul
Connor
  • 867
  • 7
  • 18
  • Define "reverse". `\+` has caveats: https://stackoverflow.com/questions/14715070/prolog-negation-and-logical-negation – brebs Jul 21 '22 at 10:36
  • @brebs I added additional information on what I mean by reversing the logic, does that make it clearer? – Connor Jul 21 '22 at 11:17

3 Answers3

1

Negation is a really complex topic... Prolog offers a practical way to model some of its features in the restricted domain it can handle. For your example, use sufficiently instantiated arguments to get a constructive proof:

passed(X, Y) :- mark(X, Y, Z), Z >= 40.
mark(john, maths, 50).
mark(paul, maths, 10).
mark(harry, maths, 78).

?- mark(Student,_,_),\+passed(Student,math).
CapelliC
  • 59,646
  • 5
  • 47
  • 90
1

Could represent as:

mark(john, maths, 50).
mark(paul, maths, 10).
mark(harry, maths, 78).

pass_mark(maths, 40).

% Passed is a Boolean, i.e. true or false
passed_subject_t(Person, Subject, Passed) :-
    mark(Person, Subject, Score),
    pass_mark(Subject, PassMark),
    call_t(Score >= PassMark, Passed).

% Generic predicate
call_t(Goal, Bool) :-
    % Don't use *-> because Goal might contain ";" alternatives
    (   call(Goal)
    ->  Bool = true
    ;   Bool = false
    ).

Results in swi-prolog:

?- findall(P, passed_subject_t(P, maths, true), Ps).
Ps = [john, harry].

?- findall(P, passed_subject_t(P, maths, false), Ps).
Ps = [paul].
brebs
  • 3,462
  • 2
  • 3
  • 12
0

In some cases, you can but it won't be automatic. Here, you could use a clpfd "reified" constraint. For example, for SWI, in the docs, one can find #\ Q predicate.

Example queries:

?- use_module(library(clpfd)).
true.

?- X #>= 40.
X in 40..sup.

?- #\ X #>= 40.
X in inf..39.