trending_deploy/optimization.py (28 lines of code) (raw):

from typing import List import numpy as np from tqdm import trange from trending_deploy.constants import Model def solve_knapsack(model_candidates: List[Model], budget: int) -> tuple[float, int, List[Model]]: """ Solve the 0/1 Knapsack Problem using dynamic programming with NumPy. Args: model_candidates (List[Model]): A list of model candidates. budget (int): The maximum total cost that we can allocate. Returns: tuple: A tuple containing the maximum reward, the spent budget, and the selected models. """ # Extract costs and rewards from the model candidates costs: List[int] = [model.cost for model in model_candidates] rewards: List[float] = [model.reward for model in model_candidates] num_models = len(costs) assert num_models == len(rewards) # This can be seen as the number of models seen so far and the remaining budget rewards_table = np.zeros((num_models + 1, budget + 1), dtype=int) for model_idx in trange(1, num_models + 1, desc="Solving Model Optimization", leave=False): for budget_idx in range(1, budget + 1): if costs[model_idx - 1] <= budget_idx: # If the current item's cost is within the remaining budget, choose the maximum reward between # not taking the item and taking the item rewards_table[model_idx, budget_idx] = max( rewards_table[model_idx - 1, budget_idx], # Not taking the item rewards_table[model_idx - 1, budget_idx - costs[model_idx - 1]] + rewards[model_idx - 1] # Taking the item ) else: # If the current item's cost exceeds the remaining budget, skip the item by setting the reward to be # the same as before this model was considered rewards_table[model_idx, budget_idx] = rewards_table[model_idx - 1, budget_idx] max_reward = rewards_table[num_models, budget] selected_models = [] budget_idx = budget for model_idx in range(num_models, 0, -1): if rewards_table[model_idx, budget_idx] != rewards_table[model_idx - 1, budget_idx]: selected_models.append(model_candidates[model_idx - 1]) budget_idx -= costs[model_idx - 1] spent_budget = budget - budget_idx return max_reward, spent_budget, selected_models[::-1]