You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 09:47:07