Merge branch 'develop' into feature/QUANT-3102

This commit is contained in:
brmnjsh 2023-10-31 17:38:24 +00:00
commit bc46854c70
6 changed files with 19 additions and 7 deletions

View File

@ -1,6 +1,7 @@
import logging import logging
from lib.irt.models.three_parameter_logistic import ThreeParameterLogistic from lib.irt.models.three_parameter_logistic import ThreeParameterLogistic
from lib.irt.models.rasch import Rasch
from lib.errors.item_generation_error import ItemGenerationError from lib.errors.item_generation_error import ItemGenerationError
@ -20,6 +21,10 @@ class ItemInformationFunction():
return (self.model_data.a_param * q * return (self.model_data.a_param * q *
(p - self.model_data.c_param)**2) / (p * ( (p - self.model_data.c_param)**2) / (p * (
(1 - self.model_data.c_param)**2)) (1 - self.model_data.c_param)**2))
elif self.model_data.model == 'rasch':
p = Rasch(self.model_data, kwargs).result()
q = 1 - p
return p * q
else: else:
# potentially error out # potentially error out
raise ItemGenerationError( raise ItemGenerationError(

View File

@ -1,4 +1,5 @@
from lib.irt.models.three_parameter_logistic import ThreeParameterLogistic from lib.irt.models.three_parameter_logistic import ThreeParameterLogistic
from lib.irt.models.rasch import Rasch
from lib.errors.item_generation_error import ItemGenerationError from lib.errors.item_generation_error import ItemGenerationError
@ -10,5 +11,7 @@ class ItemResponseFunction():
def calculate(self, **kwargs): def calculate(self, **kwargs):
if self.model_data.model == '3PL': if self.model_data.model == '3PL':
return ThreeParameterLogistic(self.model_data, kwargs).result() return ThreeParameterLogistic(self.model_data, kwargs).result()
elif self.model_data.model == 'rasch':
return Rasch(self.model_data, kwargs).result()
else: else:
raise ItemGenerationError("irt model not supported or provided") raise ItemGenerationError("irt model not supported or provided")

View File

@ -5,7 +5,10 @@ from lib.irt.models.base import *
class Rasch(Base): class Rasch(Base):
def result(self): def result(self):
return 0.0 # contains the primary Rasch function, determining the probably of an inidividual
# that an individual at a certain theta would get a particular question correct
# https://edres.org/irt/baker/chapter6.pdf
return (1 / (1 + self.e(-1 * (self.theta - self.b_param))))
@classmethod @classmethod
def ability_estimate(self, items) -> float: def ability_estimate(self, items) -> float:

View File

@ -1,11 +1,11 @@
from pydantic import BaseModel from pydantic import BaseModel
from typing import Dict from typing import Dict, Optional
class IRTModel(BaseModel): class IRTModel(BaseModel):
a_param: float a_param: Optional[float] = None
b_param: Dict = {"schema_bson_id": str, "field_bson_id": str} b_param: Dict = {"schema_bson_id": str, "field_bson_id": str}
c_param: float c_param: Optional[float] = None
model: str model: str
def formatted_b_param(self): def formatted_b_param(self):

View File

@ -13,7 +13,7 @@ class Item(BaseModel):
workflow_state: Optional[str] = None workflow_state: Optional[str] = None
attributes: List[Attribute] = None attributes: List[Attribute] = None
b_param: float = 0.00 b_param: float = 0.00
response: Optional[str] = None response: Optional[int] = None
def iif(self, solver_run, theta): def iif(self, solver_run, theta):
return ItemInformationFunction(solver_run.irt_model).calculate(b_param=self.b_param, theta=theta) return ItemInformationFunction(solver_run.irt_model).calculate(b_param=self.b_param, theta=theta)

View File

@ -1,6 +1,6 @@
import json, random, io, logging import json, random, io, logging
from pulp import LpProblem, LpVariable, LpMinimize, LpMaximize, LpAffineExpression, LpConstraint, LpStatus, lpSum from pulp import LpProblem, LpVariable, LpMinimize, LpStatus, lpSum
from lib.application_configs import ApplicationConfigs from lib.application_configs import ApplicationConfigs
from helpers import aws_helper, tar_helper, csv_helper, service_helper, solver_helper from helpers import aws_helper, tar_helper, csv_helper, service_helper, solver_helper
@ -72,6 +72,7 @@ class FormGenerationService(Base):
current_drift = 0 # FF Tokyo Drift current_drift = 0 # FF Tokyo Drift
# adding an element of randomness to the items and bundles used # adding an element of randomness to the items and bundles used
# may need to change impl based on limit of items available
selected_items = self.solver_run.select_items_by_percent(30) selected_items = self.solver_run.select_items_by_percent(30)
selected_bundles = self.solver_run.select_bundles_by_percent( selected_bundles = self.solver_run.select_bundles_by_percent(
30) 30)
@ -88,7 +89,7 @@ class FormGenerationService(Base):
upBound=1, upBound=1,
cat='Binary') cat='Binary')
logging.info(f'Generating Solution for Form {form_number}') logging.info(f'Generating Solution for Form {form_number} using the {self.solver_run.irt_model.model} IRT model')
while current_drift <= Target.max_drift(): while current_drift <= Target.max_drift():
drift_percent = current_drift / 100 drift_percent = current_drift / 100