94 lines
3.3 KiB
Python
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
|
|
) |