[docs]defget_makespan_with_penalties_objective(deadline_penalty_factor:float=1_000_000,due_date_penalty_factor:float=100,)->ObjectiveFunction:"""Builds an objective function that returns the makespan plus penalties. This factory returns a callable that evaluates a Schedule as the sum of its makespan and penalties for violating operation-level deadlines and due dates. Penalties are applied per scheduled operation that finishes after its corresponding attribute value: - Deadline violation: adds ``deadline_penalty_factor`` once per violating operation (hard constraint surrogate). - Due date violation: adds ``due_date_penalty_factor`` once per violating operation (soft constraint surrogate). Args: deadline_penalty_factor: Cost added for each operation that finishes after its deadline. Defaults to 1_000_000. due_date_penalty_factor: Cost added for each operation that finishes after its due date. Defaults to 100. Returns: A function ``f(schedule) -> float`` that computes ``schedule.makespan() + penalty``. Notes: - Deadlines and due dates are taken from each operation. If an operation does not define the attribute (``None``), no penalty is applied for that attribute. - If the instance has neither deadlines nor due dates, the objective is simply the makespan. """defobjective(schedule:Schedule)->float:makespan=schedule.makespan()instance=schedule.instance# Fast path: no constraint attributes present in the instanceifnotinstance.has_deadlinesandnotinstance.has_due_dates:returnmakespanpenalty=0.0formachine_scheduleinschedule.schedule:forscheduled_opinmachine_schedule:op=scheduled_op.operation# Deadline (hard) penaltyif(op.deadlineisnotNoneandscheduled_op.end_time>op.deadline):penalty+=deadline_penalty_factor# Due date (soft) penaltyif(op.due_dateisnotNoneandscheduled_op.end_time>op.due_date):penalty+=due_date_penalty_factorreturnmakespan+penaltyreturnobjective