<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def select(self, personae, relative=False, roles=1):
 """Select a persona for each entity declared in the scene. :param personae: A sequence of Personae. :param bool relative: Affects imports from namespace packages. Used for testing only. :param int roles: The maximum number of roles allocated to each persona. :return: An OrderedDict of {Entity: Persona}. """


        def constrained(entity):
            return (
                len(entity["options"].get("types", [])) +
                len(entity["options"].get("states", []))
            )

        rv = OrderedDict()
        performing = defaultdict(set)
        pool = list(personae)
        self.log.debug(pool)
        entities = OrderedDict([
            ("".join(entity.attributes["names"]), entity)
            for entity in sorted(
                group_by_type(self.doc)[EntityDirective.Declaration],
                key=constrained,
                reverse=True
            )
        ])
        for e in entities.values():
            types = tuple(filter(
                None,
                (e.string_import(t, relative)
                 for t in e["options"].get("types", []))
            ))
            states = tuple(filter(
                None,
                (int(t) if t.isdigit() else e.string_import(t, relative)
                 for t in e["options"].get("states", []))
            ))
            otherRoles = {i.lower() for i in e["options"].get("roles", [])}
            typ = types or object
            persona = next(
                (i for i in pool
                 if isinstance(i, typ) and
                 getattr(i, "get_state", not states) and
                 all(str(i.get_state(type(s))).startswith(str(s)) for s in states) and
                 (performing[i].issubset(otherRoles) or not otherRoles)),
                None
            )
            rv[e] = persona
            performing[persona].update(set(e.attributes["names"]))

            if not otherRoles or list(rv.values()).count(persona) == roles:
                try:
                    pool.remove(persona)
                except ValueError:
                    self.log.debug(
                        "No persona for type {0} and states {1} with {2} {3}.".format(
                            typ, states, roles, "role" if roles == 1 else "roles"
                        )
                    )
        return rv