Example #1
0
    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 = list(zip(self.debates, panels))

        if avoid_conflicts:
            for i, (debate, panel) in enumerate(self.pairings):
                if panel.conflicts(debate):
                    j = self.search_swap(i, list(range(i, 0, -1)))
                    if j is None:
                        j = self.search_swap(i, list(range(i+1, len(panels))))

        from adjallocation.allocation 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
Example #2
0
    def allocate(self):
        from adjallocation.allocation import AdjudicatorAllocation

        debates = self.debates
        adjs = self.adjudicators

        result = []
        for debate in debates:
            alloc = AdjudicatorAllocation(debate)
            alloc.chair = adjs.pop(0)
            result.append(alloc)

        while len(adjs) >= 2:
            for alloc in reversed(result):
                if len(adjs) >= 2:
                    alloc.panel.append(adjs.pop(0))
                    alloc.panel.append(adjs.pop(0))

        return result
Example #3
0
    def allocate(self):
        from adjallocation.allocation import AdjudicatorAllocation

        # Remove trainees
        self.adjudicators = [a for a in self.adjudicators if a.score >= self.MIN_VOTING_SCORE]
        logger.info("There are %s non-trainee adjudidcators", len(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)
        logger.info("There are %s debates", n_debates)
        if n_adjudicators < n_debates:
            logger.critical("There are %d debates but only %d adjudicators", n_debates, n_adjudicators)

        # If not setting panellists allocate all debates a solo chair
        if self.NO_PANELLISTS is True:
            n_solos = n_debates
        else:
            n_solos = n_debates - (n_adjudicators - n_debates)//2

        # get adjudicators that can adjudicate solo
        chairs = self.adjudicators_sorted[:n_solos]
        logger.info("There are %s chairs", len(chairs))

        # 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]
        logger.info("There are %s panellists", len(panellists))

        # For tournaments with duplicate allocations there are typically not
        # enough adjudicators to form full panels, so don't crash in that case
        if not self.DUPLICATE_ALLOCATIONS and len(panellists) < len(panel_debates) * 3:
            logger.critical("There are %d panel debates but only %d available panellists (less than %d)",
                    len(panel_debates), len(panellists), len(panel_debates) * 3)

        m = Munkres()
        # TODO I think "chairs" actually means "solos", rename variables if correct
        if len(chairs) > 0:

            logger.info("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)

            logger.info("optimizing")

            indexes = m.compute(cost_matrix)

            total_cost = 0
            for r, c in indexes:
                total_cost += cost_matrix[r][c]

            logger.info('total cost for solos %f', total_cost)
            logger.info('number of solo debates %d', 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]

            for a in alloc:
                logger.info("%s %s", a.debate, a.chair)

        else:
            logger.info("No solo adjudicators.")
            alloc = []

        # Skip the next step if there is the panellist position is disabled
        if self.NO_PANELLISTS is True:
            npan = False
        else:
            n = len(panel_debates)
            npan = len(panellists)

        if npan:
            logger.info("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)

            logger.info("optimizing")

            indexes = m.compute(cost_matrix)

            cost = 0
            for r, c in indexes:
                cost += cost_matrix[r][c]

            logger.info('total cost for panellists %f', 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.panellists = p[i]
                alloc.append(a)

        for a in alloc[len(chairs):]:
            logger.info("%s %s %s", a.debate, a.chair, a.panellists)

        return alloc