如何编辑此algorithm,以便创build组合而不更换或重用元素?

我对计算机科学很陌生 – 这是我的第一个程序。 我写了一个python程序,它从excel表格“Labels”中的两列中获取数据:“Values”,并将它们重新configuration为各自值总和为30的标签列表。每个标签是唯一的,只出现一次,但不同的标签可以具有相同的价值。

但是,当我第一次使用我的程序时,运行时间接近30分钟,因为algorithm创build了标签的所有可能的组合。 显然给出了50个值小于10的标签,这是很多可能的组合。

我想要一些帮助编辑我的当前algorithm,以便它创build唯一的组。 一旦使用了标签,我不希望它出现在任何其他组中。

目前我的代码如下所示:

def combinator(X): #this function pulls two lists together to create a dictionary from xlrd import open_workbook wb = open_workbook(X) L = [] P = [] for s in wb.sheets(): for col in range(s.ncols): for row in range(s.nrows): if row !=0: l = s.cell(row,0).value L.append(l) p = s.cell(row,1).value P.append(p) Lots = L[0:(len(L)/2)] Pallets = P[0:(len(L)/2)] D = dict(zip(Lots,Pallets)) return D def grouper(D, N):#this finds combinations of 30 and puts them in groups from itertools import combinations groups_of_thirty = [] for l in range(0, len(D)): for y in combinations(D.items(), l): keys = [] sum = 0 for key, value in y: keys.append(key) sum += value if sum == N: groups_of_thirty.append(keys) flattened = [v for flat in groups_of_thirty for v in flat] K = D.keys() s = set(K) remainder = list(s - set(flattened)) list(groups_of_thirty) return groups_of_thirty, \ remainder def transposer(G):#this exports the final list into each cell and writes the spreadsheet as a csv to a different directory. import os os.chdir(Q) import csv with open(O, "wb") as f: writer = csv.writer(f) str(writer.writerows(G)) return transposer(grouper(combinator(I),N)) 

将不胜感激这种任何帮助 – 逻辑或伪代码的首选,但一些指针与不常见的语法将是有益的,因为我是一个新手。

谢谢!

编辑:这是Excel表格中的示例数据的屏幕截图。

具有input和期望输出的Excel工作表的屏幕截图

下面是我在评论中提到的线性规划方法:

 import pandas as pd from pulp import * import random random.seed(0) num_items = 50 labels = ['Label{0:02d}'.format(i) for i in range(num_items)] values = [random.randint(5, 30) for _ in range(num_items)] df = pd.DataFrame({'Value': values}, index=labels) feasible_solutions = [] var = LpVariable.dicts('x', labels, 0, 1, LpInteger) prob = pulp.LpProblem('Fixed Sum', pulp.LpMinimize) prob += 0 prob += lpSum([var[label] * df.at[label, 'Value'] for label in labels]) == 30 while prob.solve() == 1: current_solution = [label for label in labels if value(var[label])] feasible_solutions.append(current_solution) prob += lpSum([var[label] for label in current_solution]) <= len(current_solution) - 1 

labels是一个常规列表,它包含标签, values是5到30之间的随机整数。它以空集合开始。

这个代码中最重要的元素之一是var 。 这是决定variables取值0还是1.当在解决scheme中包含特定标签时,取值为1,否则取值为0。

例如,假设你有这个列表[12, 7, 5, 13] 。 这里,对于可能的解决schemevar00 (12), var02 (5)和var03 (13)可以取值1。

下一行创build了一个线性编程问题。 我们指定一个任意的目标函数( prob += 0 ),因为我们不是最小化或最大化任何函数 – 我们试图find所有可能的解决scheme。

这些解决scheme应该满足下一行的限制。 在这里, var[label]是一个二元决策variables,正如我所提到的。 如果它包含在解决scheme中,则值为1,1乘以其值。 所以我们只是把这个集合中包含的项目的值加起来。 它们的总和应该等于30.这里, prob.solve()会产生一个可行的解决scheme,但是因为你想要所有可行的解决scheme,所以你在while循环中调用prob.solve() 。 只要它可以返回一个可行的解决scheme(== 1)继续循环。 但在每次迭代中,我们应该排除当前的解决scheme,以便减lesssearch空间。 这是由最后一行完成的。 例如,如果在当前的解决scheme中我们有var00var04var07 ,那么对于后续问题,它们的总和应该小于3(所有三个不应该同时为1)。 如果你运行这个,它会为你的问题产生所有可能的解决scheme。

这是前五个:

 feasible_solutions[:5] Out: [['Label00', 'Label47'], ['Label17', 'Label46'], ['Label42', 'Label45'], ['Label03', 'Label13', 'Label47'], ['Label02', 'Label03', 'Label48']] 

这是他们的价值观:

 Out: [[17, 13], [9, 21], [11, 19], [6, 11, 13], [18, 6, 6]]