zurück

:- use_module(library(fd)).

anzahlTage(AnzTage) :-
  findall(TagID, tag(TagID, _), TagesListe),
  length(TagesListe, AnzTage).

anzahlZeiten(AnzZeiten) :-
  findall(ZeitID, zeit(ZeitID, _), ZeitenListe),
  length(ZeitenListe, AnzZeiten).

anzahlRaeume(AnzRaeume) :-
  findall(RaumID, raum(RaumID, _, _, _), RaumListe),
  length(RaumListe, AnzRaeume).

mkProbVar(VerID, ProblemVar) :-
  ProblemVar=raumTagZeit(Raum, Tag, Zeit, VerID),
  anzahlRaeume(AnzRaeume),
  anzahlTage(AnzTage),
  anzahlZeiten(AnzZeiten),
  AnzRaeume0 is AnzRaeume-1,
  AnzTage0 is AnzTage-1,
  AnzZeiten0 is AnzZeiten-1,
  Raum::0..AnzRaeume0,
  Tag::0..AnzTage0,
  Zeit::0..AnzZeiten0.

% mkProblemVars(Veranstaltungen, ProblemVars)
mkProblemVars([], []).
mkProblemVars([VerID|VRest], [ProblemVar|PRest]) :-
  mkProbVar(VerID, ProblemVar),
  mkProblemVars(VRest, PRest).

teilMenge([], Menge2).
teilMenge([Kopf1|Rest1], Menge2) :- 
  member(Kopf1, Menge2),
  teilMenge(Rest1, Menge2).

zaehleTeilnehmer([], 0).
zaehleTeilnehmer([Teilnehmer|TRest], Anzahl) :-
  teilnehmer(Teilnehmer, TeilnehmerAnz),
  zaehleTeilnehmer(TRest, AnzRest),
  Anzahl is TeilnehmerAnz + AnzRest.

holeGueltigeRaeume([], _, []).
holeGueltigeRaeume([RaumID|RRest], VerID, GueltigeRaeume) :-
  veranstaltung(VerID, Teilnehmer, _),
  raum(RaumID, Groesse, _, _),
  zaehleTeilnehmer(Teilnehmer, AnzTeilnehmer),
  Groesse < AnzTeilnehmer,
  holeGueltigeRaeume(RRest, VerID, GueltigeRaeume).
holeGueltigeRaeume([RaumID|RRest], VerID, GueltigeRaeume) :-
  veranstaltung(VerID, Teilnehmer, VerRessourcen),
  raum(RaumID, Groesse, RaumRessourcen, _),
  zaehleTeilnehmer(Teilnehmer, AnzTeilnehmer),
  Groesse >= AnzTeilnehmer,
  not(teilMenge(VerRessourcen, RaumRessourcen)),
  holeGueltigeRaeume(RRest, VerID, GueltigeRaeume).
holeGueltigeRaeume([RaumID|RRest], VerID, [RaumID0|GueltigeRaeume]) :-
  veranstaltung(VerID, Teilnehmer, VerRessourcen),
  raum(RaumID, Groesse, RaumRessourcen, _),
  zaehleTeilnehmer(Teilnehmer, AnzTeilnehmer),
  Groesse >= AnzTeilnehmer,
  teilMenge(VerRessourcen, RaumRessourcen),
  RaumID0 is RaumID - 1,
  holeGueltigeRaeume(RRest, VerID, GueltigeRaeume).

raumConstr([]).
raumConstr([raumTagZeit(Raum, _, _, VerID)|PRest]) :-
  findall(RaumID, raum(RaumID, _, _, _), RaumListe),
  holeGueltigeRaeume(RaumListe, VerID, GueltigeRaeume),
  Raum::GueltigeRaeume,
  raumConstr(PRest).


mkDiffVars([], []).
mkDiffVars([raumTagZeit(Raum, Tag, Zeit, _)|Rest], [DiffVar|DVRest]) :-
  anzahlTage(AnzTage),
  anzahlZeiten(AnzZeiten),  
  AnzTageUndZeiten is AnzTage * AnzZeiten,
  (AnzTageUndZeiten * Raum + AnzZeiten * Tag + Zeit) #= DiffVar,
  mkDiffVars(Rest, DVRest).

