Salta ai contenuti. | Salta alla navigazione

Strumenti personali

CLP 17 luglio 2013

Applicazioni di Intelligenza Artificiale - CLP

Prof. Marco Gavanelli

17 luglio 2013

Esercizio (8 punti)

Una rete logica è costituita da porte AND e OR, collegate come in un albero binario. La rete è descritta nel file rete1.pl .

Il file contiene dei fatti

tree(NodoPadre,TipoPorta,Figlio1,Figlio2)

dove

  • NodoPadre è un numero intero che rappresenta il nodo
  • TipoPorta è il tipo di porta e può essere and oppure or
  • Figlio1 e Figlio2 sono gli identificatori dei nodi figli.

Ad esempio, il fatto

tree(1,and,2,3)

vuol dire che il nodo 1 è l'AND dei valori sui nodi 2 e 3.

Il file rete1.pl contiene anche dei fatti

leaf(Nodo,Valore)

che rappresentano le foglie dell'albero.

  • Nodo è l'identificatore del nodo
  • Valore può essere 0 o 1, dove 0 sta per FALSO e 1 per VERO (logica positiva).

Ad esempio, i fatti:

tree(1,and,2,3).
tree(2,or,4,5).
tree(3,or,6,7).
tree(4,or,8,9).
leaf(5,1).
leaf(6,0).
leaf(7,1).
leaf(8,0).
leaf(9,1).

rappresentano la rete riportata in figura:

usata nel compito CLP del 17 luglio 2013

Il nodo 1 è sempre la radice dell'albero (il valore di output della rete combinatoria). Dati i valori di ingresso delle foglie, è possibile calcolare il valore di uscita sul nodo 1; nell'esempio in figura l'output è 1.

Il valore in output, però, non è quello che voleva ottenere il progettista; il valore che voleva ottenere è riportato nel file rete1.pl nel fatto

result(V).

Si scriva un programma CLP(FD) che calcola qual è il numero minimo di porte che bisogna cambiare (da AND a OR o viceversa) perché il nodo 1 fornisca il risultato nel fatto result.

Nell'esempio in figura, se si ha il fatto result(0), si dovrà calcolare qual è il numero minimo di porte da sostituire per ottenere il valore 0 sul nodo 1 (in questo esempio viene 1, perché basta sostituire la porta che ha come output il nodo 3).

 


 

 

 

 

Soluzione

:- lib(fd).
:- lib(fd_global).
:- lib(propia).
:- [rete1].

change(Changes,LNodi):-
	result(V),
	vincoli(1,Bools,V,Changes,LNodi),
	sumlist(Changes,Nchange),
	append(Bools,Changes,Vars),
	minimize(labeling(Vars),Nchange).

vincoli(Nodo,[V],V,[],[]):-
	leaf(Nodo,V),!.
vincoli(Nodo,[V|Bools],V,[Change|Changes],[Nodo|LNodi]):-
	tree(Nodo,OP,A,B),!,
	vincoli(A,BoolsA,VA,ChangesA,LNodiA),
	vincoli(B,BoolsB,VB,ChangesB,LNodiB),
	and_or(OP,VA,VB,V,Change) infers most,
	append(BoolsA,BoolsB,Bools),
	append(ChangesA,ChangesB,Changes),
	append(LNodiA,LNodiB,LNodi).
% La lista LNodi serve solo per interpretare il risultato:
% Serve per capire dall'output quali sono le porte che sono state cambiate

% and_or(TipoPorta,A,B,V,Cambiato)
% se Cambiato = 0, V e` il risultato della porta TipoPorta
% se Cambiato = 1, V e` il risultato della porta opposta
and_or(and,A,B,V,0):- minlist([A,B],V). % Oppure: #/\(A,B,V)
and_or(and,A,B,V,1):- maxlist([A,B],V).
and_or(or,A,B,V,0):- maxlist([A,B],V).
and_or(or,A,B,V,1):- minlist([A,B],V).