Reading Constraint Handling Rules (2009) by Thom Frühwirth.
In p.65, it says that
The wake-up policy of an implementation is a function wakeup(S, c,B) that defines which CHR constraints of S are woken by adding the constraint c to the built-in store B. We say that these constraints are woken (triggered) by c. One never wakes constraints that have become ground (i.e. that only contain fixed (determined) variables that are bound to ground terms). In practice, only CHR constraints which may potentially cause a rule to fire are woken. This is the case if the newly added built-in constraint further constrains variables of the constraint. If the same built-in constraints are added a second time, this should not wake any CHR constraints.
It seems theoretical that CHR constraints can be woken by more than just =
. So I’d like to confirm whether the SWI-Prolog implementation of CHR could interact with CLP(R).
I wrote the following program:
%% test.pl
:- use_module(library(chr)).
:- use_module(library(clpr)).
:- chr_constraint lss/2.
lss(X,Y) <=> entailed(X<Y) | writeln("rule fired").
?- lss(X,Y).
lss($VAR(X),$VAR(Y)).
?- lss(X,Y), {X<Y}.
rule fired
lss($VAR(X),$VAR(Y)),
{$VAR(Y)= $VAR(X)+ $VAR(_A),$VAR(_A)>0.0}.
Notice the result of the 2nd query, rule fired but the constraint lss
did not be deleted.
On the surface it seems that CHR can interact with CLP(R), but actually not.
See the following example,
:- use_module(library(chr)).
:- use_module(library(clpr)).
:- chr_constraint lss/2, foo/0.
lss(X,Y) <=> entailed(X<Y) | foo, writeln("rule fired").
?- lss(X,Y).
lss($VAR(X),$VAR(Y)).
?- lss(X,Y), {X<Y}.
rule fired
lss($VAR(X),$VAR(Y)),
{$VAR(Y)= $VAR(X)+ $VAR(_A),$VAR(_A)>0.0}.
Noticed that the writeln("rule fired")
was called, but foo
did not be added to the store, so IMO the rule did not actually be fired.
The conclusion is that the current implementation of CHR can not interact with other libraries (except built-in =
). Confusingly printing rule fired
may be a bug and it may be related to A strange behavior of CHR package
What really confuses me is that if {X<Y}
can not wake-up lss
, it should not touch anything about the rule (and lss
) when {X<Y}
called, However, it obvious touched!
Compare the following two programs
%% wake-up by `=`, correct!
lss(X,Y) <=> writeln("guard1") ,entailed(X=Y), writeln("guard2") | foo, writeln("rule fired").
?- lss(X,Y), writeln("q1"), X=Y, writeln("q2").
guard1
q1
guard1
guard2
rule fired
q2
X = $VAR(Y),
foo.
vs
%% wake-up by `{X<Y}`, printing logs are mess!
lss(X,Y) <=> writeln("guard1") ,entailed(X<Y), writeln("guard2") | foo, writeln("rule fired").
?- lss(X,Y), writeln("q1"), {X<Y}, writeln("q2").
guard1
q1
q2
guard1
guard2
rule fired
lss($VAR(X),$VAR(Y)),
{$VAR(Y)= $VAR(X)+ $VAR(_A),$VAR(_A)>0.0}.