%implementation of the final step of ACC '98 %differs slightly from the original model (constraints #7 and mirroring). timetable(X, Home, Away, Bye):- get_pattern_sets(PatternSet), Schedule = [S1,S2,S3,S4,S5,S6,S7,S8,S9], make_schedule(S1), make_schedule(S2), make_schedule(S3), make_schedule(S4), make_schedule(S5), make_schedule(S6), make_schedule(S7), make_schedule(S8), make_schedule(S9), %1. all teams playing on a specific date are different (columns of Schedule) transpose(Schedule, ScheduleT), all_rows_different(ScheduleT), %2. the schedule of two opposing teams must relate (Schedule[i,w] = j <=> Schedule[j,w] = i) numlist(1,9,TeamIndex), foreach(TeamIndex, foreach(TeamIndex, relate_schedule(ScheduleT))), %3. and 4. each team must meet all other teams exactly 2 times and does not play itself count_games(Schedule), %5. The byes in the schedule correspond to the byes in the Bye pattern. numlist(1,18,WeekIndex), foreach(TeamIndex, foreach(WeekIndex, relate_byes(Schedule, Bye))), %6. if schedule[i,w] = j that must be reflected into the Home / Away patterns foreach(TeamIndex, foreach(TeamIndex, relate_games(ScheduleT, Home, Away))), %7. may not be needed. %MIRRORING mirroring(ScheduleT, 1,8), mirroring(ScheduleT, 2,9), mirroring(ScheduleT, 3,12), mirroring(ScheduleT, 4,13), mirroring(ScheduleT, 5,14), mirroring(ScheduleT, 6,15), mirroring(ScheduleT, 7,16), mirroring(ScheduleT, 10,17), mirroring(ScheduleT, 11,18), %8. constraint8(Schedule, 1, 4), constraint8(Schedule, 2, 6), constraint8(Schedule, 5, 8), constraint8(Schedule, 7, 9), constraint8(Schedule, 4, 1), constraint8(Schedule, 6, 2), constraint8(Schedule, 8, 5), constraint8(Schedule, 9, 7), %9 constraint9(Schedule, 2, 4), constraint9(Schedule, 2, 9), constraint9(Schedule, 4, 6), constraint9(Schedule, 6, 9), %10 numlist(1,17,WeekIndex1), foreach(TeamIndex, foreach(WeekIndex1, constraint10a(Schedule, Away))), numlist(1,16,WeekIndex2), foreach(TeamIndex, foreach(WeekIndex2, constraint10b(Schedule))), %11 get_matrix_ij(Schedule, 6, 11, 2), get_matrix_ij(Schedule, 6, 18, 2), get_matrix_ij(Schedule, 6, 2, 1), get_pattern_constraints(PatternSet, Home, Away, Bye), flatten(Schedule, LabelThis), labeling(LabelThis), %writeln(Home), %writeln(Away), %writeln(Bye), X = Schedule. mirroring(ScheduleT, I, J):- nth(I, ScheduleT, Column_i), nth(J, ScheduleT, Column_j), equal(Column_i, Column_j). get_pattern_constraints(PatternSet, HomeP, AwayP, ByeP):- PatternSet = [HomePattern, AwayPattern, ByePattern], get_matrix_ij(Bye, 2, 16, 1), get_matrix_ij(Bye, 9, 1, 1), get_matrix_ij(Bye, 3, 18, 0), get_matrix_ij(Bye, 7, 18, 0), get_matrix_ij(Bye, 6, 1, 0), get_matrix_ij(Away, 1, 18, 0), get_matrix_ij(Away, 2, 18, 0), get_matrix_ij(Away, 5, 18, 0), get_matrix_ij(Away, 9, 18, 0), get_matrix_ij(Away, 1, 1, 0), get_matrix_ij(Away, 3, 1, 0), get_matrix_ij(Away, 4, 1, 0), get_matrix_ij(Away, 9, 1, 0), get_matrix_ij(Home, 9, 17, 0), P = [_, _, _, _, _, _, _, _, _], P in [1..9], all_different(P), get_pattern(AwayPattern, P, Away), %writeln(away), get_pattern(HomePattern, P, Home), %writeln(home), get_pattern(ByePattern, P, Bye), %writeln(bye), labeling(P), %writeln(P), ByeP = Bye, HomeP = Home, AwayP = Away. %Out is a matrix formed from Pattern by taking rows in the order defined by P get_pattern(Pattern, P, Out):- get_pattern(Pattern, P, Out, []). get_pattern(_, [], Out, Out). get_pattern(Pattern, [P|Ps], Out, Acc):- nth(P, Pattern, Row), RowList = [Row], append(Acc, RowList, Acc1), get_pattern(Pattern, Ps, Out, Acc1). make_schedule(Schedule):- Schedule = [_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_], Schedule in [0..9]. %(Schedule[i,w] = j <=> Schedule[j,w] = i) or (ScheduleT[w,i] = j <=> ScheudleT[w,j] = i for any w in [1..18]) relate_schedule([], _, _). relate_schedule([Row|ScheduleT], I, J):- (I = J, !; nth(I, Row, Swi), nth(J, Row, Swj), %writeln((Swi #= J) #<=> (Swj #= I)), (Swi #= J) #<=> (Swj #= I), relate_schedule(ScheduleT, I, J)). %make sure that each team plays with all other exactly 2 times and does not meet itself. count_games(Schedule):- count_games(Schedule, 1). count_games([], _). count_games([S|Schedule], Index):- exactly(2,S,0), (Index = 1, !, exactly(0,S,1) ; exactly(2,S,1)), (Index = 2, !, exactly(0,S,2) ; exactly(2,S,2)), (Index = 3, !, exactly(0,S,3) ; exactly(2,S,3)), (Index = 4, !, exactly(0,S,4) ; exactly(2,S,4)), (Index = 5, !, exactly(0,S,5) ; exactly(2,S,5)), (Index = 6, !, exactly(0,S,6) ; exactly(2,S,6)), (Index = 7, !, exactly(0,S,7) ; exactly(2,S,7)), (Index = 8, !, exactly(0,S,8) ; exactly(2,S,8)), (Index = 9, !, exactly(0,S,9) ; exactly(2,S,9)), Index1 is Index + 1, count_games(Schedule, Index1). %make sure that Schedule corresponds to the pattern in byes relate_byes(Schedule, Bye, I,W):- get_matrix_ij(Schedule, I, W, Game), get_matrix_ij(Bye, I, W, B), ((Game #= 0) #<=> (B #= 1)). %make sure that Schedule corresponds to the pattern relate_games(Schedule, Home, Away, I, J):- (I = J, !; relate_games(Schedule, Home, Away, I, J, 1)). relate_games([], _, _, _, _, _). relate_games([S|Schedule], Home, Away, I, J, W):- nth(I, S, Oponent_i), get_matrix_ij(Home, I, W, H1), get_matrix_ij(Away, I, W, A1), get_matrix_ij(Home, J, W, H2), get_matrix_ij(Away, J, W, A2), (Oponent_i #= J) #=> ( ((H1 #= 1) #/\ (A2 #= 1)) #\/ ((H2 #= 1) #/\ (A1 #= 1))), W1 is W + 1, relate_games(Schedule, Home, Away, I, J, W1). constraint8(Schedule, I, J):- get_matrix_ij(Schedule, I, 18, X), (X #= J) #\/ (X#=3) #\/ (X#=0). constraint9(Schedule, I, J):- get_matrix_ij(Schedule, I, 11, X1), get_matrix_ij(Schedule, I, 12, X2), get_matrix_ij(Schedule, I, 13, X3), get_matrix_ij(Schedule, I, 14, X4), get_matrix_ij(Schedule, I, 15, X5), get_matrix_ij(Schedule, I, 16, X6), get_matrix_ij(Schedule, I, 17, X7), get_matrix_ij(Schedule, I, 18, X8), (X1 #= J) #= B1, (X2 #= J) #= B2, (X3 #= J) #= B3, (X4 #= J) #= B4, (X5 #= J) #= B5, (X6 #= J) #= B6, (X7 #= J) #= B7, (X8 #= J) #= B8, at_least_one([B1, B2, B3, B4, B5, B6, B7, B8]). constraint10a(Schedule, Away, I, W):- get_matrix_ij(Schedule, I, W, X1), get_matrix_ij(Away, I, W, X3), W1 is W + 1, get_matrix_ij(Schedule, I, W1, X2), get_matrix_ij(Away, I, W, X4), B1 #= ((X1 #= 2) #\/ (X1 #= 6)), B2 #= ((X2 #= 2) #\/ (X2 #= 6)), X3 + X4 + B1 + B2 #< 4. constraint10b(Schedule, I, W):- get_matrix_ij(Schedule, I, W, X1), W1 is W + 1, get_matrix_ij(Schedule, I, W1, X2), W2 is W + 2, get_matrix_ij(Schedule, I, W2, X3), B1 #= ((X1 #= 2) #\/ (X1 #= 6) #\/ (X1 #= 9)), B2 #= ((X2 #= 2) #\/ (X2 #= 6) #\/ (X2 #= 9)), B3 #= ((X3 #= 3) #\/ (X3 #= 6) #\/ (X3 #= 9)), B1 + B2 + B3 #< 3.