def bin_packing( num_items: int, seed: int = 32, weight_range: Tuple[int, int] = (10, 30), ) -> ConstrainedQuadraticModel: """Returns a constrained quadratic model encoding a bin packing problem Given the number of items, the code generates a random bin packing problem formulated as a Constrained Quadratic model. The weights for each item are integers uniformly drawn from in the weight_range. The bin capacity is set to num_items * mean(weights) / 5. Args: num_items: Number of items to choose from. seed: Seed for numpy random number generator. weight_range: The range of the randomly generated weights for each item. Returns: The constrained quadratic model encoding the bin packing problem. Variables are labeled as y_{j} where y_{j} = 1 means that bin j has been used and x_{i}_{j} where x_{i}_{j} = 1 means that item i has been placed in bin j. """ max_num_bins = num_items np.random.seed(seed) weights = list(np.random.randint(*weight_range, num_items)) bin_capacity = int(num_items * np.mean(weights) / 5) model = ConstrainedQuadraticModel() obj = BinaryQuadraticModel(vartype='BINARY') y = {j: obj.add_variable(f'y_{j}') for j in range(max_num_bins)} for j in range(max_num_bins): obj.set_linear(y[j], 1) model.set_objective(obj) x = {(i, j): model.add_variable(f'x_{i}_{j}', vartype='BINARY') for i in range(num_items) for j in range(max_num_bins)} # Each item goes to one bin for i in range(num_items): model.add_constraint([(x[(i, j)], 1) for j in range(max_num_bins)] + [(-1, )], sense="==", label='item_placing_{}'.format(i)) # Bin capacity constraint for j in range(max_num_bins): model.add_constraint([(x[(i, j)], weights[i]) for i in range(num_items)] + [(y[j], -bin_capacity)], sense="<=", label='capacity_bin_{}'.format(j)) return model
def random_knapsack( num_items: int, seed: int = 32, value_range: Tuple[int, int] = (10, 30), weight_range: Tuple[int, int] = (10, 30), tightness_ratio: float = 0.5, ) -> ConstrainedQuadraticModel: """Returns a Constrained Quadratic Model encoding a knapsack problem. Given the number of items, the code generates a random knapsack problem, formulated as a Constrained Quadratic model. The capacity of the bin is set to be ``tightness_ratio`` times the sum of the weights. Args: num_items: Number of items to choose from. seed: Seed for numpy random number generator. value_range: The range of the randomly generated values for each item. weight_range: The range of the randomly generated weights for each item. tightness_ratio: ratio of capacity over sum of weights. Returns: The quadratic model encoding the knapsack problem. Variables are denoted as ``x_{i}`` where ``x_{i} == 1`` means that the item ``i`` has been placed in the knapsack. """ rng = np.random.RandomState(seed) value = {i: rng.randint(*value_range) for i in range(num_items)} weight = {i: rng.randint(*weight_range) for i in range(num_items)} capacity = int(sum(weight.values()) * tightness_ratio) model = ConstrainedQuadraticModel() obj = BinaryQuadraticModel(vartype='BINARY') x = {i: obj.add_variable(f'x_{i}') for i in range(num_items)} for i in range(num_items): obj.set_linear(x[i], -value[i]) model.set_objective(obj) constraint = [(x[i], weight[i]) for i in range(num_items)] + [(-capacity, )] model.add_constraint(constraint, sense="<=", label='capacity') return model
def random_multi_knapsack( num_items: int, num_bins: int, seed: int = 32, value_range: Tuple[int, int] = (10, 50), weight_range: Tuple[int, int] = (10, 50), ) -> ConstrainedQuadraticModel: """Return a constrained quadratic model encoding a multiple knapsack problem. Given the number of items and the number of bins, the code generates a multiple-knapsack problem, formulated as a Constrained Quadratic Model. Values and weights for each item are uniformly sampled within the provided ranges. Capacities of bins are randomly assigned. Args: num_items: Number of items. num_bins: Number of bins. seed: seed for RNG. value_range: The range of the randomly generated values for each item. weight_range: The range of the randomly generated weights for each item. Returns: A constrained quadratic model encoding the multiple knapsack problem. Variables are labelled as ``x_{i}_{j}``, where ``x_{i}_{j} == 1`` means that item ``i`` is placed in bin ``j``. """ rng = np.random.RandomState(seed) weights = rng.randint(*weight_range, num_items) values = rng.randint(*value_range, num_items) cap_low = int(weight_range[0] * num_items / num_bins) cap_high = int(weight_range[1] * num_items / num_bins) capacities = rng.randint(cap_low, cap_high, num_bins) model = ConstrainedQuadraticModel() obj = BinaryQuadraticModel(vartype='BINARY') x = {(i, j): obj.add_variable(f'x_{i}_{j}') for i in range(num_items) for j in range(num_bins)} for i in range(num_items): for j in range(num_bins): obj.set_linear(x[(i, j)], -values[i]) model.set_objective(obj) # Each item at most goes to one bin. for i in range(num_items): model.add_constraint([(x[(i, j)], 1) for j in range(num_bins)] + [(-1, )], sense="<=", label='item_placing_{}'.format(i)) # Build knapsack capacity constraints for j in range(num_bins): model.add_constraint([(x[(i, j)], weights[i]) for i in range(num_items)] + [(-capacities[j], )], sense="<=", label='capacity_bin_{}'.format(j)) return model