How to find best solution from all brute force combinations?

耗尽温柔 提交于 2019-12-11 05:17:43

问题


I want to find the best solution from all brute force combinations of a dictionary. For the context of the problem, I need to find out the minimum number of trips needed to transport all the cows given a weight limit.

The combinations are already given to me with the helper functions get_partitions. The function returns a nested list, with each inner list represents a trip and names of cows on that trip.

Helper functions:

def partitions(set_):
    if not set_:
        yield []
        return
    for i in range(2**len(set_)//2):
        parts = [set(), set()]
        for item in set_:
            parts[i&1].add(item)
            i >>= 1
        for b in partitions(parts[1]):
            yield [parts[0]]+b

def get_partitions(set_):
    for partition in partitions(set_):
        yield [list(elt) for elt in partition]

What I tried to do was sorting all combinations by length then iterate over them with a nested loop. If the total weight exceed the limit, then I break out of the inner loop and append the next sublist to another list. The problem is that the next sublist still contain leftover lists from the partition since their total weight is below the limit.

My code:

def brute_force_cow_transport(cows, limit):

    # Generate and sort all combinations by length
    partitions = [item for item in get_partitions(cows)]
    partitions.sort(key=len)

    # Iterate over each sublist of combinations
    possibles = []
    for partition in partitions:
        trips = []
        for section in partition:
            total = sum([cows.get(cow) for cow in section])
            if total > limit:
                break
            else:
                # Appending next sublists create duplicates
                trips.append(section)
            possibles.append(trips)

    # Remove duplicates from possible solutions
    best = []
    for item in possibles:
        if item and item not in best:
            best.append(item)
    return min(best)

When I run my function, it keeps returning a different result each time. I think it's because the leftover sublists I appended to the results is causing the problem but I'm not sure:

cows = {'MooMoo': 50, 'Miss Bella': 25, 'Boo': 20, 
        'Milkshake': 40, 'Horns': 25, 'Lotus': 40}

>>> brute_force_cow_transport(cows, limit=100)
[['Boo', 'Miss Bella', 'MooMoo']]

Correct result:

[['MooMoo', 'Horns', 'Miss Bella'], ['Milkshake', 'Lotus', 'Boo']]

If anyone can help me point out where I went wrong, that would be greatly appreciated.

Edit: Added helper functions


回答1:


We can approach this as a depth-first-search problem.

def getCows(dict, limit):
    best_solution = []
    best_solution_score = 0

    def dfs(current_cows, current_total):
        nonlocal best_solution_score
        nonlocal best_solution
        if current_total > best_solution_score:
            #replace best solution
            best_solution = [tuple(sorted(current_cows))]
            best_solution_score = current_total
        elif current_total == best_solution_score:
            #add to best solution
            best_solution.append(tuple(sorted(current_cows))) 
        for cow, weight in dict.items():
            if cow not in current_cows and current_total + weight <= limit:
                #if adding next cow under limit recurse
                dfs(current_cows + [cow], current_total + weight)

    dfs([], 0)
    return list(set(best_solution)) #remove duplicates

cows = {'MooMoo': 50, 'Miss Bella': 25, 'Boo': 20,
    'Milkshake': 40, 'Horns': 25, 'Lotus': 40}


print(getCows(cows, limit=100))
>>>[('Horns', 'Miss Bella', 'MooMoo'), ('Boo', 'Lotus', 'Milkshake')]


来源:https://stackoverflow.com/questions/49826746/how-to-find-best-solution-from-all-brute-force-combinations

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!