irt-service/app/models/irt_target_constraint.py
2023-11-10 15:21:16 -05:00

51 lines
2.1 KiB
Python

from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from pulp import lpSum
from models import Constraint, Problem, Attribute, Target, Item, Bundle
if TYPE_CHECKING:
from models.solver_run import SolverRun
class IrtTargetConstraint(Constraint):
reference_attribute: Optional[Attribute]
minimum: Optional[float]
maximum: Optional[float]
target: Target
target_type: str
def build(self, problem_handler: Problem, solver_run: SolverRun):
problem_handler.problem += lpSum([
self.bundle_irt_function(bundle, solver_run.irt_model, self.target.theta)
* problem_handler.solver_bundles_var[bundle.id]
for bundle in problem_handler.bundles
] + [
self.item_irt_function(item, solver_run.irt_model, self.target.theta) *
problem_handler.solver_items_var[item.id]
for item in problem_handler.items
]) >= self.target.minimum(
), f'Min {self.target_type} theta({self.target.theta}) at target {self.target.value}'
problem_handler.problem += lpSum([
self.bundle_irt_function(bundle, solver_run.irt_model, self.target.theta)
* problem_handler.solver_bundles_var[bundle.id]
for bundle in problem_handler.bundles
] + [
self.item_irt_function(item, solver_run.irt_model, self.target.theta) *
problem_handler.solver_items_var[item.id]
for item in problem_handler.items
]) <= self.target.maximum(
), f'Max {self.target_type} theta({self.target.theta}) at target {self.target.value}'
def item_irt_function(self, item: Item, irt_model: str, theta: float) -> float:
if self.target_type == 'tcc':
return item.irf(irt_model, theta)
elif self.target_type == 'tif':
return item.iif(irt_model, theta)
def bundle_irt_function(self, bundle: Bundle, irt_model: str, theta: float) -> float:
if self.target_type == 'tcc':
return bundle.trf(irt_model, theta)
elif self.target_type == 'tif':
return bundle.tif(irt_model, theta)