I was playing around with clpBNR and leap years and found the following:
:- use_module(library(clpBNR)).
% constraints-only version
leap(Y) :-
Y::integer(1583,_),
[Q0,Q1,Q2]::integer(1,_),
[R0,R1,R2]::integer(0,_),
{ ( Y == Q0*4 + R0, R0 == 0 ) and % multiple of four and
( (Y == Q1*100 + R1, R1 > 0, R1 < 100 ) % ( not multiple of 100
or % or
(Y == Q2*400 + R2, R2 == 0 ) ) % multiple of 400 )
}.
% mixing prolog with constraints
leap1(Y) :-
Y::integer(1583,_),
multiple_of(Y,4), % multiple of four and
( not_multiple_of(Y,100) % ( not multiple of 10
; multiple_of(Y,400) % or
). % multiple of 400 )
% Y not multiple of X
not_multiple_of(Y,X) :-
[Y,Q,R]::integer(0,_),
{ Y == Q*X + R, R > 0, R < X }. % not multiple of X
% Y multiple of X
multiple_of(Y,X) :-
[Y,Q,R]::integer(0,_),
{ Y == Q*X + R, R == 0 }. % multiple of X
The problem is that 2100 is not a leap year, but the constraints-only version succeeds when it should fail:
23 ?- leap(2100). % this is the wrong result
true.
24 ?- leap1(2100). % this works fine
false.
I think it boils down to the following problem:
19 ?- { B or B }. % should this not bind B to 1?
B::boolean.
20 ?- { B xor B}. % should this not fail?
B::boolean.
So I figured the constraint propagation was not strong enough, so I tried 'solve(âŚ)` and the following gets the results:
21 ?- { B xor B}, solve(B).
false.
22 ?- { B or B }, solve(B).
B = 1.
The fact that {B xor B}
does not fail is the most troubling case, because it succeeds with B unbound.
The problem is that using solve(...)
in the case of the leap year doesnât work. I am already providing a ground year. I can see it happens because the internal variables (Q1,Q2
, etc) in leap/1
are not bound, but calling solve on them makes the predicate unusable.
Any ideas?