Merge branch 'develop' into feature/QUANT-3102
This commit is contained in:
commit
d58954ec1d
@ -43,7 +43,7 @@ class ServiceListener(Consumer):
|
|||||||
logging.error(f'action of type {action} does not exist.')
|
logging.error(f'action of type {action} does not exist.')
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
logging.info('Starting IRT Service: The Enemies Within (v1.7.0)...')
|
logging.info('Starting IRT Service: Tokyo Drift 2: Driftocolypse (v1.8.0)...')
|
||||||
|
|
||||||
# ToDo: Figure out a much better way of doing this.
|
# ToDo: Figure out a much better way of doing this.
|
||||||
# LocalStack wants 'endpoint_url', while prod doesnt :(
|
# LocalStack wants 'endpoint_url', while prod doesnt :(
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import logging
|
|
||||||
from pydantic import BaseModel, validator
|
from pydantic import BaseModel, validator
|
||||||
from typing import List, Optional, Tuple
|
from typing import List, Optional
|
||||||
|
|
||||||
from models.attribute import Attribute
|
from models.attribute import Attribute
|
||||||
|
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
from typing import TYPE_CHECKING, Any, Literal, Union
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel, validator
|
||||||
from typing import Dict, List, AnyStr
|
from typing import Dict, List
|
||||||
from pulp import lpSum
|
from pulp import lpSum, LpMinimize, LpMaximize
|
||||||
|
|
||||||
from models.targets.tif_target import TifTarget
|
from models.targets.tif_target import TifTarget
|
||||||
from models.targets.tcc_target import TccTarget
|
from models.targets.tcc_target import TccTarget
|
||||||
from models.problem import Problem
|
from models.problem import Problem
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from models.solver_run import SolverRun
|
||||||
|
|
||||||
class ObjectiveFunction(BaseModel):
|
class ObjectiveFunction(BaseModel):
|
||||||
# minimizing tif/tcc target value is only option currently
|
# minimizing tif/tcc target value is only option currently
|
||||||
# as we add more we can build this out to be more dynamic
|
# as we add more we can build this out to be more dynamic
|
||||||
@ -15,18 +19,46 @@ class ObjectiveFunction(BaseModel):
|
|||||||
tif_targets: List[TifTarget]
|
tif_targets: List[TifTarget]
|
||||||
tcc_targets: List[TccTarget]
|
tcc_targets: List[TccTarget]
|
||||||
target_variance_percentage: int = 10
|
target_variance_percentage: int = 10
|
||||||
objective: AnyStr = "minimize"
|
objective: Literal[1,-1] = 1
|
||||||
|
functions: List[Literal['tcc', 'tif']] = ['tcc', 'tif']
|
||||||
weight: Dict = {'tif': 1, 'tcc': 1}
|
weight: Dict = {'tif': 1, 'tcc': 1}
|
||||||
|
|
||||||
def for_problem(self, problem_handler: Problem) -> None:
|
@validator("objective", pre=True)
|
||||||
problem_handler.problem += lpSum([
|
def set_objective(cls, v) -> List[int]:
|
||||||
bundle.count * problem_handler.solver_bundles_var[bundle.id]
|
if v == 'minimize':
|
||||||
|
return 1
|
||||||
|
elif v == 'maximize':
|
||||||
|
return -1
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def for_problem(self, problem_handler: Problem, solver_run: SolverRun) -> List[lpSum]:
|
||||||
|
functions = []
|
||||||
|
|
||||||
|
for function in self.functions:
|
||||||
|
if function == 'tcc':
|
||||||
|
functions.append(lpSum([
|
||||||
|
bundle.trf(solver_run.irt_model, solver_run.theta_cut_score)
|
||||||
|
* problem_handler.solver_bundles_var[bundle.id]
|
||||||
for bundle in problem_handler.bundles
|
for bundle in problem_handler.bundles
|
||||||
] + [
|
] + [
|
||||||
|
item.irf(solver_run.irt_model, solver_run.theta_cut_score) *
|
||||||
|
problem_handler.solver_items_var[item.id]
|
||||||
|
for item in problem_handler.items
|
||||||
|
]))
|
||||||
|
elif function == 'tif':
|
||||||
|
problem_handler.problem += lpSum([
|
||||||
|
bundle.tif(solver_run.irt_model, solver_run.theta_cut_score)
|
||||||
|
* problem_handler.solver_bundles_var[bundle.id]
|
||||||
|
for bundle in problem_handler.bundles
|
||||||
|
] + [
|
||||||
|
item.iif(solver_run.irt_model, solver_run.theta_cut_score) *
|
||||||
problem_handler.solver_items_var[item.id]
|
problem_handler.solver_items_var[item.id]
|
||||||
for item in problem_handler.items
|
for item in problem_handler.items
|
||||||
])
|
])
|
||||||
|
|
||||||
|
return functions
|
||||||
|
|
||||||
def increment_targets_drift(self,
|
def increment_targets_drift(self,
|
||||||
limit: float or bool,
|
limit: float or bool,
|
||||||
all: bool = False,
|
all: bool = False,
|
||||||
|
@ -43,7 +43,12 @@ class Problem(BaseModel):
|
|||||||
|
|
||||||
def solve(self, solver_run: SolverRun, enemy_ids: List[int] = []) -> LpProblem:
|
def solve(self, solver_run: SolverRun, enemy_ids: List[int] = []) -> LpProblem:
|
||||||
logging.info('solving problem...')
|
logging.info('solving problem...')
|
||||||
self.problem.solve()
|
|
||||||
|
# creating problem multi-objective functions
|
||||||
|
objective_functions = solver_run.objective_function.for_problem(self, solver_run)
|
||||||
|
self.problem.sequentialSolve(objective_functions)
|
||||||
|
|
||||||
|
return self.problem
|
||||||
|
|
||||||
# NOTICE: Legacy enemies implementation
|
# NOTICE: Legacy enemies implementation
|
||||||
# leaving this in, just in case the current impl fails to function
|
# leaving this in, just in case the current impl fails to function
|
||||||
@ -106,9 +111,6 @@ class Problem(BaseModel):
|
|||||||
|
|
||||||
def generate(self, solution: Solution, solver_run: SolverRun) -> None:
|
def generate(self, solution: Solution, solver_run: SolverRun) -> None:
|
||||||
try:
|
try:
|
||||||
# creating problem objective function
|
|
||||||
solver_run.objective_function.for_problem(self)
|
|
||||||
|
|
||||||
logging.info('Creating Constraints...')
|
logging.info('Creating Constraints...')
|
||||||
# generic constraints
|
# generic constraints
|
||||||
for constraint in solver_run.constraints:
|
for constraint in solver_run.constraints:
|
||||||
|
@ -18,10 +18,6 @@ from models.bundle import Bundle
|
|||||||
from models.objective_function import ObjectiveFunction
|
from models.objective_function import ObjectiveFunction
|
||||||
from models.advanced_options import AdvancedOptions
|
from models.advanced_options import AdvancedOptions
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from models.solution import Solution
|
|
||||||
from models.problem import Problem
|
|
||||||
|
|
||||||
ConstraintType = TypeVar('ConstraintType', bound=GenericConstraint)
|
ConstraintType = TypeVar('ConstraintType', bound=GenericConstraint)
|
||||||
|
|
||||||
class SolverRun(BaseModel):
|
class SolverRun(BaseModel):
|
||||||
@ -36,6 +32,8 @@ class SolverRun(BaseModel):
|
|||||||
theta_cut_score: float = 0.00
|
theta_cut_score: float = 0.00
|
||||||
drift_style: Literal['constant', 'variable'] = 'constant'
|
drift_style: Literal['constant', 'variable'] = 'constant'
|
||||||
allow_enemies: bool = False
|
allow_enemies: bool = False
|
||||||
|
max_attempts: int
|
||||||
|
max_drift: int = 10
|
||||||
advanced_options: Optional[AdvancedOptions]
|
advanced_options: Optional[AdvancedOptions]
|
||||||
engine: str
|
engine: str
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import json, random, io, logging
|
import json, random, io, logging
|
||||||
|
|
||||||
from pulp import LpProblem, LpMinimize, LpStatus
|
from pulp import LpProblem, LpStatus
|
||||||
|
|
||||||
from lib.application_configs import ApplicationConfigs
|
from lib.application_configs import ApplicationConfigs
|
||||||
from helpers import aws_helper, tar_helper, csv_helper, service_helper
|
from helpers import aws_helper, tar_helper, csv_helper, service_helper
|
||||||
@ -71,17 +71,22 @@ class FormGenerationService(Base):
|
|||||||
# iterate for number of forms that require creation
|
# iterate for number of forms that require creation
|
||||||
for form_count in range(self.solver_run.total_forms):
|
for form_count in range(self.solver_run.total_forms):
|
||||||
form_number = form_count + 1
|
form_number = form_count + 1
|
||||||
|
drift_increment = self.solver_run.max_drift / (self.solver_run.max_attempts - 1)
|
||||||
current_drift = 0 # FF Tokyo Drift
|
current_drift = 0 # FF Tokyo Drift
|
||||||
|
current_attempt = 0
|
||||||
|
|
||||||
logging.info(f'Generating Solution for Form {form_number} using the {self.solver_run.irt_model.model} IRT model')
|
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():
|
# respect max attempts
|
||||||
|
# this will likely be more built out when we add increment rate & drif limit
|
||||||
|
while current_attempt <= self.solver_run.max_attempts:
|
||||||
drift_percent = current_drift / 100
|
drift_percent = current_drift / 100
|
||||||
self.solver_run.objective_function.update_targets_drift(
|
self.solver_run.objective_function.update_targets_drift(
|
||||||
drift_percent)
|
drift_percent)
|
||||||
|
|
||||||
# create problem
|
# create problem
|
||||||
problem_handler = Problem(items = self.solver_run.unbundled_items(), bundles = self.solver_run.bundles, problem = LpProblem('ata-form-generate', LpMinimize))
|
problem = LpProblem('ata-form-generate', self.solver_run.objective_function.objective)
|
||||||
|
problem_handler = Problem(items = self.solver_run.unbundled_items(), bundles = self.solver_run.bundles, problem = problem)
|
||||||
problem_handler.generate(solution, self.solver_run)
|
problem_handler.generate(solution, self.solver_run)
|
||||||
problem = problem_handler.solve(self.solver_run)
|
problem = problem_handler.solve(self.solver_run)
|
||||||
|
|
||||||
@ -90,7 +95,7 @@ class FormGenerationService(Base):
|
|||||||
f'attempt infeasible for drift of {current_drift}%')
|
f'attempt infeasible for drift of {current_drift}%')
|
||||||
|
|
||||||
if current_drift >= Target.max_drift(
|
if current_drift >= Target.max_drift(
|
||||||
): # this is the last attempt, so lets finalize the solution
|
) or current_attempt >= self.solver_run.max_attempts: # this is the last attempt, so lets finalize the solution
|
||||||
if ApplicationConfigs.local_dev_env:
|
if ApplicationConfigs.local_dev_env:
|
||||||
service_helper.print_problem_variables(problem)
|
service_helper.print_problem_variables(problem)
|
||||||
|
|
||||||
@ -103,7 +108,8 @@ class FormGenerationService(Base):
|
|||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
current_drift += Target.max_drift_increment()
|
current_drift += drift_increment
|
||||||
|
current_attempt += 1
|
||||||
else:
|
else:
|
||||||
if ApplicationConfigs.local_dev_env:
|
if ApplicationConfigs.local_dev_env:
|
||||||
service_helper.print_problem_variables(problem)
|
service_helper.print_problem_variables(problem)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user