Solve extremely simple equation in prolog: A = B + C? - prolog

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

Related

Contradiction in Prolog

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.

What is the difference in execution if the cut '!' is present?

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))
)
)
).

Prolog - Make two Instantiations Equal

I'm very new to Prolog so please bear with me.
Lets say I have the following:
foo(bar(a,b)).
foo(bar(b,a)).
Then I enter foo(X) as a query:
?- foo(X).
X = bar(a, b) ;
X = bar(b, a).
Prolog returns two instantiations of X to satisfy the query: bar(a, b) and bar(b,a).
Is there away I can make these two instantiations equivalent? Once Prolog instantiates X to bar(a,b), it won't instantiate it to bar(b,a).
So when I enter foo(X) as a query:
?- foo(X).
X = bar(a, b).
X was no instantiated as bar(b,a), because it's equivalent to bar(a,b). Is this possible to do with Prolog, or does it go against the fundamental principals of Prolog?
The first clause of symmetry/2 deals with cases in which both foo(bar(a,b)) and foo(bar(b,a)) occur. I use the standard order of terms in order to return only the former. Notice that the use of #< would have falsely excluded results like foo(bar(e,e)).
The second clause treats cases in which either foo(bar(c,d)) or foo(bar(d,c)) occur.
foo(bar(a, b)).
foo(bar(b, a)).
foo(bar(c, d)).
foo(bar(e, e)).
symmetry(X, Y):-
foo(bar(X, Y)),
foo(bar(Y, X)),
X #=< Y.
symmetry(X, Y):-
foo(bar(X, Y)),
\+ foo(bar(Y, X)).
Example of usage:
?- symmetry(X, Y).
X = a,
Y = b ;
X = Y, Y = e ;
X = c,
Y = d ;
false
Hope this helps!
Identity of literals it's the core of unification - the fundamental operation of Prolog algorithm - and then the answer to your question it's no, it's not possible to handle bar(a,b) as bar(b,a).

SWI-Prolog Creating/Printing lists, Recursion etc

I'm trying to teach myself some Prolog, however right now i'm really struggling just adapting to the declarative style having never done declarative programming before.
I'm attempting to get my program to come up with a two positive integer numbers, A & B, where A + B =< 50 and B > A. Obviously there are lots of solutions (e.g. A = 5 & B = 12 or A = 15 & B = 17) and i want my program to print all the different solutions.
I honestly don't really know where to begin and would appreciate some guidance or some example code of how to do something as explained above.
Cheers!
Looks like a good problem to use constraint logic programming:
:- use_module(library(clpfd)).
model(A, B) :-
A #> 0, B #> 0,
A + B #=< 50,
B #> A.
(I assume you want only positive integer solutions, otherwise there will be infinite number of them). Look how the model code directly reflects the problem statement.
After you have the model you can use it to find all solutions:
?- findall(_, (model(A, B), label([A, B]), writeln([A, B])), _).
[1,2]
[1,3]
[1,4]
[1,5]
[1,6]
... skipped many lines ...
[24,25]
[24,26]
true.
A more traditional Prolog solution without constraint programming (with the same results):
model2(A, B) :-
between(1, 50, A),
between(1, 50, B),
A + B =< 50,
B > A.
?- findall(_, (model2(A, B), writeln([A, B])), _).
You could do something like this:
combos(A,B) :-
between(1,50,A) ,
between(1,50,B) ,
S is A+B ,
S =< 50
.
This, on backtracking, will successively find all the solutions.
Use findall/3 to collect the results into a list:
findall(A+B,combos(A,B),X).

Prolog: partition integer list items by their parity

