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(_,_,_,_,_,[]).