writeDomains(VarNumber,[X|Domains]):-
write('Variable '), write(VarNumber), write(': '),
write(X), nl,
VarNumber2 is VarNumber + 1,
writeDomains(VarNumber2,Domains).
writeDomains(_,[]).
defineVars(Vars):-
latestStartingHour(N),
length(Vars,N).
defineDomains([S|Vars],Slot,[L|Tail]):-
findall([Subject,Group],
class(Slot,Subject,Group),L),
length(L,M),
M >= 1,
S in 1..M,
Slot2 is Slot + 1,
defineDomains(Vars,Slot2,Tail).
defineDomains([S|Vars],Slot,[L|Tail]):-
findall(Slot,class(Slot,_,_),L),
length(L,M),
M =:= 0,
S in 0,
Slot2 is Slot + 1,
defineDomains(Vars,Slot2,Tail).
defineDomains([],_,[]).
defineConstraints(Vars,Domains):-
onlyOneGroup(Vars,Domains,1).
onlyOneGroup(Vars,Domains,CurrentSubject):-
numberOfSubjects(N),
CurrentSubject =< N,
findall(GTheory,group(CurrentSubject,GTheory,1),LTheory),
auxOnlyOneGroup(Vars,Domains,CurrentSubject,LTheory),
findall(GLab,group(CurrentSubject,GLab,0),LLab),
auxOnlyOneGroup(Vars,Domains,CurrentSubject,LLab),
Subj2 is CurrentSubject + 1,
onlyOneGroup(Vars,Domains,Subj2).
onlyOneGroup(_,_,_).
auxOnlyOneGroup(Vars,Domains,CurrentSubject,[G|Groups]):-
findall(S1,class(S1,CurrentSubject,G),L1),
findall([S2,G2],(member(G2,Groups),class(S2,CurrentSubject,G2)),L2),
iterateExclusion(Vars,Domains,CurrentSubject,G,L1,L2),
auxOnlyOneGroup(Vars,Domains,CurrentSubject,Groups).
auxOnlyOneGroup(_,_,_,[]).
iterateExclusion(Vars,Domains,Subject,G1,[X|RestOfSlots],GroupAndSlot):-
auxIterate(Vars,Domains,Subject,G1,X,GroupAndSlot),
iterateExclusion(Vars,Domains,Subject,G1,RestOfSlots,GroupAndSlot).
iterateExclusion(_,_,_,_,[],_).
auxIterate(Vars,Domains,Subj,G1,CurrentSlot,[[S2,G2]|RestOfPairs]):-
nth1(CurrentSlot,Vars,FirstVar),
nth1(S2,Vars,SecondVar),
nth1(CurrentSlot,Domains,FirstList),
nth1(S2,Domains,SecondList),
nth1(FirstIndex,FirstList,[Subj,G1]),
nth1(SecondIndex,SecondList,[Subj,G2]),
FirstVar #= FirstIndex #==> SecondVar #\= SecondIndex,
SecondVar #= SecondIndex #==> FirstVar #\= FirstIndex,
auxIterate(Vars,Domains,Subj,G1,CurrentSlot,RestOfPairs).
auxIterate(_,_,_,_,_,[]).