#maxint=30.

% Orario del Primo Trimestre del Primo Anno SMFN
% Studenti divisi in 8 gruppi

orario(Gruppo,Giorno,Ora,Materia,Lezione) v -orario(Gruppo,Giorno,Ora,Materia,Lezione) :-
	 oraAmmissibile(Gruppo,Giorno,Ora,Materia,Lezione),
	 not oraAssegnata(Gruppo,Giorno,Ora).

% eventuali allocazioni obbligate (lezioni che *devono* necessariamente
% essere tenute in un orario prefissato, ad esempio per via della
% disponibilita` dei laboratori) devono essere specificate
% in forma di fatti del tipo "prefissato(Gruppo,Giorno,Materia,Lezione)".
% la presenza di tali fatti riduce lo spazio di ricerca.
prefissato(1,sab,8,labInformatica,1).
prefissato(1,sab,9,labInformatica,2).

oraAssegnata(Gr,Gi,H) :- prefissato(Gr,Gi,H,_,_).

orario(Gruppo,Giorno,Ora,Materia,Lezione) :-
	prefissato(Gruppo,Giorno,Ora,Materia,Lezione).

% qui bisogna elencare tutti i vincoli forti (cioe` non derogabili)
% esistenti sull'orario, che sono esprimibili con i soli predicati
% di base (oraInizio, gruppo, lezione, giorno).

inammissibile(G,sab,H,M,L):-
	gruppo(G), oraInizio(H), H > 12, lezione(M,L).

inammissibile(G,sab,H,M,L):-
	gruppo(G), oraInizio(H), lezione(M,L),
	M <> informatica, M <> labInformatica.

oraAmmissibile(Gruppo,Giorno,Ora,Materia,Lezione) :- 
	gruppo(Gruppo), giorno(Giorno), 
	oraInizio(Ora), lezione(Materia,Lezione),
	not inammissibile(Gruppo,Giorno,Ora,Materia,Lezione).

% ogni lezione deve essere prevista in orario
inOrario(Gr,M,L) :- orario(Gr,_,_,M,L).
:- lezione(M,L), gruppo(Gr), not inOrario(Gr,M,L).

% ogni lezione deve essere presente una sola volta in orario,
% ovvero le lezioni non devono essere ripetute.
:- orario(Gr,Gi,_,M,L), orario(Gr,Gi1,_,M,L), Gi <> Gi1.
:- orario(Gr,Gi,H,M,L), orario(Gr,Gi,H1,M,L),  H <> H1.

% una classe segue una sola lezione alla volta.
:- orario(Gr,Gi,H,M,L), orario(Gr,Gi,H,M1,L1), lezioniDiverse(M,L,M1,L1).
lezioniDiverse(M,L,M1,L1) :- lezione(M,L), lezione(M1,L1), M <> M1.
lezioniDiverse(M,L,M1,L1) :- lezione(M,L), lezione(M1,L1), L <> L1.

% le lezioni di una stessa materia devono essere erogate 
% seguendo il numero di ordine.

:- orario(Gr,Gi,H,M,L), orario(Gr,Gi1,H1,M,L1),
   precede(Gi,Gi1), L > L1.

:- orario(Gr,Gi,H,M,L), orario(Gr,Gi,H1,M,L1),
   precede(H,H1), L > L1.

% VINCOLI FORTI

% lezioni di almeno due ore
:- orario(Gr,Gi,H,M,L), not precedeStessaLezione(Gr,Gi,H,M,L),
   not segueStessaLezione(Gr,Gi,H,M,L).

% lezioni di almeno due ore
%:- orario(Gr,Gi,H,M,L), not precedeStessaLezione(Gr,Gi,H,M,L),
%   not segueStessaLezione(Gr,Gi,H,M,L).

