1:- module(relational_clpq, [
    2    op(700, xfx, :>:),
    3    op(700, xfx, :<:),    
    4    op(700, xfx, :>=:),  
    5    op(700, xfx, :=<:),   
    6    op(700, xfx, :=:),   
    7    op(700, xfx, :\=:)
    8]).    9
   10:- use_module(library(clpfd)).   11:- set_prolog_flag(clpfd_monotonic, true).   12
   13
   14% Reification operators:
   15% :- op(760, yfx, :<==>:). % P :<==>: Q	True iff P and Q are equivalent
   16% :- op(750, xfy, :==>:).  % P :==>: Q	True iff P implies Q
   17% :- op(750, yfx, :<==:).  % P :<==: Q	True iff Q implies P
   18% :- op(740, yfx, :\/:).   % P :\/: Q	    True iff either P or Q
   19% :- op(730, yfx, :\:).    % P :\: Q	    True iff either P or Q, but not both
   20% :- op(720, yfx, :/\:).   % P :/\: Q	    True iff both P and Q
   21% :- op(710,  fy, :\).     % :\ Q	        True iff Q is false
   22
   23% Comparison operators:
   24:- op(700, xfx, :>:).    % Expr1 #> Expr2	 Expr1 is greater than Expr2
   25:- op(700, xfx, :<:).    % Expr1 #< Expr2	 Expr1 is less than Expr2
   26:- op(700, xfx, :>=:).   % Expr1 #>= Expr2	 Expr1 is greater than or equal to Expr2
   27:- op(700, xfx, :=<:).   % Expr1 #=< Expr2	 Expr1 is less than or equal to Expr2
   28:- op(700, xfx, :=:).    % Expr1 #= Expr2	 Expr1 equals Expr2
   29:- op(700, xfx, :\=:).   % Expr1 #\= Expr2	 Expr1 is not equal to Expr2
   30
   31% Domain operators:
   32% :- op(700, xfx, in).
   33% :- op(700, xfx, ins).
   34% :- op(450, xfx, .:.). % should bind more tightly than \/ - equivalent clpfd to ..
   35% :- op(150, fx, :). % equivalent to clpfd #
   36
   37A :=: B :-  phrase(eval(A :=: B,_),_).
   38
   39A :\=: B :- phrase(eval(A :\=: B,_),_).
   40
   41A :=<: B :- phrase(eval(A :=<: B,_),_).
   42
   43A :<: B :-  phrase(eval(A :<: B,_),_).
   44
   45A :>=: B :- phrase(eval(B :=<: A,_),_).
   46
   47A :>: B :-  phrase(eval(B :<: A,_),_).
   48
   49eval(N,N/1) --> {number(N)}, !.  
   50eval(V,V/1) --> {var(V)}, !.
   51
   52eval((L * R), Numerator/Denominator) -->
   53    eval(L,LP/LQ), eval(R,RP/RQ),
   54    {#(Numerator) #= #(LP) * #(RP), #(Denominator) #= #(LQ) * #(RQ)}.
   55
   56eval((L / R), Numerator/Denominator) -->
   57    eval(L,LP/LQ), eval(R,RP/RQ),
   58    {#(Numerator) #= #(LP) * #(RQ), #(Denominator) #= #(LQ) * #(RP)}.
   59
   60eval((L + R), Numerator/Denominator) -->
   61    eval(L,LP/LQ), eval(R,RP/RQ),
   62    {
   63            #(LQ) #= #(RQ),
   64            #(Numerator) #= #(LP) + #(RP),
   65            #(Denominator) #= #(LQ)
   66        ;
   67            #(LQ) #\= #(RQ),
   68            #(LP_RQ) #= #(LP) * #(RQ), #(RP_LQ) #= #(RP) * #(LQ),
   69            #(Numerator) #= #(LP_RQ) + #(RP_LQ),
   70            #(Denominator) #= #(LQ) * #(RQ)
   71    }.
   72
   73eval((L - R), Numerator/Denominator) -->
   74    eval(L,LP/LQ), eval(R,RP/RQ),
   75    {
   76            #(LQ) #= #(RQ),
   77            #(Numerator) #= #(LP) - #(RP),
   78            #(Denominator) #= #(LQ)
   79        ;
   80            #(LP_RQ) #= #(LP) * #(RQ), #(RP_LQ) #= #(RP) * #(LQ),
   81            #(Numerator) #= #(LP_RQ) - #(RP_LQ),
   82            #(Denominator) #= #(LQ) * #(RQ)
   83    }.
   84
   85eval((L :=: R), true) -->
   86    eval(L,LP/LQ), eval(R,RP/RQ),
   87    {#(LP) * #(RQ) #= #(RP) * #(LQ)}.
   88
   89eval((L :\=: R), true) -->
   90    eval(L,LP/LQ), eval(R,RP/RQ),
   91    {#(LP) * #(RQ) #\= #(RP) * #(LQ)}.
   92
   93eval((L :=<: R), true) -->
   94    eval(L,LP/LQ), eval(R,RP/RQ),
   95    {#(LP) * #(RQ) #=< #(RP) * #(LQ)}.
   96
   97eval((L :<: R), true) -->
   98    eval(L,LP/LQ), eval(R,RP/RQ),
   99    {#(LP) * #(RQ)