Prolog implying a negative predicate - prolog

How can I write the following rule in PROLOG: if P then not Q
I understand that you can easily write if P then Q the predicates like q(X) :- p(X), but how can you negate the q/1 predicate? I don't want to define new predicates with other semantics like non_q/1.

The clause "if P then not Q" is logically equivalent to the negative clause "not P OR not Q". As such it is a Horn clause without a positive literal, and as an application of the correspondence of SLD theorem proving and Horn clauses, can be represented in Prolog programming as a goal clause or "query":
?- P, Q.
Let's come back to this idea in a minute.
But the goal clause is perhaps not the sort of representation you have in mind. The facts and rules that constitute a Prolog "knowledgebase" are definite clauses, i.e. Horn clauses each with exactly one positive literal. "If P then not Q" has no positive literal, so in this sense it cannot be represented (as a definite clause).
The goal clause shown above "asks" if P and Q can both be proven. Prolog provides a notion of "negation as failure", so a more natural way to "ask" whether "not P OR not Q" holds would be:
?- not((P,Q)).
Then we would get success if either P or Q fails, and failure if both succeed.
However if your purpose is to assert the negation something in the knowledgebase, Prolog doesn't naturally support this. Depending on your application, there may be a reasonable way to work around the Prolog syntax and accomplish what is needed (there's always an unreasonable way to do it, as you've hinted as with a non_q predicate).

Have you ever heard about cut in Prolog?
Anyway I don't know much about Prolog standard, but in SWI-Prolog the symbol \+ means negation. I know it don't have to work in every Prolog's interpreter.
You can make the predicate negation with Prolog's cut. The predicate is defined like:
not(Goal) :- call(Goal),!,fail.
not(Goal).
It means that Goal can't be proven, not the Goal is false.
Maybe this Prolog & Cut link will be useful.

"...if P then not Q" can be represented via the -> if-then control-flow predicate (e.g., GNU) , along with the \+ negation (or 'not-provable') operator (e.g., GNU), as follows:
(P -> \+ Q),
Note that, typically, \+ will implement what is known as negation-as-failure; i.e., the subgoal/expression \+ Q will succeed iff Q cannot. Note that the evaluation of Q under \+ will not affect the bindings of any variables present in the expression Q at execution.
For example, consider:
foo(a).
bar(b).
Given these facts, the following hold:
foo(a) -> \+ bar(a). % succeeds, as bar(a) is not provable.
foo(a) -> \+ bar(b). % fails, as bar(b) is provable.
foo(a) -> \+ bar(X). % fails, as bar(X) is provable; note that X remains unbound.
foo(X) -> \+ bar(X). % succeeds, as bar(X) where X unified to 'a' isn't provable.
Implementing something akin to \+ q(X) :- p(X) as you might want (in terms of a 'rule') isn't straightforward, as you describe, however a potential hack is:
q(X) :- p(X), !, fail.
This definition will only reflect the intention that q(X) is to fail for all X where p(X) succeeds iff it is asserted before any other clauses of q(X), but may not be ideal.

You can use minimal logic to define a negative head. In minimal logic
~A can be viewed as A -> ff. Thus the following
P -> ~Q
Can be viewed as:
P -> (Q -> ff).
Now if we take the following identity (A -> (B -> C)) = (A & B -> C), we
see that the above is equivalent to:
P & Q -> ff.
There is now one problem, how can we ask negative queries? There is one
way to make use of minimal logic which is different from negation as
failure. The idea is that a query of the form:
G |- A -> B
is answered by temporarily adding A to the prolog program G, and then
trying to solve B, i.e. doing the following:
G, A |- B
Now lets turn to Prolog notation, we will show that p, and p -> ~q
implies ~q by executing a (minimal logic) Prolog program. The
prolog program is:
p.
ff :- p, q.
And the query is:
?- q -: ff.
We first need to define the new connective (-:)/2. A quick solution
is as follows:
(A -: B) :- (assert(A); retract(A), fail), B, (retract(A); assert(A), fail).
Here you see a realisation of this minimal logic negation in SWI Prolog:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 5.10.4)
Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam
1 ?- [user].
:- op(1200,xfy,-:).
|: (A -: B) :- (assertz(A); retract(A), fail), B, (retract(A); assertz(A), fail).
|: p.
|: ff :- p, q.
|:
% user://1 compiled 0.02 sec, 1,832 bytes
true.
2 ?- q -: ff.
true .
Best Regards
Reference:
Uniform Proofs as a Foundation for Logic Programming (1989)
by Dale Miller, Gopalan Nadathur, Frank Pfenning, Andre Scedrov

