from __future__ import annotations from typing import TYPE_CHECKING from pydantic import BaseModel from typing import Any, List from pulp import LpProblem, LpVariable, lpSum import logging from models.solution import Solution from models.item import Item from models.bundle import Bundle from lib.errors.item_generation_error import ItemGenerationError if TYPE_CHECKING: from models.solver_run import SolverRun class Problem(BaseModel): items: List[Item] bundles: List[Bundle] problem: Any solver_items_var: Any = None solver_bundles_var: Any = None def __init__(self, **data) -> None: super().__init__(**data) # setup common Solver variables self.solver_items_var = LpVariable.dicts("Item", [item.id for item in self.items], lowBound=0, upBound=1, cat='Binary') self.solver_bundles_var = LpVariable.dicts("Bundle", [bundle.id for bundle in self.bundles], lowBound=0, upBound=1, cat='Binary') def solve(self) -> LpProblem: self.problem.solve() return self.problem def generate(self, solution: Solution, solver_run: SolverRun) -> None: try: # creating problem objective function solver_run.objective_function.for_problem(self) logging.info('Creating Constraints...') # generic constraints for constraint in solver_run.constraints: constraint.build(self, solver_run=solver_run, solution=solution) # irt target constraints for target in solver_run.objective_function.all_targets(): target.constraints(self, solver_run) logging.info('Constraints Created...') except ValueError as error: logging.error(error) raise ItemGenerationError( error.msg, error.args[0])