Esempio n. 1
0
    def move_pieces(self):
        """
        Move pieces to new action F instances to make it fit, if needed.

        @return: Created action F instances.
        @rtype:  C{list} of L{ActionF}

        @note: Function may change L{pieces}.
        """
        global townname_serial

        if len(self.pieces) <= 255:
            return []  # Trivially correct.

        # There are too many pieces.
        number_action_f = (len(self.pieces) + 254) // 255
        pow2 = 1
        while pow2 < number_action_f:
            pow2 = pow2 * 2
        if pow2 < 255: number_action_f = pow2

        heap = []  # Heap of (summed probability, subset-of-pieces)
        i = 0
        while i < number_action_f:
            # Index 'i' is added to have a unique sorting when lists have equal total probabilities.
            heapq.heappush(heap, (0, i, []))
            i = i + 1

        finished_actions = []
        # Index 'idx' is added to have a unique sorting when pieces have equal probabilities.
        rev_pieces = sorted(((p.probability.value, idx, p)
                             for idx, p in enumerate(self.pieces)),
                            reverse=True)
        for prob, _idx, piece in rev_pieces:
            while True:
                sub = heapq.heappop(heap)
                if len(sub[2]) < 255:
                    break
                # If a subset already has the max number of parts, consider it finished.
                finished_actions.append(sub)

            sub[2].append(piece)
            sub = (sub[0] + prob, sub[1], sub[2])
            heapq.heappush(heap, sub)

        finished_actions.extend(heap)

        # To ensure the chances do not get messed up due to one part needing less bits for its
        # selection, all parts are forced to use the same number of bits.
        max_prob = max(sub[0] for sub in finished_actions)
        num_bits = 1
        while (1 << num_bits) < max_prob:
            num_bits = num_bits + 1

        # Assign to action F
        actFs = []
        for _prob, _idx, sub in finished_actions:
            actF_name = expression.Identifier(
                "**townname #{:d}**".format(townname_serial), None)
            townname_serial = townname_serial + 1
            town_part = TownNamesPart(sub, self.pos)
            town_part.set_numbits(num_bits)
            actF = actionF.ActionF(actF_name, None, None, [town_part],
                                   self.pos)
            actFs.append(actF)

            # Remove pieces of 'sub' from self.pieces
            counts = len(self.pieces), len(sub)
            sub_set = set(sub)
            self.pieces = [
                piece for piece in self.pieces if piece not in sub_set
            ]
            assert len(self.pieces) == counts[0] - counts[1]

            self.pieces.append(
                TownNamesEntryDefinition(actF_name,
                                         expression.ConstantNumeric(1),
                                         self.pos))

        # update self.parts
        return actFs
Esempio n. 2
0
 def get_action_list(self):
     return self.actFs + [
         actionF.ActionF(self.name, self.id_number, self.style_name,
                         self.parts, self.pos)
     ]