random select recursive solution for bundle constraints

This commit is contained in:
Joshua Burman 2022-02-09 03:26:09 -05:00
parent 8ce5e6e540
commit 14a07ff9b2
2 changed files with 53 additions and 20 deletions

View File

@ -56,6 +56,22 @@ def build_constraints(solver_run: SolverRun, problem: LpProblem, items: list[Ite
logging.error(error) logging.error(error)
raise ItemGenerationError("Bundle min and/or max larger than bundle amount provided", error.args[0]) raise ItemGenerationError("Bundle min and/or max larger than bundle amount provided", error.args[0])
def get_random_bundles(total_form_items: int, total_bundles: int, bundles: list[Bundle], found_bundles = False) -> list[Bundle]:
selected_bundles = None
total_bundle_items = 0
while found_bundles == False:
selected_bundles = sample(bundles, total_bundles)
total_bundle_items = sum(bundle.count for bundle in selected_bundles)
if total_bundle_items <= total_form_items:
found_bundles = True
if found_bundles == True:
return selected_bundles
else:
return get_random_bundles(total_form_items, total_bundles - 1, bundles)
def valid_bundle_combinations(total_form_items: int, total_bundles: int, min_bundles: int, bundles: list[Bundle], selected_bundle_combinations: list[list[Bundle]] = []) -> list[list[Bundle]]: def valid_bundle_combinations(total_form_items: int, total_bundles: int, min_bundles: int, bundles: list[Bundle], selected_bundle_combinations: list[list[Bundle]] = []) -> list[list[Bundle]]:
if total_bundles < min_bundles: if total_bundles < min_bundles:
return selected_bundle_combinations return selected_bundle_combinations

View File

@ -74,33 +74,36 @@ class LoftService(Base):
response_id=random.randint(100, 5000), response_id=random.randint(100, 5000),
forms=[] forms=[]
) )
# initiate problem # initiate problem
problem = None problem = None
count = 0 count = 0
if bundle_constraint: if bundle_constraint:
# generate valid bundle combinations # # generate valid bundle combinations
bundle_combinations = solver_helper.valid_bundle_combinations( # bundle_combinations = solver_helper.valid_bundle_combinations(
self.solver_run.total_form_items, # self.solver_run.total_form_items,
int(bundle_constraint.maximum), # int(bundle_constraint.maximum),
int(bundle_constraint.minimum), # int(bundle_constraint.minimum),
self.solver_run.bundles) # self.solver_run.bundles)
# scramble bundle_combinations to ensure distinctiveness for each form generated # # scramble bundle_combinations to ensure distinctiveness for each form generated
random.shuffle(bundle_combinations) # random.shuffle(bundle_combinations)
for bundles in bundle_combinations: # for bundles in bundle_combinations:
problem = self.solve_problem(items, bundles) # problem = self.solve(items, bundles)
# if optimal solution found, break loop # # if optimal solution found, break loop
if LpStatus[problem.status] == 'Optimal': # if LpStatus[problem.status] == 'Optimal':
break # break
bundles_amount = random.randint(int(bundle_constraint.minimum), int(bundle_constraint.maximum))
problem = self.recursive_solve(items, bundles_amount)
else: # no bundles else: # no bundles
problem = self.solve_problem(items) problem = self.solve(items)
# successfull form, increment and exit out of loop # successfull form, increment and exit out of loop
f += 1 f += 1
# add return items and create as a form # add return items and create as a form
form_items = service_helper.solution_items(problem.variables(), self.solver_run) form_items = service_helper.solution_items(problem.variables(), self.solver_run)
@ -108,8 +111,22 @@ class LoftService(Base):
solution.forms.append(Form.create(form_items, self.solver_run, LpStatus[problem.status])) solution.forms.append(Form.create(form_items, self.solver_run, LpStatus[problem.status]))
return solution return solution
def solve_problem(self, items: list[Item], bundles: list[Bundle] or None = None) -> LpProblem: def recursive_solve(self, items, bundles_amount, attempts = 1000) -> LpProblem:
selected_bundles = solver_helper.get_random_bundles(
self.solver_run.total_form_items,
bundles_amount,
self.solver_run.bundles)
problem = self.solve(items, selected_bundles)
# if optimal solution found, break loop
if LpStatus[problem.status] == 'Optimal' or attempts == 0:
return problem
else:
return self.recursive_solve(items, max, attempts - 1)
def solve(self, items: list[Item], bundles: list[Bundle] or None = None) -> LpProblem:
# create problem # create problem
problem = LpProblem("ata-form-generate", LpMinimize) problem = LpProblem("ata-form-generate", LpMinimize)