Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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