%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ANALOGY: A program to solve intelligence tests based on analogies of figures %
%                                                                              %
% File analogy.pl                                                              %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

/* We want to write a program which solves tests 
   of the following form: given the figures A, B, and C,
   find the figure D which is to C like B is to A.
   
   Representation of figures: 
   We will represent figures like terms. Let us consider the following
   kinds of figures: 
   - Basic figures 
       c  for  circle
       s  for  square
       t  for  triangle
   - Composite figures
       in(F,G)    for the figure obtained by inserting figure F inside figure G
       above(F,G) for the figure obtained by putting figure F above figure G
       aside(F,G) for the figure obtained by putting figure F aside figure G
   
   We define now a predicate figure(F) which holds iff F is a term which 
   represents a figure constructed according to the above possibilities */

figure(c).
figure(s).
figure(t).
figure(in(F,G)) :- figure(F), figure(G).
figure(above(F,G)) :- figure(F), figure(G).
figure(aside(F,G)) :- figure(F), figure(G).


/* Now let us consider the problem of solving the test. 
   
   To this purpose, we define the predicate analogy(A,B,C,D) 
   whose intended meaning is: 
   analogy(A,B,C,D) holds iff D is to C like B is to A.

   Note that there is a base case, corresponding to the case in which 
   A and B are equal (and in this case D has to be equal to C). 
   The inductive cases are represented by transforming composite 
   figures. For instance, we can obtain in(B1,B2) from in(A1,A2) 
   by putting A2 inside A1, and then transform recursively
   A1 into B2, and A2 into B1. 
   Alternatively, we can leave A1 inside A2, and then transform
   recursively A1 into B1 and A2 into B2
   Similar choices can be done for all the other composite figures. 
   For each of these transformations, we need to apply the same 
   transformation to the third figure (C) so to obtain D.  */     

analogy(A,A,C,C) :- figure(A), figure(C).  % base case

analogy(in(A1,A2),in(B1,B2),in(C1,C2),in(D1,D2)) :- 
   analogy(A1,B2,C1,D2), analogy(A2,B1,C2,D1).      % put A2 inside A1 

analogy(in(A1,A2),in(B1,B2),in(C1,C2),in(D1,D2)) :- 
   analogy(A1,B1,C1,D1), analogy(A2,B2,C2,D2).      % leave A1 inside A2 

analogy(above(A1,A2),above(B1,B2),above(C1,C2),above(D1,D2)) :- 
   analogy(A1,B2,C1,D2), analogy(A2,B1,C2,D1).      % put A2 above A1 

analogy(above(A1,A2),above(B1,B2),above(C1,C2),above(D1,D2)) :- 
   analogy(A1,B1,C1,D1), analogy(A2,B2,C2,D2).      % leave A1 above A2

analogy(aside(A1,A2),aside(B1,B2),aside(C1,C2),aside(D1,D2)) :- 
   analogy(A1,B2,C1,D2), analogy(A2,B1,C2,D1).      % switch side of A1 and A2

analogy(aside(A1,A2),aside(B1,B2),aside(C1,C2),aside(D1,D2)) :- 
   analogy(A1,B1,C1,D1), analogy(A2,B2,C2,D2).   % leave A1 and A2 on same side

/* Note that we could have avoided the conditions figure(A), figure(C)      
   in the body of the base case. However, without those conditions, 
   we could have applied analogy to any kind of structure (also those
   which do not represent legal figures according to our definition, 
   and we could even obtain a success. 
   The presence of those conditions restricts the success of analogy only to 
   those terms which represent legal figures. 
   Inserting such conditions is, in a sense, a way of imposing a 
   type-discipline on the predicate analogy   */

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

   
   


