Salta ai contenuti. | Salta alla navigazione

Strumenti personali

Esercizio divisione delle sfere

ho provato a risolvere il problema dei due fratelli che si devono dividere le sfere.

sfera(N,L):-length(L,N),
            L :: 0..1,
            somma(L,0,FRATELLOA),
            somma(L,0,FRATELLOB),
            FTRATELLOA #= FRATELLOB,
            labeling (L).

somma(F,L,TOT):-somma(F,L,1,0,TOT).	%(1)
somma(F,[],POS,ACC,ACC).		%(2)
somma(F,[F|T],POS,ACC,TOT):-ACC1 is ACC+POS*POS*POS,	%(3)
                            POS1 is POS+1,
                            somma(F,T,POS1,ACC1,TOT).
somma(F,[H|T],POS,ACC,TOT):-POS1 is POS+1,		%(4)
                            somma(F,T,POS1,ACC,TOT).

Penso che la soluzione si commenti da sola, la procedura somma è giusta xchè l'ho provata singolarmente. Facendo girare il programma su eclipse, mi dà sempre risposta negativa, ho sbagliato qualcosa?

Forse la somma andrebbe invocata in altro modo: la invoca con una lista come primo parametro, mentre nella definizione la lista e` il secondo parametro. Da quello che capisco, la sua intenzione era di invocarla cosi`:

	somma(1,L,FRATELLOA), % calcola la somma delle sfere del fratello 1
	somma(0,L,FRATELLOB), % calcola la somma delle sfere del fratello 0

Questa soluzione pero` fa gia` implicitamente il labeling all'interno della somma: viene aperto un punto di scelta e, se prendo la clausola (3) assegno la sfera al fratello F, se prendo la clausola (4) non assegno la sfera.

Inoltre, alla clausola (4) si dovrebbe aggiungere che in questo caso H deve assumere il negato di F, mettendo ad es H #= 1-F, altrimenti rischio di lasciare unbound un elemento della lista, ma la somma l'ho gia` calcolata, quindi la domma non avra` alla fine il valore giusto.

In CLP si cerca di evitare di creare punti di scelta finche' non effettuo il labeling. Quindi dovro` evitare di mettere 2 clausole e raggruppare la (3) e la (4) in una sola clausola. In questa clausola dovro` cercare di legare il valore della variabile H con quello della variabile TOT per mezzo di vincoli. Sono da escludere le is perche' queste richiedono che il predicato sia ground; dovro` invece usare il vincolo #=

Se voglio seguire la sua filosofia e calcolare la somma dato in ingresso il numero del fratello, potrei dire: "aggiungo all'accumulatore il valore POS*POS*POS se la variabile H assume il valore F". Di nuovo, devo farlo con dei vincoli e non con dei punti di scelta. Eclipse mi da` i reified constraints (lucido 73). Posso scrivere

	ACC1 #= ACC+POS*POS*POS #<=> BOOL,
	ACC1 #= ACC #<=> 1-BOOL,

e questo impone che ACC1 prenda quel valore se la variabile BOOL prende il valore 1 e che prenda il valore ACC se BOOL prende il valore 0. Noti che questo non impone punti di scelta: viene imposto un vincolo. A questo punto dobbiamo legare questo nuovo BOOL che abbiamo creato al fatto che la variabile H sia uguale ad F. Quindi:

	H #= F #<=> BOOL