Related

what's the semantics of Prolog's implementation of negation with non-ground literals

I am familiar with Prolog's implementation of negation as NaF and that even its implementation of NaF is incomplete, esp. floundering with non ground negated literals. My question here is regarding the specific semantics. Suppose you have a clause p(X) :- q(Y). This is the clausal form of \A x,y(q(y) -> p(x)) which is \E y q(y) -> \A x p(x), and this is indeed the semantics that prolog implements. But now consider if I have p(X) :- \+ q(Y). In FOL this would be expressed as \E y ~q(y) -> \A x p(x) ie "if q fails for some y then p holds for every x" but this does not appear to be the semantics that Prolog implements. Rather Prolog will require q to finitely fail for every y before \+ q(y) succeeds and p is true for any x. So its semantics appears to be very different, not just incomplete. Am I missing something?
thanks
In Prolog, p(X) :- \+ q(Y). on its own doesn't sufficiently express the notion that p holds true for every X if q fails for some Y because Prolog doesn't know the possible universe of Y values that are eligible to test q. So, it doesn't know of any values of Y for which q(Y) is not provable.
Let's suppose you had, though, the following:
q(a).
q(b).
q(c).
valid_y(Y) :- member(Y, [a,b,c,d,e]).
Then you could write:
p(_) :- valid_y(Y), \+ q(Y).
Then p(_) succeeds twice as Prolog seeks all solutions. You could use a cut or once/1 to avoid that.

Logical Negation in Prolog

