diff --git a/examples/edt/edt.ez b/examples/edt/edt.ez new file mode 100644 index 0000000000000000000000000000000000000000..f55b5e00821c446886cafa704c7873b5d11d92a9 --- /dev/null +++ b/examples/edt/edt.ez @@ -0,0 +1,1179 @@ +/*________________________________________________________________________________________________ +Projet de recherche stochastique : Université de Strasbourg (2010-11) - Besset Samuel [M1 ILC] +Création d'un emplois du temps +Selection operator: Tournament +________________________________________________________________________________________________*/ + + +\User declarations : + +#include +#include +#include +#include +#include + +#define Abs(x) ((x) < 0 ? -(x) : (x)) +#define MAX(x,y) ((x)>(y)?(x):(y)) +#define MIN(x,y) ((x)<(y)?(x):(y)) + +/* -------------------------------------------------------------------------------------------- */ +/* Valeurs permettant la sélection par la fitness des individus : */ + +#define VALERR0 100000 /* = Valeur de pénalité contrainte oblig */ +#define VALERR1 1000 /* = Valeur de pénalité contrainte forte */ +#define VALERR2 1 /* = Valeur de pénalité contrainte faible */ + +/* -------------------------------------------------------------------------------------------- */ +/* Le bon fonctionnement du programme est garanti par la justesse des calculs suivants : */ + +#define NBCRENEAUX 20 /* => NBJOURS * NBHORAIRES */ + +#define NBCLASSES 4 /* => SOMME(NBCLASSESx) */ + /* avec x € nombre de typee de classes */ +#define NBCOURS 44 /* => SOMME(SOMME(NBCOURSTxCy) * NBCLASSESCy)) */ + /* avec x € NBMATIERES et y € NBCLASSES */ +#define NBSALLES 5 /* => SOMME(NBSALLESTx) */ + /* avec x € NBMATIERES */ +#define NBPROFS 10 /* => SOMME(NBPROFSTx) */ + /* avec x € NBMATIERES */ +/* -------------------------------------------------------------------------------------------- */ +/* Le bon fonctionnement du programme est garanti par le respect des intervals suivants : */ + +#define NBJOURS 5 /* [ 1 - 6 ] = Jours de la semaine */ +#define NBHORAIRES 4 /* [ 1 - 12 ] = Créneaux de 2h par jours */ + +#define NBCOURSMAX 4 /* [ 1 - 12 ] = Nbre max de cours par jours par elem */ + +#define NBMATIERES 4 /* [ 4 - 4 ] = Nombre de matières différentes */ +#define NBCxCLASSE 2 /* [ 2 - 2 ] = Nombre de types de classes */ +#define NBTxSALLE 3 /* [ 3 - 3 ] = Nombre de types de salles */ + +#define NBCLASSESC0 2 /* [ 1 - 5 ] = Nbre de classes de type 0 */ +#define NBCLASSESC1 2 /* [ 1 - 5 ] = Nbre de classes de type 1 */ + +#define NBSALLESTA 3 /* [ 1 - 10 ] = Nbre de salles de type A (Math/Phy) */ +#define NBSALLESTB 1 /* [ 1 - 10 ] = Nbre de salles de type B (Info) */ +#define NBSALLESTC 1 /* [ 1 - 10 ] = Nbre de salles de type C (Anglais) */ + +#define NBPROFST0 3 /* [ 1 - 5 ] = Nbre de prof de type 0 (Math) */ +#define NBPROFST1 3 /* [ 1 - 5 ] = Nbre de prof de type 1 (Phy) */ +#define NBPROFST2 2 /* [ 1 - 5 ] = Nbre de prof de type 2 (Info) */ +#define NBPROFST3 2 /* [ 1 - 5 ] = Nbre de prof de type 3 (Anglais) */ + +#define NBCOURSP0 6 /* [ 0 - 9 ] = Nbre d'horaires pour le prof 0 */ +#define NBCOURSP1 4 /* [ 0 - 9 ] = Nbre d'horaires pour le prof 1 */ +#define NBCOURSP2 2 /* [ 0 - 9 ] = Nbre d'horaires pour le prof 2 */ +#define NBCOURSP3 4 /* [ 0 - 9 ] = Nbre d'horaires pour le prof 3 */ +#define NBCOURSP4 4 /* [ 0 - 9 ] = Nbre d'horaires pour le prof 4 */ +#define NBCOURSP5 4 /* [ 0 - 9 ] = Nbre d'horaires pour le prof 5 */ +#define NBCOURSP6 6 /* [ 0 - 9 ] = Nbre d'horaires pour le prof 6 */ +#define NBCOURSP7 6 /* [ 0 - 9 ] = Nbre d'horaires pour le prof 7 */ +#define NBCOURSP8 6 /* [ 0 - 9 ] = Nbre d'horaires pour le prof 8 */ +#define NBCOURSP9 2 /* [ 0 - 9 ] = Nbre d'horaires pour le prof 9 */ + +#define NBCOURSC0 11 /* = Nbre de cours de la classe de type 0 */ + +#define NBCOURST0C0 4 /* [ 0 - 5 ] = Nbre de cours de type 0 (Math) */ +#define NBCOURST1C0 2 /* [ 0 - 5 ] = Nbre de cours de type 1 (phy) */ +#define NBCOURST2C0 3 /* [ 0 - 5 ] = Nbre de cours de type 2 (Info) */ +#define NBCOURST3C0 2 /* [ 0 - 5 ] = Nbre de cours de type 3 (Anglais) */ + +#define NBCOURSC1 11 /* = Nbre de cours de la classe de type 1 */ + +#define NBCOURST0C1 2 /* [ 0 - 5 ] = Nbre de cours de type 0 (Math) */ +#define NBCOURST1C1 4 /* [ 0 - 5 ] = Nbre de cours de type 1 (Phy) */ +#define NBCOURST2C1 3 /* [ 0 - 5 ] = Nbre de cours de type 2 (Info) */ +#define NBCOURST3C1 2 /* [ 0 - 5 ] = Nbre de cours de type 3 (Anglais) */ +/* -------------------------------------------------------------------------------------------- */ + + +/************************************************************************************************/ +/***************/// DECLARATION DES VARIABLES GLOBALES ///*************/ +/************************************************************************************************/ + +float pMutPerGene = 0.5; /* = probabilité de mutation par individu */ +int nbProfsManquants = 0; /* = nombre de profs suposés manquants */ +int nbSallesManquantes = 0; /* = nombre de salles suposées manquantes */ +int nbCreneauxManquants = 0; /* = nombre de creneaux suposés manquants */ + +clock_t start, finish; /* = permet l'estimation du temps de calcul*/ +double duration; /* = temps de calcul */ + +/* -------------------------------------------------------------------------------------------- */ +\end + + +\User functions: +/************************************************************************************************/ +/***************/// DECLARATION DES FONCTIONS GLOBALES ///*************/ +/************************************************************************************************/ + +/* Fonction d'affichage, utilisée pour mettre des tirets. */ +string cmpTiret(int unsigned n) + { string Emot = ""; while (Emot.length() < n) { Emot += "-"; } return Emot; } +/* Fonctions d'affichage, utilisées pour placer des espaces à coté du texte. */ +string cmpEspaceAlignGauche(string mot, int unsigned n) + { string Emot = mot; if ((Emot.length() > n) && (n > 2)) { Emot = mot.substr(0,n-3) + "..."; } + while (Emot.length() < n) { Emot = Emot + " "; } return Emot; } +string cmpEspaceAlignCentre(string mot, int unsigned n) + { string Emot = mot; bool pos = true; if ((Emot.length() > n) && (n > 2)) { Emot = mot.substr(0,n-3) + "..."; } + while (Emot.length() < n) { if (pos) { Emot = Emot + " "; pos = false; } else { Emot = " " + Emot; pos = true; } } return Emot; } +string cmpEspaceAlignDroite(string mot, int unsigned n) + { string Emot = mot; if ((Emot.length() > n) && (n > 2)) { Emot = mot.substr(0,n-3) + "..."; } + while (Emot.length() < n) { Emot = + " " + Emot; } return Emot; } +/* Fonction de convertion, permet de changer une valeur numérique en texte pour son affichage */ +template +string chiffre2string(T c) { ostringstream oss; oss << c; return oss.str(); } + +/* -------------------------------------------------------------------------------------------- */ +\end + + +/************************************************************************************************/ +/**************/// DECLARATION DES FONCTIONS TEMPORELLES ///***********/ +/************************************************************************************************/ +\Before everything else function: +/* Sauvegarde de l'heure de début du calcul */ + start = clock(); +\end + +\After everything else function: +/* Sauvegarde de l'heure de fin du calcul */ + finish = clock(); +/* Affichage du meilleur individu */ + bBest->printOn(cout); + +/* Estimation et affichage du temps de calcul */ + duration = (double)(finish - start) / CLOCKS_PER_SEC; + cout<<"OBJECTIF\t\t:\t"<<"Atteindre 0 pts."<evaluate()<<" pts"<evaluate()<evaluate()<(this)).classes[k].occupation[j] = 0; + (*const_cast(this)).classes[k].matiere[j] = -1; + } + + for (int k=0; k(this)).profs[k].occupation[j] = 0; + (*const_cast(this)).profs[k].classe[j] = -1; + } + + for (int k=0; k(this)).salles[k].occupation[j] = 0; } + + (*const_cast(this)).creneaux[j].potentiel = NBSALLES; +} + +/* Affectation des compteurs */ +for (int i=0; i(this)).classes [Genome.cours[i].classe] .occupation[j]++; + (*const_cast(this)).classes [Genome.cours[i].classe] .matiere[j] = Genome.cours[i].matiere; + (*const_cast(this)).profs [Genome.cours[i].prof] .occupation[j]++; + (*const_cast(this)).profs [Genome.cours[i].prof] .classe[j] = Genome.cours[i].classe; + (*const_cast(this)).salles [Genome.cours[i].salle] .occupation[j]++; + (*const_cast(this)).creneaux [j] .potentiel--; +} + + +/* -------------------------------------------------------------------------------------------- */ +/* EVALUATION DES CLASSES (Commentée) */ +/* -------------------------------------------------------------------------------------------- */ +tmpJ = ""; tmpH = ""; tmpF = ""; tmpC = ""; txtT = ""; tmpE = ""; +nbE = floor(65/NBCLASSES)-1, nbT = 65%NBCLASSES+1; +totalJ = 0, totalH = 0, totalC = 0, totalE = 0; + +/* Pour chaque classe on cherche à relever les points d'erreurs */ +for (int k=0; k 0) + { + if (nb_creux > 0) + { nb_creux_total += nb_creux; nb_creux = 0; } + nb_horaires++; + matiere_par_jour[Genome.classes[k].matiere[j]]++; + } +/* Si le creux n'est pas entre deux cours, il est juste enregistré */ + else if (nb_horaires > 0) + { nb_creux++; } + +/* On cherche à repérer les autres erreurs dans le dernier créneau de la journée */ + if (j%NBHORAIRES == NBHORAIRES-1) + { + if (nb_horaires > 0) + { +/* Si c'est un jour avec 1 cours pour la classe on met une erreur. */ +/* Si c'est un jour avec plus de NBCOURSMAX cours pour la classe on met une erreur. */ + if ((nb_horaires == 1) || (nb_horaires >= NBCOURSMAX)) { nb_fautes_horaires++; } + nb_jours++; + nb_horaires_total += nb_horaires; + +/* Pour chaque matière, on met une erreur si elle est deux fois dans la journée. */ + for (int m=0; m 1) + { nb_fautes_matieres += matiere_par_jour[m]-1; } + } + } + } + } + + totalJ += nb_jours; totalH += nb_horaires_total; totalE += nb_fautes_matieres; totalF += nb_fautes_horaires; totalC += nb_creux_total; + txtT += cmpEspaceAlignCentre(chiffre2string(k),nbE) + "|"; + tmpJ += cmpEspaceAlignDroite(chiffre2string(nb_jours),nbE) + "|"; + tmpH += cmpEspaceAlignDroite(chiffre2string(nb_horaires_total),nbE) + "|"; + tmpF += cmpEspaceAlignDroite(chiffre2string(nb_fautes_horaires),nbE) + "|"; + tmpC += cmpEspaceAlignDroite(chiffre2string(nb_creux_total),nbE) + "|"; + tmpE += cmpEspaceAlignDroite(chiffre2string(nb_fautes_matieres),nbE) + "|"; +} + + +/* Ajout des erreurs de creux aux erreurs de type 2. */ +totalR2 += totalC; +/* Ajout des erreurs du nombre de jours aux erreurs de type 2. */ +totalR2 += totalJ; +/* Ajout des erreurs de matières répétées aux erreurs de type 2. */ +totalR2 += totalE; +/* Ajout des erreurs d'horaires aux erreurs de type 2. */ +totalR2 += totalF; + +/* -------------------------------------------------------------------------------------------- */ +/* AFFICHAGE STATS DES CLASSES */ +/* -------------------------------------------------------------------------------------------- */ + +txtE = "+" + cmpTiret(20+nbT) + "+" + cmpTiret(65-nbT) + "+"; +txtJ = cmpEspaceAlignGauche("Nb jours",10) + "|" + cmpEspaceAlignDroite(chiffre2string(totalJ),9+nbT); +txtH = cmpEspaceAlignGauche("Nb Horaire",10) + "|" + cmpEspaceAlignDroite(chiffre2string(totalH),9+nbT); +txtF = "Err." + cmpEspaceAlignDroite("H.",6) + "|" + cmpEspaceAlignDroite(chiffre2string(totalF),9+nbT); +txtCr = cmpEspaceAlignGauche("Err. Creux",10) + "|" + cmpEspaceAlignDroite(chiffre2string(totalC),9+nbT); +txtR = "Err." + cmpEspaceAlignDroite("m/j",6) + "|" + cmpEspaceAlignDroite(chiffre2string(totalE),9+nbT); + +cout < 0) + { + if (nb_creux > 0) + { nb_creux_total += nb_creux; nb_creux = 0; } + nb_horaires++; + classe_par_jour[Genome.profs[k].classe[j]]++; + } + else if (nb_horaires > 0) + { nb_creux++; } + + if (j%NBHORAIRES == NBHORAIRES-1) + { + if (nb_horaires > 0) + { + if ((nb_horaires == 1) || (nb_horaires >= NBCOURSMAX)) { nb_fautes_horaires++; } + nb_jours++; + nb_horaires_total += nb_horaires; + for (int c=0; c 1) + { nb_fautes_classes += classe_par_jour[c]-1; } + } + } + } + } + + totalJ += nb_jours; totalH += nb_horaires_total; totalE += nb_fautes_classes; totalF += nb_fautes_horaires; totalC += nb_creux_total; + txtT += cmpEspaceAlignCentre(chiffre2string(k),nbE) + "|"; + tmpJ += cmpEspaceAlignDroite(chiffre2string(nb_jours),nbE) + "|"; + tmpH += cmpEspaceAlignDroite(chiffre2string(nb_horaires_total),nbE) + "|"; + tmpF += cmpEspaceAlignDroite(chiffre2string(nb_fautes_horaires),nbE) + "|"; + tmpC += cmpEspaceAlignDroite(chiffre2string(nb_creux_total),nbE) + "|"; + tmpE += cmpEspaceAlignDroite(chiffre2string(nb_fautes_classes),nbE) + "|"; +} + +totalR2 += totalC; +totalR2 += totalJ; +totalR2 += totalE; +totalR2 += totalF; + +/* -------------------------------------------------------------------------------------------- */ +/* AFFICHAGE STATS DES PROFS */ +/* -------------------------------------------------------------------------------------------- */ + +txtE = "+" + cmpTiret(20+nbT) + "+" + cmpTiret(65-nbT) + "+"; +txtJ = cmpEspaceAlignGauche("Nb jours",10) + "|" + cmpEspaceAlignDroite(chiffre2string(totalJ),9+nbT); +txtH = cmpEspaceAlignGauche("Nb Horaire",10) + "|" + cmpEspaceAlignDroite(chiffre2string(totalH),9+nbT); +txtF = "Err." + cmpEspaceAlignDroite("H.",6) + "|" + cmpEspaceAlignDroite(chiffre2string(totalF),9+nbT); +txtCr = cmpEspaceAlignGauche("Err. Creux",10) + "|" + cmpEspaceAlignDroite(chiffre2string(totalC),9+nbT); +txtR = "Err." + cmpEspaceAlignDroite("c/j",6) + "|" + cmpEspaceAlignDroite(chiffre2string(totalE),9+nbT); + +cout < 1) + { nbR1 += Genome.classes[k].occupation[j]-1; } + } + + for (int k=0; k 1) + { nbR1 += Genome.profs[k].occupation[j]-1; } + } + + for (int k=0; k 1) + { nbR1 += Genome.salles[k].occupation[j]-1; } + } + + totalR1 += nbR1; totalO += NBSALLES - Genome.creneaux[j].potentiel; + txtT += cmpEspaceAlignDroite(chiffre2string(j),nbE) + "|"; + tmp1 += cmpEspaceAlignDroite(chiffre2string(nbR1),nbE) + "|"; + tmpO += cmpEspaceAlignDroite(chiffre2string(NBSALLES - Genome.creneaux[j].potentiel),nbE) + "|"; +} + +/* -------------------------------------------------------------------------------------------- */ +/* AFFICHAGE STATS DES CRENEAUX */ +/* -------------------------------------------------------------------------------------------- */ + +txtE = "+" + cmpTiret(20+nbT) + "+" + cmpTiret(65-nbT) + "+"; tmpE = ""; +txtO = cmpEspaceAlignGauche("Occup. ",10) + "|" + cmpEspaceAlignDroite(chiffre2string(totalO),9+nbT); +txt1 = "Err."+cmpEspaceAlignDroite(chiffre2string(VALERR1),6) + "|" + cmpEspaceAlignDroite(chiffre2string(totalR1),9+nbT); +txt2 = "Err."+cmpEspaceAlignDroite(chiffre2string(VALERR2),6) + "|" + cmpEspaceAlignDroite(chiffre2string(totalR2),9+nbT); + +cout < 0) +{ cout<<"Une ERREUR concernant les PROFS est apparue. >> Vérifiez que leur nombre est suffisant !"< 0) +{ cout<<"Une ERREUR concernant les SALLES est apparue. >> Vérifiez que leur nombre est suffisant !"< 0) +{ cout<<"Une ERREUR concernant les CRENEAUX est apparue. >> Vérifiez que leur nombre est suffisant !"< 0) + { seuilS += nbSallesTx[x]; } +} + +/* Initialisation des Cours par Classe (Matière & Creneau) semi-aléatoire */ +for(int i=0; i NBCRENEAUX) { break; } } + while ((Genome.creneaux[r].potentiel <= 0) || (Genome.classes[indexClasse].occupation[r] > 0)); + + if (t > NBCRENEAUX) { nbCreneauxManquants++; } + + Genome.cours[i].classe = indexClasse; + Genome.cours[i].creneau = r; + Genome.classes[indexClasse].occupation[r]++; + Genome.creneaux[r].potentiel--; +} + +/* Affectation guidée des Profs & Salles */ +for (int i=0; i maxprof) + { + minprof = maxprof; + maxprof += nbProfsTx[++k]; + } + + if (p == maxprof) { y = minprof; } + else { y = p+1; } + + for (int x=0; x 1) { err = 1; } } + + if (err == 0) + { if (Genome.profs[p].occupation[j] > 1) { err = 2; } } + + if (err == 0) + { if (Genome.salles[s].occupation[j] > 1) { err = 3; } } + + if (err == 0) + { if (Genome.salles[s].occupation[j] > 1) { err = 3; } } + +/* en cas d'erreur, on "corrige" le cours en le réinitialisant de manière valide. */ + if (err > 0) + { + nb++; + r = j; int mode = 1; + do + { + r = (r + 1)%NBCRENEAUX; + if (r == j) { if (mode == 2) { break; } else { mode++; } } + } + while + ( + (Genome.creneaux[r].potentiel <= 0) || + ( + ((Genome.creneaux[r].potentiel == NBSALLES) && (mode < 2)) || + (Genome.classes [c] .occupation[r] > 0) || + (Genome.profs [p] .occupation[r] > 0) || + (Genome.salles [s] .occupation[r] > 0) + ) + ); + + Genome.classes [c] .occupation[j]--; + Genome.profs [p] .occupation[j]--; + Genome.salles [s] .occupation[j]--; + Genome.creneaux [j] .potentiel++; + + Genome.classes [c] .occupation[r]++; + Genome.profs [p] .occupation[r]++; + Genome.salles [s] .occupation[r]++; + Genome.creneaux [r] .potentiel--; + } + + Genome.cours[i].creneau = r; +} + +return nb; + +\end +/* -------------------------------------------------------------------------------------------- */ + + +/************************************************************************************************/ +/********************/// EVALUATION ///*******************/ +/************************************************************************************************/ + +\GenomeClass::evaluator : // retourne le score + +/* Méthode réutilisée dans l'affichage (voir plus haut dans le code) et y est commentée */ + +/* -------------------------------------------------------------------------------------------- */ +/* DECLARATION DES VARIABLES */ +/* -------------------------------------------------------------------------------------------- */ +int totalR0 = 0, totalR1 = 0, totalR2 = 0; +float score = 0; + +/* -------------------------------------------------------------------------------------------- */ +/* EVALUATION DES CRENEAUX */ +/* -------------------------------------------------------------------------------------------- */ + +/* Initialisation des compteurs */ +for (int k=0; k 0) + { + if (nb_creux > 0) + { nbR2 += nb_creux; nb_creux = 0; } + nb_horaires++; + matiere_par_jour[Genome.classes[k].matiere[j]]++; + } + else if (nb_horaires > 0) + { nb_creux++; } + + if (j%NBHORAIRES == NBHORAIRES-1) + { + if (nb_horaires > 0) + { + if ((nb_horaires == 1) || (nb_horaires >= NBCOURSMAX)) { totalR2++; } + nb_jours++; + nb_horaires_total += nb_horaires; + for (int m=0; m 1) + { totalR2 += matiere_par_jour[m]-1; } + } + } + } + } + + totalJ += nb_jours; totalH += nb_horaires_total; totalC += nbR2; +} + +totalR2 += totalC; +totalR2 += totalJ; + +/* -------------------------------------------------------------------------------------------- */ +/* EVALUATION DES PROFS */ +/* -------------------------------------------------------------------------------------------- */ +totalJ = 0, totalH = 0, totalC = 0; + +for (int k=0; k 0) + { + if (nb_creux > 0) + { nbR2 += nb_creux; nb_creux = 0; } + nb_horaires++; + classe_par_jour[Genome.profs[k].classe[j]]++; + } + else if (nb_horaires > 0) + { nb_creux++; } + + if (j%NBHORAIRES == NBHORAIRES-1) + { + if (nb_horaires > 0) + { + if ((nb_horaires == 1) || (nb_horaires >= NBCOURSMAX)) { totalR2++; } + nb_jours++; + nb_horaires_total += nb_horaires; + for (int c=0; c 1) + { totalR2 += classe_par_jour[c]-1; } + } + } + } + } + + totalJ += nb_jours; totalH += nb_horaires_total; totalC += nbR2; +} + +totalR2 += totalC; +totalR2 += totalJ; + +/* -------------------------------------------------------------------------------------------- */ +/* EVALUATION DES CRENEAUX */ +/* -------------------------------------------------------------------------------------------- */ + +for(int j=0; j 1) + { nbR1 += Genome.classes[k].occupation[j]-1; } + } + + for (int k=0; k 1) + { nbR1 += Genome.profs[k].occupation[j]-1; } + } + + for (int k=0; k 1) + { nbR1 += Genome.salles[k].occupation[j]-1; } + } + + totalR1 += nbR1; +} + +/* -------------------------------------------------------------------------------------------- */ +/* RETOUR DU SCORE */ +/* -------------------------------------------------------------------------------------------- */ + +score = totalR0 * VALERR0 + totalR1 * VALERR1 + totalR2 * VALERR2; +//cout<<"SCORE :"<