80 lines
2.8 KiB
Python
80 lines
2.8 KiB
Python
from pydantic import BaseModel
|
|
from typing import Any, List
|
|
from pulp import LpProblem, LpVariable, lpSum
|
|
|
|
import logging, math
|
|
|
|
from helpers import solver_helper
|
|
|
|
from models.solver_run import SolverRun
|
|
from models.solution import Solution
|
|
from models.item import Item
|
|
from models.bundle import Bundle
|
|
|
|
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')
|
|
|
|
# objective function
|
|
self.problem += lpSum([
|
|
bundle.count * self.solver_bundles_var[bundle.id]
|
|
for bundle in self.bundles
|
|
] + [
|
|
self.solver_items_var[item.id]
|
|
for item in self.items
|
|
])
|
|
|
|
def solve(self) -> LpProblem:
|
|
self.problem.solve()
|
|
return self.problem
|
|
|
|
def generate(self, solution: Solution, solver_run: SolverRun):
|
|
|
|
# Form Constraints
|
|
self.problem += lpSum(
|
|
[
|
|
bundle.count * self.solver_bundles_var[bundle.id]
|
|
for bundle in self.bundles
|
|
] + [
|
|
1 * self.solver_items_var[item.id]
|
|
for item in self.items
|
|
]
|
|
) == solver_run.total_form_items, f'Total bundle form items for form'
|
|
|
|
# each time a form is generated, we want to ensure
|
|
# that it is unique to all other forms generated before it
|
|
self.problem += lpSum(
|
|
[
|
|
solution.items_exist_in_forms(bundle.items) * self.solver_bundles_var[bundle.id]
|
|
for bundle in self.bundles
|
|
] + [
|
|
solution.items_exist_in_forms([item]) * self.solver_items_var[item.id]
|
|
for item in self.items
|
|
]
|
|
) <= solver_run.total_form_items - 1, f'Ensuring uniqueness for form'
|
|
|
|
def generate_constraints(self, solver_run: SolverRun, current_drift: int):
|
|
self.problem = solver_helper.build_constraints(
|
|
solver_run, self.problem, self.solver_items_var, self.solver_bundles_var, self.items, self.bundles, current_drift)
|
|
|
|
|
|
|