% declaration to load rational solver
:- use_module(library(r)).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                     4.1 User Defined Constraints                    %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% parallel_resistors rule p134.
parallel_resistors(V,I,R1,R2) :- V $= I1*R1, V $= I2*R2, I1+I2 $= I.

%% first goal on p134.
gp134a(V,I,R1,R2) :-
	parallel_resistors(V,I,R1,R2), R1 $= 10, R2 $= 5.

%% second goal on p134.
gp134b(I,R) :-
	parallel_resistors(10,I,R,R).


%% goal for example 4.2 p135.
gp135(V,I) :-
     parallel_resistors(VA, IA, 10, 5), 
     parallel_resistors(VB, IB, 8, 3), 
     VA + VB $= V,  I $= IB, I $= IA.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                     4.2 Programming with Rules                      %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 
%% Rules for voltage divider program p138.
voltage_divider(V, I, R1, R2, VD, ID) :- 
     V1 $= I * R1, VD $= I2 * R2, V $= V1 + VD, I $= I2 + ID.
 
cell(V) :- V $= 9.   % note that the constraints must be explicit
cell(V) :- V $= 12. 
 
resistor(R) :- R $= 5. 
resistor(R) :- R $= 9. 
resistor(R) :- R $= 14. 
 
%% Goal for voltage divider program p138.
gp138(V,R1,R2) :-
     voltage_divider(V, _I, R1, R2, VD, ID), 
     5.4 $<= VD, VD $<= 5.5, ID $= 0.1, 
     cell(V), resistor(R1), resistor(R2).
 
% Factorial program p139.
fac(N,F) :- N $= 0, F $= 1.   
fac(N, NF)   :-   N $>= 1, NF $= N * F, N1 $= N - 1, fac(N1,F).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                           4.3 Evaluation                            %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
% Goals for factorial program
gp140(X) :- fac(2,X).
gp143(X) :- X = 2, nodefinition(X).
gp146 :- fac(0,2).
gp155(F) :- F $<= 0, fac(0,F).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                4.4 Derivation Trees and Finite Failure              %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
% Stupid program for infinite derivations p 146
stupid(X) :- stupid(X).                  
stupid(X) :- X $= 1.                 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                          4.7 The CLP Scheme                         %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
% delete program p152.
delete(cons(Y,X), Y, X).
delete(cons(A,X), Y, cons(A,Z)) :- delete(X, Y, Z).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%       4.8 Independence from Rule Ordering and Literal Selection     %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
% infinite program
p :- p.

% goal showing order dependence for finite failure
gp157a :- p, 1 $= 2.
gp157b :- 1 $= 2, p.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                               4.10 Exercises                        %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Exercise 4.1
p41(A,B) :- A $= 0, B $= 0. 
p41(X,B) :-  B $= (X*X)+Y, X1 $= X - 1, p41(X1,Y).

gex41(Y) :- p41(2,Y).
 
% Exercise 4.2
p42(X, B) :-  X $>= 1, B $= Y + X, X1 $= X - 1, p42(X1, Y). 
p42(A, B) :- A $= 0, B $= 0. 
 
q42(X, B)  :-  X $>= 1, Y $>= 0, B $= Y + X, X1 $= X - 1, q42(X1, Y). 
q42(A, B) :- A $= 0, B $= 0. 

gex42a(X) :- p42(X,3).
gex42b(X) :- q42(X,3).

% Exercise 4.3 
p43(X,Y)  :-  X $= Y + 2, Y $>= 0, q43(X,Y). 
 
q43(X,Y)  :-  X $<= 1, r43(X, Y). 
q43(X,Y)  :-  X $<= 3, r43(X, Y). 
 
r43(A,B) :- A $= 2, B $= 0. 
r43(_X,B) :- B $= 2. 

% Exercise 4.4
gex44a(X,R) :- delete(cons(a, cons(b, nil)), X, R).
gex44b(L) :- delete(cons(a, cons(b, nil)), b, L).

