不确定如何在数据生成算法中集成负数函数?

时间:2012-02-11 19:55:45

标签: python algorithm dynamic-programming

我在控制我正在处理的数据生成算法的结果时遇到了一些麻烦。基本上它从列表中获取值,然后列出所有不同的组合以获得特定的总和。到目前为止代码工作正常(尚未测试使用许多变量进行扩展),但我需要允许在列表中包含负数。

我认为我可以解决这个问题的方法是在可能的结果上设置一个项圈以防止无穷大的结果(如果苹果是2而橙子是-1然后对于任何总和,将会有无限的解决方案但是如果我说有一个限制,那么它不能永远持续下去。)

所以这是检测权重的超级基本代码:

import math

data = [-2, 10,5,50,20,25,40]
target_sum = 100
max_percent = .8 #no value can exceed 80% of total(this is to prevent infinite solutions

for node in data:
    max_value = abs(math.floor((target_sum * max_percent)/node))
    print node, "'s max value is ", max_value

这是生成结果的代码(第一个函数生成一个表,如果可能,第二个函数组成实际结果。算法的详细信息/伪代码在这里:Can brute force algorithms scale?):

from collections import defaultdict

data = [-2, 10,5,50,20,25,40]
target_sum = 100
# T[x, i] is True if 'x' can be solved
# by a linear combination of data[:i+1]
T = defaultdict(bool)           # all values are False by default
T[0, 0] = True                # base case


for i, x in enumerate(data):    # i is index, x is data[i]
    for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself
        for c in range(s / x + 1):  
            if T[s - c * x, i]:
                T[s, i+1] = True

coeff = [0]*len(data)
def RecursivelyListAllThatWork(k, sum): # Using last k variables, make sum
    # /* Base case: If we've assigned all the variables correctly, list this
    # * solution.
    # */
    if k == 0:
        # print what we have so far
        print(' + '.join("%2s*%s" % t for t in zip(coeff, data)))
        return
    x_k = data[k-1]
    # /* Recursive step: Try all coefficients, but only if they work. */
    for c in range(sum // x_k + 1):
       if T[sum - c * x_k, k - 1]:
           # mark the coefficient of x_k to be c
           coeff[k-1] = c
           RecursivelyListAllThatWork(k - 1, sum - c * x_k)
           # unmark the coefficient of x_k
           coeff[k-1] = 0

RecursivelyListAllThatWork(len(data), target_sum)

我的问题是,我不知道在哪里/如何将限制代码集成到主代码中以限制结果并允许负数。当我向列表中添加一个负数时,它会显示它,但不会在输出中包含它。我认为这是因为它没有被添加到表中(第一个函数)而且我不确定如何添加它(并且仍然保留程序结构以便我可以使用更多变量来扩展它)。

提前致谢,如果有任何不清楚的地方,请告诉我。

编辑:有点无关(如果有问题就会忽略,但是因为你已经看过代码了,有没有办法可以在我的机器上使用这个代码的cpus?现在当我运行它时,它只使用一个cpu。我知道python中并行计算的技术方法,但不知道如何在逻辑上并行化这个算法)

1 个答案:

答案 0 :(得分:4)

您可以通过从

更改c上的两个循环来限制结果
for c in range(s / x + 1):  

max_value = int(abs((target_sum * max_percent)/x))
for c in range(max_value + 1):

这将确保最终答案中的任何系数都是0到max_value范围内的整数。

添加负值的一种简单方法是从

更改循环
for s in range(target_sum + 1):

R=200 # Maximum size of any partial sum
for s in range(-R,R+1):

请注意,如果您这样做,那么您的解决方案将有一个额外的约束。 新约束是每个部分加权和的绝对值必须是< = R。

(你可以使R大,以避免这种约束减少解决方案的数量,但这会减慢执行速度。)

完整的代码如下:

from collections import defaultdict

data = [-2,10,5,50,20,25,40]

target_sum = 100
# T[x, i] is True if 'x' can be solved
# by a linear combination of data[:i+1]
T = defaultdict(bool)           # all values are False by default
T[0, 0] = True                # base case

R=200 # Maximum size of any partial sum
max_percent=0.8 # Maximum weight of any term

for i, x in enumerate(data):    # i is index, x is data[i]
    for s in range(-R,R+1): #set the range of one higher than sum to include sum itself
        max_value = int(abs((target_sum * max_percent)/x))
        for c in range(max_value + 1):  
            if T[s - c * x, i]:
                T[s, i+1] = True

coeff = [0]*len(data)
def RecursivelyListAllThatWork(k, sum): # Using last k variables, make sum
    # /* Base case: If we've assigned all the variables correctly, list this
    # * solution.
    # */
    if k == 0:
        # print what we have so far
        print(' + '.join("%2s*%s" % t for t in zip(coeff, data)))
        return
    x_k = data[k-1]
    # /* Recursive step: Try all coefficients, but only if they work. */
    max_value = int(abs((target_sum * max_percent)/x_k))
    for c in range(max_value + 1):
       if T[sum - c * x_k, k - 1]:
           # mark the coefficient of x_k to be c
           coeff[k-1] = c
           RecursivelyListAllThatWork(k - 1, sum - c * x_k)
           # unmark the coefficient of x_k
           coeff[k-1] = 0

RecursivelyListAllThatWork(len(data), target_sum)