我该如何编辑这个算法,以便它在不替换或重用元素的情况下创建组合?
How do I edit this algorithm so that it creates combinations without replacement or reusing an element?
我对计算机科学还很陌生 - 这是我的第一个程序。我写了一个 python 程序,它从 excel sheet "Labels":"Values" 的两列中获取数据,并将它们重新配置到标签列表中,标签列表各自的值总和为30. 每个标签都是唯一的,只出现一次,但不同的标签可以有相同的值。
但是,当我第一次应用我的程序时,运行时间将近 30 分钟,因为算法正在创建标签的所有可能组合。显然给定 50 个值小于 10 的标签,这是很多可能的组合。
我需要一些帮助来编辑我当前的算法,以便它创建独特的组。使用标签后,我不希望它出现在任何其他组中。
目前我的代码如下所示:
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 sheet.
中示例数据的屏幕截图
这是我在评论中提到的线性规划方法:
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
。它是取值 0 或 1 的决策变量。当您在解决方案中包含特定标签时,它取值 1,否则它等于零。
例如,假设您有此列表 [12, 7, 5, 13]
。这里,对于可能的解决方案var00
(12),var02
(5)和var03
(13)可以取值1。
下一行创建一个线性规划问题。我们指定了一个任意的 objective 函数 (prob += 0
),因为我们没有最小化或最大化任何函数 - 我们试图找到所有可能的解决方案。
这些解决方案应满足下一行中的约束条件。在这里,var[label]
是我提到的二元决策变量。如果它包含在解决方案中,则它取值 1,然后 1 乘以它的值。所以我们只对集合中包含的项目的值求和。它们的总和应该等于 30。在这里,prob.solve()
会生成一个可行的解决方案,但由于您想要所有可行的解决方案,因此您在 while 循环中调用 prob.solve()
。只要能return个可行解(==1)就继续循环。但是在每次迭代中,我们应该排除当前的解决方案,以便我们的搜索 space 减少。它由最后一行完成。例如,如果在当前解决方案中我们有 var00
、var04
和 var07
,对于后续问题,它们的总和应该小于 3(所有三个不应该同时为 1时间)。如果你 运行 这个,它会为你的问题生成所有可能的解决方案。
这是前五个:
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]]
我对计算机科学还很陌生 - 这是我的第一个程序。我写了一个 python 程序,它从 excel sheet "Labels":"Values" 的两列中获取数据,并将它们重新配置到标签列表中,标签列表各自的值总和为30. 每个标签都是唯一的,只出现一次,但不同的标签可以有相同的值。
但是,当我第一次应用我的程序时,运行时间将近 30 分钟,因为算法正在创建标签的所有可能组合。显然给定 50 个值小于 10 的标签,这是很多可能的组合。
我需要一些帮助来编辑我当前的算法,以便它创建独特的组。使用标签后,我不希望它出现在任何其他组中。
目前我的代码如下所示:
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 sheet.
中示例数据的屏幕截图这是我在评论中提到的线性规划方法:
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
。它是取值 0 或 1 的决策变量。当您在解决方案中包含特定标签时,它取值 1,否则它等于零。
例如,假设您有此列表 [12, 7, 5, 13]
。这里,对于可能的解决方案var00
(12),var02
(5)和var03
(13)可以取值1。
下一行创建一个线性规划问题。我们指定了一个任意的 objective 函数 (prob += 0
),因为我们没有最小化或最大化任何函数 - 我们试图找到所有可能的解决方案。
这些解决方案应满足下一行中的约束条件。在这里,var[label]
是我提到的二元决策变量。如果它包含在解决方案中,则它取值 1,然后 1 乘以它的值。所以我们只对集合中包含的项目的值求和。它们的总和应该等于 30。在这里,prob.solve()
会生成一个可行的解决方案,但由于您想要所有可行的解决方案,因此您在 while 循环中调用 prob.solve()
。只要能return个可行解(==1)就继续循环。但是在每次迭代中,我们应该排除当前的解决方案,以便我们的搜索 space 减少。它由最后一行完成。例如,如果在当前解决方案中我们有 var00
、var04
和 var07
,对于后续问题,它们的总和应该小于 3(所有三个不应该同时为 1时间)。如果你 运行 这个,它会为你的问题生成所有可能的解决方案。
这是前五个:
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]]