Desse trabalho fiz esse código:

TOTAL_SLOTS = 50 # 5 dias, 2 turnos, 5 aulas

with open("matrizcur.json", "r", encoding='utf-8') as file:

    data = json.load(file)

class Disciplina:

    def init(self, codigo, periodo, aulas, depedencias):

        self.codigo = codigo

        self.periodo = periodo

        self.aulas_semana = aulas

        self.dependencias = depedencias

        #Atribui um professor fixo para cada disciplina

        self.professor = f"Professor_{random.randint(1,15)}"

disciplinas = [

    Disciplina(

        d["codigo"],

        d["periodo"],

        d["aulas_semana"],

        d["pre_requisitos"]

    ) 

    for d in data["DISCIPLINAS"]

]

N_GENES = sum(d.aulas_semana for d in disciplinas)

PARAMETROS = [

    {"POP_SIZE": 500, "MUTPB":0.15, "CXPB": 0.8, "NGEN": 5000, "TOURNSIZE": 3}

]

def numslot_para_horario(slot):

    aulas_por_turnos = 5

    dia = slot // (2 * aulas_por_turnos)

    turno = (slot % (2 * aulas_por_turnos)) // aulas_por_turnos

    aula = (slot % (2 * aulas_por_turnos)) % aulas_por_turnos

    return dia, turno, aula

creator.create("FitnessMin", base.Fitness, weights=(-1.0,))

creator.create("Individual", list, fitness=creator.FitnessMin)

toolbox = base.Toolbox()

toolbox.register("attr_slot", random.randint, 0, TOTAL_SLOTS-1)

toolbox.register("individual", tools.initRepeat, creator.Individual,

                 toolbox.attr_slot, n=N_GENES)

toolbox.register("population", tools.initRepeat, list, toolbox.individual)

toolbox.register("evaluate", fitness)

toolbox.register("select", tools.selTournament, tournsize=5)

toolbox.register("mate", tools.cxOnePoint)

toolbox.register("mutate", tools.mutUniformInt, low=0, up=TOTAL_SLOTS-1,indpb=1.0/N_GENES)

stats = tools.Statistics(lambda ind: ind.fitness.values[0])

stats.register("min", np.min)

stats.register("avg", lambda vals: sum(vals)/len(vals))

hof = tools.HallOfFame(1)

POP_SIZE = 1000

CXPB = 0.8

MUTPB = 0.25

if name == "__main__":

    populacao = toolbox.population(n=POP_SIZE)

    populacao = algorithms.eaSimple(populacao, toolbox, cxpb=CXPB, mutpb=MUTPB,

                                    ngen=200, stats=stats, halloffame=hof)

    #{"POP_SIZE": 500, "MUTPB":0.15, "CXPB": 0.8, "NGEN": 5000, "TOURNSIZE": 3}

    

    best = hof[0]

    print("Melhor Fitness: ", best.fitness.values[0])

    gerar_pdf(best)

    for d in disciplinas:

        print(d.professor)

* Queria ajudar para criar a função fitness, as restrições que deve ter inclua se necessario(não coloque coisas de administração de salas ou invente regras do rabo). 

Tem as:

* Uma disciplina do mesmo periodo não deve ocupar mesmo horario e dia

* Professores não devem ter + 1 aula no mesmo dia

* O tempo ocioso entre aulas de um mesmo periodo deve ser minimizado

* Não deve haver +3 aulas seguidas(ou no dia) da mesma matéria

* "não existam conflitos entre os

horários de disciplinas que são pré-requisito e suas correspondentes" (está no arquivo de descrição), OBS: no meus dados eu tenho qual matéria é dependecia de qual

Balanceamento semanal

    Cada período deve ter suas aulas distribuídas de forma relativamente “uniforme” pelos 5 dias (evitar, por exemplo, um dia com 0 aulas e outro com 5).