Files
OperatorSchedule/constraints/__init__.py

94 lines
3.3 KiB
Python

"""Constraints package."""
from dataclasses import dataclass
from typing import List, Dict, Any, Optional, Union
from constraints.base_constraint import Constraint, ConstraintViolation, ConstraintType
from constraints.hard_constraints import (
SkillRequirementConstraint,
ShiftCoverageConstraint,
MaxWorkTimeConstraint,
DepartmentAssignmentConstraint,
MinCoverageConstraint,
ConflictPreventionConstraint,
create_hard_constraints
)
from constraints.soft_constraints import (
OperatorPreferenceConstraint,
DayAvailabilityConstraint,
WorkBalanceConstraint,
ContinuityPreference,
SeniorityPriorityConstraint,
create_soft_constraints
)
@dataclass
class ConstraintSet:
"""Container for all constraints (hard and soft)."""
hard_constraints: List[Constraint]
soft_constraints: List[Constraint]
scenario: Dict[str, Any]
def validate(self, context: Dict[str, Any]) -> List[ConstraintViolation]:
"""Validate all constraints and return violations."""
violations = []
# Check hard constraints
for constraint in self.hard_constraints:
if constraint.enabled:
violation = constraint.get_violation(context)
if violation:
violations.append(violation)
# Check soft constraints (only warn, don't fail)
for constraint in self.soft_constraints:
if constraint.enabled:
violation = constraint.get_violation(context)
if violation:
violations.append(violation)
return violations
def get_enabled_hard_constraints(self) -> List[Constraint]:
"""Get all enabled hard constraints."""
return [c for c in self.hard_constraints if c.enabled]
def get_enabled_soft_constraints(self) -> List[Constraint]:
"""Get all enabled soft constraints."""
return [c for c in self.soft_constraints if c.enabled]
def get_disabled_constraints(self) -> List[Constraint]:
"""Get all disabled constraints."""
return [c for c in self.hard_constraints + self.soft_constraints if not c.enabled]
def enable_constraint(self, constraint_id: str) -> bool:
"""Enable a constraint by ID."""
for constraint in self.hard_constraints + self.soft_constraints:
if constraint.constraint_id == constraint_id:
constraint.enabled = True
return True
return False
def disable_constraint(self, constraint_id: str) -> bool:
"""Disable a constraint by ID."""
for constraint in self.hard_constraints + self.soft_constraints:
if constraint.constraint_id == constraint_id:
constraint.enabled = False
return True
return False
def clear_violations(self, context: Dict[str, Any]) -> bool:
"""Check if all violations can be cleared in context."""
violations = self.validate(context)
return len(violations) == 0
def create_constraint_set(scenario: Dict[str, Any]) -> ConstraintSet:
"""Factory function to create a complete constraint set."""
hard = create_hard_constraints(scenario)
soft = create_soft_constraints(scenario)
return ConstraintSet(
hard_constraints=hard,
soft_constraints=soft,
scenario=scenario
)