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
Beispiel #2
0
def RandomSearch(kp: Knapsack, items: List[Item], stopCriteria=10):
    # Random Search implementation

    #  Initialize the variables
    mh = Metaheuristic()
    heuristics = list(heuristicComparison.keys())
    countNone = 0

    while countNone < stopCriteria:
        # Choice randomly the next heuristic
        nextHeuristic = np.random.choice(heuristics)
        kp_candidate = kp.copy()
        items_candidate = items.copy()
        nextItem = SimpleHeuristic(nextHeuristic).apply(
            kp_candidate, items_candidate)

        if nextItem == None or kp_candidate.getValue() <= kp.getValue():
            # Reject the heuristic
            countNone += 1
            continue
        countNone = 0

        # Accept the heuristic
        kp = kp_candidate
        items = items_candidate
        mh.addHeuristic(nextHeuristic)
    return kp, mh
def solver(method: str, kp: Knapsack, items: List[Item], additionalArgs=None):
    if method == 'Heuristic':
        # Execute the heuristic method
        simple_heuristic = SimpleHeuristic(additionalArgs)
        return ConstructiveSolution(kp, items, simple_heuristic).getValue()
    elif method == 'SimulatedAnnealing':
        # Execute the Simulated Annealing metaheuristic
        return solveMetaheuristic(method, kp, items, additionalArgs)
    elif method == 'RandomSearch':
        # Execute the Random Search metaheuristic
        return solveMetaheuristic(method, kp, items, additionalArgs)
    elif method == 'HyperheuristicNaive':
        # Execute the Hyper-heuristic naive model
        hh = HyperheuristicNaive(additionalArgs)
        return ConstructiveSolution(kp, items, hh).getValue()
    elif method == 'Hyperheuristic':
        # Execute the Hyper-heuristic based on LSTM model
        return hyperheuristicSolver(kp, items, additionalArgs).getValue()
    elif method == 'Backtracking':
        # Execute the recursive backtracking method
        return kpBacktracking(kp.getCapacity(), items).getValue()
    elif method == 'DP':
        # Execute the dynamic programming method
        return kpDP(kp.getCapacity(), items).getValue()
    elif method == 'MILP':
        # Execute the mixed integer linear programming method
        return kpMILP(kp.getCapacity(), items).getValue()
    elif method in list(heuristicComparison.keys()):
        # Given the heuristic as method parameter, execute the constructive heuristic method
        simple_heuristic = SimpleHeuristic(method)
        return ConstructiveSolution(kp, items, simple_heuristic).getValue()
    else:
        return 0
def hyperheuristicSolverHH(kp: Knapsack, items: List[Item], hh: Hyperheuristic, stopCritaria = 10):
    # Prepare the HH variables
    hh.reset()
    mh = Metaheuristic()
    kp_best = kp.copy()
    mh_best = mh.copy()
    countNone = 0
    while countNone < stopCritaria:
        # Choice the next heuristic
        nextHeuristic = hh.getHeuristic(items)
        # Apply the heuristic
        nextItem = SimpleHeuristic(nextHeuristic).apply(kp, items)
        if nextItem == None:
            # Reject the heuristic
            countNone += 1
            continue
        countNone = 0
        # Accept the heuristic
        mh.addHeuristic(nextHeuristic)
        # Save the best solution reached
        if kp_best.getValue() < kp.getValue():
            kp_best = kp.copy()
            mh_best = mh.copy()
    # Return the best solution reached
    return kp_best, mh_best
Beispiel #5
0
def SimulatedAnnealing(kp: Knapsack,
                       items: List[Item],
                       n_iterations=100,
                       temp=200,
                       stopCriteria=10):
    # Simulated Annealing implementation
    #  Initialization of the variables
    mh = Metaheuristic()
    heuristics = list(heuristicComparison.keys())
    countNone = 0

    kp_best = kp.copy()
    mh_best = Metaheuristic()
    n_iterations = max(n_iterations, 2 * len(items))
    for i in range(n_iterations):
        if countNone == stopCriteria:
            # Stop criteria met
            break

        # Choice randomly the next heuristic
        nextHeuristic = np.random.choice(heuristics)
        kp_candidate = kp.copy()
        items_candidate = items.copy()
        nextItem = SimpleHeuristic(nextHeuristic).apply(
            kp_candidate, items_candidate)
        if nextItem == None:
            # Heuristic does not change the instance
            countNone += 1
            continue
        countNone = 0

        if kp_best.getValue() < kp_candidate.getValue():
            # Heuristic improve the performance of the solution
            kp_best = kp_candidate.copy()
            mh_best = mh.copy()
            mh_best.addHeuristic(nextHeuristic)

        # Calculate the metropolis variable
        diff = kp.getValue() - kp_candidate.getValue()
        t = temp / (i + 1)
        if -10 <= -diff / t and -diff / t <= 0:
            metropolis = np.exp(-diff / t)
        elif -diff / t <= -10:
            metropolis = 0
        else:
            metropolis = 1
        # Acceptance criteria
        if diff < 0 or np.random.rand() <= metropolis:
            kp = kp_candidate
            items = items_candidate
            mh.addHeuristic(nextHeuristic)
        else:
            countNone += 1
    # Return the best solution reached
    return kp_best, mh_best
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
Beispiel #7
0
 def cleanHeuristics(self, W: int, items: List[Item]):
     # Only considered heuristics that changes the instance
     kp = Knapsack(W)
     mh = []
     for heuristic in self.sequenceHeuristics:
         nextItem = SimpleHeuristic(heuristic).apply(kp, items)
         if nextItem != None:
             mh.append(heuristic)
     self.sequenceHeuristics = mh
 def nextItem(self, kp: Knapsack, items: List[Item]):
     # Choice the next packable item
     if self.onKP:
         return None
     idx = None
     for i, item in enumerate(items):
         if kp.canPack(item):
             if idx == None or heuristicComparison[self.name](items[idx],
                                                              item):
                 idx = i
     return idx
