jmetalpy排课类实现报错:无法实例化抽象类
问题分析与解决
报错TypeError: Can't instantiate abstract class TimetablingProblem with abstract methods name, number_of_constraints, number_of_objectives的核心原因是你没有正确实现FloatProblem抽象类要求的属性。
jmetalpy的FloatProblem继承自Problem抽象基类,要求子类必须公开number_of_objectives、number_of_constraints、name这三个属性,且这些属性需要是类可直接访问的(类属性或通过@property暴露的实例属性)。你之前在__init__方法里给实例赋值这些属性,抽象类在初始化前的类检查阶段无法识别,因此判定你没有实现抽象方法/属性。
解决方案
有两种可行的修改方式:
方式1:定义为类属性(适用于属性值固定的场景)
直接在类中声明这三个属性为类级变量,这是最简单的方式:
class TimetablingProblem(FloatProblem): # 满足抽象类要求的类属性 number_of_objectives = 2 # 拥挤度、错位率两个目标 number_of_constraints = 0 name = "Timetabling Problem" def __init__(self, horarioblank, caracteristicas_salas): super().__init__() self.horarioblank = horarioblank self.caracteristicas_salas = caracteristicas_salas self.number_of_variables = len(horarioblank) # 班次数量 self.lower_bound = np.zeros(self.number_of_variables) self.upper_bound = np.full(self.number_of_variables, len(caracteristicas_salas) - 1) def evaluate(self, solution: FloatSolution) -> None: alocacoes_salas = solution.variables sobrelotacao = 0 inadequacao = 0 for i, turno in enumerate(self.horarioblank): sala_alocada = self.caracteristicas_salas.iloc[int(alocacoes_salas[i])] inscritos = turno['Inscritos no turno'] if inscritos > sala_alocada['Capacidade_Normal']: sobrelotacao += inscritos - sala_alocada['Capacidade_Normal'] if sala_alocada['combined'] not in turno['Características reais da sala']: inadequacao += 1 solution.objectives[0] = sobrelotacao solution.objectives[1] = inadequacao def create_solution(self) -> FloatSolution: solution = FloatSolution( lower_bound=self.lower_bound, upper_bound=self.upper_bound, number_of_objectives=self.number_of_objectives, number_of_constraints=self.number_of_constraints ) return solution
方式2:用@property封装(适用于属性值需要动态计算的场景)
如果需要根据输入参数动态调整目标数或约束数,可以用@property装饰器将实例属性暴露为抽象类要求的属性:
class TimetablingProblem(FloatProblem): def __init__(self, horarioblank, caracteristicas_salas): super().__init__() self.horarioblank = horarioblank self.caracteristicas_salas = caracteristicas_salas self.number_of_variables = len(horarioblank) # 班次数量 # 用私有变量存储实际值 self._number_of_objectives = 2 self._number_of_constraints = 0 self.lower_bound = np.zeros(self.number_of_variables) self.upper_bound = np.full(self.number_of_variables, len(caracteristicas_salas) - 1) @property def number_of_objectives(self): return self._number_of_objectives @property def number_of_constraints(self): return self._number_of_constraints @property def name(self): return "Timetabling Problem" def evaluate(self, solution: FloatSolution) -> None: alocacoes_salas = solution.variables sobrelotacao = 0 inadequacao = 0 for i, turno in enumerate(self.horarioblank): sala_alocada = self.caracteristicas_salas.iloc[int(alocacoes_salas[i])] inscritos = turno['Inscritos no turno'] if inscritos > sala_alocada['Capacidade_Normal']: sobrelotacao += inscritos - sala_alocada['Capacidade_Normal'] if sala_alocada['combined'] not in turno['Características reais da sala']: inadequacao += 1 solution.objectives[0] = sobrelotacao solution.objectives[1] = inadequacao def create_solution(self) -> FloatSolution: solution = FloatSolution( lower_bound=self.lower_bound, upper_bound=self.upper_bound, number_of_objectives=self.number_of_objectives, number_of_constraints=self.number_of_constraints ) return solution
关键说明
- 原代码中的
get_name方法是多余的,抽象类要求的是name属性而非该方法,因此可以直接删除。 - 确保
number_of_objectives、number_of_constraints、name这三个属性能被类直接访问,抽象基类的类型检查才能通过。
内容的提问来源于stack exchange,提问作者Daniela Rodrigues
相关产品推荐
相关产品推荐

