refactor of model targets and constraints, addition of new constraint types and constraint construction process
This commit is contained in:
15
app/models/constraints/bundle_constraint.py
Normal file
15
app/models/constraints/bundle_constraint.py
Normal file
@ -0,0 +1,15 @@
|
||||
from random import randint
|
||||
|
||||
from models.constraints.generic_constraint import *
|
||||
|
||||
class BundleConstraint(GenericConstraint):
|
||||
def build(self, problem_handler: Problem, **kwargs) -> None:
|
||||
logging.info('Bundles Constraint Generating...')
|
||||
|
||||
# TODO: account for many different bundle types, since the id condition in L33 could yield duplicates
|
||||
if problem_handler.bundles != None and len(problem_handler.bundles) > 0:
|
||||
# make sure the total bundles used in generated form is limited between min-max set
|
||||
problem_handler.problem += lpSum([
|
||||
problem_handler.solver_bundles_var[bundle.id] for bundle in problem_handler.bundles
|
||||
]) == randint(int(self.minimum),
|
||||
int(self.maximum)), f'Allowing min - max bundles'
|
34
app/models/constraints/form_uniqueness_constraint.py
Normal file
34
app/models/constraints/form_uniqueness_constraint.py
Normal file
@ -0,0 +1,34 @@
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from models.constraints.generic_constraint import *
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models.solver_run import SolverRun
|
||||
|
||||
class FormUniquenessConstraint(GenericConstraint):
|
||||
@classmethod
|
||||
def create(cls: Type[_T], total_items: int) -> _T:
|
||||
return cls(
|
||||
minimum=0,
|
||||
maximum=0,
|
||||
reference_attribute=Attribute(
|
||||
value=total_items,
|
||||
type='form_uniqueness',
|
||||
id='form_uniqueness'
|
||||
)
|
||||
)
|
||||
|
||||
def build(self, problem_handler: Problem, **kwargs) -> None:
|
||||
logging.info('Form Uniqueness Constraint Generating...')
|
||||
|
||||
# form uniqueness constraint
|
||||
problem_handler.problem += lpSum(
|
||||
[
|
||||
kwargs['solution'].items_exist_in_forms(bundle.items) * problem_handler.solver_bundles_var[bundle.id]
|
||||
for bundle in problem_handler.bundles
|
||||
] + [
|
||||
kwargs['solution'].items_exist_in_forms([item]) * problem_handler.solver_items_var[item.id]
|
||||
for item in problem_handler.items
|
||||
]
|
||||
) <= self.reference_attribute.value, f'Ensuring uniqueness for form'
|
17
app/models/constraints/generic_constraint.py
Normal file
17
app/models/constraints/generic_constraint.py
Normal file
@ -0,0 +1,17 @@
|
||||
import logging
|
||||
|
||||
from pulp import lpSum
|
||||
from pydantic import BaseModel
|
||||
from typing import TypeVar, Type
|
||||
|
||||
from helpers.common_helper import *
|
||||
|
||||
from models.attribute import Attribute
|
||||
from models.problem import Problem
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
class GenericConstraint(BaseModel):
|
||||
reference_attribute: Attribute
|
||||
minimum: float
|
||||
maximum: float
|
29
app/models/constraints/metadata_constraint.py
Normal file
29
app/models/constraints/metadata_constraint.py
Normal file
@ -0,0 +1,29 @@
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from models.constraints.generic_constraint import *
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models.solver_run import SolverRun
|
||||
|
||||
class MetadataConstraint(GenericConstraint):
|
||||
def build(self, problem_handler: Problem, **kwargs) -> None:
|
||||
logging.info('Metadata Constraint Generating...')
|
||||
|
||||
problem_handler.problem += lpSum(
|
||||
[
|
||||
len(bundle.items_with_attribute(self.reference_attribute)) * problem_handler.solver_bundles_var[bundle.id] for bundle in problem_handler.bundles
|
||||
] +
|
||||
[
|
||||
item.attribute_exists(self.reference_attribute).real * problem_handler.solver_items_var[item.id] for item in problem_handler.items
|
||||
]
|
||||
) >= round(kwargs['solver_run'].total_form_items * (self.minimum / 100)), f'{self.reference_attribute.id} - {self.reference_attribute.value} - min'
|
||||
|
||||
problem_handler.problem += lpSum(
|
||||
[
|
||||
len(bundle.items_with_attribute(self.reference_attribute)) * problem_handler.solver_bundles_var[bundle.id] for bundle in problem_handler.bundles
|
||||
] +
|
||||
[
|
||||
item.attribute_exists(self.reference_attribute).real * problem_handler.solver_items_var[item.id] for item in problem_handler.items
|
||||
]
|
||||
) <= round(kwargs['solver_run'].total_form_items * (self.maximum / 100)), f'{self.reference_attribute.id} - {self.reference_attribute.value} - max'
|
33
app/models/constraints/total_form_items_constraint.py
Normal file
33
app/models/constraints/total_form_items_constraint.py
Normal file
@ -0,0 +1,33 @@
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from models.constraints.generic_constraint import *
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from models.solver_run import SolverRun
|
||||
|
||||
class TotalFormItemsConstraint(GenericConstraint):
|
||||
@classmethod
|
||||
def create(cls: Type[_T], total_items: int) -> _T:
|
||||
return cls(
|
||||
minimum=0,
|
||||
maximum=0,
|
||||
reference_attribute=Attribute(
|
||||
value=total_items,
|
||||
type='form_uniqueness',
|
||||
id='form_uniqueness'
|
||||
)
|
||||
)
|
||||
|
||||
def build(self, problem_handler: Problem, **kwargs) -> None:
|
||||
logging.info('Total Form Items Constraint Generating...')
|
||||
|
||||
problem_handler.problem += lpSum(
|
||||
[
|
||||
bundle.count * problem_handler.solver_bundles_var[bundle.id]
|
||||
for bundle in problem_handler.bundles
|
||||
] + [
|
||||
1 * problem_handler.solver_items_var[item.id]
|
||||
for item in problem_handler.items
|
||||
]
|
||||
) == self.reference_attribute.value, f'Total bundle form items for form'
|
Reference in New Issue
Block a user