Programmazione Logica -- Lezione 8: Analogy

/*
Programma ANALOGY

Date tre figure A, B e C,
analogy(A,B,C,X) restituisce la figura X
che sta a C come B sta ad A.
*/

/* Definizione del tipo di dato "figura" */

figura(cerchio).
figura(quadrato).
figura(triangolo).
figura(sopra(A,B)) :- figura(A), figura(B).
figura(dentro(A,B)) :- figura(A), figura(B).
figura(accanto(A,B)) :- figura(A), figura(B).

/*
Definizione del predicato principale "analogy".
L'idea e': trova la trasformazione T che permette
di trasformare A in B, ed applicala a C per ottenere X
*/
analogy(A,B,C,X) :-
trasforma(A,B,T), trasforma(C,X,T),
figura(A), figura(B), figura(C), figura(X).
/*
Tutta "l'intelligenza" del programma sta nella definizione
di questo predicato "trasforma".
L'idea e' quella di rappresentare la trasformazione come
un albero (ovvero un termine) in cui ad ogni nodo
sono associate le trasformazioni elementari che abbiamo
applicato nei vari punti della figura.
La definizione di "trasforma" dipende da che tipo di
trasformazioni elementari vogliamo.
Quella che diamo sotto considera come trasformazioni elementari:
l'identita' (ident : identity),
la inversione sopra-sotto, (invert_ab : invert above-below),
la inversione destra-sinista, (invert_lr : invert left-right),
la inversione dentro-fuori, (invert_io : invert inside-outside).
Queste trasformazioni saranno applicate ricorsivamente
anche ai vari pezzi delle figure.
Inoltre dovemo avere delle operazioni che in quel punto
non fanno niente, ma che permettono comunque di accedere
ai vari pezzi della figura e di trasformarli:
entra sopra e sotto, (go_ab : go above and below),
entra a destra e a sinista, (go_lr : go left and right),
entra dentro e fuori, (go_io : go inside and outside).
*/
trasforma(A,A,ident).

trasforma(sopra(A,B), sopra(C,D), invert_ab(T1,T2)) :-
trasforma(A,D,T1), trasforma(B,C,T2).


trasforma(sopra(A,B), sopra(C,D), go_ab(T1,T2)) :-
trasforma(A,C,T1), trasforma(B,D,T2).


trasforma(dentro(A,B), dentro(C,D), invert_io(T1,T2)) :-
trasforma(A,D,T1), trasforma(B,C,T2).


trasforma(dentro(A,B), dentro(C,D), go_io(T1,T2)) :-
trasforma(A,C,T1), trasforma(B,D,T2).


trasforma(accanto(A,B), accanto(C,D), invert_lr(T1,T2)) :-
trasforma(A,D,T1), trasforma(B,C,T2).


trasforma(accanto(A,B), accanto(C,D), go_lr(T1,T2)) :-
trasforma(A,C,T1), trasforma(B,D,T2).

Esempio di sessione:

Il Programma e' stato salvato in un file "Prog2.pl"

[cygnus:catuscia:~/Prolog:13] pl
Welcome to SWI-Prolog (Version 2.7.15)
Copyright (c) 1993-1996 University of Amsterdam. All rights reserved.

For help, use ?- help(Topic). or ?- apropos(Word).

1 ?- consult('Prog2').
Prog2 compiled, 0.01 sec, 3,200 bytes.

Yes
2 ?- analogy(sopra(cerchio,dentro(triangolo,quadrato)),
| sopra(dentro(quadrato,triangolo),cerchio),
| sopra(triangolo,dentro(cerchio,quadrato)),
| X).

X = sopra(dentro(quadrato, cerchio), triangolo) ;

No
3 ?- analogy(sopra(cerchio,dentro(triangolo,quadrato)),
| sopra(dentro(quadrato,triangolo),cerchio),
| X, Y).

X = sopra(cerchio, dentro(cerchio, cerchio))
Y = sopra(dentro(cerchio, cerchio), cerchio) ;

X = sopra(cerchio, dentro(cerchio, quadrato))
Y = sopra(dentro(quadrato, cerchio), cerchio) ;

X = sopra(cerchio, dentro(cerchio, triangolo))
Y = sopra(dentro(triangolo, cerchio), cerchio) ;

X = sopra(cerchio, dentro(cerchio, sopra(cerchio, cerchio)))
Y = sopra(dentro(sopra(cerchio, cerchio), cerchio), cerchio) ;

X = sopra(cerchio, dentro(cerchio, sopra(cerchio, quadrato)))
Y = sopra(dentro(sopra(cerchio, quadrato), cerchio), cerchio) ;

X = sopra(cerchio, dentro(cerchio, sopra(cerchio, triangolo)))
Y = sopra(dentro(sopra(cerchio, triangolo), cerchio), cerchio) ;

X = sopra(cerchio, dentro(cerchio, sopra(cerchio, sopra(cerchio, cerchio))))
Y = sopra(dentro(sopra(cerchio, sopra(cerchio, cerchio)), cerchio), cerchio)

Yes
4 ?- halt.
[cygnus:catuscia:~/Prolog:14]