def apply(self, kp: Knapsack, items: List[Item]):
     if self.name == None:
         return None
     if self.onKP:
         # Choice the item that will be unpacked from the knapsack
         idx = None
         kp_packed = kp.getPackedItems()
         for i, item in enumerate(kp_packed):
             if idx == None or heuristicComparison[self.name](
                     kp_packed[idx], item):
                 idx = i
         if idx != None:
             items.append(kp.unpack(idx))
         return idx
     else:
         # Choice the item that will be packed
         idx = None
         for i, item in enumerate(items):
             if kp.canPack(item):
                 if idx == None or heuristicComparison[self.name](
                         items[idx], item):
                     idx = i
         if idx != None:
             kp.pack(items.pop(idx))
         return idx
def ConstructiveSolution(kp: Knapsack, items: List[Item], itemSelector):
    # Find the first item to pack to the knapsack
    nextItem = itemSelector.nextItem(kp, items)

    while nextItem is not None:
        # Pack the items until no other item can be packed
        kp.pack(items[nextItem])
        items.pop(nextItem)
        nextItem = itemSelector.nextItem(kp, items)

    # Return the solution reached
    return kp
def kpMILP(W: int, items: List[Item]):
    # Prepare the solver
    solver = pywrapknapsack_solver.KnapsackSolver(
        pywrapknapsack_solver.KnapsackSolver.
        KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER, 'Knapsack BC-MILP')

    # Prepare the data
    profit = [item.getProfit() for item in items]
    weights = [[item.getWeight() for item in items]]
    capacities = [W]

    # Execute the solver
    solver.Init(profit, weights, capacities)
    solver.Solve()

    # Find the best solution
    kp = Knapsack(W)
    for i, item in enumerate(items):
        if solver.BestSolutionContains(i):
            kp.pack(item)
    return kp
def kpDP(W: int, items: List[Item]):
    n = len(items)
    A = np.zeros((n + 1, W + 1))

    # Calculate the DP in the bottom-up fashion way
    for idx, item in enumerate(items, start=1):
        w, p = item.getWeight(), item.getProfit()
        for Wi in range(W + 1):
            if Wi == 0:
                continue
            elif idx == 0:
                A[idx, Wi] = p if w <= Wi else 0
            elif w <= Wi:
                A[idx, Wi] = max(A[idx - 1, Wi], A[idx - 1, Wi - w] + p)
            else:
                A[idx, Wi] = A[idx - 1, Wi]

    # Find the items that get the best solution
    kp, idx = Knapsack(W), n
    while idx >= 1 and kp.getCapacity() > 0:
        if A[idx - 1, kp.getCapacity()] != A[idx, kp.getCapacity()]:
            kp.pack(items[idx - 1])
        idx -= 1
    return kp