/* Euler direction --------------------------------------------------------- */ void Euler_angles2direction(DOUBLE alpha, DOUBLE beta, Matrix1D<DOUBLE> &v) { DOUBLE ca, sa, cb, sb; DOUBLE sc, ss; v.resize(3); alpha = DEG2RAD(alpha); beta = DEG2RAD(beta); ca = cos(alpha); cb = cos(beta); sa = sin(alpha); sb = sin(beta); sc = sb * ca; ss = sb * sa; v(0) = sc; v(1) = ss; v(2) = cb; }
//gamma is useless but I keep it for simmetry //with Euler_direction void Euler_direction2angles(Matrix1D<DOUBLE> &v0, DOUBLE &alpha, DOUBLE &beta) { DOUBLE abs_ca, sb, cb; DOUBLE aux_alpha; DOUBLE aux_beta; DOUBLE error, newerror; Matrix1D<DOUBLE> v_aux; Matrix1D<DOUBLE> v; //if not normalized do it so v.resize(3); v = v0; v.selfNormalize(); v_aux.resize(3); cb = v(2); if (fabs((cb)) > 0.999847695)/*one degree */ { std::cerr << "\nWARNING: Routine Euler_direction2angles is not reliable\n" "for small tilt angles. Up to 0.001 deg it should be OK\n" "for most applications but you never know"; } if (fabs((cb - 1.)) < FLT_EPSILON) { alpha = 0.; beta = 0.; } else {/*1*/ aux_beta = acos(cb); /* beta between 0 and PI */ sb = sin(aux_beta); abs_ca = fabs(v(0)) / sb; if (fabs((abs_ca - 1.)) < FLT_EPSILON) aux_alpha = 0.; else aux_alpha = acos(abs_ca); v_aux(0) = sin(aux_beta) * cos(aux_alpha); v_aux(1) = sin(aux_beta) * sin(aux_alpha); v_aux(2) = cos(aux_beta); error = fabs(dotProduct(v, v_aux) - 1.); alpha = aux_alpha; beta = aux_beta; v_aux(0) = sin(aux_beta) * cos(-1. * aux_alpha); v_aux(1) = sin(aux_beta) * sin(-1. * aux_alpha); v_aux(2) = cos(aux_beta); newerror = fabs(dotProduct(v, v_aux) - 1.); if (error > newerror) { alpha = -1. * aux_alpha; beta = aux_beta; error = newerror; } v_aux(0) = sin(-aux_beta) * cos(-1. * aux_alpha); v_aux(1) = sin(-aux_beta) * sin(-1. * aux_alpha); v_aux(2) = cos(-aux_beta); newerror = fabs(dotProduct(v, v_aux) - 1.); if (error > newerror) { alpha = -1. * aux_alpha; beta = -1. * aux_beta; error = newerror; } v_aux(0) = sin(-aux_beta) * cos(aux_alpha); v_aux(1) = sin(-aux_beta) * sin(aux_alpha); v_aux(2) = cos(-aux_beta); newerror = fabs(dotProduct(v, v_aux) - 1.); if (error > newerror) { alpha = aux_alpha; beta = -1. * aux_beta; error = newerror; } }/*else 1 end*/ beta = RAD2DEG(beta); alpha = RAD2DEG(alpha); }/*Eulerdirection2angles end*/
//The following 2 functions (GetTeachersTimetable & GetSubgroupsTimetable) //are very similar to the above 2 ones (GetTeachersMatrix & GetSubgroupsMatrix) //void Solution::getTeachersTimetable(Rules& r, qint16 a[MAX_TEACHERS][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY], QList<qint16> b[TEACHERS_FREE_PERIODS_N_CATEGORIES][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY]){ //void Solution::getTeachersTimetable(Rules& r, Matrix3D<qint16>& a, QList<qint16> b[TEACHERS_FREE_PERIODS_N_CATEGORIES][MAX_DAYS_PER_WEEK][MAX_HOURS_PER_DAY]){ void Solution::getTeachersTimetable(Rules& r, Matrix3D<qint16>& a, Matrix3D<QList<qint16> >& b){ //assert(HFitness()==0); //This is only for perfect solutions, that do not have any non-satisfied hard constrains assert(r.initialized); assert(r.internalStructureComputed); a.resize(r.nInternalTeachers, r.nDaysPerWeek, r.nHoursPerDay); b.resize(TEACHERS_FREE_PERIODS_N_CATEGORIES, r.nDaysPerWeek, r.nHoursPerDay); int i, j, k; for(i=0; i<r.nInternalTeachers; i++) for(j=0; j<r.nDaysPerWeek; j++) for(k=0; k<r.nHoursPerDay; k++) //a1[i][j][k]=a2[i][j][k]=UNALLOCATED_ACTIVITY; a[i][j][k]=UNALLOCATED_ACTIVITY; Activity *act; for(i=0; i<r.nInternalActivities; i++) if(this->times[i]!=UNALLOCATED_TIME) { act=&r.internalActivitiesList[i]; int hour=this->times[i]/r.nDaysPerWeek; int day=this->times[i]%r.nDaysPerWeek; for(int dd=0; dd < act->duration; dd++){ assert(hour+dd<r.nHoursPerDay); for(int ti=0; ti<act->iTeachersList.count(); ti++){ int tch = act->iTeachersList.at(ti); //teacher index /*if(a1[tch][day][hour+dd]==UNALLOCATED_ACTIVITY) a1[tch][day][hour+dd]=i; else a2[tch][day][hour+dd]=i;*/ assert(a[tch][day][hour+dd]==UNALLOCATED_ACTIVITY); a[tch][day][hour+dd]=i; } } } //Prepare teachers free periods timetable. //Code contributed by Volker Dirr (http://timetabling.de/) BEGIN int d,h,tch; for(d=0; d<r.nDaysPerWeek; d++){ for(h=0; h<r.nHoursPerDay; h++){ for(int tfp=0; tfp<TEACHERS_FREE_PERIODS_N_CATEGORIES; tfp++){ b[tfp][d][h].clear(); } } } for(tch=0; tch<r.nInternalTeachers; tch++){ for(d=0; d<r.nDaysPerWeek; d++){ int firstPeriod=-1; int lastPeriod=-1; for(h=0; h<r.nHoursPerDay; h++){ if(a[tch][d][h]!=UNALLOCATED_ACTIVITY){ if(firstPeriod==-1) firstPeriod=h; lastPeriod=h; } } if(firstPeriod==-1){ for(h=0; h<r.nHoursPerDay; h++){ b[TEACHER_HAS_A_FREE_DAY][d][h]<<tch; } } else { for(h=0; h<firstPeriod; h++){ if(firstPeriod-h==1){ b[TEACHER_MUST_COME_EARLIER][d][h]<<tch; } else { b[TEACHER_MUST_COME_MUCH_EARLIER][d][h]<<tch; } } for(; h<lastPeriod+1; h++){ if(a[tch][d][h]==UNALLOCATED_ACTIVITY){ if(a[tch][d][h+1]==UNALLOCATED_ACTIVITY){ if(a[tch][d][h-1]==UNALLOCATED_ACTIVITY){ b[TEACHER_HAS_BIG_GAP][d][h]<<tch; } else { b[TEACHER_HAS_BORDER_GAP][d][h]<<tch; } } else { if(a[tch][d][h-1]==UNALLOCATED_ACTIVITY){ b[TEACHER_HAS_BORDER_GAP][d][h]<<tch; } else { b[TEACHER_HAS_SINGLE_GAP][d][h]<<tch; } } } } for(; h<r.nHoursPerDay; h++){ if(lastPeriod-h==-1){ b[TEACHER_MUST_STAY_LONGER][d][h]<<tch; } else { b[TEACHER_MUST_STAY_MUCH_LONGER][d][h]<<tch; } } } } } //care about not available teacher and breaks for(tch=0; tch<r.nInternalTeachers; tch++){ for(d=0; d<r.nDaysPerWeek; d++){ for(h=0; h<r.nHoursPerDay; h++){ if(teacherNotAvailableDayHour[tch][d][h]==true || breakDayHour[d][h]==true){ int removed=0; for(int tfp=0; tfp<TEACHER_IS_NOT_AVAILABLE; tfp++){ if(b[tfp][d][h].contains(tch)){ removed+=b[tfp][d][h].removeAll(tch); if(breakDayHour[d][h]==false) b[TEACHER_IS_NOT_AVAILABLE][d][h]<<tch; } } assert(removed==1); } } } } //END of Code contributed by Volker Dirr (http://timetabling.de/) END //bool visited[MAX_TEACHERS]; Matrix1D<bool> visited; visited.resize(r.nInternalTeachers); for(d=0; d<r.nDaysPerWeek; d++){ for(h=0; h<r.nHoursPerDay; h++){ for(tch=0; tch<r.nInternalTeachers; tch++) visited[tch]=false; for(int tfp=0; tfp<TEACHERS_FREE_PERIODS_N_CATEGORIES; tfp++){ foreach(int tch, b[tfp][d][h]){ assert(!visited[tch]); visited[tch]=true; } } } }