def allocate(self, avoid_conflicts=True): p = PanelMaker() panels = p.form_panels(self.adjudicators, len(self.debates)) assert len(self.debates) <= len(panels) self.debates.sort(key=lambda d: self.get_debate_energy(d), reverse=True) panels.sort(key=lambda p:p.get_energy(), reverse=True) self.pairings = zip(self.debates, panels) if avoid_conflicts: for i, (debate, panel) in enumerate(self.pairings): if panel.conflicts(debate): j = self.search_swap(i, range(i, 0, -1)) if j is None: j = self.search_swap(i, range(i+1, len(panels))) from debate.models import AdjudicatorAllocation allocation = [] for debate, panel in self.pairings: a = AdjudicatorAllocation(debate) a.chair = panel[0] a.panel = panel[1:] allocation.append(a) return allocation
def allocate(self, initial=None): from debate.models import AdjudicatorAllocation if initial is None: initial = StabAllocator(self.debates, self.adjudicators).allocate() pairs = [(aa.debate, tuple(a[1] for a in aa)) for aa in initial] top_bracket = pairs[0][0].bracket bot_bracket = pairs[-1][0].bracket # 4-0 - 5 brackets, needs 6 gaps # 5-2 gaps = (top_bracket - bot_bracket) + 2 div = 3.0 / gaps for debate, panel in pairs: setattr(debate, 'target_panel', 2 + (debate.bracket - bot_bracket + 1) * div) print[d.target_panel for d, p in pairs] self.state = dict(pairs) self.anneal(800, 1, 1e4, self.state) #i = 0 #while self.best_energy > 0 and i < self.MAX_TRIES: # self.anneal(100, 1, 1e3, self.best_state) # i += 1 result = [] for debate, panel in self.best_state.items(): aa = AdjudicatorAllocation(debate) panel = list(panel) panel.sort(key=lambda x: x.score, reverse=True) aa.chair = panel.pop(0) aa.panel = panel result.append(aa) return result
print 'total cost for panellists', cost # transfer the indices to the debates # the debate corresponding to row r is floor(r/3) (i.e. r // 3) p = [[] for i in range(n)] for r, c in indexes[:n*3]: p[r // 3].append(panellists[c]) # create the corresponding adjudicator allocations, making sure # that the chair is the highest-ranked adjudicator in the panel for i, d in enumerate(panel_debates): a = AdjudicatorAllocation(d) p[i].sort(key=lambda a: a.score, reverse=True) a.chair = p[i].pop(0) a.panel = p[i] alloc.append(a) print [(a.debate, a.chair, a.panel) for a in alloc[len(chairs):]] return alloc def test(): from debate.models import Round r = Round.objects.get(pk=4) debates = r.debates() adjs = list(r.active_adjudicators.all()) HungarianAllocator(debates, adjs).allocate() if __name__ == '__main__':
def allocate(self): from debate.models import AdjudicatorAllocation # remove trainees self.adjudicators = filter(lambda a: a.score > self.MIN_SCORE, self.adjudicators) # sort adjudicators and debates in descending score/importance self.adjudicators_sorted = list(self.adjudicators) self.adjudicators_sorted.sort(key=lambda a: a.score, reverse=True) self.debates_sorted = list(self.debates) self.debates_sorted.sort(key=lambda a: a.importance, reverse=True) n_adjudicators = len(self.adjudicators) n_debates = len(self.debates) n_solos = n_debates - (n_adjudicators - n_debates) / 2 # get adjudicators that can adjudicate solo chairs = self.adjudicators_sorted[:n_solos] #chairs = [a for a in self.adjudicators_sorted if a.score > # self.CHAIR_CUTOFF] # get debates that will be judged by solo adjudicators chair_debates = self.debates_sorted[:len(chairs)] panel_debates = self.debates_sorted[len(chairs):] panellists = [a for a in self.adjudicators_sorted if a not in chairs] assert len(panel_debates) * 3 <= len(panellists) print "costing chairs" n = len(chairs) cost_matrix = [[0] * n for i in range(n)] for i, debate in enumerate(chair_debates): for j, adj in enumerate(chairs): cost_matrix[i][j] = self.calc_cost(debate, adj) print "optimizing" m = Munkres() indexes = m.compute(cost_matrix) total_cost = 0 for r, c in indexes: total_cost += cost_matrix[r][c] print 'total cost for solos', total_cost print 'number of solo debates', n result = ((chair_debates[i], chairs[j]) for i, j in indexes if i < len(chair_debates)) alloc = [AdjudicatorAllocation(d, c) for d, c in result] print[(a.debate, a.chair) for a in alloc] # do panels n = len(panel_debates) npan = len(panellists) if npan: print "costing panellists" # matrix is square, dummy debates have cost 0 cost_matrix = [[0] * npan for i in range(npan)] for i, debate in enumerate(panel_debates): for j in range(3): # for the top half of these debates, the final panellist # can be of lower quality than the other 2 if i < npan / 2 and j == 2: adjustment = -1.0 else: adjustment = 0 for k, adj in enumerate(panellists): cost_matrix[3 * i + j][k] = self.calc_cost( debate, adj, adjustment) print "optimizing" indexes = m.compute(cost_matrix) cost = 0 for r, c in indexes: cost += cost_matrix[r][c] print 'total cost for panellists', cost # transfer the indices to the debates # the debate corresponding to row r is floor(r/3) (i.e. r // 3) p = [[] for i in range(n)] for r, c in indexes[:n * 3]: p[r // 3].append(panellists[c]) # create the corresponding adjudicator allocations, making sure # that the chair is the highest-ranked adjudicator in the panel for i, d in enumerate(panel_debates): a = AdjudicatorAllocation(d) p[i].sort(key=lambda a: a.score, reverse=True) a.chair = p[i].pop(0) a.panel = p[i] alloc.append(a) print[(a.debate, a.chair, a.panel) for a in alloc[len(chairs):]] return alloc
self.anneal(800, 1, 1e4, self.state) #i = 0 #while self.best_energy > 0 and i < self.MAX_TRIES: # self.anneal(100, 1, 1e3, self.best_state) # i += 1 result = [] for debate, panel in self.best_state.items(): aa = AdjudicatorAllocation(debate) panel = list(panel) panel.sort(key=lambda x: x.score, reverse=True) aa.chair = panel.pop(0) aa.panel = panel result.append(aa) return result def save_best(self): self.best_energy = self.energy self.best_state = dict(self.state) def anneal(self, steps, min_temp, max_temp, state): self.energy = self.calc_energy(state) print "start energy", self.energy self.save_best() tf = -math.log(float(max_temp) / min_temp)
def allocate(self): from debate.models import AdjudicatorAllocation # remove trainees self.adjudicators = filter(lambda a: a.score >= self.MIN_SCORE, self.adjudicators) # sort adjudicators and debates in descending score/importance self.adjudicators_sorted = list(self.adjudicators) shuffle(self.adjudicators_sorted) # randomize equally-ranked judges self.adjudicators_sorted.sort(key=lambda a: a.score, reverse=True) self.debates_sorted = list(self.debates) self.debates_sorted.sort(key=lambda a: a.importance, reverse=True) n_adjudicators = len(self.adjudicators) n_debates = len(self.debates) n_solos = n_debates - (n_adjudicators - n_debates)/2 # get adjudicators that can adjudicate solo chairs = self.adjudicators_sorted[:n_solos] #chairs = [a for a in self.adjudicators_sorted if a.score > # self.CHAIR_CUTOFF] # get debates that will be judged by solo adjudicators chair_debates = self.debates_sorted[:len(chairs)] panel_debates = self.debates_sorted[len(chairs):] panellists = [a for a in self.adjudicators_sorted if a not in chairs] assert len(panel_debates) * 3 <= len(panellists) m = Munkres() # TODO I think "chairs" actually means "solos", rename variables if correct if len(chairs) > 0: print "costing chairs" n = len(chairs) cost_matrix = [[0] * n for i in range(n)] for i, debate in enumerate(chair_debates): for j, adj in enumerate(chairs): cost_matrix[i][j] = self.calc_cost(debate, adj) print "optimizing" indexes = m.compute(cost_matrix) total_cost = 0 for r, c in indexes: total_cost += cost_matrix[r][c] print 'total cost for solos', total_cost print 'number of solo debates', n result = ((chair_debates[i], chairs[j]) for i, j in indexes if i < len(chair_debates)) alloc = [AdjudicatorAllocation(d, c) for d, c in result] print [(a.debate, a.chair) for a in alloc] else: print "No solo adjudicators." alloc = [] # do panels n = len(panel_debates) npan = len(panellists) if npan: print "costing panellists" # matrix is square, dummy debates have cost 0 cost_matrix = [[0] * npan for i in range(npan)] for i, debate in enumerate(panel_debates): for j in range(3): # for the top half of these debates, the final panellist # can be of lower quality than the other 2 if i < npan/2 and j==2: adjustment = -1.0 else: adjustment = 0 for k, adj in enumerate(panellists): cost_matrix[3*i+j][k] = self.calc_cost(debate, adj, adjustment) print "optimizing" indexes = m.compute(cost_matrix) cost = 0 for r, c in indexes: cost += cost_matrix[r][c] print 'total cost for panellists', cost # transfer the indices to the debates # the debate corresponding to row r is floor(r/3) (i.e. r // 3) p = [[] for i in range(n)] for r, c in indexes[:n*3]: p[r // 3].append(panellists[c]) # create the corresponding adjudicator allocations, making sure # that the chair is the highest-ranked adjudicator in the panel for i, d in enumerate(panel_debates): a = AdjudicatorAllocation(d) p[i].sort(key=lambda a: a.score, reverse=True) a.chair = p[i].pop(0) a.panel = p[i] alloc.append(a) print [(a.debate, a.chair, a.panel) for a in alloc[len(chairs):]]