Write a predicate which takes as input a list of integers, L, and produces two lists: the list containing the even elements from L and the list of odd elements from L.
?- separate_parity([1,2,3,4,5,6], Es, Os).
Es = [2,4,6], Os = [1,3,5] ? ;
no
Just use structural recursion on lists. Write down the equivalences for each mutually exclusive case:
parity_partition([A|B], [A|X], Y):- 0 is A mod 2, parity_partition(B,X,Y).
parity_partition([A|B], X, [A|Y]):- 1 is A mod 2, parity_partition(B,X,Y).
parity_partition([],[],[]).
This means: relation parity_partition(L,E,O) holds,
in case L=[A|B] and A is even, when E=[A|X], O=Y and relation parity_partition(B,X,Y) holds.
in case L=[A|B] and A is odd, when E=X, O=[A|Y] and relation parity_partition(B,X,Y) holds.
in case L=[], when E=[] and O=[].
Just writing down these equivalences gives us the Prolog program to solve this.
Operationally, this means: to separate a list L into a list of evens E and a list of odds O,
1. if `L` is a non-empty list `[A|B]`,
1a. if `A` is even,
allocate new list node for `E=[H|T]`,
set its data field `H=A`,
and continue separating the rest of input list `B`
into `T` and `O` ; or
1b. if `A` is odd,
allocate new list node for `O=[H|T]`,
set its data field `H=A`,
and continue separating the rest of input list `B`
into `E` and `T` ; or
2. if `L` is an empty list, set both `E` and `O` to be empty lists
the actual sequence of operations might be a little bit different but conceptually the same:
1. try to unify L=[A|B], E=[A|X]. If not, go to 2.
1a. check if A is even.
If not, abandon the instantiations made
as part of unifications, and go to 2.
1b. Continue with B, X, and the same O: use B as L, X as E, and go to 1.
2. try to unify L=[A|B], O=[A|Y]. If not, go to 3.
2a. check if A is odd.
If not, abandon the instantiations made
as part of unifications, and go to 3.
2b. Continue with B, Y, and the same E: use B as L, Y as O, and go to 1.
3. Unify L,E,O with [].
This answer is based on clpfd, meta-predicate tpartition/4, and reified test zodd_t/2:
:- use_module(library(clpfd)).
Using tpartition/4 in combination with zodd_t/2 we can simply write:
?- tpartition(zodd_truth,[1,2,3,4,5,6],Es,Os).
Es = [1,3,5], Os = [2,4,6]. % succeeds deterministically
You can use clpfd for this. In this manner you get a pure relation:
:- use_module(library(clpfd)).
list_evens_odds([], [], []).
list_evens_odds([E|Zs], [E|Es], Os) :-
0 #= E mod 2,
list_evens_odds(Zs, Es, Os).
list_evens_odds([E|Zs], Es, [E|Os]) :-
1 #= E mod 2,
list_evens_odds(Zs, Es, Os).
You can use this not only to split a list into evens and odds. But you can go even further. The following interaction is with SWI, but you get similar in SICStus with asserta(clpfd:full_answer).
?- list_evens_odds([1,2,3,4,5,6], Es, Os).
Es = [2,4,6], Os = [1,3,5]
; false.
?- Zs = [A,B,C], list_evens_odds(Zs, Es, Os).
Zs = [A,B,C], Es = [A,B,C], Os = [], A mod 2#=0, B mod 2#=0, C mod 2#=0
; Zs = [A,B,C], Es = [A,B], Os = [C], A mod 2#=0, B mod 2#=0, C mod 2#=1
; Zs = [A,B,C], Es = [A,C], Os = [B], A mod 2#=0, B mod 2#=1, C mod 2#=0
; ... .
?- Es = [E], Os = [O], list_evens_odds(Zs, Es, Os).
Es = [E], Os = [O], Zs = [E, O], E mod 2#=0, O mod 2#=1
; Es = [E], Os = [O], Zs = [O, E], E mod 2#=0, O mod 2#=1
; false.
The next is probably most irritating: Here, we ask whether there is an integer EO that is both even and odd. Certainly, such an integer cannot exist. But we still get two answers!
?- EOs=[EO], list_evens_odds(Zs, EOs, EOs).
EOs = [EO], Zs = [EO, EO], EO mod 2#=1, EO mod 2#=0
; EOs = [EO], Zs = [EO, EO], EO mod 2#=0, EO mod 2#=1
; false.
This illustrates the difference between answers and solutions. We get here two answers, but both do not contain a solution. Most of the time an answer contains one or more solutions, but it can also contain none as in this case. Such answers are sometimes called inconsistencies.
Inconsistencies are not necessarily considered a bug of an implementation. They are rather an engineering tradeoff: Ensuring consistency might be very costly compared to the actual benefits. And: Prolog does not produce an incorrect answer: For the condition that has to hold is shown. Even if that condition turns out to be false.
the answer from #Will Ness is good and detailed. I'll just add the possibility, if your Prolog offers it, to use a 'higher order' builtin (i.e. a predicate that receives a predicate as argument):
separate_parity(L, E, O) :-
partition(is_even, L, E, O).
is_even(N) :- N mod 2 =:= 0.
You can find here a brief explanation for the builtin.

Resources