% lezioni di non piu` di due ore
%:- segueStessaLezione(Gr,Gi,H,M,L), precedeStessaLezione(Gr,Gi,H,M,L).

segueStessaLezione(Gr,Gi,H,M,L) :- 
	orario(Gr,Gi,H,M,L), orario(Gr,Gi,H1,M,L1),
	oraSuccessiva(H,H1), L1=L+1.

precedeStessaLezione(Gr,Gi,H,M,L) :- 
	orario(Gr,Gi,H,M,L), orario(Gr,Gi,H1,M,L1),
	oraSuccessiva(H1,H), L=L1+1.

% nella stessa giornata non piu` di due ore della stessa materia.
% basta imporre che la stessa materia non occorra a due
% ore di distanza nella stessa giornata; cio` e` sufficiente
% poiche` le lezioni non eccedono le due ore.
% in effetti questo vincolo sussume il precedente vincolo
% "lezioni di non piu` di due ore"
:- orario(Gr,Gi,H,M,L), orario(Gr,Gi,H1,M,L1), H1=H+Diff, Diff>1.

% max 6 ore al giorno. poiche` le lezioni sono erogate in gruppi
% di due ore, basta imporre che non ci siano erogate 3 materie
% diverse nella stessa giornata.
erogata(Gi,Gr,M) :- orario(Gi,Gr,_,M,_).
:- erogata(Gi,Gr,M1), erogata(Gi,Gr,M2), erogata(Gi,Gr,M3),
   M1 <> M2, M1 <> M3, M2 <> M3.

% minimizzazione dei "buchi"
impegnato(Gr,Gi,H) :-  orario(Gr,Gi,H,_,_).
buco(Gr,Gi,Durata) :- 
	impegnato(Gr,Gi,H1), impegnato(Gr,Gi,H2),
	not impegnatoTra(Gr,Gi,H1,H2), 
	H2=H1+Diff, Diff=Durata+1, Durata > 0.

impegnatoTra(Gr,Gi,H1,H2) :-
	oraInizio(H1), oraInizio(H2), H1<H2,
	impegnato(Gr,Gi,H3), H3 < H2, H3 > H1.

:~ buco(Gr,Gi,Durata). [Durata:2]

% PREFERENZE DEI DOCENTI.

% il docente di calcolo non gradisce lezioni pomeridiane.
:~  orario(Gi,Gr,H,calcolo,_), H>12. [1:1]

% il docente di informatica non gradisce lezioni in primo mattino.
:~  orario(Gi,Gr,H,informatica,_), H<11. [1:1]

% DATI DI INGRESSO
numeroGruppi(2).
gruppo(G) :- numeroGruppi(N), #int(G), G>0, G<=N.

giorno(lun).
giorno(mar).
giorno(mer).
giorno(gio).
giorno(ven).
giorno(sab).

%il primo argomento e` il piu` piccolo
giornoSuccessivo(lun,mar).
giornoSuccessivo(mar,mer).
giornoSuccessivo(mer,gio).
giornoSuccessivo(gio,ven).
giornoSuccessivo(ven,sab).

oraInizio(8).
oraInizio(9).
oraInizio(10).
oraInizio(11).
oraInizio(12).
oraInizio(14).
oraInizio(15).
oraInizio(16).
oraInizio(17).
oraInizio(18).

%il primo argomento e` il piu` piccolo
oraSuccessiva(8,9).
oraSuccessiva(9,10).
oraSuccessiva(10,11).
oraSuccessiva(11,12).
oraSuccessiva(14,15).
oraSuccessiva(15,16).
oraSuccessiva(16,17).
oraSuccessiva(17,18).

%il primo argomento e` il piu` piccolo
precede(H,H1) :- oraInizio(H), oraInizio(H1), H < H1.
precede(G,G1) :- giornoSuccessivo(G,G1).
precede(G,G1) :- giornoSuccessivo(G,G2), precede(G2,G1).

lezione(Materia,Lezione) :-
	oreSettimanali(Materia,TotaleOre), 
	#int(Lezione), Lezione>0, Lezione <= TotaleOre.

oreSettimanali(informatica,4).
oreSettimanali(labInformatica,2).
oreSettimanali(fisica,4).
oreSettimanali(calcolo,6).
oreSettimanali(inglese,4).