I've read quite a bit about Prolog's Negation by Failure where Prolog in order to prove that \+Goal holds tries to prove that Goal fails.
This is highly connected with CWA (close world assumption) where for example if we query \+P(a) (where P is a predicate of arity 1) and we have no clues that lead to prove P(a) Prolog assumes (due to CWA) that not P(a) holds so \+P(a) succeeds.
From what I've searched this is a way to solve classical logic weakness where if we had no clue about P(a) then we could not answer whether \+P(a) holds.
What described above was the way of introducing non-monotonic reasoning in Prolog. Moreover the interesting part is that Clark proved that Negation by Failure is compatible/similar with classical negation only for ground clauses. I understand that for example:
X=1, \+X==1.: should return false in Prolog (and in classical Logic).
\+X==1, X=1.: should return false in classical logic but it succeeds in Prolog since the time that NF is examined X is not bound, this differs from classic-Pure Logic.
\+X==1.: should not give any answer in classical logic until X is bound, but in Prolog it returns false (possibly to break weakness of classical logic) and this is not same/compatible with pure Logic.
My attempt was to simulate classic negation, thanks to #false's suggestions in comments, current implementation is:
\\+(Goal) :- when(ground(Goal), \+Goal).
Some testing:
?- \\+(X==1).
when(ground(X), \+X==1).
?- X=1, \\+(X==1).
false.
?- \\+(X==1), X=1.
false.
My question:
Is the above a correct interpretation of classical negation?
(Are there any obvious corner cases that it misses?? also I'm concerned about Logic Purity when using when/2, is it safe to assume that the above is pure??).
Prolog cannot do classical negation. Since it does not
use classical inference. Even in the presence of Clark
completion, it cannot detect the following
two classical laws:
Law of noncontradiction: ~(p /\ ~p)
Law of excluded middle: p \/ ~p
Here is an example, take this logic program
and these queries:
p :- p
?- \+(p, \+p)
?- p; \+p
The Clark completion of the logic program is
as follows and the negation as failure query
execution yields the following:
p <-> p
loops
loops
Clark completion adresses the issue of predicate definitions
and negative information. See also section 5.2 Rules and
their Completion. On the other hand, when no predicate
definitions are around, CLP(X) can sometimes do both laws,
when a negation operator is defined deMorgan style. Here is
a negation operator for CLP(B):
?- listing(neg/1).
neg((A;B)) :-
neg(A),
neg(B).
neg((A, _)) :-
neg(A).
neg((_, A)) :-
neg(A).
neg(neg(A)) :-
call(A).
neg(sat(A)) :-
sat(~A).
And here is some execution:
?- sat(P); neg(sat(P)).
P = 0
P = 1.
?- neg((sat(P), neg(sat(P)))).
P = 0
P = 1.
CLP(X) will also have problems when the negation affects domains,
that are usually finite and that would then get infinite. So for
example a constraint such as (#=)/2, ... shouldn't be a problem,
since it can be replaced by a constraint (#\=)/2, ... .
But negation for CLP(FD) will usually not work when applied to constraints
(in)/2. The situation can slightly be mitigated if the CLP(X) system offers
reification. In this case the disjunction can be rendered a little bit more intelligent than just using Prolog backtracking disjunction.
In SWI-Prolog, it is possible to implement the rules of inference for classical logic in Constraint Handling Rules, including de Morgan's laws and the law of noncontradiction:
:- use_module(library(chr)).
:- chr_constraint is_true/1.
:- chr_constraint animal/2.
:- initialization(main).
:- set_prolog_flag('double_quotes','chars').
is_true(A),is_true(A) <=> is_true(A).
is_true(A=B) ==> A=B.
is_true(A\=B) ==> not(A=B).
is_true(not(A)),is_true(A) ==> false.
is_true(not((A;B))) ==> is_true((not(A),not(B))).
is_true(not((A,B))) ==> is_true((not(A);not(B))).
is_true((A,B)) ==> is_true(A),is_true(B).
is_true((A;B)) ==> is_true(A),(is_true(B);is_true(not(B)));is_true(B),(is_true(A);is_true(not(A))).
is_true(not(not(A))) ==> is_true(A).
Then, you can use the solver like this:
is_true(animal(X,A)),is_true(animal((Y,A))) ==> X \= Y,false;X==Y.
is_true((A->B)) ==> is_true(((A;not(A)),B));is_true(((not(A);A),not(B))).
main :- is_true(((X=cat;X=dog;X=moose),(not((animal(dog,tom);animal(moose,tom))),animal(X,tom)))),writeln(animal(X,tom)).
This program prints animal(cat,tom).
But this formula could be solved more efficiently using a different algorithm, such as DPLL.

How to properly express inequality in prolog?

TL;DR: sibling(a,X) succeeds with the answer X = a, but sibling(a,a) fails.
I have the following Prolog file:
children(a, c).
children(a, d).
children(b, c).
children(b, d).
sibling(X, Y) :-
X \== Y, A \== B,
children(X, A), children(X, B),
children(Y, A), children(Y, B).
It seems clear enough to me, two person are siblings if their parents are the same. Also, a person is not their own sibling.
But when I tried to run some queries on GNU Prolog, I get some strange results:
| ?- sibling(a, b).
true ? a
true
true
yes
This is the intended behavior. a and b are siblings. There are three results, which is a bit weird, but I assume Prolog is binding A = c, B = d and A = d, B = c.
| ?- sibling(a, a).
no
I think this means a and a are not siblings.
| ?- sibling(a, X).
X = a ? a
X = b
X = a
X = b
X = a
X = b
X = a
X = b
(15 ms) yes
This is where I got stuck: It says X = a, which means sibling(a,a) is true, but sibling(a,a) failed in the previous query!
I feel that I'm not understanding what \== actually does in Prolog.
What is happening, and how do I fix this?
TL;DR: Use prolog-dif—or iso_dif/2 (on iso-prolog conforming systems like gnu-prolog)!
Good question, +1!
In fact, it's a question I have asked myself, and the answer has to do with logical-purity: logical purity is a central aspect of what
makes Prolog as a language so special, as it enables you to:
describe—not prescribe
write code that is relational—not just functional
think in terms of problems / solutions—not the individual steps of the search process itself
operate on a higher level—not get lost in nitty-gritty details
Unlike many other programming languages, Prolog programs have both procedural semantics (defining the execution steps and their order) and declarative semantics (allowing you to state relations that should hold and let the Prolog processor find a proper way of execution by itself).
But, beware: Prolog has some features that, when used, ruin declarative semantics. To prevent this, try to structure your application into two parts: an impure shell for dealing with side-effects (input/output) and a logically pure base which comprises pure monotonic Prolog code.
Try moving the inequality to the end of the predicate. Maybe it gives you true because it's not instantiated already.
sibling(X,Y):- children(X, A), children(X, B),
children(Y, A), children(Y, B),
X \== Y, A \== B.

PROLOG CLPFD minimize expression

I have a list of variables L over a finite domain. For example:
:- use_module(library(clpfd)).
example :-
L = [_,_,_],
L ins 1..10,
...
Moreover, I have a predicate
pred(L,C)
that, for any assignment of L to values of the domain, gives a cost C.
The question is how to use the labeling feature of CLPFD to find the assignment of L that minimizes C.
example :-
L = [_,_,_],
L ins 1..10,
pred(L,C),
labeling([min(C)],L),
write(L).
Doesn't work. It just chooses the first assignment (i.e. [1,1,1]).
Most likely, C is already instantiated at the time labeling/2 is called in this example. The goal then reads similar to:
labeling([min(1)], Ls)
and of course, no room is left for actually minimizing C here during labeling/2.
To make this work, you have to formulate pred/2 such that C is deterministically related to the variables Vs via constraints. For example:
sum(Vs, #=, C),
labeling([min(C)], Vs)
works as intended if the cost function is the sum of the finite domain variables Vs.
I illustrate my further suggestions by rewriting your example as:
example(Ls) :-
Ls = [_,_,_],
Ls ins 1..10,
pred(Ls, C),
labeling([min(C)], Ls).
Notice in particular:
I do not need to use write/1 because the Prolog toplevel will display the solution for me when I query ?- example(Ls).
I let the names of variables that denote lists end with an s in analogy of building an English plural.

Negation as failure in Prolog is a procedural behavior?

I have a little question about the negation as failure in Prolog language:
This is a question more theoretical than practical because I have clear how this example work.
so I have the following Prolog program:
/* Fatti che specificano quali esseri sono degli animali: */
animal(cat).
animal(dog).
animal(frog).
animal(horse).
animal(viper).
animal(boa).
animal(python).
/* Fatti che specificano quali esseri sono dei serpenti: */
snake(viper).
snake(boa).
snake(python).
/* X è un serpente, fallisce ed impedisce il backtracking quindi
il predicato likes(mary,X) risulta essere falso: */
likes(mary,X) :- snake(X),
!,
fail.
/* Se X è un animale allora a mary piace: */
likes(mary, X) :- animal(X).
In Prolog I can't simply say something like: "Mary loves every animals, BUT NOT THE SNAKES"
and I have to formulate it in this way: "If X is a snake, then Mary don't love it. Otherwise, if X it is an animal, mary love it"
The precedent program do exactly this thing, by the rule:
likes(mary,X) :- snake(X),
!,
fail.
Prolog check if it is true that X it is a snake, imposes the cut to avoid backtracking and force a failure of the predicate.
In this way if snake(X) is TRUE the program force the failure also of the head prediate likes(mary,X) and imposing backtracking avoid the possibility to execute the other rule in the program (that answer true because a snake is also an animal)
My question is: it seems me that this use of Prolog falls outside from the logical and declarative paradigm and in some way fall in some sort of procedural paradigm
Because:
I have to impose an order of the 2 predicate (so in some way I am saying: if the first fail, try the second).
But even more I am saying that: if the first rule match (X it is a snake) then execute a forced failure and imposes no backtracking.
This seems to me more near to a procedural meaning that a classical logical meaning...
Is it that? Is it that in these cases, Prolog uses a procedural behavior to overcome a limitation of the logic?
I disagree with 'limitations of the logic'.
The same would be
likes(mary,X) :- not(snake(X)) , animal(X).
Because Prolog uses a depth-first-search some things can be expressed in an shorter way that then depends on the depth-first-search backtracking algorithm.
x :- a, !, b.
x :- c.
x :- d.
is the same as
x :- a, b.
x :- not(a), c.
x :- not(a), d.
Programs that make use of cut (!) are most of the time
sensitive to the ordering of goals and clauses in their
meaning and not only in their termination, so they are
often not declarative.
The negation as failure (\+) ecapsulates in a certain way
the cut. It is defined and even implemented by most Prolog
systems as follows:
\+ X :- X, !, fail.
\+ _ .
Although it hints a logical meaning and thus declarativity,
the negation as failure is still sensitive to ordering of
goals. Here is an example. Assume we have the following
database:
p(a).
q(b,c).
Then the following query produces X=a as a solution:
?- p(X), \+ q(X,Y).
X = a.
But if the arguments of the conjunction (,)/2 switch side,
a different result is obtained:
?- \+ q(X,Y), p(X).
false.
Ergo, negation as failure is not declarative per se. For
ground term flow of arguments, negation as failure sneeks
in an existential quantifiers. So a query of the form:
?- A(X), \+ B(X,Y).
Has essentially the meaning that it quantifies the fresh
variables Y inside the negation:
?- A(X), ~ exists Y B(X,Y).
So in the above example where conjunction is switched, the
set of fresh variables in the negation as failure changes, thats
why different solutions are obtained.
Bye
In short, yes, it is procedural.
Negation as failure uses a cut, and cuts are procedural concepts. You cannot use negation as failure in a declarative way - it is not possible.
It is worth mentioning that not all uses of cuts throw declarativeness out of the window - some of them just increase efficiency. But unfortunately, this is not the case with negation as failure - declarativeness goes out the window.
(Prolog is just a procedural prover disguised as a declarative language lol)

Resources