raumClashConstr(ProblemVars) :-
  mkDiffVars(ProblemVars, DiffVars),
  alldistinct(DiffVars).

schnittMenge([], Menge2) :- fail.
schnittMenge([Kopf|Rest], Menge2) :- 
  member(Kopf, Menge2).
schnittMenge([Kopf|Rest], Menge2) :- 
  schnittMenge(Rest, Menge2).

holeSchnittVar(_, [], []).
holeSchnittVar(Teilnehmer, [PVar|PRest], SchnittVar) :-
  PVar=raumTagZeit(Raum, Tag, Zeit, VerID),
  veranstaltung(VerID, VerTeilnehmer, _),
  not(schnittMenge(Teilnehmer, VerTeilnehmer)),
  holeSchnittVar(Teilnehmer, PRest, SchnittVar).
holeSchnittVar(Teilnehmer, [PVar|PRest], [PVar|SchnittVar]) :-
  PVar=raumTagZeit(Raum, Tag, Zeit, VerID),
  veranstaltung(VerID, VerTeilnehmer, _),
  schnittMenge(Teilnehmer, VerTeilnehmer),
  holeSchnittVar(Teilnehmer, PRest, SchnittVar).

verhindereTeilnehmerClash(_, []).
verhindereTeilnehmerClash(PVar, [SchnittVar|SVRest]) :-
  PVar=raumTagZeit(_, Tagi, Zeiti, _),
  SchnittVar=raumTagZeit(_, Tagj, Zeitj, _),
  anzahlZeiten(AnzZeiten),  
  (AnzZeiten * Tagi + Zeiti) #\= (AnzZeiten * Tagj + Zeitj),
  verhindereTeilnehmerClash(PVar, SVRest).

teilnehmerClashConstr([]).
teilnehmerClashConstr([PVar|PRest]) :-
  PVar = raumTagZeit(_, _, _, VerID),
  veranstaltung(VerID, Teilnehmer, _),  
  holeSchnittVar(Teilnehmer, PRest, SchnittVars),
  verhindereTeilnehmerClash(PVar, SchnittVars),
  teilnehmerClashConstr(PRest).

labeling([]).
labeling([PVar|PVRest]) :-
  PVar = raumTagZeit(Raum, Tag, Zeit, VerID),
  indomain(Raum),
  indomain(Tag),
  indomain(Zeit),
  labeling(PVRest).

ausgabe2(ProblemVars, Ausgabe) :-
  open(Ausgabe, write, Stream),
  ausgabe22(ProblemVars, Stream),  
  close(Stream).

ausgabe22([],_).
ausgabe22([PVar|PVars], Stream) :-
  PVar=raumTagZeit(Raum, Tag, Zeit, VerID),
  Raum0 is Raum + 1,
  Tag0 is Tag + 1,
  Zeit0 is Zeit + 1,
  print(Stream, 'loesung('),
  print(Stream, VerID),
  print(Stream, ', '),
  print(Stream, Raum0),
  print(Stream, ', '),
  print(Stream, Tag0),
  print(Stream, ', '),
  print(Stream, Zeit0),
  print(Stream, ').'),
  nl(Stream),
  ausgabe22(PVars, Stream).


stundenplan(Wissensbasis, Ausgabe) :-
  print('Wissensbasis laden ...'),
  compile(Wissensbasis),
  print('Problemvariablen erstellen ...'),
  nl,
  findall(VerID, veranstaltung(VerID, _, _), Veranstaltungen),
  mkProblemVars(Veranstaltungen, ProblemVars),
  print('Raeume constrainen ...'),
  nl,
  raumConstr(ProblemVars),
  print('Raum clash constrainen ...'),
  nl,
  raumClashConstr(ProblemVars),
  print('Teilnehmer clash constrainen ...'),
  nl,
  teilnehmerClashConstr(ProblemVars),
  print('labeling ...'),
  nl,
  labeling(ProblemVars),
  print('Heureka !!!'),
  ausgabe2(ProblemVars, Ausgabe).