CLP 2 apr 2009
Applicazioni di Intelligenza Artificiale - CLP
Dott. Ric. Marco Gavanelli
2 Aprile 2009
Esercizio (8 punti)
Un neonato deve mangiare 10 volte al giorno, ad intervalli di 3 ore al massimo, comprese le ore della notte (anche quelle a cavallo della mezzanotte). Il papà e la mamma hanno deciso di dividersi il compito di dare le poppate al figlio (5 il papà e 5 la mamma), in modo che ciascuno di loro abbia un intervallo di ore in cui riesce a dormire che sia il più lungo possibile.
Si scriva un programma CLP che stabilisce gli orari in cui il bambino riceverà le poppate. Si consideri come funzione obiettivo da massimizzare il numero di ore in cui riesce a dormire il genitore che dorme di meno fra i due.
Ad esempio, se la mamma dà le poppate delle ore 0, 4, 10, 14, 20, vuol dire che riuscirà a dormire 6 ore (dalle 4 alle 10). Se il papà dà le poppate delle 3, 7, 12, 17, 23, vuol dire che ha a disposizione 5 ore di sonno consecutive (ad esempio, dalle 12 alle 17). Il valore della funzione obiettivo è 5, in quanto il genitore che ha meno ore di sonno consecutive è il papà, che dorme 5 ore di seguito.
Soluzione
:- lib(fd).
:- lib(fd_global).
poppate(Mamma,Papa):-
length(Papa,5), % Poppate date dal papa`
length(Mamma,5),% Poppate date dalla mamma
append(Papa,Mamma,L),
L :: 0..23, % Definizione domini
ordered(<,Mamma), % Impongo che le poppate date
% dalla mamma siano ordinate, in quanto non mi
% interessano le soluzioni simmetriche
ordered(<,Papa),
% Ordinate e` la lista totale delle poppate ordinata
sorted(L,Ordinate),
Ordinate = [Prima|_],
GiornoDopo #= Prima+24,
% Il giorno dopo si deve continuare con lo stesso schema
% quindi aggiungo una variabile che rappresenta la prima
% poppata del giorno dopo
append(Ordinate,[GiornoDopo],Tutte),
max_3ore(Tutte), % Impongo che il bambino mangi ogni 3 ore
% Calcolo gli intervalli in cui la mamma puo` dormire
intervalli(Mamma,IntMamma),
intervalli(Papa,IntPapa),
% Trovo l'intervallo massimo in cui dorme la mamma
maxlist(IntMamma,OreSonnoMamma),
maxlist(IntPapa,OreSonnoPapa),
% Calcolo quale dei due genitori dorme di meno
minlist([OreSonnoMamma,OreSonnoPapa],Fneg),
% Inverto la funzione obiettivo perche' ECLiPSe permette
% solo di minimizzare ed io devo invece massimizzare
Fneg+F #= 0,
min_max(labeling(L),F).
my_labeling([]).
my_labeling([H|T]):- indomain(H), my_labeling(T).
max_3ore([_]).
max_3ore([A,B|T]):-
B-A #=< 3,
max_3ore([B|T]).
intervalli(L,Lint):-
L= [Prima|_],
Ultima #= Prima+24,
append(L,[Ultima],Tot),
intervalli_tot(Tot,Lint).
intervalli_tot([_],[]).
intervalli_tot([A,B|T],[I|TI]):-
I #= B-A,
intervalli_tot([B|T],TI).