I am a beginner in Prolog and I figured I could try to write a simple test to check if a set of integers mod K (L) is a group. I started by trying to find if the said set is additive, ie. if the sum of every two elements of L is also an element of L.
I wrote the following:
group(A,K):-member(B,A),member(C,A),As is B+C, Bs is mod(As,K), member(Bs,A).
I then tried it with this:
trace. group([0,1,2],3).
This, naturally, produces all possible sums and, correctly, answers that the answer is true for all of them.
But after all these cases it finally prints the following:
1 1 Redo: group([0,1,2],3) ?
6 2 Redo: member(1,[0,1,2]) ?
6 2 Fail: member(1,[0,1,2]) ?
1 1 Fail: group([0,1,2],3) ?
no
Why the program checks this final case, that, to me, seems nonsensical?
The last case before this is:
1 1 Redo: group([0,1,2],3) ?
6 2 Redo: member(0,[0,1,2]) ?
6 2 Fail: member(0,[0,1,2]) ?
3 2 Redo: member(1,[0,1,2]) ?
3 2 Exit: member(2,[0,1,2]) ?
4 2 Call: _158 is 2+2 ?
4 2 Exit: 4 is 2+2 ?
5 2 Call: _186 is 4 mod 3 ?
5 2 Exit: 1 is 4 mod 3 ?
6 2 Call: member(1,[0,1,2]) ?
6 2 Exit: member(1,[0,1,2]) ?
1 1 Exit: group([0,1,2],3) ?
true
which does what it should.
Using a tracer for such a purpose is not very helpful. It shows you lots of detail that is irrelevant. Instead, concentrate on a good formulation of the problem. Concentrate on meaningful names. You use
Afor the set, andBandCfor elements. That can be improved!What you currently test is this:
What you want to test is that :
The operation itself can be written as:
Z is (X+Y) mod KHow can a tracer explain that to you?
group(S, K) :- \+ ( member(X,S), member(Y,S), Z is (X+Y) mod K, \+ member(Z,S) ). ?- group([0,1,2],3). true. ?- group([0,2],3). false.