Beispiel #9
0
def solveMetaheuristic(method: str,
                       kp: Knapsack,
                       items: List[Item],
                       saveMetaheuristic=False,
                       fileName='traindata.csv',
                       overwrite=False):
    W = kp.getCapacity()
    items_copy = items.copy()

    # Execute the chosen method
    if method == 'SimulatedAnnealing':
        kp, mh = SimulatedAnnealing(kp, items)
    elif method == 'RandomSearch':
        kp, mh = RandomSearch(kp, items)
    else:
        return 0

    # Save the sequence of heuristics
    if saveMetaheuristic:
        mh.saveMetaheuristic(W, items_copy, fileName, overwrite)
    return kp.getValue()
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 kpBacktracking(W: int, items: List[Item]):
    if items == [] or W == 0:
        return Knapsack(W)
    item = items[0]
    if item.getWeight() > W:
        # Not choice the item
        return kpBacktracking(items[1:], W)
    else:
        # Choice the item
        kpWithItem = kpBacktracking(items[1:], W - item.getWeight())
        kpWithItem.capacity += item.getWeight()
        kpWithItem.pack(item)

        # Not choice the item
        kpWithoutItem = kpBacktracking(items[1:], W)

        # Decide best option
        if kpWithItem.getValue() < kpWithoutItem.getValue():
            return kpWithoutItem
        else:
            return kpWithItem
Beispiel #12
0
    def saveMetaheuristic(self,
                          W: int,
                          items: List[Item],
                          fileName='traindata.csv',
                          overwrite=False):
        # Save the sequence of heuristics in a CSV file
        labels = list(featuresCalculation.keys()) + ['NextHeuristic']

        featureDataFrame = []
        featureDict = dict()

        kp = Knapsack(W)
        for heuristic in self.sequenceHeuristics:
            # Obtain the characterization of the instance and store it
            values = getAllFeatures(items) + [heuristic]
            for name, value in zip(labels, values):
                featureDict[name] = value
            featureDataFrame.append(featureDict.copy())

            SimpleHeuristic(heuristic).apply(kp, items)
        # Save the sequence of characterization in a CSV file
        saveDataCSV(fileName, featureDataFrame, labels, overwrite)
Beispiel #13
0
def generateTrainDataset(trainFilename='traindata.csv',
                         overwrite=True,
                         instances='Pisinger'):
    if type(instances) == str:
        # Obtain the instances to generate the train dataset of the LSTM model
        # If type(instances) != str, then instances is a list of strings with
        # the filenames considered to generate the train dataset
        instances = obtainFilenames(tapia_path, instances)
    # Per each instance, execute the Simulated Annealing metaheuristic and
    # save the sequence of heuristics generated
    for filePath in instances:
        _, W, weights, profits = loadInstance(filePath)
        kp = Knapsack(W)
        items = generateItemList(weights, profits)

        np.random.seed(0)
        solveMetaheuristic('SimulatedAnnealing',
                           kp,
                           items,
                           saveMetaheuristic=True,
                           fileName=trainFilename,
                           overwrite=overwrite)
        overwrite = False
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
Beispiel #15
0
 def solveInstance(self, W: int, items: List[Item]):
     # Apply the sequence of heuristics saved in the given instance
     kp = Knapsack(W)
     for heuristic in self.sequenceHeuristics:
         SimpleHeuristic(heuristic).apply(kp, items)
     return kp
    #  Prepare the dict to save the data
    resultsTestDict = dict()  
    for method in methods:
        resultsTestDict[method] = []
        resultsTestDict[f'{method}_time'] = []
    
    #  Obtain the path to each test instance 
    instances = obtainFilenames(tapia_path, testDataset)
    for instance in instances:
        # Read the instance
        n, W, weights, profits = loadInstance(instance)

        for method, iterations in zip(methods, methodIterations):
            sumResults, sumTime = 0, 0
            for i in range(iterations):
                kp = Knapsack(W)
                items = generateItemList(weights, profits)

                start = perf_counter()
                if method == 'Hyperheuristic':
                    # Run the respective HH
                    kp, mh = hyperheuristicSolverHH(kp, items, HH[i])
                    result = kp.getValue()
                else:
                    # Run the respective solver method
                    result = solver(method, kp, items)
                end = perf_counter()

                sumResults += result 
                sumTime += end-start
            # Store the average results and average time per method