significantly reduced chance of getting a group not seeing a colleur (took me an entire afternoon >:/)
This commit is contained in:
parent
bbcdfe259c
commit
cbd86dd50f
215
src/algorithm.c
215
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,13 +292,18 @@ 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) {
|
||||
//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,13 +353,18 @@ 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) {
|
||||
//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,13 +410,18 @@ 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) {
|
||||
//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;
|
||||
for(int tch = 0; tch < ht; tch++) {
|
||||
score -= penalty_poly(occ[grp-1][tch], n_weeks);
|
||||
}
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue