If I have two premises as follows:
a -> c (a implies c)
b -> c (b implies c)
and a derived conclusion:
a -> b (a therefore implies b),
then the conclusion can be shown to be invalid because:
a -> c is valid for statement #1 when a is true and c is true, and
b -> c is valid for statement #2 when b is false and c is true. This leads to a -> b when a is true and b is false, a direct contradiction of statement #3.
Or, per proof with a truth table that contains a line for where the premises are true but the conclusion is false:
Truth Table with true premises and false conclusion
My question is: "Is there a way to use prolog to show that the assertions of statements #1 and #2 contradict the conclusion of statement #3? If so, what is a clear and concise way to do so?"
#coder has already given a very good answer, using clpb constraints.
I would like to show a slightly different way to show that the conclusion does not follow from the premises, also using CLP(B).
The main difference is that I post individual sat/1 constraints for each of the premises, and then use taut/2 to see whether the conclusion follows from the premises.
The first premise is:
a → c
In CLP(B), you can express this as:
sat(A =< C)
The second premise, i.e., b → c, becomes:
sat(B =< C)
If the a → b followed from these premises, then taut/2 would succeed with T = 1 in:
?- sat(A =< C), sat(B =< C), taut(A =< B, T).
false.
Since it doesn't, we know that the conclusion does not follow from the premises.
We can ask CLP(B) to show a counterexample, i.e., an assignment of truth values to variables where a → c and b → c both hold, and a → b does not hold:
?- sat(A =< C), sat(B =< C), sat(~(A =< B)).
A = C, C = 1,
B = 0.
Simply posting the constraints suffices to show the unique counterexample that exists in this case. If the counterexample were not unique, we could use labeling/1 to produce ground instances, for example: labeling([A,B,C]).
For comparison, consider for example:
?- sat(A =< B), sat(B =< C), taut(A =< C, T).
T = 1,
sat(A=:=A*B),
sat(B=:=B*C).
This shows that a → c follows from a → b ∧ b → c.
You could use library(clpb):
Firstly assign to a variable Expr your expression:
Expr = ((A + ~C)*(B + ~C)+(~(A + ~B)).
Note that:
'+' stands for logical OR
'*' for logical AND
'~' for logical NOT
Also A->B is equivalent with A+(~B). So the above expression is equivalent with ((A->C),(B->C))-> (A->C) where we wrote '->' using +,~ and ',' with *.
Now if we query:
?- use_module(library(clpb)).
true.
?- Expr=((A + ~C)*(B + ~C))+(~(A + ~B)),taut(Expr,T).
false.
Predicate taut/2 takes as input an clpb Expression and returns T=1 if it tautology, T=0 if expression cannot be satisfied and fails in any other case. So the fact that the above query failed means that Expr was nor a tautology neither could not be satisfied, it meant that it could be satisfied.
Also by querying:
?- Expr=((A + ~C)*(B + ~C))+(~(A + ~B)),sat(Expr).
Expr = (A+ ~C)* (B+ ~C)+ ~ (A+ ~B),
sat(1#C#C*B),
sat(A=:=A).
Predicate sat/1 returns True iff the Boolean expression is satisfiable and gives the answer that the above Expression is satisfiable when:
sat(1#C#C*B),
sat(A=:=A).
where '#' is the exclusive OR which means that your expression (we know from taut/2 that is satisfiable) is satisfied when 1#C#C*B is satisfied.
Another solution without using libraries could be:
truth(X):-member(X,[true,false]).
test_truth(A,B,C):-
truth(A),
truth(B),
truth(C),
((A->C),(B->C)->(A->C)).
Example:
?- test_truth(A,B,C).
A = B, B = C, C = true ;
false.
Also if I understood correctly from your comment, to collect all possible solutions you could write:
?- findall([A,B,C],test_truth(A,B,C),L).
L = [[true, true, true]].
Which gives a list of lists, where the inner lists have the form [true,true,true] in the above example which means a solution is A=true,B=true,C=true and in the above case it has only one solution.
To find all contradictions you could write:
truth(X):-member(X,[true,false]).
test_truth(A,B,C):-
truth(A),
truth(B),
truth(C),
not( (\+ ((\+A; C),(\+B ; C)) ; (\+A ; B)) ).
last line could also been written as:
not( ( (A->C;true),(B->C;true) ) -> (A->B;true) ;true ).
Example:
?- findall([A,B,C],test_truth(A,B,C),L).
L = [[true, false, true]].
Related
What would be the ZDD approach in Prolog that also provides quantifiers.
Notation for existential quantifier would be as follows:
X^F
where X is the bound variable and F is the formula. It corresponds
to the following formula:
F[X/0] v F[X/1]
How would one go about and write a Prolog routine that takes a ZDD
for F and a variable X and produces the ZDD for X^F ?
Daniel Pehoushek posted some interesting C-code, which I translated to Prolog. Its not directly working with ZDD, but rather with sets of sets of variables, which is also explained here. But I guess the algorithm can be translated from sets of sets of variables to ZDD.
It only needs two new operations, the rest works with the operations from library(lists). One operation is split/4 which gives the left and right branch for a tree root. And the other operation is join/4 which does the inverse. The main routine is bob/3:
bob(_, [], []) :- !.
bob([], A, A).
bob([V|W], A, T) :-
split(A, V, L, R),
intersection(L, R, H),
bob(W, H, P),
union(L, R, J),
bob(W, J, Q),
join(V, P, Q, T).
What does bob do? It transforms a formula P into a formula Q. The original formula P has propositional variables x1,..,xn. The resulting formulas has propositional variables x1',..,xn' which act as switches, where xi'=0 means ∀xi and xi'=1 means ∃xi. So the desired quantification result can be read off in the corresponding truth table row of Q.
Lets make an example:
P = (- A v B) & (-B v C)
Q = (A' v B') & (B' v C') & (A' v C')
A'B'C' Q
000 0
001 0
010 0
011 1 eg: (All A)(Exists B)(Exists C) P
100 0
101 1
110 1
111 1
Or as a Prolog call, computing Q from P for the above example:
?- bob([c,b,a], [[],[c],[b,c],[a,b,c]], A).
A = [[b, a], [c, a], [c, b], [c, b, a]]
Open source:
Some curious transformation by Daniel Pehoushek
https://gist.github.com/jburse/928f060331ed7d5307a0d3fcd6d4aae9#file-bob-pl
I'm testing Prolog ability to test contradiction. To test this, I came up with the following scenario:
There are three suspects: a, b, and c, who are on trial, and one of the suspect is guilty and the rest are innocent.
The facts of the case are,
(Fact 1) if a is innocent then c must be guilty, and
(Fact 2) if a is innocent then c must be innocent.
The answer to who is guilty is suspect 'a' because suspect 'c' cannot be both guilty and innocent. The following code is my implementation:
who_guilty(Suspects) :-
% Knowledge Base
Suspects=[[Name1,Sentence1],
[Name2, Sentence2],
[Name3,Sentence3]],
% Suspects
Names=[a,b,c],
Names=[Name1,Name2,Name3],
% One Is Guilty
Sentences=[innocent,innocent,guilty],
permutation(Sentences,[Sentence1,Sentence2,Sentence3]),
% If A Innocent Then C Is Guilty
(member([a,innocent],Suspects) -> member([c,guilty], Suspects) ; true),
% If A Innocent Then C Is Innocent
(member([a,innocent],Suspects) -> member([c,innocent], Suspects) ; true).
To get Prolog's answer, the query that needs to be run is who_guilty(S). Prolog will then output two identical answers:
S = [[a, guilty], [b, innocent], [c, innocent]] ?
S = [[a, guilty], [b, innocent], [c, innocent]]
My central question is how can I get only one answer instead of two?
Using clpfd library, you can solve this problem easily:
solve(L):-
L = [A,B,C], %0 innocent, 1 guilty
L ins 0..1,
A + B + C #= 1, %one is guilty
A #= 0 #==> C #= 1, %if a is innocent then c must be guilty
A #= 0 #==> C #= 0, %if a is innocent then c must be innocent
label(L).
?- solve(L).
L = [1, 0, 0]
Using clpb :
:- use_module(library(clpb)).
% 0 means guilty
% 1 means innocent
guilty(A,B,C) :-
% only one is guilty
sat(~A * B * C + A * ~B * C + A * B * ~C),
% Fact 1
sat(A =< ~C),
% Fact 2
sat(A =< C).
?- guilty(A,B,C).
A = 0,
B = C, C = 1.
A compact solution, that follows your intuition about expressing the facts.
who_guilty(L) :-
select(guilty,L,[innocent,innocent]),
( L = [innocent,_,_] -> L = [_,_,guilty] ; true ),
( L = [innocent,_,_] -> L = [_,_,innocent] ; true ).
yields:
?- who_guilty(L).
L = [guilty, innocent, innocent] ;
false.
thanks to joel76 (+1), here is a more synthetic solution based on library(clpb)
?- sat(card([1],[A,B,C])*(~A =< ~C)*(~A =< C)).
A = 1,
B = C, C = 0.
1 means guilty...
You should add a new predicate which checks whether someone is both innocent and guilty, which then answers yes to whether there are contradictory outcomes. You are giving Prolog two facts, meaning two correct conclusions to the query. Your real question is "do I have facts contradicting each other?", which means A and NOT A are both true at the same time. contradiction(A, not(A)).
All truths are universal and you are giving two truths that are contradictory to Prolog, so both are true to Prolog.
counter([],[]).
counter([H|T],[[H,C1]|R]) :- counter(T,[[H,C]|R]),!, C1 is C+1.
counter([H|T],[[H,1]|R]) :- counter(T,R).
What is the effect of the "!" as I'm getting the same output for an input in both the above and below code?
counter([],[]).
counter([H|T],[[H,C1]|R]) :- counter(T,[[H,C]|R]),C1 is C+1.
counter([H|T],[[H,1]|R]) :- counter(T,R).
I'm new to Prolog.
What is the effect of the "!"
The cut prunes the search space. That is, in an otherwise pure and monotonic program, the cut will remove some solutions or answers. As long as those are redundant that's fine. It sounds so innocent and useful, doesn't it? Let's have a look!
And lest I forget, using [E,Nr] to denote pairs is rather unusual, better use a pair E-Nr.
We will now compare counter_cut/2 and counter_sans/2.
| ?- counter_cut([a,a],Xs).
Xs = [[a,2]].
| ?- counter_sans([a,a],Xs).
Xs = [[a, 2]]
; Xs = [[a, 1], [a, 1]]. % <<< surprise !!!
So the cut-version has fewer solutions. Seems the solution counter_cut/2 retained is the right one. In this very particular case. Will it always take the right one? I will try a minimally more general query:
| ?- counter_cut([a,B],Xs).
B = a,
Xs = [[a, 2]].
| ?- counter_sans([a,B],Xs).
B = a,
Xs = [[a, 2]]
; Xs = [[a, 1], [B, 1]].
Again, _sans is chattier, and this time, it is even a bit right-er; for the last answer includes B = b. In other words,
| ?- counter_cut([a,B], Xs), B = b.
fails. % incomplete !
| ?- counter_sans([a,B], Xs), B = b.
B = b,
Xs = [[a,1],[b,1]].
So sometimes the _cut version is better, and sometimes _sans. Or to put more directly: Both are wrong somehow, but the _sans-version at least includes all solutions.
Here is a "purified" version, that simply rewrites the last rule into two different cases: One for the end of the list and the other for a further, different element.
counter_pure([],[]).
counter_pure([H|T],[[H,C1]|R]) :- counter_pure(T,[[H,C]|R]), C1 is C+1.
counter_pure([H],[[H,1]]).
counter_pure([H,D|T],[[H,1]|R]) :- dif(H,D), counter_pure([D|T],R).
From an efficiency viewpoint that is not too famous.
Here is a test case for efficiency for a system with rational tree unification:
?- Es = [e|Es], counter(Es, Dict).
resource_error(stack).
Instead, the implementation should loop smoothly, at least till the end of this universe. Strictly speaking, that query has to produce a resource error, but only after it has counted up to a number much larger than 10^100000000.
Here's my pure and hopefully efficient solution:
counter([X|L], C):- counter(L, X, 1, C).
counter([],X, Cnt, [[X,Cnt]]).
counter([Y|L], X, Cnt, [[X,Cnt]|C]):-
dif(X, Y),
counter(L, Y, 1, C).
counter([X|L],X, Cnt, [[X,XCnt]|C]):-
Cnt1 #= Cnt+1,
Cnt1 #=< XCnt,
counter(L, X, Cnt1, [[X,XCnt]|C]).
Using if_3 as suggested by #false:
counter([X|L], C):- counter(L, X, 1, C).
counter([],X, Cnt, [[X,Cnt]]).
counter([Y|L], X, Cnt, [[X,XCnt]|C]):-
if_(X=Y,
(
Cnt1 #= Cnt+1,
Cnt1 #=< XCnt,
counter(L, X, Cnt1, [[X,XCnt]|C])
),
(
XCnt=Cnt,
counter(L, Y, 1, C)
)
).
The cut operator ! commits to the current derivation path by pruning all choice points. Given some facts
fact(a).
fact(b).
you can compare the answers with and without cut:
?- fact(X).
X = a ;
X = b.
?- fact(X), !.
X = a.
As you can see, the general query now only reports its first success. Still, the query
?- fact(b), !.
true.
succeeds. This means, that cut violates the interpretation of , as logical conjunction:
?- X = b, fact(X), !.
X = b.
?- fact(X), !, X=b.
false.
but from our understanding of conjunction, A ∧ B should hold exactly when B ∧ A holds. So why do this at all?
Efficiency: cuts can be used such that they only change execution properties but not the answers of a predicate. These so called green cuts are for instance described in Richard O'Keefe's Craft of Prolog. As demonstrated above, maintaining correctness of a predicate with cut is much harder than one without, but obviously, correctness should come before efficiency.
It looks as if your problem was green, but I am not 100% sure if there is not a change in the answers.
Negation: logical negation according to the closed world assumption is expressed with cut. You can define neg(X) as:
neg(X) :-
call(X),
!,
false.
neg(_) :-
true.
So if call(X) succeeds, we cut the choice point for the second rule away and derive false. Otherwise, nothing is cut and we derive true. Please be aware that this is not negation in classical logic and that it suffers from the non-logical effects of cut. Suppose you define the predicate land/1 to be one of the continents:
land(africa).
land(america).
land(antarctica).
land(asia).
land(australia).
land(europe).
and then define water as everything not on land:
water(X) :-
neg(land(X)).
then you can correctly obtain:
?- water(pacific).
true.
?- water(africa).
false.
But you can also derive:
?- water(space).
true.
which should not hold. In particular, in classical logic:
land(africa) ∧
land(america) ∧
land(antarctica) ∧
land(asia) ∧
land(australia) ∧
land(europe) → ¬ land(space).
is not valid. Again, you should know well what you are doing if you use negation in Prolog.
Here is my attempt using if_/3:
counter([], []).
counter([H|T], [[H,C]|OutT] ):-
if_(
T=[],
(C = 1,OutT=[]),
(
[H|T] = [H,H1|T2],
if_(
H=H1,
(counter([H1|T2], [[H1,C1]|OutT]), C is C1+1),
(C = 1, counter([H1|T2], OutT))
)
)
).
I have an extremely simple equation that I would like to be able to solve in prolog:
A = B + C
I'd like to be able to write a predicate expressing this relation, that can handle any one of the arguments not being instantiated. There is no need to generalize to more complex relations or equations.
myEquation(A, B, C) :-
...something...
That I could call with the following semantics:
myEquation(A,1,2).
> A = 3.
myEquation(3,B,2).
> B = 1.
myEquation(3,1,C).
> C = 2.
Any ideas? Working with arithmetic operators yields a lot of "Arguments are not sufficiently instantiated" errors. It looks like solving arbitrary systems of equations is beyond the scope of most prolog implementations, but I'm hoping that this extremely simple equation is tractable.
Not particularly fancy, but here it is. If you're not an absolute beginner, you could have done this too:
myEquation(A, B, C):-
var(A),number(B),number(C) -> A is B+C;
var(B),number(A),number(C) -> B is A-C;
var(C),number(A),number(B) -> C is A-B;
A =:= B + C.
update:
The same with Constraint Logic Programming:
:- use_module(library(clpq)).
myEquation(A, B, C):-
{A = B + C}.
If your domain is integers, use clpfd!
:- use_module(library(clpfd)).
:- assert(clpfd:full_answer). % for SICStus Prolog
myEquation(A,B,C) :-
A #= B+C.
Some sample queries with sicstus-prolog, version 4.3.2:
?- myEquation(A,B,C).
B+C#=A, A in inf..sup, B in inf..sup, C in inf..sup ? ;
no
?- myEquation(A,2,C).
2+C#=A, A in inf..sup, C in inf..sup ? ;
no
?- myEquation(X,X,X).
X+X#=X, X in inf..sup ? ;
no
Let's run the same queries with swi-prolog, version 7.3.3:
?- myEquation(A,B,C).
B+C#=A.
?- myEquation(A,2,C).
2+C#=A.
?- myEquation(X,X,X).
X = 0. % succeeds deterministically
To calculate the hamming distance between two lists of the same length, I use foldl(hamm, A, B, 0, R). with this definition of hamm/4:
hamm(A, A, V, V) :- !.
hamm(A, B, V0, V1) :- A \= B, V1 is V0 + 1.
The cut in the first rule prevents the unnecessary backtracking. The second rule, however, could have been written differently:
hamm2(A, A, V, V) :- !.
hamm2(_, _, V0, V1) :- V1 is V0 + 1.
and hamm2/4 will still be correct together with foldl/5 or for queries where both A and B are ground.
So is there a really good reason to prefer the one over the other? Or is there a reason to keep the rules in that order or switch them around?
I know that the query
hamm(a, B, 0, 1).
is false, while
hamm2(a, B, 0, 1).
is true, but I can't quite decide which one makes more sense . . .
The OP implemented two accumulator-style predicates for calculating the Hamming distance (hamm/4 and hamm2/4), but wasn't sure which one made more sense.
Let's read the query that puzzled the OP: "Is there an X such that distance(a,X) is 1?". Here are the "answers" Prolog gives:
?- hamm(a,X,0,1).
false. % wrong: should succeed conditionally
?- hamm2(a,X,0,1). % wrong: should succeed, but not unconditionally
true.
From a logical perspective, both implementations misbehave in above test. Let's do a few tests for steadfastness:
?- hamm(a,X,0,1),X=a. % right
false.
?- hamm(a,X,0,1),X=b. % wrong: should succeed as distance(a,b) is 1
false.
?- hamm2(a,X,0,1),X=a. % wrong: should fail as distance(a,a) is 0
X = a.
?- hamm2(a,X,0,1),X=b. % right
X = b.
Note that in previous queries hamm/4 rightly fails when hamm2/4 wrongly succeeded, and vice-versa.
So both are half-right/half-wrong, and neither one
is steadfast.
What can be done?
Based on if_/3 and (=)/3 presented by #false in this answer, I implemented the following pure code for predicate hamm3/4:
:- use_module(library(clpfd)).
hamm3(A,B,V0,V) :-
if_(A = B, V0 = V, V #= V0+1).
Now let's repeat above queries using hamm3/4:
?- hamm3(a,X,0,1).
dif(X,a).
?- hamm3(a,X,0,1),X=a.
false.
?- hamm3(a,X,0,1),X=b.
X = b.
It works! Finally, let's ask the most general query to see the entire solution set of hamm3/4:
?- hamm3(A,B,N0,N).
A = B, N0 = N ;
dif(A,B), N0+1 #= N.
You already spotted the differences between those definitions: efficiency apart, you should decide about your requirements. Are you going to accept variables in your data structures? Such programming style introduces some of advanced Prolog features (incomplete data structures).
Anyway, I think the first form is more accurate (not really sure about, I would say steadfast on 4° argument)
?- hamm(a, B, 0, 1).
false.
?- hamm(a, B, 0, 0).
B = a.
while hamm2 is
?- hamm2(a, B, 0, 1).
true.
?- hamm2(a, B, 0, 0).
B = a.