diff --git a/src/algorithm.c b/src/algorithm.c index 2b7a7b7..bd5531f 100755 --- a/src/algorithm.c +++ b/src/algorithm.c @@ -62,7 +62,7 @@ colleur* get_colleurs(colleur* cl, int len_cl, date d, int* how_many) { for(int j = 0; j < cl[i].n_disp; j++) { if(is_equal_date(cl[i].disp[j], d)) { if(ptr >= 30) { - warn("Too many colleurs detected for a creneau\n"); + //warn("Too many colleurs detected for a creneau\n"); } res[ptr] = cl[i]; ptr++; @@ -195,7 +195,17 @@ int free_math_space(creneau* edt, int len_edt, int id) { static int* perm0 ; static int perm0len ; -void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleur* chads, int len_chads, int n_weeks, int grp, topic start_rotation, int mth, int inf, int* skip_count, int mat_halt, int info_app) { +int colleur_to_id(colleur* colleurs, int len_colleurs, char* name) { + for(int i = 0; i < len_colleurs; i++) { + if(str_equal(name, colleurs[i].name)) { + return i; + } + } + fatal("colleur %d not found", name); + exit(1); +} + +void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleur* chads, int len_chads, int n_weeks, int grp, topic start_rotation, int mth, int inf, int* skip_count, int mat_halt, int info_app, int** occs, int* averages) { topic rotation = start_rotation; // physics/english rotation int math = mth; // math (3/4) int info = inf; // info (1/6) @@ -219,6 +229,7 @@ void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleu int weeklen; bool is_searching_in_blacklisted = true ; + bool is_limiting_sames = true ; bool normal_skip = true; @@ -248,6 +259,7 @@ void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleu info++; is_searching_in_blacklisted = true ; + is_limiting_sames = true ; // info colle while(info >= info_app) { if(edt[k+r%weeklen].mat == NOTHING && edt[k+r%weeklen].length == 2 && (!is_searching_in_blacklisted || edt[k+r%weeklen].blacklisted == true)) { @@ -267,8 +279,9 @@ void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleu // - he is a INFO colleur // if a colle has been addded, interrupt the for andwhile loops for(int dude = 0; dude < len_perm*(1-found); dude++) { - if(dudes[perm[dude]].mat == INFO && edt[k+r%weeklen].allow_grps[grp-1] == true) { + if(dudes[perm[dude]].mat == INFO && (!is_limiting_sames || occs[grp-1][perm[dude]] <= averages[perm[dude]]) && edt[k+r%weeklen].allow_grps[grp-1] == true) { add_colle(edt, dudes, grp, k+r%weeklen, perm[dude]); + occs[grp-1][colleur_to_id(chads, len_chads, dudes[perm[dude]].name)] += 1; found = true; info = 0; } else if(edt[k+r%weeklen].allow_grps[grp-1] == true) { @@ -279,12 +292,17 @@ void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleu } free(dudes); } - if(!found && halt > 2*weeklen) { + if(!found && halt > 3*weeklen) { info = 0; *skip_count += (1-normal_skip); - warn("skipping info colle for group %d (week %d)", grp, week); - } else if(halt > weeklen) { - is_searching_in_blacklisted = false ; + //warn("skipping info colle for group %d (week %d)", grp, week); + } else { + if(halt > weeklen) { + is_searching_in_blacklisted = false ; + } + if(halt > 2*weeklen) { + is_limiting_sames = false ; + } } r++; halt++; @@ -295,6 +313,7 @@ void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleu halt = 0; normal_skip = true; is_searching_in_blacklisted = true ; + is_limiting_sames = true ; // if there is a math colle to add, enter this loop while(remaining_to_add == 2) { @@ -317,13 +336,14 @@ void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleu // - he does not have another colle at the same time (is_overlap) // if a colle has been addded, interrupt the for andwhile loops for(int dude = 0; dude < len_perm*(1-found); dude++) { - if(dudes[perm[dude]].mat == MATH && edt[k+r%weeklen].allow_grps[grp-1] == true) { + if(dudes[perm[dude]].mat == MATH && (!is_limiting_sames || occs[grp-1][perm[dude]] <= averages[perm[dude]]) && edt[k+r%weeklen].allow_grps[grp-1] == true) { add_colle(edt, dudes, grp, k+r%weeklen, perm[dude]); if(is_overlap(edt, len_edt, k+r%weeklen)) { remove_colle(edt, k+r%weeklen); } else { found = true; remaining_to_add--; + occs[grp-1][colleur_to_id(chads, len_chads, dudes[perm[dude]].name)] += 1; } } } @@ -333,12 +353,17 @@ void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleu } free(dudes); } - if(!found && halt > 2*weeklen) { + if(!found && halt > 3*weeklen) { remaining_to_add--; *skip_count += 1; - warn("skipping math colle for group %d (week %d)", grp, week); - } else if(halt > weeklen) { - is_searching_in_blacklisted = false ; + //warn("skipping math colle for group %d (week %d)", grp, week); + } else { + if(halt > weeklen) { + is_searching_in_blacklisted = false ; + } + if(halt > 2*weeklen) { + is_limiting_sames = false ; + } } r++; halt++; @@ -348,6 +373,7 @@ void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleu found = false; halt = 0; is_searching_in_blacklisted = true ; + is_limiting_sames = true ; // do it again for physics/english colles while(remaining_to_add == 1) { @@ -365,13 +391,14 @@ void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleu } } for(int dude = 0; dude < len_perm*(1-found); dude++) { - if(dudes[perm[dude]].mat == rotation && edt[k+r%weeklen].allow_grps[grp-1] == true) { + if(dudes[perm[dude]].mat == rotation && (!is_limiting_sames || occs[grp-1][perm[dude]] <= averages[perm[dude]]) && edt[k+r%weeklen].allow_grps[grp-1] == true) { add_colle(edt, dudes, grp, k+r%weeklen, perm[dude]); if(math_dude > free_math_space(edt, len_edt, k+r%weeklen) || is_overlap(edt, len_edt, k+r%weeklen)) { remove_colle(edt, k+r%weeklen); } else { found = true; remaining_to_add--; + occs[grp-1][colleur_to_id(chads, len_chads, dudes[perm[dude]].name)] += 1; } } else if(edt[k+r%weeklen].allow_grps[grp-1] == true) { normal_skip = false; @@ -383,12 +410,17 @@ void add_colles_for_group_MP2I(int* weeks_len, creneau* edt, int len_edt, colleu } free(dudes); } - if(!found && halt > 2*weeklen) { + if(!found && halt > 3*weeklen) { remaining_to_add--; *skip_count += 1; - warn("skipping L2 colle for group %d (week %d)", grp, week); - } else if(halt > weeklen) { - is_searching_in_blacklisted = false ; + //warn("skipping L2 colle for group %d (week %d)", grp, week); + } else { + if(halt > 2*weeklen) { + is_limiting_sames = false ; + } + if(halt > weeklen) { + is_searching_in_blacklisted = false ; + } } r++; halt++; @@ -438,7 +470,14 @@ int max(int x, int y) { return y; } -int score(creneau* edt, int len_edt, int grp, int n_weeks) { +int penalty_poly(int occ, int n_weeks) { + if(occ == 0) { + return n_weeks*2; + } + return (occ-1)*(occ-1)*(occ-1); +} + +int score(creneau* edt, int len_edt, int grp, int n_weeks, int** occ, int wd, int ht) { int score = n_weeks*300; int dist = 0; @@ -447,49 +486,25 @@ int score(creneau* edt, int len_edt, int grp, int n_weeks) { if(edt[i].group == grp && edt[j].group == grp) { dist = date_dist(edt[i].date, edt[j].date); if(dist == 0) { - score -= 4; + score -= n_weeks*2; } if(dist == 7 && edt[i].date.hour == edt[j].date.hour) { - score -= 5; + score -= n_weeks; + } + if(dist <= 12) { + score -= n_weeks; } if(dist < 5 && edt[i].date.hour == 18 && edt[j].date.hour == 18) { - score -= 5; + score -= n_weeks; } } } } - char** met = malloc(sizeof(char*)*3*n_weeks); - int p = 0; - for(int i = 0; i < len_edt; i++) { - if(edt[i].group == grp) { - met[p] = malloc(sizeof(char)*30); - str_copy(edt[i].name, edt[i].namelen, met[p]); - for(int k = p-1; k >= 0; k--) { - if(str_equal(met[k], met[p])) { - switch(edt[i].mat) { - case MATH: - score -= 12; - break; - case PHYSICS: - score -= 12; - break; - case ENGLISH: - score -= 12; - break; - default: - break; - } - } - } - p++; - } + for(int tch = 0; tch < ht; tch++) { + score -= penalty_poly(occ[grp-1][tch], n_weeks); } - - for(int f = 0; f < p; f++) { - free(met[f]); - } - free(met); + //printf("((%d))\n", score); return score; } @@ -583,8 +598,63 @@ bool retreive_indexes(creneau* edt, int len_edt, int* p1, int* p2, int g1, int g return false; } +topic int_to_mat(colleur* colleur, int id) { + return colleur[id].mat ; +} + +void fill_zeroes(creneau* edt, int len_edt, colleur* colleurs, int len_colleurs, int n_groups, int n_weeks, int weeklen, int** occs, int* averages) { + for(int gr1 = 0; gr1 < n_groups; gr1++) { + for(int col1 = 0; col1 < len_colleurs; col1++) { + char* researched_colleur = colleurs[col1].name ; + if(occs[gr1][col1] == 0) { + int halt = 0 ; + for(int week = 0; week < n_weeks*(1-halt); week++) { + int r1 = rand()%weeklen; + int count1 = 0 ; + while(!halt && count1 < weeklen) { + int edtptr1 = week*weeklen + (r1+count1)%weeklen; + if(edt[edtptr1].group == gr1 +1 && edt[edtptr1].mat == int_to_mat(colleurs, col1)) { + // search another + if(occs[gr1][colleur_to_id(colleurs, len_colleurs, edt[edtptr1].name)] > 1) { // G1 has enough colles with proposed_colleur + int r2 = rand()%weeklen; + int count2 = 0 ; + while(!halt && count2 < weeklen) { + int edtptr2 = week*weeklen + (r2+count2)%weeklen; + if( + edt[edtptr2].group != gr1 +1 && // not the same group + edt[edtptr2].mat == int_to_mat(colleurs, col1) && // same topic + str_equal(edt[edtptr2].name, colleurs[col1].name) && // colleur with 0 G1 colles + + occs[edt[edtptr2].group-1][col1] > 1 && // G2 has some backup + occs[edt[edtptr2].group-1][colleur_to_id(colleurs, len_colleurs, edt[edtptr1].name)] <= + averages[colleur_to_id(colleurs, len_colleurs, edt[edtptr1].name)] // no overflow for G2 + ) { + halt = true ; + + occs[gr1][col1] += 1; + occs[gr1][colleur_to_id(colleurs, len_colleurs, edt[edtptr1].name)] -= 1; + + occs[edt[edtptr2].group-1][col1] -= 1; + occs[edt[edtptr2].group-1][colleur_to_id(colleurs, len_colleurs, edt[edtptr1].name)] += 1; + + edt[edtptr1].group = edt[edtptr2].group; + edt[edtptr2].group = gr1+1; + } + count2++; + } + } + } + count1++; + } + } + } + } + } +} + int** occurencies(creneau* edt, int len_edt, colleur* dudes, int n_groups, int n_colleurs, int n_weeks, bool is_debug) { int max_occ = 1; + int** res = generate_matrix(n_groups, n_colleurs, 0); for(int c = 0; c < len_edt; c++) { @@ -593,10 +663,20 @@ int** occurencies(creneau* edt, int len_edt, colleur* dudes, int n_groups, int n } } + int* averages = malloc(sizeof(int)*n_colleurs); + for(int i = 0; i < n_colleurs; i++) { + averages[i] = 0; + for(int grp = 0; grp < n_groups; grp++) { + averages[i] += res[grp][i]; + } + averages[i] = averages[i] / n_groups; + } + bool halt = false; for(int it = 0; it < 5*(1-is_debug); it++) { for(int grp = 0; grp < n_groups; grp++) { for(int dud = 0; dud < n_colleurs; dud++) { + max_occ = max(1, averages[dud]); if(res[grp][dud] > max_occ && get_mat_from_id(dudes, n_colleurs, dud) != INFO) { for(int grp2 = 0; grp2 < n_groups*(1-halt); grp2++) { if(grp2 != grp) { @@ -654,6 +734,7 @@ int** occurencies(creneau* edt, int len_edt, colleur* dudes, int n_groups, int n } } + free(averages); return res; } @@ -695,11 +776,27 @@ void aux_2(creneau* edt, int len_edt, colleur* chads, int len_chads, int n_group int temp = 0; int skipped = 0; int a = 0; + + int* permut = malloc(sizeof(int)*n_groups); + + int** occs = malloc(sizeof(int*)*n_groups); + for(int i = 0; i < n_groups; i++) { + occs[i] = malloc(sizeof(int)*len_chads); + } + + int* averages = malloc(sizeof(int)*len_chads); + for(int i = 0; i < len_chads; i++) { + averages[i] = 1+(int)(((double)chads[i].n_disp)/((double)n_groups)); + } + print_arr(averages, len_chads); + int** occ_data = generate_matrix(n_groups, len_chads, 0);; info("Testing %d combinations...", n_sim); printf("\n"); perm0 = malloc(sizeof(int)*20) ; for(int k = 0; k < n_sim*(1 - (max_score == n_groups*100)); k++) { + generate_random_perm(permut, n_groups); + if(k >= a) { printf("\x1b[1F"); printf("\x1b[2K"); @@ -709,12 +806,21 @@ void aux_2(creneau* edt, int len_edt, colleur* chads, int len_chads, int n_group local_score = 0; local_min = 909090909; skipped = 0; - for(int i = 0; i < n_groups; i++) { - add_colles_for_group_MP2I(weeks_len, edt, len_edt, chads, len_chads, n_weeks, i+1, (topic)(2+i%2), i%math_halt, i%info_app, &skipped, math_halt, info_app); + for(int iii = 0; iii < n_groups; iii++) { + for(int jjj = 0; jjj < len_chads; jjj++) { + occs[iii][jjj] = 0; + } } - int** temp_data = occurencies(edt, len_edt, chads, n_groups, len_chads, n_weeks, false); for(int i = 0; i < n_groups; i++) { - temp = score(edt, len_edt, i+1, n_weeks); + ////warn("(%d) at (%d)", permut[i]+1, k); + add_colles_for_group_MP2I(weeks_len, edt, len_edt, chads, len_chads, n_weeks, (permut[i])+1, (topic)(2+(permut[i])%2), (permut[i])%math_halt, (permut[i])%info_app, &skipped, math_halt, info_app, occs, averages); + } + //int** temp_data = occurencies(edt, len_edt, chads, n_groups, len_chads, n_weeks, false); + fill_zeroes(edt, len_edt, chads, len_chads, n_groups, n_weeks, len_edt/n_weeks, occs, averages); + int** temp_data = occs; + //int** temp_data = adjust(edt, len_edt, chads, n_groups, len_chads, n_weeks); + for(int i = 0; i < n_groups; i++) { + temp = score(edt, len_edt, i+1, n_weeks, temp_data, n_groups, len_chads); local_score += temp; group_temp[i] = temp; if(local_min > temp) { @@ -737,7 +843,7 @@ void aux_2(creneau* edt, int len_edt, colleur* chads, int len_chads, int n_group for(int r = 0; r < len_edt; r++) { remove_colle(edt, r); } - destroy_matrix(temp_data, n_groups); + //destroy_matrix(temp_data, n_groups); } printf("\x1b[1F"); @@ -760,9 +866,12 @@ void aux_2(creneau* edt, int len_edt, colleur* chads, int len_chads, int n_group print_arr(occ_data[k], len_chads); } info("Took %ds to find", end-start); + free(permut); + free(averages); free(perm0); free(group_stats); free(group_temp); free(weeks_len); destroy_matrix(occ_data, n_groups); + info("Done."); } diff --git a/src/algorithm.h b/src/algorithm.h index 9d08d7c..23c2713 100755 --- a/src/algorithm.h +++ b/src/algorithm.h @@ -54,11 +54,11 @@ bool is_overlap_creneau(creneau* edt, int len_edt, int id, int grp); int free_math_space(creneau *edt, int len_edt, int id); -void add_colles_for_group_MP2I(int *weeks_len, creneau *edt, int len_edt, colleur *chads, int len_chads, int n_weeks, int grp, topic start_rotation, int mth, int inf, int *skip_count, int math_halt, int info_app); +void add_colles_for_group_MP2I(int *weeks_len, creneau *edt, int len_edt, colleur *chads, int len_chads, int n_weeks, int grp, topic start_rotation, int mth, int inf, int *skip_count, int math_halt, int info_app, int** occs, int* averages); void write_to_file(char *filename, creneau *edt, int len_edt); -int score(creneau *edt, int len_edt, int grp, int n_weeks); +int score(creneau *edt, int len_edt, int grp, int n_weeks, int** occ, int wd, int ht); int get_colleur_id(colleur* dudes, int n_dudes, char* target);