def create_schedule(self): if self.debug: print "{}: Starting".format(dg.datetime.datetime.today()) matchups = None initialState = dom.Matchups(None, self.data.league, self.data.game_indices) if self.matchups_json: matchups = read_output(self.data.league, "Matchups") else: matchups, matchups_statesExplored = self.DFS(initialState) if self.debug: print "{}: Matchups, {} states explored, {}".format( dg.datetime.datetime.today(), matchups_statesExplored, matchups is not None) if matchups is not None: write_output(matchups, "Matchups") #now we have our matchups which is a dict of (team, game_num) -> [opponent] #we next want to assign home/away so we create a map of the form: #(team1, team2, game_num) -> [True/False] #where True indicates it's played at team1's venue #also team1 < team2 alphabetically venues_dates = None if self.venues_dates_json: venues_dates = {} venues = read_output(self.data.league, "Venues") dates = read_output(self.data.league, "Dates") self.data.game_indices = read_output(self.data.league, "I2D") for state in venues: venues_dates[state] = (dates[state], venues[state]) else: venues_domains = {} venues_selected = {} master_dates = {} for state in matchups: t, g_n = state o = matchups[state] sk = (t, o, g_n) if t.name < o.name else (o, t, g_n) dk = (t, o) if t.name < o.name else (o, t) if sk not in venues_selected: venues_selected[sk] = None dates_true = date_ranges(2, dk[0], g_n) dates_false = date_ranges(2, dk[1], g_n) master_dates[(sk, True)] = dates_true master_dates[(sk, False)] = dates_false venues_domains[dk] = [True, False] * ( (dom.constraint.total_games(initialState, t, o) + 1) / 2) venueState = dom.Venues({initialState.domains: venues_domains, initialState.selected: venues_selected,\ initialState.master_dates: master_dates}) venues_dates, venues_statesExplored = self.DIJKSTRAS( venueState) #venues_dates, venues_statesExplored = self.DFS(venueState) if self.debug: print "{}: Venues, {} states explored, {}".format( dg.datetime.datetime.today(), venues_statesExplored, venues_dates is not None) if venues_dates is not None: venues = {} dates = {} #write_output(venu, "Dates") #create a master map of everything of the form: #(team, game_num) -> (opponent, home, dateindex) #where home is true if played at team's venue sched_map = {} for state in venues_dates: t1, t2, g_n = state date, home = venues_dates[state] sched_map[(t1, g_n)] = (t2, home, date) sched_map[(t2, g_n)] = (t1, not home, date) venues[state] = home dates[state] = date #sanity check that everything is right for team in self.data.league.teams(): date = -20 opponent_venue = {} for i in range(1, 83): opponent, t_f, d = sched_map[(team, i)] if date >= d: print "invalid date. game {} has date {}, game {} has date {}".format( i - 1, date, i, d) date = d key = (opponent, t_f) constraint.add(opponent_venue, key) for opponent in self.data.league.teams(): if opponent is not team: if opponent_venue[( opponent, True)] < (constraint.total_games( initialState, team, opponent)) / 2: print "not enough home games" if opponent_venue[ (opponent, False)] < (constraint.total_games( initialState, team, opponent)) / 2: print "not enough away games" if opponent_venue[ (opponent, True)] + opponent_venue[ (opponent, False)] != constraint.total_games( initialState, team, opponent): print "not enough games" write_output(venues, "Venues") write_output(dates, "Dates") write_output(self.data.i2d, "I2D") return sched_map return None
def create_schedule(self): if self.debug: print "{}: Starting".format(dg.datetime.datetime.today()) matchups = None initialState = dom.Matchups(None, self.data.league, self.data.game_indices) if self.matchups_json: matchups = read_output(self.data.league, "Matchups") else: matchups, matchups_statesExplored = self.DFS(initialState) if self.debug: print "{}: Matchups, {} states explored, {}".format(dg.datetime.datetime.today(), matchups_statesExplored, matchups is not None) if matchups is not None: write_output(matchups, "Matchups") #now we have our matchups which is a dict of (team, game_num) -> [opponent] #we next want to assign home/away so we create a map of the form: #(team1, team2, game_num) -> [True/False] #where True indicates it's played at team1's venue #also team1 < team2 alphabetically venues_dates = None if self.venues_dates_json: venues_dates = {} venues = read_output(self.data.league, "Venues") dates = read_output(self.data.league, "Dates") self.data.game_indices = read_output(self.data.league, "I2D") for state in venues: venues_dates[state] = (dates[state], venues[state]) else: venues_domains = {} venues_selected = {} master_dates = {} for state in matchups: t, g_n = state o = matchups[state] sk = (t, o, g_n) if t.name < o.name else (o, t, g_n) dk = (t, o) if t.name < o.name else (o, t) if sk not in venues_selected: venues_selected[sk] = None dates_true = date_ranges(2, dk[0], g_n) dates_false = date_ranges(2, dk[1], g_n) master_dates[(sk,True)] = dates_true master_dates[(sk,False)] = dates_false venues_domains[dk] = [True, False] * ((dom.constraint.total_games(initialState, t, o) + 1)/2) venueState = dom.Venues({initialState.domains: venues_domains, initialState.selected: venues_selected,\ initialState.master_dates: master_dates}) venues_dates, venues_statesExplored = self.DIJKSTRAS(venueState) #venues_dates, venues_statesExplored = self.DFS(venueState) if self.debug: print "{}: Venues, {} states explored, {}".format(dg.datetime.datetime.today(), venues_statesExplored, venues_dates is not None) if venues_dates is not None: venues = {} dates = {} #write_output(venu, "Dates") #create a master map of everything of the form: #(team, game_num) -> (opponent, home, dateindex) #where home is true if played at team's venue sched_map = {} for state in venues_dates: t1, t2, g_n = state date, home = venues_dates[state] sched_map[(t1, g_n)] = (t2, home, date) sched_map[(t2, g_n)] = (t1, not home, date) venues[state] = home dates[state] = date #sanity check that everything is right for team in self.data.league.teams(): date = -20 opponent_venue = {} for i in range(1, 83): opponent, t_f, d = sched_map[(team, i)] if date >= d: print "invalid date. game {} has date {}, game {} has date {}".format(i-1, date, i, d) date = d key = (opponent, t_f) constraint.add(opponent_venue, key) for opponent in self.data.league.teams(): if opponent is not team: if opponent_venue[(opponent, True)] < (constraint.total_games(initialState, team, opponent))/2: print "not enough home games" if opponent_venue[(opponent, False)] < (constraint.total_games(initialState, team, opponent))/2: print "not enough away games" if opponent_venue[(opponent, True)] + opponent_venue[(opponent, False)] != constraint.total_games(initialState, team, opponent): print "not enough games" write_output(venues, "Venues") write_output(dates, "Dates") write_output(self.data.i2d, "I2D") return sched_map return None
def min_key(self): ''' Goal is to first assign the games for teams with opponents they have an even number of games with. Then once they are all assigned we try to fit the remaining games, there's a little more flexibility there as it's not strict split ''' teams_selected_even = {} teams_selected_odd = {} #calculate number of games against even-gamed opponents total_even_games = 4*self.DIVISIONAL_GAMES + 6*self.CONF_OPPONENTS_GAMES + 15*self.INTERCONF_GAMES total_odd_games = self.TOTAL_GAMES - total_even_games begin_search = True for state in self.states[self.selected]: if self.states[self.selected][state] is not None: begin_search = False t1, t2, g_n = state total_games = total_even_games if constraint.total_games(self, t1, t2)%2==0 else total_odd_games teams_selected = teams_selected_even if constraint.total_games(self, t1, t2)%2==0 else teams_selected_odd constraint.add(teams_selected, t1) constraint.add(teams_selected, t2) if teams_selected[t1] == total_games: teams_selected.pop(t1, None) if teams_selected[t2] == total_games: teams_selected.pop(t2, None) #teams_selected_* stores how many teams have selected their home/away for games #removing those that have had all their games scheduled with home/away #if it's empty then no team has had a selected home/away yet if begin_search: for k in self.states[self.domains]: if len(self.states[self.domains][k]) > 0 and constraint.total_games(self, k[0], k[1])%2==0: return (k, self.min_key_helper(k)) elif len(teams_selected_even) == 0 and len(teams_selected_odd) == 0: for k in self.states[self.domains]: if len(self.states[self.domains][k]) > 0 and constraint.total_games(self, k[0], k[1])%2!=0: return (k, self.min_key_helper(k)) #choose the team with the most selected home/away venues, i.e. least domain size remaining min_k = None if len(teams_selected_even) > 0: min_k = sorted(teams_selected_even.keys(), key=lambda x: -teams_selected_even[x])[0] elif len(teams_selected_odd) > 0: min_k = sorted(teams_selected_odd.keys(), key=lambda x: -teams_selected_odd[x])[0] else: return (None, None) best_k_even = None best_len_even = float("-inf") best_k_odd = None best_len_odd = float("-inf") #we have the team we want to next choose a venue for, but domains are pairs of teams, #so choose the pair with the largest remaining games to choose from for k in self.states[self.domains]: t1, t2 = k #store best_k for opponents u play even/odd # of games w/ l = len(self.states[self.domains][k]) if t1 is min_k or t2 is min_k: if constraint.total_games(self, t1, t2)%2 == 0: if l > 0 and l > best_len_even: best_len_even = l best_k_even = k else: if l > 0 and l > best_len_odd: best_len_odd = l best_k_odd = k #want to first assign games with teams you play even # of games with if best_k_even is not None: return (best_k_even, self.min_key_helper(best_k_even)) elif best_k_odd is not None: return (best_k_odd, self.min_key_helper(best_k_odd)) else: return (None, None)
def min_key(self): ''' Goal is to first assign the games for teams with opponents they have an even number of games with. Then once they are all assigned we try to fit the remaining games, there's a little more flexibility there as it's not strict split ''' teams_selected_even = {} teams_selected_odd = {} #calculate number of games against even-gamed opponents total_even_games = 4 * self.DIVISIONAL_GAMES + 6 * self.CONF_OPPONENTS_GAMES + 15 * self.INTERCONF_GAMES total_odd_games = self.TOTAL_GAMES - total_even_games begin_search = True for state in self.states[self.selected]: if self.states[self.selected][state] is not None: begin_search = False t1, t2, g_n = state total_games = total_even_games if constraint.total_games( self, t1, t2) % 2 == 0 else total_odd_games teams_selected = teams_selected_even if constraint.total_games( self, t1, t2) % 2 == 0 else teams_selected_odd constraint.add(teams_selected, t1) constraint.add(teams_selected, t2) if teams_selected[t1] == total_games: teams_selected.pop(t1, None) if teams_selected[t2] == total_games: teams_selected.pop(t2, None) #teams_selected_* stores how many teams have selected their home/away for games #removing those that have had all their games scheduled with home/away #if it's empty then no team has had a selected home/away yet if begin_search: for k in self.states[self.domains]: if len( self.states[self.domains][k] ) > 0 and constraint.total_games(self, k[0], k[1]) % 2 == 0: return (k, self.min_key_helper(k)) elif len(teams_selected_even) == 0 and len(teams_selected_odd) == 0: for k in self.states[self.domains]: if len( self.states[self.domains][k] ) > 0 and constraint.total_games(self, k[0], k[1]) % 2 != 0: return (k, self.min_key_helper(k)) #choose the team with the most selected home/away venues, i.e. least domain size remaining min_k = None if len(teams_selected_even) > 0: min_k = sorted(teams_selected_even.keys(), key=lambda x: -teams_selected_even[x])[0] elif len(teams_selected_odd) > 0: min_k = sorted(teams_selected_odd.keys(), key=lambda x: -teams_selected_odd[x])[0] else: return (None, None) best_k_even = None best_len_even = float("-inf") best_k_odd = None best_len_odd = float("-inf") #we have the team we want to next choose a venue for, but domains are pairs of teams, #so choose the pair with the largest remaining games to choose from for k in self.states[self.domains]: t1, t2 = k #store best_k for opponents u play even/odd # of games w/ l = len(self.states[self.domains][k]) if t1 is min_k or t2 is min_k: if constraint.total_games(self, t1, t2) % 2 == 0: if l > 0 and l > best_len_even: best_len_even = l best_k_even = k else: if l > 0 and l > best_len_odd: best_len_odd = l best_k_odd = k #want to first assign games with teams you play even # of games with if best_k_even is not None: return (best_k_even, self.min_key_helper(best_k_even)) elif best_k_odd is not None: return (best_k_odd, self.min_key_helper(best_k_odd)) else: return (None, None)